* chore(wiki): 導入 system-dev-template + 合併 wiki 到新位置 - system-dev/ 模板包進版控(VERSION/docs/scripts/wiki 骨架) - 逐檔合併舊 .claude/wiki/ → system-dev/wiki/: - status/mistakes/decisions-summary 真資料覆蓋空範本 - INDEX 新「多角度視圖」結構 + 舊決策/導航併入(過時詞「萬物皆 Block」改 API-as-Wall) - principles/TAXONOMY 為新位置獨有,保留 - 刪舊 .claude/wiki/(git 識別為 rename,內容完整搬移) - 三層機敏防護 hooks + wiki 命令更新 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sdd): 立 ingest-contract SDD + 搬入 ingest-candidate 契約 (T3.1+T3.8) 對應 issue #1(頂層 mira-dissolve T3)。 - contracts/ingest-candidate.json:ingest→graph 邊界契約(自頂層搬入) - contracts/README.md:標明候選(輸入)≠已存(triplet) - docs/3-specs/ingest-contract/design.md + tasks.md: - ensureTemplate 改 slot-diff 補丁(取代 early-return,免遷移腳本) - 補 KbdbClient.updateRecord(base PATCH /records/:id) - ingest 流程:驗證(422)→idempotency(uri+hash)→先 append 後 deprecate - triplet template 增 source_uri+content_hash slot 承載 idempotency - 跨 repo 協調點(3.6 圖工具併 KBDB MCP)明列需 arcrun 配合 總管已認可四個設計決定(issue #1 comment)。鐵律:零建表/零 SQL/零 migration。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ingest): POST /triplets/ingest 寫入端 + deprecate-then-append (T3.2-3.5) 對應 issue #1 T3 B 段。 - templates: TRIPLET_SLOTS 加 status/superseded_by/source_uri/content_hash; ENTITY_SLOTS 加 gloss;recordToTriplet 映射新欄位(缺省 status=active 相容舊資料) - kbdb-client: ensureTemplate 改 slot-diff 補丁(既有 template 走 PATCH /templates/:id 補缺 slot,取代 early-return → 免遷移腳本);新增 updateRecord(PATCH /records/:id) - triplet-ingest action(88 行純函式):Zod strict 鏡射 ingest-candidate 契約 → idempotency(uri+hash 同→no-op)→ 先 append 後 deprecate(無「全無 active」空窗) - POST /triplets/ingest route:strict 驗證失敗 → 422(禁送 graph 領域欄位) - queryTriplets 預設 active-only(traverse/search/neighbors 皆經此), includeDeprecated opt-out 供 rollback/考古 - 6 測試案全綠(vitest 16 passed);mock-client 同步 slot-diff + updateRecord gates: zero SQL / zero migration / 無 D1·Vectorize·AI 綁定 / dry-run bundle 乾淨 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(graph): get_source + refresh 端點 + keyword 收斂 (T3.6-3.7) 對應 issue #1 T3 C 段(圖工具 HTTP API 備好,MCP 註冊薄殼待 arcrun)。 - get_source (3.7): graph-source.ts + GET /graph/source/:name — 回節點的 active triplet 來源指標(uri/anchor/block_id/content_hash),去重。 連帶加 source_anchor slot,ingest 從 source.anchor 帶入 - refresh (3.6/3.6b): graph-refresh.ts + POST /graph/refresh — 純被動代轉 ingest(KBDB_INGEST_URL),只人發起、無排程/webhook(fan-out 紅線)。 未設 URL → 誠實 forwarded:false,不假綠 - 3.6d: POST /search 移除公開 keyword 模式(重複 KBDB MCP),收斂 suggest-only; keywordSearch helper 留作 suggest 內部建構塊 - 3 新測試(get_source uri+anchor / active-only / refresh 未就緒誠實回報) gates: vitest 19 passed / zero SQL / 無新綁定 / dry-run bundle 乾淨 待接:MCP 註冊薄殼併 arcrun u6u-mcp-server;refresh 端到端待 ingest(T4) 部署 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: richblack <leo21c@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
1.10.0
|
||||
@@ -0,0 +1,30 @@
|
||||
# [主題] — Architecture Decision Record
|
||||
|
||||
> 日期:[YYYY-MM-DD]
|
||||
> 狀態:[提議中 / 已採納 / 已廢棄]
|
||||
> 影響範圍:[哪些子系統 / 模組]
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
[遇到了什麼問題,需要做這個決定?]
|
||||
|
||||
## 決定
|
||||
|
||||
**[結論,一句話。]**
|
||||
|
||||
## 原因
|
||||
|
||||
[詳細說明為什麼這樣決定。]
|
||||
|
||||
## 放棄的選項
|
||||
|
||||
| 選項 | 放棄原因 |
|
||||
|------|---------|
|
||||
| [選項 A] | [原因] |
|
||||
| [選項 B] | [原因] |
|
||||
|
||||
## 影響與後續
|
||||
|
||||
[這個決定影響哪些地方?有什麼技術債或需要注意的事?]
|
||||
@@ -0,0 +1,76 @@
|
||||
# [子系統名稱] — Design
|
||||
|
||||
> 狀態:[草稿 / 審核中 / 已採納 / 已廢棄]
|
||||
> 建立:[YYYY-MM-DD] | 最後更新:[YYYY-MM-DD]
|
||||
> 負責人:[名稱]
|
||||
|
||||
---
|
||||
|
||||
## 一句話說明
|
||||
|
||||
[這個子系統做什麼,一句話。]
|
||||
|
||||
---
|
||||
|
||||
## 背景與問題
|
||||
|
||||
[為什麼需要這個子系統?解決了什麼問題?]
|
||||
|
||||
---
|
||||
|
||||
## 範圍
|
||||
|
||||
### 包含(In Scope)
|
||||
- [這個 SDD 涵蓋的功能]
|
||||
|
||||
### 不包含(Out of Scope)
|
||||
- [明確排除的功能,避免 CC 自行延伸]
|
||||
|
||||
---
|
||||
|
||||
## 設計
|
||||
|
||||
### 架構概覽
|
||||
|
||||
[用文字或 ASCII 描述系統結構]
|
||||
|
||||
```
|
||||
[元件 A] → [元件 B] → [元件 C]
|
||||
```
|
||||
|
||||
### 關鍵決策
|
||||
|
||||
| 決策 | 選擇 | 原因 | 放棄的選項 |
|
||||
|------|------|------|----------|
|
||||
| [問題] | [選擇] | [原因] | [其他選項] |
|
||||
|
||||
### API / 介面定義
|
||||
|
||||
[端點、資料格式、輸入輸出規格]
|
||||
|
||||
### 資料模型
|
||||
|
||||
[資料結構、欄位說明]
|
||||
|
||||
---
|
||||
|
||||
## 技術限制
|
||||
|
||||
- [不能用什麼]
|
||||
- [必須相容什麼]
|
||||
- [效能要求]
|
||||
|
||||
---
|
||||
|
||||
## 驗收標準
|
||||
|
||||
完成的定義(CC 完成任何 task 前必須確認):
|
||||
- [ ] [可客觀驗證的條件,例如:POST /api/xxx 回傳 200]
|
||||
- [ ] [...]
|
||||
|
||||
---
|
||||
|
||||
## 相關文件
|
||||
|
||||
- [連結到相關 ADR]
|
||||
- [連結到相關 SDD]
|
||||
@@ -0,0 +1,50 @@
|
||||
# [子系統名稱] — Tasks
|
||||
|
||||
> 權威來源:此檔案是進度真相,不是 CLAUDE.md 或對話。
|
||||
> 規則:動手前標 [🔄],完成立刻標 [x],不批次更新。
|
||||
|
||||
---
|
||||
|
||||
## Phase 1:[Phase 名稱]
|
||||
|
||||
### 前置條件
|
||||
- [ ] [這個 Phase 開始前必須完成的事]
|
||||
|
||||
### Tasks
|
||||
|
||||
- [ ] 1.1 [task 描述]
|
||||
- 驗收:[客觀可驗證的完成標準]
|
||||
- 注意:[CC 容易犯的錯,可選]
|
||||
|
||||
- [ ] 1.2 [task 描述]
|
||||
- 驗收:[...]
|
||||
|
||||
---
|
||||
|
||||
## Phase 2:[Phase 名稱]
|
||||
|
||||
> 前置條件:Phase 1 全部完成
|
||||
|
||||
- [ ] 2.1 [task 描述]
|
||||
- 驗收:[...]
|
||||
|
||||
---
|
||||
|
||||
## 完成定義
|
||||
|
||||
整個 SDD 完成 = 以下全部達成:
|
||||
- [ ] 所有 tasks 標 [x]
|
||||
- [ ] 驗收標準通過(有客觀證據)
|
||||
- [ ] design.md 與實作一致(如有出入需更新)
|
||||
|
||||
---
|
||||
|
||||
## 狀態說明
|
||||
|
||||
| 標記 | 意義 |
|
||||
|------|------|
|
||||
| `[ ]` | 未開始 |
|
||||
| `[🔄]` | 進行中(當前 session)|
|
||||
| `[x]` | 完成(有驗收證據)|
|
||||
| `[~]` | 暫緩(說明原因)|
|
||||
| `[!]` | 阻擋中(說明阻擋原因)|
|
||||
@@ -0,0 +1,56 @@
|
||||
# 文件分類索引
|
||||
|
||||
> CC 整理文件時的分類依據。找不到分類就問,不要猜。
|
||||
|
||||
---
|
||||
|
||||
## 分類規則
|
||||
|
||||
| 目錄 | 放什麼 | 判斷標準 |
|
||||
|------|--------|---------|
|
||||
| **1-vision/** | 為什麼做這個 | 產品願景、北極星、設計哲學 |
|
||||
| **2-architecture/** | 系統怎麼設計的 | 架構圖、技術棧、元件關係 |
|
||||
| **2-architecture/decisions/** | 為什麼這樣設計 | ADR,選A不選B的原因 |
|
||||
| **3-specs/** | 要做什麼 | SDD,每個子系統一個目錄 |
|
||||
| **4-guides/** | 怎麼做 | 部署、開發流程、CLI 用法 |
|
||||
| **5-records/** | 發生過什麼 | 歷史記錄,不修改只增加 |
|
||||
| **5-records/incidents/** | 生產問題復盤 | 故障原因、時間線、改進方案 |
|
||||
| **5-records/test-reports/** | 測試結果 | 壓測報告、驗收記錄 |
|
||||
| **6-user/** | 給使用者看的 | README、安裝教學、FAQ |
|
||||
|
||||
---
|
||||
|
||||
## CC 整理文件時的判斷流程
|
||||
|
||||
```
|
||||
這個文件是...
|
||||
├── 有明確子系統 + 設計內容? → docs/3-specs/[子系統]/
|
||||
├── 解釋為什麼做某個決定? → docs/2-architecture/decisions/
|
||||
├── 說明怎麼操作? → docs/4-guides/
|
||||
├── 記錄發生過的事? → docs/5-records/
|
||||
├── 給外部使用者看的? → docs/6-user/
|
||||
└── 以上都不確定? → 列為「待確認」,問負責人
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SDD 結構(docs/3-specs/ 下每個子系統)
|
||||
|
||||
```
|
||||
docs/3-specs/[子系統名]/
|
||||
├── design.md ← 設計文件(要做什麼、怎麼做、邊界在哪)
|
||||
└── tasks.md ← 任務清單([ ] 未開始 [🔄] 進行中 [x] 完成)
|
||||
```
|
||||
|
||||
CC 動手前必須有這兩個檔案。找不到就停手。
|
||||
|
||||
---
|
||||
|
||||
## .claude/wiki/ — CC 的記憶空間(CC 維護,人不手動編輯)
|
||||
|
||||
| 檔案 | 用途 | 更新時機 |
|
||||
|------|------|---------|
|
||||
| `INDEX.md` | wiki 導引 | 新增 wiki 檔案時 |
|
||||
| `mistakes.md` | CC 已知誤解 + 避坑 | 每次被糾正後 |
|
||||
| `status.md` | 當前進度 + 下一步 | 每次 session 結束 |
|
||||
| `decisions-summary.md` | 架構決策摘要 | 重大決策後 |
|
||||
@@ -0,0 +1,238 @@
|
||||
---
|
||||
name: wiki-cowork-scan
|
||||
description: "掃描本機 Documents 下所有裝了 system-dev-template 的資料夾,自動整理 LLM Wiki。支援一般專案、Logseq vault、Obsidian vault 三種結構,偵測方式與 install.sh 一致。觸發時機:使用者說「整理 wiki」「幫我掃 wiki」「更新我的 wiki」「wiki 掃描」,或 Cowork cron 定期觸發。"
|
||||
---
|
||||
|
||||
# Wiki Cowork Scan
|
||||
|
||||
## 核心原則
|
||||
|
||||
這個 skill 與 Claude Code 的 `/wiki-init` `/wiki-capture` 共用同一套規則:
|
||||
|
||||
| 層 | 規則 |
|
||||
|------------|-------------------------------------------|
|
||||
| raw source | 只讀,不動 |
|
||||
| `system-dev/wiki/` | 唯一輸出地點,只增不覆 |
|
||||
| `CLAUDE.md` | 不動 |
|
||||
| `logseq/`、`.obsidian/`、`assets/` | 絕對不動 |
|
||||
|
||||
**CC 和 Cowork 輸出格式相同,任何一方整理過的內容,另一方看到就跳過或補充,不覆蓋。**
|
||||
|
||||
---
|
||||
|
||||
## 第一步:發現所有目標資料夾
|
||||
|
||||
掃描 `~/Documents`(遞迴深度 3 層),找出所有含 `system-dev/wiki/` 的資料夾。
|
||||
|
||||
```
|
||||
~/Documents/
|
||||
project-a/system-dev/wiki/ ← ✅ 目標
|
||||
Logseq/system-dev/wiki/ ← ✅ 目標
|
||||
其他資料夾/ ← ❌ 跳過
|
||||
```
|
||||
|
||||
找到後列出清單,告訴使用者:「找到 N 個 wiki 資料夾,開始整理。」
|
||||
|
||||
---
|
||||
|
||||
## 第二步:對每個資料夾偵測 vault 類型
|
||||
|
||||
進入每個目標資料夾的**根目錄**(`system-dev/wiki/` 的上兩層),依序判斷:
|
||||
|
||||
### 判斷順序(與 install.sh 一致)
|
||||
|
||||
```
|
||||
if 根目錄有 logseq/ 資料夾
|
||||
→ vault 類型:Logseq
|
||||
→ raw source:pages/、journals/
|
||||
→ 忽略:logseq/、assets/
|
||||
|
||||
else if 根目錄有 .obsidian/ 資料夾
|
||||
→ vault 類型:Obsidian
|
||||
→ raw source:根目錄下所有 .md(排除 .obsidian/ 內的檔案)
|
||||
|
||||
else
|
||||
→ vault 類型:一般專案
|
||||
→ raw source:docs/ 下所有 .md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第三步:讀取現有 wiki 狀態
|
||||
|
||||
進入 `system-dev/wiki/`,讀取:
|
||||
|
||||
- `INDEX.md`:目前已有哪些 wiki 頁面(多角度視圖入口)
|
||||
- `status.md`:上次整理時間、進度
|
||||
- `principles.md`(如果有):本專案跨全局的設計原則——整理時必須服從
|
||||
|
||||
目的:**知道哪些已整理過,只處理新增或有變動的 raw source**,不重複整理。
|
||||
|
||||
---
|
||||
|
||||
## 第四步:整理規則
|
||||
|
||||
### 核心判準:push vs pull(wiki 是給 AI 看的)
|
||||
|
||||
整理任何內容前,先判斷它該進 **push 檔** 還 **cards(pull)**——判準是「**CC 做事時會不會被動看見**」:
|
||||
|
||||
- **push 檔**(`status.md` / `mistakes.md` / `principles.md`):CC session 開始就被 hook 注入。給「CC 不會主動查、但不看就出事」的東西。
|
||||
- **pull**(`cards/`):CC 想到要查才看見。一切知識內容(原文摘要、AI 筆記、決策、概念…)都寫成 cards。
|
||||
|
||||
| 內容 | 去哪 | 理由 |
|
||||
|------|------|------|
|
||||
| 當前進度、下一步 | `status.md`(push 全文) | 時態狀態,不看會重做 |
|
||||
| 跨全局設計原則(一行一條,≤15) | `principles.md`(push 全文) | 會被遺忘的盲區,CC 設計時必服從 |
|
||||
| 踩坑、被糾正的誤解 | `mistakes.md`(push 摘要+按需展開) | 防 CC 不自覺的盲區 |
|
||||
| 決策、原文摘要、概念知識、其餘一切 | `cards/<bucket>/`(pull) | 知識內容;CC 面對時自然會查 |
|
||||
|
||||
> `decisions-summary.md` 已**降級為 cards + INDEX 決策視圖**(決策=知識內容)。既有的保留為相容,不刪。
|
||||
> CC 與 Cowork **共用此判準**,產出一致:任一方寫進 push 檔或 cards,另一方看到就跳過或補充,不覆蓋。
|
||||
|
||||
### 讀 raw source
|
||||
|
||||
逐一讀取 raw source 的 `.md` 檔。跳過:
|
||||
- 檔名以 `.` 開頭的隱藏檔
|
||||
- `.wikiignore` 裡列出的 glob pattern(如果存在)
|
||||
- 含有 `<!-- wiki:ignore -->` 標記的區段
|
||||
|
||||
### 整理邏輯
|
||||
|
||||
每個 raw source 檔案,判斷:
|
||||
|
||||
1. **INDEX.md 裡已有對應條目,且 raw source 未修改** → 跳過
|
||||
2. **INDEX.md 裡已有條目,但 raw source 有新內容** → 更新對應 wiki 頁面,補充新資訊,不刪舊內容
|
||||
3. **INDEX.md 裡沒有對應條目** → 新建 wiki 頁面
|
||||
|
||||
### Wiki 卡片格式(概念原子卡,存到 `cards/<bucket>/`)
|
||||
|
||||
```markdown
|
||||
---
|
||||
tags: [知識管理, AI協作, 方法論]
|
||||
gloss: 一句話定義這個概念是什麼(給下游語義 normalize 用,選填、deep tier 才產)
|
||||
---
|
||||
# 概念全名
|
||||
|
||||
← [[<bucket>/00-INDEX]]
|
||||
|
||||
**來源**:`[raw source 相對路徑]`
|
||||
**最後更新**:YYYY-MM-DD
|
||||
|
||||
## 摘要
|
||||
|
||||
[一句話核心]
|
||||
|
||||
## 重點
|
||||
|
||||
- [自包含改寫的要點,不寫「詳見原文」]
|
||||
|
||||
## 關聯
|
||||
|
||||
- [[本卡]] >> 謂詞(動詞短語) >> [[他卡]]
|
||||
- [[原子筆記]] >> 是其最小單元 >> [[卡片盒筆記法]]
|
||||
```
|
||||
|
||||
### 架構:三層 + 標籤橫切(183 卡實證)
|
||||
|
||||
```
|
||||
INDEX.md ← 頂層:標籤視圖(非資料夾列表)
|
||||
TAXONOMY.md ← 標籤字典(受控擴充:先查重再登記)
|
||||
cards/<bucket>/
|
||||
├── 00-INDEX.md ← 桶子索引(固定名,容器:只連不重寫)
|
||||
└── <概念全名>.md ← 概念原子卡
|
||||
```
|
||||
|
||||
- **資料夾只是儲存桶,分類由 frontmatter `tags:` 承載**——不繼承原稿目錄,由 AI 重新組織。
|
||||
- **桶子索引固定名 `00-INDEX.md`**:`00-` 排序最前、一眼可辨,載入任何桶先讀它。
|
||||
- **frontmatter `tags:` 而非行內 `#tag`**:內文常用 `#`(如 `#猜想`),行內標籤會讓 ingest 分不清「分類」與「內文範例」污染 graph;frontmatter 零歧義。標籤只能用 `TAXONOMY.md` 列出的;**禁止繞過字典在卡片直接冒新標籤**,但字典可受控擴充(遇新軸先查重、確認非同義詞,再登記進本 repo 的 TAXONOMY.md)。
|
||||
- **麵包屑帶路徑**:H1 次行 `← [[<bucket>/00-INDEX]]`。指 `00-INDEX` 因固定名跨桶撞名,**一律帶路徑**;卡片間連結用裸 `[[卡名]]`。
|
||||
|
||||
### 使用 typed-edge 三元組(不只裸 `[[wikilink]]`)
|
||||
|
||||
整理時,發現內容與其他頁面有關聯,用**帶語義的三元組**寫進 `## 關聯`,而非只列裸 `[[頁面]]`。裸 `[[A]]` 只說「有關」、沒說關係,下游要建 knowledge graph 還得回讀兩張卡;三元組把關係也預編譯,ingest 直接 parse 出帶類型的有向邊。
|
||||
|
||||
格式 `A >> 謂詞 >> B`,規則:
|
||||
1. **方向性**:必須讀成「A(謂詞)B」一句通順的話;A、B 順序=主→賓真實方向。
|
||||
2. **謂詞用動詞 / 動詞短語**(反駁、奠基於、是…的實作),天然帶方向。
|
||||
3. **謂詞自由書寫**,不受控詞彙;下游對謂詞 embedding 時同義謂詞會自動聚類,但方向仍靠書寫順序保證。
|
||||
4. **向後相容**:純 `[[A]]` 仍合法(無類型邊),盡量補謂詞。
|
||||
|
||||
`>>` 為分隔語法,全程一致即可。這是 Karpathy LLM Wiki「知識互連」的強化版——連結不只存在,還帶類型與方向。
|
||||
|
||||
### 萃 gloss(node 一句說明,供下游語義 normalize)
|
||||
|
||||
每張卡=一個 entity / graph node。deep tier 改寫時,frontmatter 補一句 `gloss:`——這個 node 是什麼的一句定義。下游 KBDB 對「entity 名 + gloss」一起做 embedding 求相似度,自動歸一同義詞(比只對名字準、比手維護 alias 表自動)。
|
||||
|
||||
- **在知識生產的當下、由整理者(CC / Cowork)建**:gloss 跟三元組同階段萃,**不留給下游 ingest 臨時補**——下游只有單檔/跨庫視角,編不出貼合的 gloss。
|
||||
- **選填、deep tier 才產**:淺萃不浪費。
|
||||
- **gloss ≠ 摘要**:`gloss` 是 frontmatter 給機器 normalize 的定義句(「X 是…」);`## 摘要` 是給人讀的核心句。
|
||||
- **對齊下游 envelope**:frontmatter `gloss:` 對應 ingest envelope 的 `nodes[].gloss`。
|
||||
|
||||
> **改寫時必守**:① 絕不寫入 raw source(只往 `cards/<bucket>/` 寫,事後驗 raw source 0 異動);② 檔名=卡片全名,冒號用全形「:」、斜線用全形「/」,全程一種字元避免斷鏈。
|
||||
|
||||
---
|
||||
|
||||
## 第五步:更新 INDEX.md 和 status.md
|
||||
|
||||
### INDEX.md 格式(頂層 = 標籤視圖)
|
||||
|
||||
頂層 INDEX 按 `TAXONOMY.md` 的軸聚類,指向各桶子索引(帶路徑),不是平鋪頁面列表:
|
||||
|
||||
```markdown
|
||||
# Wiki Index
|
||||
|
||||
> 最後更新:YYYY-MM-DD HH:MM | 來源:cowork-scan | 總卡數:N
|
||||
|
||||
### 知識管理
|
||||
- [[pkm/00-INDEX]] — PKM 知識管理(N 卡)
|
||||
|
||||
### AI 協作
|
||||
- [[ai/00-INDEX]] — AI 協作(M 卡)
|
||||
```
|
||||
|
||||
桶子索引 `cards/<bucket>/00-INDEX.md` 是容器(只連不重寫,H2/H3 分節列出該桶卡片)。
|
||||
|
||||
### status.md 更新
|
||||
|
||||
在現有內容**末尾追加**(不覆蓋):
|
||||
|
||||
```markdown
|
||||
## YYYY-MM-DD HH:MM|cowork-scan
|
||||
|
||||
- vault 類型:[Logseq / Obsidian / 一般專案]
|
||||
- 掃描檔案:N 個
|
||||
- 新增頁面:N 個
|
||||
- 更新頁面:N 個
|
||||
- 跳過:N 個(未變動)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第六步:回報結果
|
||||
|
||||
整理完所有資料夾後,輸出摘要:
|
||||
|
||||
```
|
||||
✅ Wiki 整理完成
|
||||
|
||||
資料夾 1:~/Documents/project-a
|
||||
類型:一般專案
|
||||
新增:3 頁,更新:1 頁,跳過:12 頁
|
||||
|
||||
資料夾 2:~/Documents/Logseq
|
||||
類型:Logseq vault
|
||||
新增:5 頁,更新:2 頁,跳過:47 頁
|
||||
|
||||
總計:8 頁新增,3 頁更新
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 絕對禁止
|
||||
|
||||
- ❌ 修改任何 raw source 檔案
|
||||
- ❌ 修改 `CLAUDE.md`
|
||||
- ❌ 動 `logseq/`、`.obsidian/`、`assets/` 資料夾
|
||||
- ❌ 刪除 `system-dev/wiki/` 裡已有的頁面(只增補,不刪除)
|
||||
- ❌ 把機敏資訊(密碼、金鑰、個資)寫進 wiki(遇到跳過並記錄)
|
||||
- ❌ 整理沒有 `system-dev/wiki/` 的資料夾(那不是這個 skill 的目標)
|
||||
Executable
+453
@@ -0,0 +1,453 @@
|
||||
#!/bin/bash
|
||||
# system-dev-template installer
|
||||
# 已有專案接入腳本——只建立缺少的東西,已有的一律不動。
|
||||
#
|
||||
# 模組化安裝:
|
||||
# --wiki 只裝 LLM Wiki(記憶系統 + 機敏防護)
|
||||
# --sdd 只裝 SDD 系統(動 code 前必須有 design.md)
|
||||
# --all 兩個都裝(預設)
|
||||
# 無參數 互動式詢問
|
||||
#
|
||||
# 為什麼留在同一個 repo 用參數選,而不是 fork:
|
||||
# 使用者多半非專業,最怕「我要去哪個 repo」。一個入口 + 選單最友善。
|
||||
# 等未來功能多到 3+ 個再演進成「模板組合器」。模組邊界先在這裡劃好。
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── i18n:依 locale 選語言,預設英文 ──────────────────
|
||||
# 為什麼預設英文:curl | bash 常是 LANG=C,外國人預設就該看得懂;
|
||||
# 台灣使用者 locale 多為 zh_TW,會自動切回繁中。
|
||||
case "${LC_ALL:-${LC_MESSAGES:-${LANG:-}}}" in
|
||||
zh*|*Hant*|*Hans*) IS_ZH="yes" ;;
|
||||
*) IS_ZH="no" ;;
|
||||
esac
|
||||
# t "中文" "English" → 依語系印出對應字串
|
||||
t() { if [ "$IS_ZH" = "yes" ]; then printf '%s\n' "$1"; else printf '%s\n' "$2"; fi; }
|
||||
# tn = 不換行版(給 prompt 用)
|
||||
tn() { if [ "$IS_ZH" = "yes" ]; then printf '%s' "$1"; else printf '%s' "$2"; fi; }
|
||||
|
||||
REPO_URL="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main/template"
|
||||
# install.sh / update.sh 住在 main/scripts/(不在 template/)。
|
||||
SCRIPTS_URL="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main/scripts"
|
||||
CREATED=()
|
||||
SKIPPED=()
|
||||
|
||||
# ── 解析模組參數 ──────────────────────────────────
|
||||
MODULE=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--wiki|--wiki-only) MODULE="wiki" ;;
|
||||
--sdd|--sdd-only) MODULE="sdd" ;;
|
||||
--all) MODULE="all" ;;
|
||||
-h|--help)
|
||||
if [ "$IS_ZH" = "yes" ]; then
|
||||
cat <<'HELP'
|
||||
用法:install.sh [--wiki | --sdd | --all]
|
||||
--wiki 只裝 LLM Wiki(CC 記憶系統 + 機敏防護)
|
||||
--sdd 只裝 SDD 系統(動 code 前強制要有設計文件)
|
||||
--all 兩個都裝(預設)
|
||||
無參數 互動式詢問要裝哪個
|
||||
HELP
|
||||
else
|
||||
cat <<'HELP'
|
||||
Usage: install.sh [--wiki | --sdd | --all]
|
||||
--wiki Install LLM Wiki only (CC memory system + secret protection)
|
||||
--sdd Install SDD system only (require a design doc before touching code)
|
||||
--all Install both (default)
|
||||
no flag Interactively ask which to install
|
||||
HELP
|
||||
fi
|
||||
exit 0 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "🔧 system-dev-template installer"
|
||||
echo "================================="
|
||||
t "只建立缺少的目錄和檔案,已有的不動。" \
|
||||
"Only creates missing dirs and files; never touches what already exists."
|
||||
echo ""
|
||||
|
||||
# ── 無參數 → 互動式詢問(給非專業使用者)──────────
|
||||
if [ -z "$MODULE" ]; then
|
||||
if [ -t 0 ]; then
|
||||
t "要安裝哪一塊?" "Which part do you want to install?"
|
||||
t " 1) LLM Wiki —— 讓 CC 記住決策、不重複犯錯(含機敏防護)" \
|
||||
" 1) LLM Wiki — let CC remember decisions and avoid repeating mistakes (with secret protection)"
|
||||
t " 2) SDD —— 動 code 前強制先有設計文件" \
|
||||
" 2) SDD — require a design doc before touching code"
|
||||
t " 3) 兩個都裝(推薦)" " 3) Install both (recommended)"
|
||||
echo ""
|
||||
tn "請輸入 1 / 2 / 3 [預設 3]:" "Enter 1 / 2 / 3 [default 3]: "
|
||||
read -r choice || choice=3
|
||||
case "$choice" in
|
||||
1) MODULE="wiki" ;;
|
||||
2) MODULE="sdd" ;;
|
||||
*) MODULE="all" ;;
|
||||
esac
|
||||
else
|
||||
# 非互動環境(如 curl | bash 無 tty)→ 預設全裝
|
||||
MODULE="all"
|
||||
fi
|
||||
fi
|
||||
|
||||
WANT_WIKI=false
|
||||
WANT_SDD=false
|
||||
case "$MODULE" in
|
||||
wiki) WANT_WIKI=true ;;
|
||||
sdd) WANT_SDD=true ;;
|
||||
all) WANT_WIKI=true; WANT_SDD=true ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
t "📦 安裝模組:$MODULE" "📦 Module: $MODULE"
|
||||
echo ""
|
||||
|
||||
# ── 偵測 vault 類型 → 決定 raw source(原始文件)路徑 ──────────
|
||||
# 為什麼:這個模板原本假設「原始文件在 docs/」,但 Logseq / Obsidian
|
||||
# 這種 PKM vault 有自己的目錄慣例,整理時不能照 docs/ 那套搬動,
|
||||
# 否則會破壞 vault 結構、讓筆記變不可讀。
|
||||
# 偵測結果寫進 CLAUDE.md,讓 CC 和未來的 Cowork skill 都知道
|
||||
# 「該讀/該整理哪裡」而不是亂動。
|
||||
# 必須在建立 CLAUDE.md 之前跑完。
|
||||
VAULT_TYPE=""
|
||||
RAW_SOURCE=""
|
||||
IS_VAULT="no" # 只有 logseq/obsidian 這種「筆記軟體 vault」才算 yes
|
||||
if [ -d "logseq" ]; then
|
||||
VAULT_TYPE="logseq"
|
||||
RAW_SOURCE="pages/, journals/"
|
||||
IS_VAULT="yes"
|
||||
elif [ -d ".obsidian" ]; then
|
||||
VAULT_TYPE="obsidian"
|
||||
RAW_SOURCE="$(tn './ (整個 vault 根目錄的 .md)' './ (all .md under the vault root)')"
|
||||
IS_VAULT="yes"
|
||||
else
|
||||
VAULT_TYPE="docs"
|
||||
RAW_SOURCE="docs/"
|
||||
fi
|
||||
# 偵測到是筆記 vault → 出聲告訴使用者「我看到了,會小心、不破壞你的筆記結構」。
|
||||
# 不是筆記(一般開發案等)→ 不囉嗦,默默把 docs/ 當原始文件夾安裝完成。
|
||||
if [ "$IS_VAULT" = "yes" ]; then
|
||||
t "🗂️ 偵測到 ${VAULT_TYPE} 筆記庫 → 原始文件:${RAW_SOURCE}" \
|
||||
"🗂️ Detected a ${VAULT_TYPE} note vault → raw source: ${RAW_SOURCE}"
|
||||
t " (會保留你筆記軟體的目錄/檔名結構,不搬動、不改名)" \
|
||||
" (your note app's directory/file structure is preserved — nothing is moved or renamed)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 把「raw source 宣告區塊」吐出來,給新建的 CLAUDE.md append 或
|
||||
# 給已存在的 CLAUDE.md 當手動補貼的提示。內容對 CC / Cowork 都是
|
||||
# 機器可讀的指令(明確路徑 + 不可破壞 vault 結構的約束)。
|
||||
# 寫進 CLAUDE.md 的 raw source 宣告區塊。給人也給 AI 看:
|
||||
# 依 locale 只寫「一種語言」進 CLAUDE.md(雙語會讓每個 session 的 context 更滿)。
|
||||
emit_raw_source_block() {
|
||||
local source_kind
|
||||
if [ "$IS_ZH" = "yes" ]; then
|
||||
if [ "$IS_VAULT" = "yes" ]; then source_kind="${VAULT_TYPE} 筆記庫"
|
||||
else source_kind="一般專案(原始文件放 raw source 路徑)"; fi
|
||||
cat <<BLOCK
|
||||
|
||||
---
|
||||
|
||||
## 原始文件空間(raw source)
|
||||
|
||||
> 安裝時偵測到的來源型態:**${source_kind}**
|
||||
> CC 與 Cowork 整理/讀取「人寫的原始文件」時,**只在這裡找、只在這裡動**。
|
||||
|
||||
| 項目 | 值 |
|
||||
|------|----|
|
||||
| 來源型態 | \`${source_kind}\` |
|
||||
| raw source | \`${RAW_SOURCE}\` |
|
||||
|
||||
**約束(CC 與 Cowork 都必須遵守)**
|
||||
|
||||
- 整理 wiki/知識時,原始文件**一律從上方 raw source 路徑讀取**,不要假設是 \`docs/\`。
|
||||
BLOCK
|
||||
if [ "$IS_VAULT" = "yes" ]; then
|
||||
cat <<BLOCK
|
||||
- 這是 **${VAULT_TYPE} 筆記庫**:保留它原本的目錄與檔名慣例,**不得搬動、改名、重新分類** \`.md\` 檔,
|
||||
以免破壞筆記軟體結構造成筆記不可讀。整理只在 \`system-dev/wiki/\` 產出,**不動 raw source 本身**。
|
||||
BLOCK
|
||||
fi
|
||||
else
|
||||
if [ "$IS_VAULT" = "yes" ]; then source_kind="${VAULT_TYPE} note vault"
|
||||
else source_kind="regular project (raw source lives at the path below)"; fi
|
||||
cat <<BLOCK
|
||||
|
||||
---
|
||||
|
||||
## Raw source space
|
||||
|
||||
> Source type detected at install time: **${source_kind}**
|
||||
> When CC and Cowork curate/read human-written raw source, **look only here and act only here**.
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Source type | \`${source_kind}\` |
|
||||
| raw source | \`${RAW_SOURCE}\` |
|
||||
|
||||
**Constraints (both CC and Cowork must obey)**
|
||||
|
||||
- When curating the wiki/knowledge, **always read raw source from the path above** — don't assume \`docs/\`.
|
||||
BLOCK
|
||||
if [ "$IS_VAULT" = "yes" ]; then
|
||||
cat <<BLOCK
|
||||
- This is a **${VAULT_TYPE} note vault**: keep its original directory and file-naming conventions. **Do not move, rename, or re-classify** \`.md\` files,
|
||||
or you'll break the note-app structure and make notes unreadable. Curation output goes only into \`system-dev/wiki/\`; **never touch the raw source itself**.
|
||||
BLOCK
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 工具函式 ──────────────────────────────────────
|
||||
create_dir() {
|
||||
if [ ! -d "$1" ]; then
|
||||
mkdir -p "$1"
|
||||
CREATED+=("$1/")
|
||||
else
|
||||
SKIPPED+=("$1/ $(tn '(已存在)' '(already exists)')")
|
||||
fi
|
||||
}
|
||||
|
||||
download_if_missing() {
|
||||
local dest="$1" src="$2"
|
||||
if [ ! -f "$dest" ]; then
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
curl -sSL "$src" -o "$dest"
|
||||
CREATED+=("$dest")
|
||||
else
|
||||
SKIPPED+=("$dest $(tn '(已存在,跳過)' '(already exists, skipped)')")
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 共用結構 ──────────────────────────────────────
|
||||
# 工具自己的文件骨架收進 system-dev/docs/(不污染用戶根目錄、不跟用戶自己的 docs/ 混)。
|
||||
# 注意語義分離:這裡的 system-dev/docs/ 是「工具文件」;用戶的 raw source(原始文件)
|
||||
# 另有其處(見上方 vault 偵測),工具只讀、不搬。
|
||||
# .claude/ 只留 CC 死綁的 commands/ + hooks/,工具資料一律不放這。
|
||||
create_dir "system-dev/docs/1-vision"
|
||||
create_dir "system-dev/docs/2-architecture/decisions"
|
||||
create_dir "system-dev/docs/4-guides"
|
||||
create_dir "system-dev/docs/5-records/incidents"
|
||||
create_dir "system-dev/docs/5-records/test-reports"
|
||||
create_dir "system-dev/docs/6-user"
|
||||
create_dir ".claude/commands"
|
||||
create_dir ".claude/hooks"
|
||||
download_if_missing "system-dev/docs/README.md" "$REPO_URL/system-dev/docs/README.md"
|
||||
|
||||
# 工具版號:放 system-dev/,不寄生 .claude/。
|
||||
download_if_missing "system-dev/VERSION" "$REPO_URL/system-dev/VERSION"
|
||||
|
||||
# ── WIKI 模組 ─────────────────────────────────────
|
||||
# wiki 是工具資料 → 放 system-dev/wiki/(不放 .claude/)。
|
||||
# commands/ 與 hooks/ 是 CC 機制檔 → 維持 .claude/。
|
||||
if $WANT_WIKI; then
|
||||
create_dir "system-dev/wiki"
|
||||
download_if_missing "system-dev/wiki/INDEX.md" "$REPO_URL/system-dev/wiki/INDEX.md"
|
||||
download_if_missing "system-dev/wiki/TAXONOMY.md" "$REPO_URL/system-dev/wiki/TAXONOMY.md"
|
||||
download_if_missing "system-dev/wiki/status.md" "$REPO_URL/system-dev/wiki/status.md"
|
||||
download_if_missing "system-dev/wiki/mistakes.md" "$REPO_URL/system-dev/wiki/mistakes.md"
|
||||
download_if_missing "system-dev/wiki/principles.md" "$REPO_URL/system-dev/wiki/principles.md"
|
||||
download_if_missing "system-dev/wiki/.wikiignore" "$REPO_URL/system-dev/wiki/.wikiignore"
|
||||
|
||||
# wiki 改寫產物(AI 自讀定稿卡片)的正式落點:由工具建好,不靠用戶自救。
|
||||
create_dir "system-dev/wiki/cards"
|
||||
[ -f "system-dev/wiki/cards/.gitkeep" ] || { : > "system-dev/wiki/cards/.gitkeep"; CREATED+=("system-dev/wiki/cards/.gitkeep"); }
|
||||
|
||||
download_if_missing ".claude/commands/wiki-init.md" "$REPO_URL/.claude/commands/wiki-init.md"
|
||||
download_if_missing ".claude/commands/wiki-capture.md" "$REPO_URL/.claude/commands/wiki-capture.md"
|
||||
download_if_missing ".claude/commands/wiki-update.md" "$REPO_URL/.claude/commands/wiki-update.md"
|
||||
download_if_missing ".claude/commands/wiki-recall.md" "$REPO_URL/.claude/commands/wiki-recall.md"
|
||||
|
||||
# wiki 相關 hooks:接關 + 機敏掃描
|
||||
download_if_missing ".claude/hooks/session-start-recall.sh" "$REPO_URL/.claude/hooks/session-start-recall.sh"
|
||||
download_if_missing ".claude/hooks/wiki-secret-scan.sh" "$REPO_URL/.claude/hooks/wiki-secret-scan.sh"
|
||||
|
||||
# Cowork(claude.ai)整理 wiki 用的 skill:與 CC 的 /wiki-init 共用同一套規則
|
||||
# (含 typed-edge、frontmatter 標籤、gloss)。沒這支 → claude.ai 來掃時身上沒規則。
|
||||
download_if_missing "system-dev/docs/SKILL.md" "$REPO_URL/system-dev/docs/SKILL.md"
|
||||
fi
|
||||
|
||||
# ── SDD 模組 ──────────────────────────────────────
|
||||
if $WANT_SDD; then
|
||||
create_dir "system-dev/docs/3-specs"
|
||||
download_if_missing "system-dev/docs/3-specs/TEMPLATE-sdd/design.md" "$REPO_URL/system-dev/docs/3-specs/TEMPLATE-sdd/design.md"
|
||||
download_if_missing "system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md" "$REPO_URL/system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md"
|
||||
download_if_missing "system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md" "$REPO_URL/system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md"
|
||||
|
||||
download_if_missing ".claude/commands/sdd-check.md" "$REPO_URL/.claude/commands/sdd-check.md"
|
||||
download_if_missing ".claude/hooks/sdd-guard.sh" "$REPO_URL/.claude/hooks/sdd-guard.sh"
|
||||
fi
|
||||
|
||||
# ── 安裝/更新腳本:一開始就放進 system-dev/scripts/ ──
|
||||
# 為什麼一開始就裝:之後要更新,用戶(或 CC)直接 `bash system-dev/scripts/update.sh`,
|
||||
# 不必每次都記那串 curl。腳本來源在 main/scripts/(不在 template/)。
|
||||
create_dir "system-dev/scripts"
|
||||
download_if_missing "system-dev/scripts/install.sh" "$SCRIPTS_URL/install.sh"
|
||||
download_if_missing "system-dev/scripts/update.sh" "$SCRIPTS_URL/update.sh"
|
||||
|
||||
# ── 共用 hook:專案自訂禁令骨架(預設停用)────────
|
||||
download_if_missing ".claude/hooks/pre-write-guard.sh" "$REPO_URL/.claude/hooks/pre-write-guard.sh"
|
||||
|
||||
# ── 共用指引:GitHub issue 處理(讀/回普世,跨 repo 發要先問,禁自動輪詢)──
|
||||
download_if_missing ".claude/commands/issue-handle.md" "$REPO_URL/.claude/commands/issue-handle.md"
|
||||
|
||||
chmod +x .claude/hooks/*.sh 2>/dev/null || true
|
||||
|
||||
# ── 依模組產生 settings.json 的 hooks 區塊 ────────
|
||||
# settings.json 因模組而異,不能直接下載單一靜態檔,改條件組裝。
|
||||
build_hooks_json() {
|
||||
local session_hooks="" pretool_hooks=""
|
||||
|
||||
if $WANT_WIKI; then
|
||||
session_hooks='{ "type": "command", "command": ".claude/hooks/session-start-recall.sh" }'
|
||||
fi
|
||||
|
||||
# PreToolUse 依模組疊加
|
||||
local pt=()
|
||||
$WANT_SDD && pt+=('{ "type": "command", "command": ".claude/hooks/sdd-guard.sh" }')
|
||||
pt+=('{ "type": "command", "command": ".claude/hooks/pre-write-guard.sh" }')
|
||||
$WANT_WIKI && pt+=('{ "type": "command", "command": ".claude/hooks/wiki-secret-scan.sh" }')
|
||||
local IFS=,
|
||||
pretool_hooks="${pt[*]}"
|
||||
|
||||
printf '{\n "hooks": {\n'
|
||||
if [ -n "$session_hooks" ]; then
|
||||
printf ' "SessionStart": [\n { "matcher": "startup|resume|clear",\n "hooks": [ %s ] }\n ],\n' "$session_hooks"
|
||||
fi
|
||||
printf ' "PreToolUse": [\n { "matcher": "Write|Edit",\n "hooks": [ %s ] }\n ]\n' "$pretool_hooks"
|
||||
printf ' }\n}\n'
|
||||
}
|
||||
|
||||
if [ ! -f ".claude/settings.json" ]; then
|
||||
build_hooks_json > .claude/settings.json
|
||||
CREATED+=(".claude/settings.json $(tn "(依 $MODULE 模組產生)" "(generated for module: $MODULE)")")
|
||||
else
|
||||
SKIPPED+=(".claude/settings.json $(tn '(已存在,請手動合併 hooks)' '(already exists — merge hooks manually)')")
|
||||
fi
|
||||
|
||||
# ── CLAUDE.md:只在完全不存在時建立 ────────────────
|
||||
# 新建時把偵測到的 raw source 宣告 append 進去(在建立的當下寫入,
|
||||
# 不回頭改使用者既有的 CLAUDE.md,維持「已有不覆蓋」原則)。
|
||||
if [ ! -f "CLAUDE.md" ]; then
|
||||
download_if_missing "CLAUDE.md" "$REPO_URL/CLAUDE.md"
|
||||
if [ -f "CLAUDE.md" ]; then
|
||||
emit_raw_source_block >> CLAUDE.md
|
||||
CREATED+=("CLAUDE.md $(tn "← 已寫入 raw source 宣告(${VAULT_TYPE})" "← raw source declaration written (${VAULT_TYPE})")")
|
||||
fi
|
||||
else
|
||||
SKIPPED+=("CLAUDE.md $(tn '(已存在,請手動加入對應區塊)' '(already exists — add the block manually)')")
|
||||
fi
|
||||
|
||||
# ── 輸出結果 ──────────────────────────────────────
|
||||
echo ""
|
||||
t "✅ 建立了:" "✅ Created:"
|
||||
# 注意:macOS bash 3.2 在 set -u 下展開「空陣列」會炸 unbound variable,
|
||||
# 所以這裡先確認有元素才展開(SKIPPED 區塊在下方本來就有守,CREATED 補上)。
|
||||
if [ ${#CREATED[@]} -gt 0 ]; then
|
||||
for item in "${CREATED[@]}"; do echo " + $item"; done
|
||||
fi
|
||||
|
||||
if [ ${#SKIPPED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "⚠️ 跳過(已存在):" "⚠️ Skipped (already exists):"
|
||||
for item in "${SKIPPED[@]}"; do echo " - $item"; done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "─────────────────────────────────"
|
||||
|
||||
# CLAUDE.md 已存在 → 依模組提醒手動加區塊
|
||||
if [ -f "CLAUDE.md" ]; then
|
||||
if ! grep -q "raw source" CLAUDE.md; then
|
||||
echo ""
|
||||
t "📌 CLAUDE.md 已存在但缺少 raw source 宣告。" \
|
||||
"📌 CLAUDE.md exists but lacks a raw source declaration."
|
||||
t " 請手動把以下區塊貼進去,讓 CC 與 Cowork 知道原始文件在哪、不要亂動既有結構:" \
|
||||
" Paste the block below in so CC and Cowork know where the raw source is and won't disturb your structure:"
|
||||
emit_raw_source_block | sed 's/^/ /'
|
||||
fi
|
||||
if $WANT_WIKI && ! grep -q "wiki/status.md" CLAUDE.md; then
|
||||
echo ""
|
||||
t "📌 CLAUDE.md 已存在但缺少 wiki 讀取順序,請手動加入:" \
|
||||
"📌 CLAUDE.md exists but lacks the wiki reading order — please add it manually:"
|
||||
echo ""
|
||||
if [ "$IS_ZH" = "yes" ]; then
|
||||
cat <<'SNIP'
|
||||
## Wiki 讀取順序(push:hook 開 session 自動注入)
|
||||
| 檔案 | 時機 | 用途 |
|
||||
|------|------|------|
|
||||
| `system-dev/wiki/status.md` | session 開始第一件事 | 當前進度 |
|
||||
| `system-dev/wiki/principles.md` | 設計任何東西前 | 跨全局原則,必服從 |
|
||||
| `system-dev/wiki/mistakes.md` | 做新功能前 | 已知踩坑 |
|
||||
SNIP
|
||||
else
|
||||
cat <<'SNIP'
|
||||
## Wiki reading order (push: auto-injected at session start)
|
||||
| File | When | Purpose |
|
||||
|------|------|---------|
|
||||
| `system-dev/wiki/status.md` | first thing at session start | current progress |
|
||||
| `system-dev/wiki/principles.md` | before designing anything | global principles, must obey |
|
||||
| `system-dev/wiki/mistakes.md` | before building a new feature | known pitfalls |
|
||||
SNIP
|
||||
fi
|
||||
fi
|
||||
if $WANT_SDD && ! grep -q "system-dev/docs/3-specs" CLAUDE.md; then
|
||||
echo ""
|
||||
t "📌 CLAUDE.md 已存在但缺少 SDD 鐵律,請手動加入:" \
|
||||
"📌 CLAUDE.md exists but lacks the SDD iron rule — please add it manually:"
|
||||
echo ""
|
||||
if [ "$IS_ZH" = "yes" ]; then
|
||||
cat <<'SNIP'
|
||||
## 絕對鐵律
|
||||
1. 任何 code 變動前必須有對應 SDD(system-dev/docs/3-specs/[子系統]/design.md)
|
||||
找不到 → 停手問負責人,不要自行建立。
|
||||
SNIP
|
||||
else
|
||||
cat <<'SNIP'
|
||||
## Iron rule
|
||||
1. Every code change must have a matching SDD (system-dev/docs/3-specs/[subsystem]/design.md).
|
||||
Not found → stop and ask the owner; do not create one on your own.
|
||||
SNIP
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# settings.json 已存在 → 依模組提醒要合併哪些 hook
|
||||
if [ -f ".claude/settings.json" ]; then
|
||||
MISSING_HOOKS=()
|
||||
$WANT_WIKI && ! grep -q "session-start-recall.sh" .claude/settings.json && MISSING_HOOKS+=("SessionStart: session-start-recall.sh")
|
||||
$WANT_WIKI && ! grep -q "wiki-secret-scan.sh" .claude/settings.json && MISSING_HOOKS+=("PreToolUse(Write|Edit): wiki-secret-scan.sh")
|
||||
$WANT_SDD && ! grep -q "sdd-guard.sh" .claude/settings.json && MISSING_HOOKS+=("PreToolUse(Write|Edit): sdd-guard.sh")
|
||||
if [ ${#MISSING_HOOKS[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "📌 .claude/settings.json 已存在,請手動把以下 hooks 合併進去(保留既有設定):" \
|
||||
"📌 .claude/settings.json exists — merge the hooks below in manually (keep your existing settings):"
|
||||
for h in "${MISSING_HOOKS[@]}"; do echo " • $h"; done
|
||||
fi
|
||||
fi
|
||||
|
||||
# pre-write-guard 是空殼,提醒它預設不攔(避免「以為有保護其實沒有」的安全錯覺)
|
||||
echo ""
|
||||
t "ℹ️ .claude/hooks/pre-write-guard.sh 是「按需手填的空插槽」,預設不攔任何東西。" \
|
||||
"ℹ️ .claude/hooks/pre-write-guard.sh is an empty slot to fill on demand — by default it blocks nothing."
|
||||
t " 需要專案禁令?最簡單是叫你的 CC 寫一支貼合的 guard hook(比範本表達力強);" \
|
||||
" Need project-specific bans? Easiest is to ask your CC to write a tailored guard hook (more expressive than the template);"
|
||||
t " 或自己填 FORBIDDEN_PATTERNS 並到 settings.json 掛上才會生效。" \
|
||||
" or fill in FORBIDDEN_PATTERNS yourself and wire it into settings.json to take effect."
|
||||
|
||||
echo ""
|
||||
t "🚀 下一步:" "🚀 Next steps:"
|
||||
if $WANT_WIKI; then
|
||||
t " 在 Claude Code 對話裡執行 /wiki-init" \
|
||||
" In a Claude Code conversation, run /wiki-init"
|
||||
t " CC 會掃描現有文件、套用 .wikiignore、建立 wiki。" \
|
||||
" CC will scan your existing docs, apply .wikiignore, and build the wiki."
|
||||
fi
|
||||
if $WANT_SDD; then
|
||||
t " 動 code 前先在 system-dev/docs/3-specs/[子系統]/ 建 design.md(可用 /sdd-check 協助)" \
|
||||
" Before touching code, create design.md under system-dev/docs/3-specs/[subsystem]/ (use /sdd-check to help)"
|
||||
fi
|
||||
t " GitHub issue:CC 可直接 /issue-handle 讀回自己 repo 的 issue(禁自動輪詢)" \
|
||||
" GitHub issues: CC can use /issue-handle to read issues from its own repo (no auto-polling)"
|
||||
echo ""
|
||||
Executable
+314
@@ -0,0 +1,314 @@
|
||||
#!/bin/bash
|
||||
# system-dev-template updater
|
||||
# 已安裝舊版的人,一鍵更新到新版。
|
||||
#
|
||||
# 核心安全原則:只覆蓋「模板/邏輯檔」,絕不碰「使用者資料檔」。
|
||||
# ✅ 可覆蓋:hooks/*.sh、commands/*.md、TEMPLATE-*、wiki/INDEX.md
|
||||
# ——這些由模板維護,使用者不會手改,新版直接換掉。
|
||||
# 🔒 絕不碰:wiki/status.md、mistakes.md、decisions-summary.md、TAXONOMY.md、.wikiignore、
|
||||
# settings.json、CLAUDE.md
|
||||
# ——這些是使用者自己填的內容,覆蓋=清空他的記憶與設定。
|
||||
#
|
||||
# 「第一次更新」的雞生蛋問題:
|
||||
# 舊版本機沒有 update.sh。所以第一次靠 README 那行 curl 從遠端抓這支腳本來跑。
|
||||
# 跑完它會把自己也更新進 scripts/update.sh,之後就能直接跑本機的 `bash scripts/update.sh`。
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── i18n:依 locale 選語言,預設英文(curl | bash 常為 LANG=C)──
|
||||
case "${LC_ALL:-${LC_MESSAGES:-${LANG:-}}}" in
|
||||
zh*|*Hant*|*Hans*) IS_ZH="yes" ;;
|
||||
*) IS_ZH="no" ;;
|
||||
esac
|
||||
t() { if [ "$IS_ZH" = "yes" ]; then printf '%s\n' "$1"; else printf '%s\n' "$2"; fi; }
|
||||
tn() { if [ "$IS_ZH" = "yes" ]; then printf '%s' "$1"; else printf '%s' "$2"; fi; }
|
||||
|
||||
REPO_RAW="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main"
|
||||
TEMPLATE_URL="$REPO_RAW/template"
|
||||
|
||||
UPDATED=()
|
||||
KEPT=()
|
||||
NEW=()
|
||||
TEMPLATED=()
|
||||
MIGRATED=()
|
||||
|
||||
# ── 版本比對:先看本機 vs 遠端,給使用者「值不值得更新」的判斷 ──
|
||||
# VERSION 新位置在 system-dev/,舊位置在 .claude/(1.8.x 以前)。優先讀新、回退舊。
|
||||
LOCAL_VER="$(tn '(未知)' '(unknown)')"
|
||||
if [ -f "system-dev/VERSION" ]; then
|
||||
LOCAL_VER="$(tr -d '[:space:]' < system-dev/VERSION)"
|
||||
elif [ -f ".claude/VERSION" ]; then
|
||||
LOCAL_VER="$(tr -d '[:space:]' < .claude/VERSION)"
|
||||
fi
|
||||
REMOTE_VER="$(curl -sSL "$TEMPLATE_URL/system-dev/VERSION" 2>/dev/null | tr -d '[:space:]' || echo '')"
|
||||
# 容錯:curl 對 404 會把「404:NotFound」當內容輸出(非空),舊版誤把它寫進 VERSION。
|
||||
# 這裡驗證必須像版號(X.Y.Z),否則一律視為取不到,避免污染 VERSION 檔。
|
||||
case "$REMOTE_VER" in
|
||||
[0-9]*.[0-9]*.[0-9]*) : ;; # 形如 1.9.0 → 合法
|
||||
*) REMOTE_VER="" ;; # 404 / HTML 錯誤頁 / 其他 → 當作沒抓到
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "🔄 system-dev-template updater"
|
||||
echo "================================="
|
||||
t " 本機版本:${LOCAL_VER}" " Local version: ${LOCAL_VER}"
|
||||
t " 最新版本:${REMOTE_VER:-取不到(檢查網路)}" \
|
||||
" Latest version: ${REMOTE_VER:-unavailable (check network)}"
|
||||
echo ""
|
||||
|
||||
if [ -z "$REMOTE_VER" ]; then
|
||||
t "❌ 取不到遠端版本,可能是網路問題。請稍後再試。" \
|
||||
"❌ Could not fetch the remote version (likely a network issue). Please try again later."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$LOCAL_VER" = "$REMOTE_VER" ]; then
|
||||
t "✅ 已是最新版(${LOCAL_VER}),不需更新。" \
|
||||
"✅ Already up to date (${LOCAL_VER}), nothing to update."
|
||||
t " (仍會同步模板邏輯檔,確保 hooks/commands 與最新一致。)" \
|
||||
" (Template logic files will still be synced to keep hooks/commands in line with the latest.)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# ── 結構遷移(1.9.0):舊版把 wiki/VERSION 放 .claude/、工具 docs 放根 docs/ ──
|
||||
# 新版一律收進 system-dev/。這裡冪等遷移:偵測舊位置 → 搬到 system-dev/,已搬過則略過。
|
||||
# 必須在「模組偵測」之前跑(偵測靠目錄存在與否判斷,搬完才看得到新位置)。
|
||||
#
|
||||
# 安全原則:
|
||||
# - wiki 整包搬(含 cards/ 與可能的 wiki/.git),用 mv 保留內含 .git。
|
||||
# - docs 只搬「工具自己鋪的白名單」子目錄;用戶自填在 docs/ 的其他內容一律不動。
|
||||
# - 目的地已存在同名 → 不覆蓋(保留用戶在新位置的東西),略過該項。
|
||||
migrate_dir() { # $1=舊路徑 $2=新路徑
|
||||
local from="$1" to="$2"
|
||||
[ -e "$from" ] || return 0 # 舊的不存在 → 無需遷移
|
||||
if [ -e "$to" ]; then
|
||||
return 0 # 新的已存在 → 冪等略過,不覆蓋
|
||||
fi
|
||||
mkdir -p "$(dirname "$to")"
|
||||
if mv "$from" "$to" 2>/dev/null; then
|
||||
MIGRATED+=("$from → $to")
|
||||
fi
|
||||
}
|
||||
|
||||
# 任一舊位置還在 → 需要遷移(遷移本身冪等:已搬的項目會被 migrate_dir 略過)。
|
||||
NEEDS_MIGRATE="no"
|
||||
if [ -d ".claude/wiki" ] || [ -f ".claude/VERSION" ] \
|
||||
|| [ -d "docs/3-specs" ] || [ -f "docs/SKILL.md" ] || [ -f "docs/README.md" ]; then
|
||||
NEEDS_MIGRATE="yes"
|
||||
fi
|
||||
|
||||
if [ "$NEEDS_MIGRATE" = "yes" ]; then
|
||||
t "🔧 偵測到舊版結構,遷移到 system-dev/ …" "🔧 Old layout detected — migrating into system-dev/ …"
|
||||
mkdir -p system-dev
|
||||
|
||||
# wiki(含 cards/ 與內含的 .git)整包搬
|
||||
migrate_dir ".claude/wiki" "system-dev/wiki"
|
||||
# 工具版號
|
||||
migrate_dir ".claude/VERSION" "system-dev/VERSION"
|
||||
# 工具文件白名單(只搬工具鋪的,用戶自填的 docs 內容不動)
|
||||
migrate_dir "docs/SKILL.md" "system-dev/docs/SKILL.md"
|
||||
migrate_dir "docs/README.md" "system-dev/docs/README.md"
|
||||
migrate_dir "docs/1-vision" "system-dev/docs/1-vision"
|
||||
migrate_dir "docs/2-architecture" "system-dev/docs/2-architecture"
|
||||
migrate_dir "docs/3-specs" "system-dev/docs/3-specs"
|
||||
migrate_dir "docs/4-guides" "system-dev/docs/4-guides"
|
||||
migrate_dir "docs/5-records" "system-dev/docs/5-records"
|
||||
migrate_dir "docs/6-user" "system-dev/docs/6-user"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# ── 工具函式 ───────────────────────────────────────
|
||||
# 覆蓋更新:模板/邏輯檔,無條件抓最新版蓋掉。
|
||||
update_file() {
|
||||
local dest="$1" src="$2"
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
if [ -f "$dest" ]; then
|
||||
if curl -sSL "$src" -o "$dest.tmp" 2>/dev/null && [ -s "$dest.tmp" ]; then
|
||||
if cmp -s "$dest" "$dest.tmp"; then
|
||||
rm -f "$dest.tmp" # 內容相同,不算更新
|
||||
else
|
||||
mv "$dest.tmp" "$dest"
|
||||
UPDATED+=("$dest")
|
||||
fi
|
||||
else
|
||||
rm -f "$dest.tmp"
|
||||
t " ⚠️ 抓取失敗,保留原檔:$dest" " ⚠️ Download failed, keeping the original: $dest"
|
||||
fi
|
||||
else
|
||||
if curl -sSL "$src" -o "$dest" 2>/dev/null && [ -s "$dest" ]; then
|
||||
NEW+=("$dest") # 新功能:舊版沒有的檔
|
||||
else
|
||||
rm -f "$dest"
|
||||
t " ⚠️ 抓取失敗:$dest" " ⚠️ Download failed: $dest"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 保留:使用者資料檔,只記錄「有保留」,永遠不動。
|
||||
keep_file() {
|
||||
[ -f "$1" ] && KEPT+=("$1") || true
|
||||
}
|
||||
|
||||
# 補新檔:舊版沒有、新版才有的「使用者資料檔」(如 principles.md)。
|
||||
# 不存在 → 抓範本下來(之後由使用者/CC 填);已存在 → 當用戶資料保留,絕不覆蓋。
|
||||
add_if_missing() {
|
||||
local dest="$1" src="$2"
|
||||
if [ -f "$dest" ]; then
|
||||
KEPT+=("$dest")
|
||||
elif curl -sSL "$src" -o "$dest" 2>/dev/null && [ -s "$dest" ]; then
|
||||
NEW+=("$dest")
|
||||
else
|
||||
rm -f "$dest"
|
||||
fi
|
||||
}
|
||||
|
||||
# 客製檔:使用者一定會手填內容(如 pre-write-guard.sh)。
|
||||
# - 已存在 → 絕不覆蓋,但把最新模板版抓到 <檔名>.template.sh 旁邊,供使用者自行 diff 採納。
|
||||
# - 不存在 → 視同新檔,直接抓本體(第一次安裝才會走這條)。
|
||||
keep_with_template() {
|
||||
local dest="$1" src="$2"
|
||||
if [ -f "$dest" ]; then
|
||||
KEPT+=("$dest")
|
||||
local tmpl="${dest%.sh}.template.sh"
|
||||
if curl -sSL "$src" -o "$tmpl.tmp" 2>/dev/null && [ -s "$tmpl.tmp" ]; then
|
||||
if [ -f "$tmpl" ] && cmp -s "$tmpl" "$tmpl.tmp"; then
|
||||
rm -f "$tmpl.tmp" # 模板版沒變,不重複提示
|
||||
else
|
||||
mv "$tmpl.tmp" "$tmpl"
|
||||
TEMPLATED+=("$tmpl")
|
||||
fi
|
||||
else
|
||||
rm -f "$tmpl.tmp"
|
||||
fi
|
||||
else
|
||||
update_file "$dest" "$src" # 還沒裝過 → 當新檔處理
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 偵測已安裝哪些模組(依現有檔案判斷,更新只動已裝的)──
|
||||
# 遷移已在上面跑完,這裡看新位置 system-dev/。
|
||||
HAS_WIKI=false
|
||||
HAS_SDD=false
|
||||
[ -d "system-dev/wiki" ] && HAS_WIKI=true
|
||||
if [ -f ".claude/hooks/sdd-guard.sh" ] || [ -d "system-dev/docs/3-specs/TEMPLATE-sdd" ]; then HAS_SDD=true; fi
|
||||
|
||||
t "📦 偵測到已安裝模組:" "📦 Detected installed modules:"
|
||||
$HAS_WIKI && echo " • LLM Wiki"
|
||||
$HAS_SDD && echo " • SDD"
|
||||
{ $HAS_WIKI || $HAS_SDD; } || \
|
||||
t " (未偵測到任何模組——這裡可能還沒安裝,請改跑 install.sh)" \
|
||||
" (No modules detected — nothing installed here yet; run install.sh instead.)"
|
||||
echo ""
|
||||
|
||||
# ── 客製檔:使用者手填的 guardrail,永不覆蓋(issue #3)──
|
||||
# pre-write-guard.sh 的定位是「空白客製模板,使用者沒配置前不提供保護」(CHANGELOG 1.2.0)。
|
||||
# 下游通常已塞滿自己的 enforcement,直接覆蓋=無聲關掉整套 guardrail。
|
||||
# 改為:保留原檔不動,新版範本另存 pre-write-guard.template.sh,由使用者自行 diff 採納。
|
||||
keep_with_template ".claude/hooks/pre-write-guard.sh" "$TEMPLATE_URL/.claude/hooks/pre-write-guard.sh"
|
||||
|
||||
# ── 模板/邏輯檔:覆蓋更新 ──────────────────────────
|
||||
# 共用 hook 與指引
|
||||
update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md"
|
||||
update_file "system-dev/VERSION" "$TEMPLATE_URL/system-dev/VERSION"
|
||||
|
||||
if $HAS_WIKI; then
|
||||
# wiki 的「邏輯檔」:導航與 hooks,可覆蓋。wiki 資料在 system-dev/,hooks/commands 留 .claude/。
|
||||
update_file "system-dev/wiki/INDEX.md" "$TEMPLATE_URL/system-dev/wiki/INDEX.md"
|
||||
update_file ".claude/hooks/session-start-recall.sh" "$TEMPLATE_URL/.claude/hooks/session-start-recall.sh"
|
||||
update_file ".claude/hooks/wiki-secret-scan.sh" "$TEMPLATE_URL/.claude/hooks/wiki-secret-scan.sh"
|
||||
update_file ".claude/commands/wiki-init.md" "$TEMPLATE_URL/.claude/commands/wiki-init.md"
|
||||
update_file ".claude/commands/wiki-capture.md" "$TEMPLATE_URL/.claude/commands/wiki-capture.md"
|
||||
update_file ".claude/commands/wiki-update.md" "$TEMPLATE_URL/.claude/commands/wiki-update.md"
|
||||
update_file ".claude/commands/wiki-recall.md" "$TEMPLATE_URL/.claude/commands/wiki-recall.md"
|
||||
# Cowork(claude.ai)的 wiki 整理 skill:規則檔,可覆蓋
|
||||
update_file "system-dev/docs/SKILL.md" "$TEMPLATE_URL/system-dev/docs/SKILL.md"
|
||||
|
||||
# wiki 的「使用者資料」:絕不碰
|
||||
keep_file "system-dev/wiki/status.md"
|
||||
keep_file "system-dev/wiki/mistakes.md"
|
||||
# principles.md(1.10):舊版沒有 → 補範本;已有 → 當用戶資料保留
|
||||
add_if_missing "system-dev/wiki/principles.md" "$TEMPLATE_URL/system-dev/wiki/principles.md"
|
||||
keep_file "system-dev/wiki/decisions-summary.md"
|
||||
keep_file "system-dev/wiki/TAXONOMY.md"
|
||||
keep_file "system-dev/wiki/.wikiignore"
|
||||
fi
|
||||
|
||||
if $HAS_SDD; then
|
||||
# SDD 範本與 hook:可覆蓋
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/design.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/design.md"
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md"
|
||||
update_file "system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md" "$TEMPLATE_URL/system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md"
|
||||
update_file ".claude/commands/sdd-check.md" "$TEMPLATE_URL/.claude/commands/sdd-check.md"
|
||||
update_file ".claude/hooks/sdd-guard.sh" "$TEMPLATE_URL/.claude/hooks/sdd-guard.sh"
|
||||
fi
|
||||
|
||||
# ── 自我更新:把最新的 update.sh / install.sh 抓到 system-dev/scripts/ ──
|
||||
# 這兩支在 main/scripts/ 下(不在 template/);落地位置新版收進 system-dev/scripts/。
|
||||
update_file "system-dev/scripts/update.sh" "$REPO_RAW/scripts/update.sh"
|
||||
update_file "system-dev/scripts/install.sh" "$REPO_RAW/scripts/install.sh"
|
||||
|
||||
chmod +x .claude/hooks/*.sh system-dev/scripts/*.sh 2>/dev/null || true
|
||||
|
||||
# ── 使用者資料檔:絕不碰,但提醒「設定可能有新欄位要手動補」──
|
||||
keep_file ".claude/settings.json"
|
||||
keep_file "CLAUDE.md"
|
||||
|
||||
# ── 結果輸出 ───────────────────────────────────────
|
||||
echo ""
|
||||
echo "─────────────────────────────────"
|
||||
if [ ${#MIGRATED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "📦 結構遷移(已收進 system-dev/):" "📦 Layout migrated (moved into system-dev/):"
|
||||
for f in "${MIGRATED[@]}"; do echo " ⇒ $f"; done
|
||||
fi
|
||||
if [ ${#NEW[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "🆕 新功能(舊版沒有,已加入):" "🆕 New features (absent in the old version, now added):"
|
||||
for f in "${NEW[@]}"; do echo " + $f"; done
|
||||
fi
|
||||
if [ ${#UPDATED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "⬆️ 已更新(覆蓋成新版):" "⬆️ Updated (overwritten with the new version):"
|
||||
for f in "${UPDATED[@]}"; do echo " ~ $f"; done
|
||||
fi
|
||||
if [ ${#NEW[@]} -eq 0 ] && [ ${#UPDATED[@]} -eq 0 ]; then
|
||||
echo ""
|
||||
t "✨ 模板邏輯檔已全部最新,無需變動。" \
|
||||
"✨ All template logic files are already up to date — no changes needed."
|
||||
fi
|
||||
if [ ${#KEPT[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "🔒 完整保留(你的內容/設定,從未碰過):" \
|
||||
"🔒 Fully preserved (your content/settings, never touched):"
|
||||
for f in "${KEPT[@]}"; do echo " = $f"; done
|
||||
fi
|
||||
if [ ${#TEMPLATED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "📋 客製檔有新版範本(你的原檔沒動,新版另存旁邊,請自行 diff 採納):" \
|
||||
"📋 Custom files have a new template version (your original is untouched; the new one is saved alongside — diff and adopt as you like):"
|
||||
for f in "${TEMPLATED[@]}"; do
|
||||
echo " → $f"
|
||||
t " 比對:diff \"${f%.template.sh}.sh\" \"$f\"" \
|
||||
" compare: diff \"${f%.template.sh}.sh\" \"$f\""
|
||||
done
|
||||
fi
|
||||
|
||||
# ── settings.json 提醒:新模組 hook 可能要手動補 ──
|
||||
if [ -f ".claude/settings.json" ]; then
|
||||
MISSING=()
|
||||
$HAS_WIKI && ! grep -q "session-start-recall.sh" .claude/settings.json && MISSING+=("SessionStart: session-start-recall.sh")
|
||||
$HAS_WIKI && ! grep -q "wiki-secret-scan.sh" .claude/settings.json && MISSING+=("PreToolUse(Write|Edit): wiki-secret-scan.sh")
|
||||
$HAS_SDD && ! grep -q "sdd-guard.sh" .claude/settings.json && MISSING+=("PreToolUse(Write|Edit): sdd-guard.sh")
|
||||
if [ ${#MISSING[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "📌 settings.json 是你的設定(沒動),但偵測到缺以下 hook,請手動補上:" \
|
||||
"📌 settings.json is yours (untouched), but these hooks are missing — please add them manually:"
|
||||
for h in "${MISSING[@]}"; do echo " • $h"; done
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
t "🚀 更新完成:${LOCAL_VER} → ${REMOTE_VER}" "🚀 Update complete: ${LOCAL_VER} → ${REMOTE_VER}"
|
||||
t " 下次更新直接跑:bash system-dev/scripts/update.sh" " Next time, just run: bash system-dev/scripts/update.sh"
|
||||
t " 改了什麼看:CHANGELOG.md" " See what changed: CHANGELOG.md"
|
||||
echo ""
|
||||
@@ -0,0 +1,36 @@
|
||||
# .wikiignore — 不想被編入 wiki 的內容(像 .gitignore)
|
||||
#
|
||||
# 三層防護的 L1(檔案層)。CC 在 /wiki-init、/wiki-capture 掃描文件時,
|
||||
# 命中這裡 pattern 的「整個檔案」不讀、不編入 wiki。
|
||||
#
|
||||
# 語法:一行一個 glob pattern,相對專案根目錄。# 開頭是註解。
|
||||
#
|
||||
# ── 同場另兩層 ──────────────────────────────────────
|
||||
# L2 行內標記:檔案要編入,但某段不要 → 在該段前後包:
|
||||
# <!-- wiki:ignore -->
|
||||
# 這幾行不會被編入 wiki
|
||||
# <!-- wiki:end -->
|
||||
# L3 機械底線:萬一機敏值仍被寫進 .claude/wiki/,wiki-secret-scan.sh 會 exit 2 擋下。
|
||||
#
|
||||
# 三層的分工:L1 整檔排除(你主動列)|L2 局部遮蔽(你標記)|L3 兜底攔截(自動掃)。
|
||||
# ────────────────────────────────────────────────────
|
||||
|
||||
# ── 機敏檔案(預設就該排除)──────────────────────
|
||||
.env
|
||||
.env.*
|
||||
*.pem
|
||||
*.key
|
||||
*.p12
|
||||
*.pfx
|
||||
*credentials*
|
||||
*secret*
|
||||
**/secrets/**
|
||||
|
||||
# ── 個資 / 客戶資料(依專案調整)────────────────
|
||||
# customers/**
|
||||
# *personal-data*
|
||||
|
||||
# ── 草稿 / 暫存(不值得進記憶)──────────────────
|
||||
# **/draft/**
|
||||
# *.tmp.md
|
||||
# SCRATCH.md
|
||||
@@ -0,0 +1,81 @@
|
||||
# system-dev/wiki/ — LLM 記憶系統
|
||||
|
||||
> 新 session 開始時從這裡導航。
|
||||
> 目的:讓 CC 不需要重新學習已知的事。
|
||||
> 維護者:CC(人不手動編輯這裡)
|
||||
|
||||
---
|
||||
|
||||
## push 檔(session 開始由 hook 主動注入,CC 行動前必看見)
|
||||
|
||||
| 檔案 | 注入形態 | 內容 |
|
||||
|------|---------|------|
|
||||
| `status.md` | 全文 | 當前進度、下一步(時態狀態)|
|
||||
| `principles.md` | 全文(一行一條)| 跨全局設計原則,行動前必服從 |
|
||||
| `mistakes.md` | 標題+一行症狀,全文按需展開 | 踩過的坑、被糾正的誤解(防不自覺盲區)|
|
||||
|
||||
> 為什麼這三個 push 而非 pull:它們是「CC 不會主動查、但不看就出事」的盲區。詳見 `/wiki-init` 的「push vs pull」。
|
||||
|
||||
---
|
||||
|
||||
## pull:cards/(CC 按需檢索)
|
||||
|
||||
一切知識內容——原文摘要、AI 筆記、決策、概念知識——都寫成 `cards/<bucket>/` 的概念原子卡。
|
||||
`decisions-summary.md` 已降級為 cards(決策=知識內容);既有的保留為相容。
|
||||
|
||||
---
|
||||
|
||||
## 維護規則
|
||||
|
||||
1. 只增不刪——記錄 append,內容改了加新條目說明「舊的已更新」
|
||||
2. status.md 每次 session 結束更新;mistakes/principles 一發現就 append
|
||||
3. principles 一行一條、≤15 條(超過代表該合併或下放成 card)
|
||||
4. **新增一個檢索角度 = 在下方「多角度視圖」加一節,不開新實體檔、不問用戶**
|
||||
|
||||
---
|
||||
|
||||
## 多角度視圖(由 /wiki-init、/wiki-capture 填入)
|
||||
|
||||
INDEX 是**所有檢索角度的入口**,不只標籤。原文是唯讀 SSoT,wiki 是改寫過的記憶。
|
||||
新增角度只要在這裡加一節(如「決策角度」「原則角度」),指向對應 cards 或 push 檔——**不必新增實體特殊檔**。
|
||||
|
||||
### 快速導航(本專案速覽)
|
||||
|
||||
**這個專案是什麼**:KBDB-graph —— KBDB 的 graph 插件(triplet 採集 + graph 查詢),類比 Apache AGE 之於 Postgres。已抽成獨立 public repo `uncle6me-web/kbdb-graph-plugin`(leo 產權)。基本盤(block CRUD,D1 三表)在 `arcrun/kbdb`,不在這。
|
||||
|
||||
**動工前必讀**:
|
||||
- `docs/HANDOFF-kbdb-plugin.md` —— 本目錄專屬交棒。
|
||||
- 上游約束見 `CLAUDE.md` 最頂 + `github.com/uncle6me-web/InkStoneCo`。
|
||||
|
||||
**文件去哪找**:
|
||||
- SDD(design+tasks)→ `docs/3-specs/`(現有:kbdb-graph-extraction、blocks-edit-api、plugin-install、arcrun-key-auth)
|
||||
- 歷史記錄 / bug 復盤 → `docs/5-records/`(PATCH 403 bug、upsert feature request)
|
||||
- 分類規則全表 → `docs/README.md`
|
||||
|
||||
**絕對限制**:本目錄只做 graph 插件 / **API-as-Wall(插件絕不碰表、零 SQL、零 migration、零建表)** / 部署繞開 GitHub、禁跨 repo Actions / 樂高法(actions < 100 行)。
|
||||
|
||||
### 標籤角度(按 `TAXONOMY.md` 的軸聚類,指向桶子索引)
|
||||
|
||||
```markdown
|
||||
#### 知識管理
|
||||
- [[pkm/00-INDEX]] — PKM 知識管理(N 卡)
|
||||
|
||||
#### AI 協作
|
||||
- [[ai/00-INDEX]] — AI 協作(M 卡)
|
||||
```
|
||||
|
||||
(尚未建 cards,現有決策見下「決策角度」。)
|
||||
|
||||
### 決策角度(取代舊 decisions-summary.md 的視圖;完整脈絡見 `decisions-summary.md` + `docs/2-architecture/decisions/`)
|
||||
|
||||
- **KBDB-graph 定位**(2026-06-13)— 本 repo = KBDB 的 graph 插件,獨立成 repo,類比 AGE 之於 Postgres。
|
||||
- **🔒 KBDB 鐵律 + API-as-Wall**(2026-06-14,最高原則)— 插件絕不碰表、零 SQL、零 migration,讀寫全走基本盤 HTTP API;新類型=建 template+填 slot,永不建表。
|
||||
- **獨立 repo 名**(2026-06-14)— public `uncle6me-web/kbdb-graph-plugin`,無 Actions。
|
||||
- **掛載介面 = 基本盤 API(非共用 D1)**(2026-06-14,推翻原判斷)— 圖在插件層記憶體從 records 組裝,不直接 SQL、不建 VIEW。
|
||||
- **安裝契約:KBDB_BASE_URL 安裝時 AI 填**(2026-06-14)— AI 查 CF subdomain 拼 URL → `wrangler secret put` + `deploy`;本地測試用 `.dev.vars`。
|
||||
- **~~萬物皆 Block(v3)~~**(2026-02-28 提出,2026-06-14 淘汰)— 帶獨立 blocks 表的「v3」是違規殘留已刪;基本盤真身 = arcrun/kbdb 3 表。
|
||||
- **避免再被 GitHub flag**(上游鐵律)— 禁跨 repo 自動同步 Actions;部署繞開 GitHub。
|
||||
|
||||
> 結構:INDEX(多角度入口)→ `cards/<bucket>/00-INDEX.md`(桶子索引,固定名)→ 概念原子卡。
|
||||
> 指 `00-INDEX` **一律帶路徑** `[[bucket/00-INDEX]]`(固定名跨桶撞名);卡片間用裸 `[[卡名]]`。
|
||||
> 分類由卡片 frontmatter `tags:` 承載,標籤字典見 `TAXONOMY.md`。詳見 `/wiki-init` 規範。
|
||||
@@ -0,0 +1,50 @@
|
||||
# TAXONOMY.md — 標籤字典(本 repo 專屬)
|
||||
|
||||
> wiki 卡片的 frontmatter `tags:` **只能用這裡列出的標籤**。
|
||||
> 這不是凍結——字典**可以擴充**,只是**禁止繞過字典在卡片裡直接冒新標籤**。
|
||||
> 維護者:CC(由 /wiki-init 初始化、隨 wiki 演進受控擴充)。
|
||||
>
|
||||
> **遇到現有軸都裝不下的內容時,照這個流程(先查、後擴、登記)**:
|
||||
> 1. **先查既有**:現有標籤真的都不合,還是只是同義詞?(`知識管理` vs `KM` vs `筆記管理` 是同一軸,別重造)
|
||||
> 2. **確實是新軸** → 把新標籤加進本檔(附一句定義),再用。不必停下來問人,但「先登記再使用」這道查核不能省。
|
||||
> 3. 自由增生才是要防的——同義標籤散開會讓同類卡片分散、下游聚類失準。受控擴充(先查重、再登記)不會。
|
||||
>
|
||||
> **字典是每個 repo 各自的**:跨 repo 引擎靠各 repo 自己一致的 taxonomy 接合,不是逼所有 repo 共用一份。
|
||||
> 知識型 vault 的領域軸(知識管理/學習認知)和開發 repo(子系統/基礎設施)本來就該不同。
|
||||
|
||||
---
|
||||
|
||||
## 分類採雙軸(一張卡可多重歸屬)
|
||||
|
||||
分類由 **frontmatter `tags:`** 承載,不靠資料夾、不靠行內 `#tag`。
|
||||
一張卡同時掛「領域 1-3 個 + 形態 0-2 個」,可從任一軸過濾。
|
||||
|
||||
### 領域(主軸,每卡 1-3 個)
|
||||
|
||||
> 由 /wiki-init 依專案性質提出。以下為 PKM / 知識型 vault 的實證一組,請按你的專案調整:
|
||||
|
||||
- `知識管理`
|
||||
- `學習認知`
|
||||
- `AI協作`
|
||||
- `生產力`
|
||||
- `系統設計`
|
||||
- `工具教學`
|
||||
|
||||
(一般開發專案的領域軸可能是:`子系統A` / `子系統B` / `基礎設施` / `前端` / `後端` …)
|
||||
|
||||
### 形態(副軸,每卡 0-2 個)
|
||||
|
||||
- `方法論`
|
||||
- `工具實作`
|
||||
- `觀點主張`
|
||||
- `架構設計`
|
||||
- `案例經驗`
|
||||
|
||||
---
|
||||
|
||||
## 規則
|
||||
|
||||
1. **先查重、再登記、才使用**:禁止繞過字典在卡片直接冒新標籤;新標籤先確認非現有同義詞,加進本檔(附定義)再用。
|
||||
2. **領域 vs 形態分開**:領域是「講什麼主題」,形態是「以什麼形式呈現」,不要混。
|
||||
3. **頂層 INDEX.md 的標籤視圖依本字典的軸聚類**——字典改了,INDEX 視圖跟著更新。
|
||||
4. **新增領域軸要慎**:領域是檢索骨架,動它影響全庫聚類;形態軸(呈現形式)擴充較安全。不確定就先用現有最接近的,並在卡片或本檔註記「待人類複核此分類」。
|
||||
@@ -0,0 +1,49 @@
|
||||
# 架構決策摘要
|
||||
|
||||
> 遇到設計判斷時查這裡。
|
||||
> 完整脈絡在 docs/2-architecture/decisions/。
|
||||
|
||||
---
|
||||
|
||||
## KBDB-graph 定位 — 2026-06-13
|
||||
**結論**:本目錄 = KBDB 的 graph 插件(triplet 採集 + graph 查詢),獨立成 repo,類比 Apache AGE 之於 Postgres。
|
||||
**原因**:graph 能力較龐大、非基本儲存功能、leo 產權、較複雜 → 不留 arcrun。基本盤(block CRUD,D1 三表)= `arcrun/kbdb`,不在本目錄。
|
||||
**詳細**:`docs/HANDOFF-kbdb-plugin.md`;來源 InkStoneCo 頂層 `matrix-rearrange` Phase 2 (R2)。
|
||||
|
||||
## 🔒 KBDB 鐵律 + 插件 API-as-Wall 形態 — 2026-06-14(最高原則)
|
||||
**結論**:插件【絕不碰表、零 SQL、零 migration】,讀寫全走基本盤 arcrun/kbdb HTTP API。新資料類型=建 template+填 slot,永不建表(連插件自建獨立 D1 都不行)。任何人不准動表(CREATE/ALTER/DROP)。embedding/語意搜尋屬基本盤 optional embed 模組,非插件職責。
|
||||
**原因**:比 AGE-on-Postgres 更嚴——AGE 能讀 Postgres 表,KBDB 插件連表都不許碰。真正的 API-as-Wall。鐵律已 hook 化(`.claude/hooks/pre-{write,bash}-guard-no-table.sh`,違反 exit 2)。
|
||||
**詳細**:`InkStoneCo/docs/3-specs/matrix-rearrange/DECISION-kbdb-v3-baseplane.md` + ADR `docs/2-architecture/decisions/0001-api-as-wall.md`。
|
||||
|
||||
## 獨立 repo 名 — 2026-06-14
|
||||
**結論**:獨立 repo = **public `uncle6me-web/kbdb-graph-plugin`**(leo 拍板,沿用目錄名)。無 .github/workflows(不開 Actions)。
|
||||
**原因**:插件與基本盤 action 層零耦合,抽出乾淨。
|
||||
**詳細**:`docs/3-specs/kbdb-graph-extraction/design.md`。
|
||||
|
||||
## 掛載介面 = 基本盤 API(非共用 D1)— 2026-06-14(推翻原判斷)
|
||||
**結論**:插件掛載 = HTTP API(`KBDB_BASE_URL`),**不共用 D1、不直接 SQL、不建 VIEW**。圖在插件層記憶體從 records 組裝。
|
||||
**原因**:⚠️ 原版「AGE-on-Postgres 共用 D1 + DB 掛載介面」是**讀違規現狀(插件直接 SQL 讀 blocks/entry_values)推出來的錯判斷**——那些直接 SQL 是違規歷史產物,不是設計依據。鐵律 > 現狀。
|
||||
**詳細**:design.md「掛載介面 = 基本盤 API」節 + mistakes.md「讀違規現狀推翻鐵律」。
|
||||
|
||||
## 安裝契約:KBDB_BASE_URL 安裝時 AI 填 — 2026-06-14
|
||||
**結論**:`KBDB_BASE_URL` 不寫死 toml、不叫人填。安裝時 AI 查 CF subdomain 拼 `https://arcrun-kbdb.<subdomain>.workers.dev`,`wrangler secret put` + `wrangler deploy`。本地整合測試用 `.dev.vars`(非 .env)。
|
||||
**原因**:因部署而異(每個 self-hosted 用戶 subdomain 不同),但確定性可算(能 deploy 就能查 subdomain,同套 CF 憑證)。
|
||||
**詳細**:`scripts/install.sh`;參考 arcrun `docs/3-specs/arcrun/sdk-and-website/self-hosted-init.md`。
|
||||
|
||||
## ~~萬物皆 Block(KBDB v3)~~ — 2026-02-28(已淘汰,2026-06-14 修正)
|
||||
**結論**:⚠️ 本目錄那套帶獨立 `blocks` 表 + 0001/0005 CREATE TABLE 的「v3」是**長歪的違規殘留,已刪**。基本盤真身 = `arcrun/kbdb` 3 表(`entries/templates/entry_values`,`entry_type='block'` 表達 block,不需獨立 blocks 表)。
|
||||
**原因**:「萬物皆 Block」獨立 blocks 表違反「不建表」鐵律。基本盤規範歸 arcrun/kbdb,本 repo CLAUDE.md 已裁剪。
|
||||
**詳細**:DECISION-kbdb-v3-baseplane.md 一節「原提問的前提是錯的」。
|
||||
|
||||
## 避免再被 GitHub flag(上游鐵律)— 沿用
|
||||
**結論**:禁跨 repo 自動同步 Actions;部署繞開 GitHub(wrangler / scp);新 repo 預設不開 Actions。
|
||||
**原因**:當初 monorepo→多 worker 的 Actions 自動同步 + 高頻 API 害帳號被 flag。
|
||||
**詳細**:InkStoneCo 頂層 CLAUDE.md。
|
||||
|
||||
---
|
||||
|
||||
格式:
|
||||
## [主題] — [YYYY-MM-DD]
|
||||
**結論**:[一句話]
|
||||
**原因**:[簡短說明]
|
||||
**詳細**:docs/2-architecture/decisions/[對應檔案]
|
||||
@@ -0,0 +1,61 @@
|
||||
# CC 已知誤解 + 避坑方法
|
||||
|
||||
> 做新功能前讀一遍。
|
||||
> 格式:每條必須有症狀 + 正確做法 + 原因。
|
||||
|
||||
---
|
||||
|
||||
## 快速檢查清單(做任何事前)
|
||||
|
||||
- [ ] 有對應 SDD 嗎?沒有 → 停手
|
||||
- [ ] 這次修改會影響哪些模組?有沒有連帶破壞?
|
||||
- [ ] 驗收標準是什麼?有客觀證據嗎?
|
||||
|
||||
---
|
||||
|
||||
## 誤解記錄
|
||||
|
||||
⚠️ MISTAKE: 把基本盤 block CRUD 當成本目錄的職責
|
||||
症狀: 在本目錄改/實作 block CRUD、migration 0001/0002、整套 v3 規範。
|
||||
正確做法: 本目錄只做 graph 插件(triplet/graph/entity)。基本盤歸 arcrun/kbdb。動手前先讀 docs/HANDOFF-kbdb-plugin.md 確認邊界。
|
||||
原因: 2026-06-13 定調 KBDB-graph = 插件(AGE-on-Postgres 模式),但舊 CLAUDE.md 下半仍是整套 v3 規範,易誤導。
|
||||
日期: 2026-06-13
|
||||
|
||||
⚠️ MISTAKE: 以為本目錄在 git 版控內、用 git mv 搬檔
|
||||
症狀: git mv 報 "not under version control" / "source directory is empty"。
|
||||
正確做法: 本目錄無獨立 git(matrix 降級後脫離,且被頂層 gitignore)→ 用普通 mv。改名 KBDB-graph 後才 git init。
|
||||
原因: git repo 是 InkStoneCo 頂層,本目錄被 gitignore。
|
||||
日期: 2026-06-14
|
||||
|
||||
⚠️ MISTAKE: 部署或同步走 GitHub Actions
|
||||
症狀: 設計依賴 GitHub API 列檔、push 觸發跨 repo 自動同步。
|
||||
正確做法: 部署繞開 GitHub(wrangler 直推 / scp);讀檔走本地 fs;新 repo 不開 Actions。
|
||||
原因: 上游鐵律——當初正是這模式害帳號被 flag。
|
||||
日期: 2026-06-14
|
||||
|
||||
⚠️ MISTAKE: 假設「核心已在 arcrun」是既成事實
|
||||
症狀: 照 HANDOFF 字面以為 arcrun/kbdb 已是 v3 基本盤、插件直接掛上去、共用同一 D1。
|
||||
正確做法: 讀真身——arcrun/kbdb 用 entry_type='block' 表達 block(不需獨立 blocks 表),是刻意設計的基本盤。動工前用 ls/grep 對真身,但**對到的是「現狀」不等於「設計依據」**(見下條)。
|
||||
原因: HANDOFF 寫的是「意圖/計劃」,未必已落地;跨 repo 重整時尤其要核對現況。
|
||||
日期: 2026-06-14(註:本條原結論「v3 真身在本目錄」被 leo 推翻——本目錄那套帶 blocks 表/CREATE TABLE 的「v3」是長歪的違規殘留,已刪)
|
||||
|
||||
⚠️ MISTAKE: 讀違規現狀去推翻鐵律(本 session 最大的錯)
|
||||
症狀: 看到插件現狀「直接 SQL 讀 blocks/entry_values(28×/31×)」,把它當「AGE-on-Postgres 訊號」當設計依據,跑去問「要不要共用 D1、直接 SQL」。
|
||||
正確做法: 現狀的直接 SQL 是【違規的歷史產物】(違反自己 CLAUDE.md「API-as-Wall」),不是設計依據。鐵律 > 現狀。插件絕不碰表、零 SQL、零 migration,全走基本盤 API;新類型只能建 template+slot,不建表(連「插件自建獨立 D1」都不行)。
|
||||
原因: 把「程式碼現在這樣寫」誤當成「所以該這樣設計」。違規代碼會自我合理化。遇到現狀與鐵律衝突 → 改現狀,不是改鐵律。
|
||||
日期: 2026-06-14
|
||||
|
||||
⚠️ MISTAKE: 把 embedding/語意搜尋當插件職責
|
||||
症狀: 插件綁 Vectorize/AI 做 entity 相似度合併、語意 search。
|
||||
正確做法: embedding/語意搜尋是基本盤的 optional embed 模組,不在插件。插件不綁 AI/Vectorize;entity 正規化降級 exact match、search 降級 keyword(GET /entries/search),語意部分標 [→arcrun embed]。
|
||||
原因: 基本盤 = D1 only(免費、無信用卡);embed 是可選加購層。插件混進來會破壞分層。
|
||||
日期: 2026-06-14
|
||||
|
||||
---
|
||||
|
||||
格式:
|
||||
⚠️ MISTAKE: [錯誤描述,一句話]
|
||||
症狀: [CC 通常怎麼表現這個錯]
|
||||
正確做法: [應該怎麼做]
|
||||
原因: [為什麼會錯]
|
||||
日期: [YYYY-MM-DD]
|
||||
@@ -0,0 +1,18 @@
|
||||
# principles — 跨全局設計原則(push:CC 行動前必服從)
|
||||
|
||||
> 這個檔由 hook 在 session 開始**全文注入**,讓 CC 設計任何東西前都先看見這些準繩。
|
||||
> 為什麼 push 而非寫成 card:原則是「會被遺忘的盲區」——沒推到眼前,CC 設計時很可能沒想到要服從就做了。
|
||||
>
|
||||
> 規則:**一行一條**,精煉成準繩(不是長篇論述)。≤15 條;超過代表某些該合併、或下放成 card。
|
||||
> 發現新的跨全局原則 → append 一行。累積原則只改這個檔,**不必問用戶開新檔**。
|
||||
> 區分:原則 = 反覆適用的準繩(這裡);單次選擇 = 決策(寫成 card);踩過的坑 = mistakes.md。
|
||||
|
||||
---
|
||||
|
||||
## 原則
|
||||
|
||||
<!-- 一行一條。範例格式:
|
||||
- **不污染用戶根目錄**:工具產物收進專屬資料夾,不在用戶根目錄撒檔、不跟用戶自己的檔混。
|
||||
-->
|
||||
|
||||
(尚未填入。由 /wiki-init 或 /wiki-capture 依本專案累積。)
|
||||
@@ -0,0 +1,35 @@
|
||||
# 當前狀態
|
||||
|
||||
> 更新時間:2026-06-14
|
||||
> 每次 session 結束必須更新此檔(用 /wiki-update)。
|
||||
|
||||
---
|
||||
|
||||
## 已完成(2026-06-14:按 leo 鐵律全面改寫 + 獨立成 repo)
|
||||
|
||||
HANDOFF 5 項待辦全做完:
|
||||
|
||||
1. ✅ **改寫成走基本盤 API**(核心):21 個違規直接 SQL action 全改走 `src/lib/kbdb-client.ts`。寫 triplet=`POST /records`(template=triplet);查圖=取 triplet records 在**插件層記憶體**組鄰接表跑演算法(不靠 DB VIEW)。entity 正規化降級 exact match。
|
||||
2. ✅ **刪所有 migrations**(插件零建表)+ 清基本盤 action/route(block-*/entry-crud/record-crud/tag/profile/admin/partner/convert/tasks/personality)。
|
||||
3. ✅ **獨立成 repo**:`git init` + 推 **public `uncle6me-web/kbdb-graph-plugin`**(無 Actions)。
|
||||
4. ✅ **裁剪 CLAUDE.md**:移除 KBDB v3 基本盤規範,只留 graph 插件 + 🔒 鐵律 + 安裝契約。
|
||||
5. ✅ **部署繞開 GitHub**:`scripts/install.sh`(wrangler 直推),無 .github/workflows。
|
||||
|
||||
驗證:`wrangler deploy --dry-run` 通過(bundle 無 D1/AI/Vectorize);`vitest run` 10 passed(mock client);全違規掃描零命中;所有 action ≤100 行。
|
||||
|
||||
## 同場修正的 SDD 錯誤判斷
|
||||
|
||||
design.md 原本「讀現狀(21 個直接 SQL)推翻鐵律、問要不要共用 D1」是**讀違規現狀推翻規則**的錯。已改正為 **API-as-Wall(走 API,非共用 D1,零建表/零 SQL)**,並記進 mistakes.md。
|
||||
|
||||
## 下次 session 第一件事
|
||||
|
||||
**實際部署**:等基本盤 `arcrun-kbdb` 上線/有網址後,跑 `bash scripts/install.sh` 一次到位
|
||||
(自動查 CF subdomain 拼 `KBDB_BASE_URL` → `wrangler secret put` → `wrangler deploy`)。
|
||||
現在不空跑部署(避免上線一個打不到基本盤的殼)。
|
||||
|
||||
## 已知缺口([→arcrun],待基本盤補)
|
||||
|
||||
- base 無 `PUT /records/:id` → entity addAlias 用「重建 record」覆寫。
|
||||
- base 無 `DELETE /records/:id` → triplet/entity update/delete、pending confirm/reject 為 soft(不硬刪)。
|
||||
- 語意搜尋 / embedding 屬基本盤 optional embed 模組,插件只做 keyword/exact。
|
||||
- arcrun 端 MCP/CLI 的 KBDB 薄殼仍待補(見 arcrun HANDOFF §2);插件目前直打基本盤 HTTP API。
|
||||
Reference in New Issue
Block a user