commit 59c16ea393ba89090100c67628a7a39ef2d47205 Author: LittleYellow Date: Tue Jul 14 07:42:45 2026 +0800 Phase 1: 骨架與 schema — 目錄結構、AGENTS.md 正本、指標檔、models.yaml、index/log 模板、manifest 結構 Co-Authored-By: Claude Fable 5 diff --git a/.gitea/workflows/.gitkeep b/.gitea/workflows/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/agents/.gitkeep b/.github/agents/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..22b1bd9 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,3 @@ +# copilot-instructions.md — 指標檔 + +本檔僅為指標:本專案所有 agent 規範(schema、工作流、硬性約束、行為紀律)的唯一正本是 [AGENTS.md](../AGENTS.md),開始任何工作前先完整閱讀並遵循該檔。 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17cd2fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.venv/ +__pycache__/ +*.pyc +.pytest_cache/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..fdf768f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,295 @@ +# AGENTS.md — QA 知識庫 schema 正本 + +> 本檔是本專案**唯一**的 agent 規範正本。`CLAUDE.md` 與 `.github/copilot-instructions.md` +> 只是指向本檔的薄指標檔,禁止在任何其他檔案複製本檔內容(見 §11 雙棧規則)。 + +## 0. 專案定位 + +為金融業(電子支付)QA 測試部門建置的部門知識庫,採 **Karpathy LLM Wiki 模式**: +知識在文件**攝入時**由 LLM 編譯成 wiki 頁面(萃取、綜合、交叉引用),查詢時只讀已編譯 +頁面。**這不是 RAG**——第一版不建向量庫、不做 chunk 檢索,檢索用 BM25 / 全文檢索。 +最終透過一層薄的 MCP server(`mcp/server.py`)供團隊成員與內部 AI agents 查詢。 + +核心哲學:**知識編譯一次、持續維護,而非每次查詢重新推導。** + +## 1. 硬性約束(不可協商,違反即為缺陷) + +1. **資料落地**:受 FSC 法遵限制,所有文件內容的 LLM 處理一律走本地 Ollama, + 任何情況下不得將文件內容送往雲端 API。格式轉換一律使用本地程式庫, + 禁止任何雲端轉換服務。**禁止使用任何 `:cloud` 後綴的 Ollama model**(在遠端執行, + 內容會離開本機)。 +2. **模型設定外部化**:所有 Ollama 連線資訊與 model tags 一律讀取 + `config/models.yaml`,不得寫死在程式碼中。程式不接受環境變數以外的其他覆寫來源; + 設定缺欄位時報錯,而非使用隱含預設值。 +3. **供應鏈限制**:禁止引入任何中國團隊開發或有中國關聯的模型與框架 + (含 bge、Qwen、GLM、MiniMax、Jina 系列)。未來若需 embedding,預設候選為 + EmbeddingGemma(Google)或 snowflake-arctic-embed(Snowflake)。 +4. **raw 層不可變**:`raw/` 內的文件只讀不改。原始檔與轉換後 Markdown 皆登記 + SHA-256 至 `raw/manifest.json`(結構見 §9),轉換檔條目必須回指原始檔 hash。 + wiki 頁面引用來源必須帶 `source_ref`(格式見 §3.3)。 +5. **HITL 閘門**:所有 wiki 層的變更以 git branch + PR 形式提交,經人工審核後才 + 合併至 main。攝入腳本永遠不直接 commit 到 main。lint 絕不擅自刪檔,一律標記 + 待人工核准。 +6. **Copilot 成本紀律**:Copilot agents 是薄編排層——文件內容的 LLM 處理一律委派給 + 本地 Ollama 腳本(shell out 至 `tools/`),Copilot 只讀取腳本回傳的精簡結果 + (狀態、統計、報告路徑),不將文件全文拉進 context。 +7. **最小詮釋原則**:遇到模糊需求時採取最小合理詮釋,並將所有假設以 + `` 註解標註在產出物內,不擅自擴大範圍。 +8. **語言**:wiki 內容與註解以繁體中文為主;程式碼、識別字、專有名詞用英文。 + +## 2. 目錄結構 + +``` +pp-qa-knowledge/ +├── AGENTS.md # 本檔:schema 正本 +├── CLAUDE.md # 指標檔 → AGENTS.md +├── .github/ +│ ├── copilot-instructions.md # 指標檔 → AGENTS.md +│ └── agents/ # Copilot Custom Agents(Phase 5) +├── config/models.yaml # Ollama 端點與 model tags(唯一設定來源) +├── raw/ +│ ├── originals/ # 原始檔(docx/xlsx/pdf/pptx/html 快照),只讀 +│ ├── converted/ # 轉換後 Markdown(攝入管線的實際輸入),只讀 +│ └── manifest.json # SHA-256 登記 + 原始檔↔轉換檔對應 +├── wiki/ +│ ├── summaries/ # 每份來源一頁摘要 +│ ├── entities/ # 實體頁:系統、模組、API、法規條目、專案 +│ └── concepts/ # 概念頁:跨來源綜合 +├── index.md # 目錄式導航:每頁一行 +├── log.md # append-only 操作日誌 +├── tools/ # convert/(Phase 2)、ingest.py(Phase 3)、 +│ # lint.py(Phase 4)、search.py(Phase 5) +├── mcp/server.py # FastMCP 薄殼(Phase 5) +└── .gitea/workflows/ # lint 定時排程(Phase 4) +``` + +## 3. 頁面類型與 frontmatter schema + +### 3.1 三種頁面類型 + +| type | 位置 | 用途 | 一份來源對應 | +|-----------|-------------------|--------------------------------------------|--------------| +| `summary` | `wiki/summaries/` | 每份來源文件一頁摘要 | 1:1 | +| `entity` | `wiki/entities/` | 系統、模組、API、法規條目、專案等具名實體 | n:m | +| `concept` | `wiki/concepts/` | 跨來源綜合:缺陷模式、測試策略、法遵準則 | n:m | + +### 3.2 YAML frontmatter(所有欄位必填,lint 檢查) + +```yaml +--- +type: entity # summary | entity | concept +title: "支付閘道" # 頁面標題,繁體中文 +description: "一句話摘要,會同步至 index.md 的條目" +tags: [payment, gateway] # 小寫英文 kebab-case,至少 1 個 +timestamp: 2026-07-14 # 最後「實質內容」更新日 YYYY-MM-DD(改錯字不算) +sources: # source_ref 列表,至少 1 筆 + - "raw/converted/2026-q2-release-report.md#a1b2c3d4" +status: draft # draft(攝入產出)| reviewed(人工審過)| stale(lint 標記過期) +--- +``` + + + +### 3.3 source_ref 格式 + +``` +# +``` + +例:`raw/converted/aml-test-guideline.md#3f9c01ab`。hash 以 `raw/manifest.json` +登記值為準;引用原始檔(罕見,如 needs_ocr 的掃描件)同格式指向 `raw/originals/`。 + +### 3.4 檔名規則 + +wiki 頁檔名用英文 kebab-case slug(如 `wiki/entities/payment-gateway.md`), +標題(`title`)用繁體中文。 + + +## 4. 新頁 vs. 就地編輯 + +- **開新頁**:內容描述一個獨立實體或概念,且預期會被其他頁連結。 +- **就地編輯**:既有實體的屬性更新、補充事實、修正錯誤——更新該頁並在 + `sources` 追加新的 source_ref、更新 `timestamp`。 +- 猶豫時傾向**就地編輯**,避免頁面碎片化;就地編輯後若頁面已涵蓋兩個獨立主題, + 才拆分成新頁。 + + +## 5. 內容邊界(wiki 化判斷準則) + +- **該 wiki 化**(綜合壓縮散落多來源的事實才有價值):跨專案缺陷模式、 + 需求與測項的追溯關係、法遵測試準則綜合(FSC/AML/KYC 相關測試要求)、 + 歷次結案報告的教訓、部門 SOP 的決策脈絡。 +- **不該 wiki 化**(單檔可 grep 的內容做鏡像是負價值):測試案例的逐步驟內容、 + 單一 API 的規格細節。這些留在 raw 層,wiki 只放指向它們的索引條目與跨案例綜合。 + +## 6. Ingest 工作流 + +1. **轉換**:`tools/convert/convert.py` 將原始檔轉為 Markdown,原始檔與轉換檔 + 皆登記 `raw/manifest.json`(含 SHA-256 與對應關係)。 +2. **建分支**:`ingest/-`,絕不在 main 上工作。 + +3. **讀來源**:讀取 `raw/converted/` 下的 Markdown(超過 + `limits.ingest_chunk_max_chars` 時分段)。 +4. **寫 summary**:每份來源產出一頁 `wiki/summaries/`,status 為 `draft`。 +5. **更新 entity / concept**:依 §4 判斷開新頁或就地編輯;單一來源可能觸及多頁。 +6. **更新 index.md**:每個新頁 / 改頁同步一行條目(格式見 §10)。 +7. **追加 log.md**:格式見 §10。 +8. **開 PR**:推分支至 Gitea remote,PR 描述列出:來源檔案 + hash、 + 新增/修改的頁面清單、LLM 使用的 model tag。人工審核後合併。 + +## 7. Lint 工作流 + +`tools/lint.py` 檢查項目: + +1. **schema 完整性**:frontmatter 欄位齊全、值合法、source_ref 在 manifest 中存在。 +2. **過期主張(staleness)**:頁面 timestamp 過舊、或其 source 對應的原始檔已有 + 更新版本攝入。 +3. **覆蓋缺口**:manifest 中已轉換但沒有對應 summary 頁的來源。 +4. **孤兒頁**:不被 index.md 或任何其他頁連結的頁面。 +5. **重複頁**:title / description 高度相似的頁面對。 + +產出 markdown 報告;**絕不擅自刪檔或改檔**,一律列為「待人工核准」項目。 +排程:Gitea Actions cron(Phase 4)。 + +## 8. Query 工作流 + +1. 先讀 `index.md` 定位候選頁,**最多 10 頁**。 +2. 只讀取候選頁內文(透過 `tools/search.py` BM25 排序輔助)。 +3. 綜合回答,**必附 source_ref**。 +4. **禁止全庫掃描**(遍歷 wiki/ 全部頁面或 raw/ 全文)。 + +## 9. raw/manifest.json 結構 + +```jsonc +{ + "version": 1, + "files": { + "raw/originals/<檔名>": { + "kind": "original", + "sha256": "<64 hex>", + "media_type": "docx | xlsx | pdf | pptx | html", + "added_at": "", + "status": "pending | converted | needs_ocr", + "source_url": "<僅網頁快照:來源 URL>", + "fetched_at": "<僅網頁快照:抓取時間 ISO-8601>" + }, + "raw/converted/<檔名>.md": { + "kind": "converted", + "sha256": "<64 hex>", + "original_path": "raw/originals/<檔名>", + "original_sha256": "<64 hex>", + "converter": "from_docx | from_xlsx | from_pdf | from_pptx | from_web", + "converted_at": "" + } + } +} +``` + + + +## 10. index.md 與 log.md 格式 + +**index.md** — 目錄式導航,依頁面類型分節,每頁一行: + +``` +- [標題](wiki/entities/payment-gateway.md) — 一句摘要 | #payment #gateway +``` + +**log.md** — append-only 操作日誌,新條目追加於檔案末尾,不修改既有條目: + +``` +## [YYYY-MM-DD] | +``` + +`op` ∈ `bootstrap` / `ingest` / `edit` / `lint` / `review`。 +<!-- ASSUMPTION: op 詞彙表為推論,原始需求只定義格式字串。 --> + +## 11. 雙棧規則 + +- 本檔為唯一正本。`CLAUDE.md`(Claude Code 入口)與 + `.github/copilot-instructions.md`(Copilot 入口)只是薄指標檔 + (一行說明 + 引用本檔),禁止複製 schema 內容。 +- Claude Code 與 Copilot 的行為差異(若有)以「附註」形式標明在本檔相關章節, + 禁止另立分叉檔。 +- Copilot Custom Agents(`.github/agents/*.agent.md`,Phase 5)遵守 §1.6 + 成本紀律:agent 是編排者不是處理者。 + +## 12. Meta-loop 紀律 + +審核者(人工 review PR 或 lint 報告時)發現**系統性**問題——同類錯誤重複出現—— +修改的是本 schema 或 lint 規則,而非逐筆修正輸出(**change the ruler, not the +output**)。單筆修正只治標;規則修正才治本。 + +## 13. Agent 行為紀律 + +<!-- 併入自原 CLAUDE.md(Karpathy LLM coding-pitfall + Ponytail minimalism ladder), + 依 Phase 0 決議 Q4(a)。權衡:偏向謹慎與極簡並重;瑣碎任務用判斷力, + 答案明顯就不問,直接寫最小可行的東西。 --> + +### 13.1 先想再寫(Think before coding) + +不假設、不隱藏困惑、主動揭露權衡。 + +- 明確陳述假設。 +- 詮釋真正分歧時,只問**一個**釐清問題;否則採最小詮釋、以行內註解標註假設、 + 繼續前進——不要停滯。 +- 存在更簡單的做法時要說出來;該反駁就反駁。 + +### 13.2 寫最少能動的程式碼(the ladder) + +動手前,停在**第一個**能解決問題的階梯: + +1. **Skip it** — 這功能真的需要嗎?(YAGNI) +2. **Stdlib** — 標準函式庫是否已提供? +3. **Native** — 平台/執行環境是否內建? +4. **Existing dependency** — 已安裝的依賴能否勝任? +5. **One line** — 能不能一行解決? +6. **Minimum** — 到此才寫最少能動的程式碼。 + +不做超出要求的功能、不為單次使用寫抽象、不做投機的彈性與可配置性、 +不為不可能發生的情境寫錯誤處理。寫了 200 行但 50 行能解決,就重寫。 + +檢驗:「資深工程師會不會說這寫得過度複雜?」會,就簡化。 + +### 13.3 不能偷懶的地方 + +13.2 **不適用**於以下情況——這些要做好做滿: + +- 信任邊界的輸入驗證。 +- 防止資料遺失的錯誤處理。 +- 資安。 +- 無障礙(accessibility)。 +- 真實硬體需要的校準(時鐘漂移、感測器偏差——平台從來不是規格書上的理想值)。 +- 使用者明確要求的任何事。 + +### 13.4 標記並驗證你的捷徑 + +沒有檢查的偷懶程式碼是未完成品。 + +- 每個刻意的簡化都以 `ponytail:` 註解標記;若捷徑有已知天花板 + (global lock、O(n²) 掃描、naive heuristic),註解要寫明天花板與升級路徑。 +- 非平凡邏輯要留下**一個**可執行的檢查——邏輯壞掉就會失敗的最小東西 + (assert 式自檢或一個小測試檔;不用框架、不用 fixtures)。 +- 把任務轉成可驗證的目標,迭代到通過: + - 「加驗證」→ 先寫無效輸入的測試,再讓它通過。 + - 「修 bug」→ 先寫重現 bug 的測試,再讓它通過。 + - 「重構 X」→ 重構前後測試都要通過。 + +多步驟任務要先列簡短計畫:`1. 步驟 → verify: 檢查方式`。 + +### 13.5 手術式修改 + +只碰必須碰的,只清自己的垃圾。 + +- 不「順手改善」相鄰的程式碼、註解、排版。 +- 不重構沒壞的東西;配合既有風格。 +- 移除**因你的變更**而失效的 import/變數/函式。 +- 既有的死程式碼:提出來,但不刪(除非被要求)。 + +檢驗:每一行變更都能直接追溯到使用者的要求。 + +**有效的跡象**:diff 裡不必要的變更變少、因過度複雜而重寫的次數變少、 +釐清問題發生在動手**之前**而非犯錯之後、刻意的捷徑是可見的(`ponytail:`) +而非沉默的。 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..eb55bdf --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +# CLAUDE.md — 指標檔 + +本檔僅為指標:本專案所有 agent 規範(schema、工作流、硬性約束、行為紀律)的唯一正本是 [AGENTS.md](AGENTS.md),開始任何工作前先完整閱讀並遵循該檔。 diff --git a/config/models.yaml b/config/models.yaml new file mode 100644 index 0000000..1246222 --- /dev/null +++ b/config/models.yaml @@ -0,0 +1,26 @@ +# Ollama 連線與模型設定 — 唯一設定來源(AGENTS.md §1.2) +# 換模型只改本檔,不動任何程式碼。缺欄位時程式報錯,不使用隱含預設值。 +# +# 供應鏈限制(AGENTS.md §1.3):禁用中國關聯模型(本機已裝的 qwen3.5、 +# glm-5.2、minimax-m3 皆不可用),且禁止任何 `:cloud` 後綴模型(雲端執行, +# 內容離開本機,違反資料落地)。 + +ollama: + base_url: "http://localhost:11434" + timeout_seconds: 300 + +tasks: # 依任務指定模型,全部可調 + ingest: + model: "gemma4:12b" # Phase 0 已確認:合規本地模型中最強者 + temperature: 0.2 + max_retries: 3 + lint: + model: "gemma4:12b" + temperature: 0.1 + max_retries: 3 + fallback: + model: "hermes3:8b" # 主模型格式驗證連續失敗時切換 + +limits: + mcp_response_max_tokens: 2000 + ingest_chunk_max_chars: 12000 # 超長文件的分段攝入門檻 diff --git a/index.md b/index.md new file mode 100644 index 0000000..3708baa --- /dev/null +++ b/index.md @@ -0,0 +1,17 @@ +# 知識庫索引 + +<!-- 目錄式導航(AGENTS.md §10):每頁一行,格式: + - [標題](路徑) — 一句摘要 | #tag1 #tag2 + 由 ingest 管線維護;查詢工作流一律先讀本檔定位候選頁(最多 10 頁)。 --> + +## 摘要頁(summaries) + +(尚無頁面) + +## 實體頁(entities) + +(尚無頁面) + +## 概念頁(concepts) + +(尚無頁面) diff --git a/log.md b/log.md new file mode 100644 index 0000000..1eecfe4 --- /dev/null +++ b/log.md @@ -0,0 +1,11 @@ +# 操作日誌 + +<!-- append-only(AGENTS.md §10):新條目一律追加於檔案末尾,不修改既有條目。 + 格式:## [YYYY-MM-DD] <op> | <title> + op ∈ bootstrap / ingest / edit / lint / review --> + +## [2026-07-14] bootstrap | Phase 1 骨架與 schema 建立 + +- 建立目錄結構、AGENTS.md v1(含併入的 agent 行為紀律)、CLAUDE.md 與 + .github/copilot-instructions.md 指標檔、config/models.yaml(ingest/lint = + gemma4:12b,fallback = hermes3:8b)、index.md、log.md、raw/manifest.json。 diff --git a/mcp/.gitkeep b/mcp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/qa-kb-wiki-bootstrap-prompt.md b/qa-kb-wiki-bootstrap-prompt.md new file mode 100644 index 0000000..eb1987b --- /dev/null +++ b/qa-kb-wiki-bootstrap-prompt.md @@ -0,0 +1,140 @@ +# QA 部門知識庫(LLM Wiki 模式)— 專案啟動 Prompt v2 + +> 使用方式:在空白專案資料夾中啟動 Claude Code(或 GitHub Copilot Chat agent mode),將本文件全文貼入作為第一則訊息。 + +--- + +## 你的角色與任務 + +你是本專案的首席架構師與實作者。任務:為一個金融業(電子支付)QA 測試部門,建置一套基於 **Karpathy LLM Wiki 模式**(https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f)的部門知識庫系統,最終透過一層薄的 MCP server 供團隊成員與內部 AI agents 查詢。 + +本專案的核心哲學:**知識編譯一次、持續維護,而非每次查詢重新推導。** 這不是 RAG 專案——不建向量庫、不做 chunk 檢索(至少第一版不做)。LLM 在文件攝入時就完成萃取、綜合與交叉引用,查詢時只讀已編譯的 wiki 頁面。 + +## 硬性約束(不可協商,違反即為缺陷) + +1. **資料落地**:受 FSC 法遵限制,所有文件內容的 LLM 處理一律走本地 Ollama,任何情況下不得將文件內容送往雲端 API。**格式轉換一律使用本地程式庫,禁止任何雲端轉換服務。** +2. **模型設定外部化**:所有 Ollama 連線資訊與 model tags 不得寫死在程式碼中,一律讀取 `config/models.yaml`(規格見下方)。 +3. **供應鏈限制**:禁止引入任何中國團隊開發或有中國關聯的模型與框架(含 bge、Qwen、Jina 系列)。未來若需 embedding,預設候選為 EmbeddingGemma(Google)或 snowflake-arctic-embed(Snowflake)。 +4. **raw 層不可變**:`raw/` 內的文件只讀不改。原始檔(含 Office/PDF 原檔)與轉換後的 Markdown 皆登記 SHA-256 至 `raw/manifest.json`,轉換檔的 manifest 條目必須回指原始檔 hash。wiki 頁面引用來源時必須帶 `source_ref`(檔案路徑 + hash 前 8 碼)。 +5. **HITL 閘門**:所有 wiki 層的變更以 git branch + PR 形式提交,經人工審核後才合併至 main。攝入腳本永遠不直接 commit 到 main。 +6. **雙棧支援,單一事實來源**:專案設定必須同時支援 Claude Code 與 GitHub Copilot。schema 正本唯一存在於 `AGENTS.md`;`CLAUDE.md` 與 `.github/copilot-instructions.md` 只是薄指標檔(一行說明 + 引用 AGENTS.md),禁止在指標檔中複製 schema 內容。 +7. **Copilot 成本紀律**:Copilot 於 2026/6/1 起按 token 計費(AI Credits)。所有 Copilot agent 設計為薄編排層——文件內容的 LLM 處理一律委派給本地 Ollama 腳本(shell out 至 `tools/`),Copilot 本身不直接讀取大量文件內容。 +8. **最小詮釋原則**:遇到模糊需求時採取最小合理詮釋,並將所有假設以 `<!-- ASSUMPTION: ... -->` 註解形式標註在產出物內,不要擅自擴大範圍。 +9. **語言**:wiki 內容與註解以繁體中文為主,程式碼、識別字、專有名詞用英文。 + +## 目標架構 + +``` +pp-qa-knowledge/ +├── AGENTS.md # schema 正本:本專案最重要的檔案(見下方要求) +├── CLAUDE.md # 指標檔 → AGENTS.md +├── .github/ +│ ├── copilot-instructions.md # 指標檔 → AGENTS.md +│ └── agents/ +│ ├── kb-ingest.agent.md # Copilot Custom Agent:攝入編排 +│ ├── kb-lint.agent.md # Copilot Custom Agent:健檢編排 +│ └── kb-query.agent.md # Copilot Custom Agent:查詢 +├── config/ +│ └── models.yaml # Ollama 端點與 model tags 設定(見下方規格) +├── raw/ +│ ├── originals/ # 原始檔(docx/xlsx/pdf/pptx/html 快照) +│ ├── converted/ # 轉換後 Markdown(攝入管線的實際輸入) +│ └── manifest.json # SHA-256 登記 + 原始檔↔轉換檔對應 +├── wiki/ +│ ├── summaries/ # 每份來源一頁摘要 +│ ├── entities/ # 實體頁:系統、模組、API、法規條目、專案 +│ └── concepts/ # 概念頁:跨來源綜合(缺陷模式、測試策略、法遵準則) +├── index.md # 目錄式導航:每頁一行(連結 + 一句摘要 + 分類) +├── log.md # append-only 操作日誌,格式 `## [YYYY-MM-DD] <op> | <title>` +├── tools/ +│ ├── convert/ +│ │ ├── convert.py # 統一入口:依副檔名分派 +│ │ ├── from_docx.py # Word → Markdown +│ │ ├── from_xlsx.py # Excel → Markdown(表格) +│ │ ├── from_pdf.py # PDF → Markdown(掃描件標記待 OCR,不擅自處理) +│ │ ├── from_pptx.py # PowerPoint → Markdown(含講者備註) +│ │ └── from_web.py # 網頁 URL → 本地 HTML 快照 + Markdown 正文萃取 +│ ├── ingest.py # 攝入管線(讀 config/models.yaml,呼叫本地 Ollama) +│ ├── lint.py # wiki 健檢(同上) +│ └── search.py # 第一版:BM25 / 全文檢索,不用向量庫 +├── mcp/ +│ └── server.py # FastMCP 薄殼:search_wiki 與 read_page 兩個 tool +└── .gitea/workflows/ # lint 定時排程(Gitea Actions,之後部署用) +``` + +## config/models.yaml 規格 + +```yaml +ollama: + base_url: "http://localhost:11434" + timeout_seconds: 300 +tasks: # 依任務指定模型,全部可調 + ingest: + model: "CHANGE_ME" # 例:gemma3:27b — Phase 0 與我確認實際 tag + temperature: 0.2 + max_retries: 3 + lint: + model: "CHANGE_ME" + temperature: 0.1 + max_retries: 3 + fallback: + model: "CHANGE_ME" # 例:devstral — 主模型格式驗證連續失敗時切換 +limits: + mcp_response_max_tokens: 2000 + ingest_chunk_max_chars: 12000 # 超長文件的分段攝入門檻 +``` + +所有 `tools/` 與 `mcp/` 下的程式讀取此檔,不接受環境變數以外的其他覆寫來源;缺欄位時報錯而非使用隱含預設值。 + +## 格式轉換規範(tools/convert/) + +- 只用本地程式庫:docx 用 mammoth 或 python-docx、xlsx 用 openpyxl、pdf 用 pymupdf 或 pdfplumber、pptx 用 python-pptx、網頁用 trafilatura 或 readability-lxml +- 流程:原始檔存入 `raw/originals/` 並登記 hash → 轉換 → Markdown 存入 `raw/converted/` 並登記 hash 與對應關係 → 之後攝入管線只讀 converted 層 +- 轉換品質規則:保留標題層級與表格結構;圖片抽出存為附檔並在 Markdown 留佔位引用;PDF 偵測到無文字層(掃描件)時登記為 `needs_ocr` 狀態並跳過,不擅自呼叫 OCR +- 網頁轉換:抓取當下同時保存完整 HTML 快照(來源可能消失),Markdown 只萃取正文;URL 與抓取時間寫入 manifest +- 每個轉換器可獨立執行也可被 `convert.py` 統一調度,皆有 `--dry-run` + +## Copilot Custom Agents(.github/agents/) + +參照 Copilot Custom Agent 慣例撰寫三個 `.agent.md`,共同原則:**agent 是編排者不是處理者**——透過終端呼叫 `tools/` 下的腳本完成實際工作,Copilot 只讀取腳本回傳的精簡結果(狀態、統計、報告路徑),不將文件全文拉進 context。 + +- `kb-ingest.agent.md`:接收檔案路徑或 URL → 呼叫 convert.py → 呼叫 ingest.py → 回報攝入結果與 PR 連結 +- `kb-lint.agent.md`:呼叫 lint.py → 摘要報告重點 → 列出需人工核准的項目 +- `kb-query.agent.md`:呼叫 search.py 取得候選頁 → 只讀取命中的少數頁面 → 綜合回答並附 source_ref + +## 內容邊界(wiki 化的判斷準則) + +- **該 wiki 化**(綜合壓縮散落多來源的事實才有價值):跨專案缺陷模式、需求與測項的追溯關係、法遵測試準則綜合(FSC/AML/KYC 相關測試要求)、歷次結案報告的教訓、部門 SOP 的決策脈絡。 +- **不該 wiki 化**(單檔可 grep 的內容做鏡像是負價值):測試案例的逐步驟內容、單一 API 的規格細節。這些留在 raw 層,wiki 只放指向它們的索引條目與跨案例綜合。 + +## AGENTS.md(schema 正本)必須涵蓋 + +1. 頁面類型定義(summary / entity / concept)及各自的 YAML frontmatter 欄位:`type`、`title`、`description`、`tags`、`timestamp`、`sources`(source_ref 列表)、`status`(draft / reviewed / stale) +2. 「新頁 vs. 就地編輯」的判斷準則:獨立實體且會被他頁連結 → 新頁;既有實體的屬性更新 → 就地編輯 +3. Ingest 工作流:轉換 → 讀來源 → 寫 summary → 更新相關 entity/concept 頁(單一來源可能觸及多頁)→ 更新 index.md → 追加 log.md → 開 PR +4. Lint 工作流:schema 完整性、過期主張(staleness)、覆蓋缺口、孤兒頁、重複頁偵測;產出 markdown 報告;**絕不擅自刪檔**,一律標記待人工核准 +5. Query 工作流:先讀 index.md 定位候選頁(最多 10 頁)再讀內文,禁止全庫掃描 +6. 雙棧規則:本檔為唯一正本;Claude Code 與 Copilot 的行為差異(若有)以附註標明,禁止另立分叉檔 +7. Meta-loop 紀律:審核者發現系統性問題時,修改的是本 schema 或 lint 規則,而非逐筆修正輸出(change the ruler, not the output) + +## 分階段交付(每階段結束停下來等我驗收,不要一次做完) + +- **Phase 0 — 對齊**:閱讀本文件後,列出你的理解摘要、所有假設清單、以及需要我確認的問題(至少包含:本機實際的 Ollama model tags、部門文件的格式分佈比例、Copilot Custom Agent 在我環境的實際支援格式)。不寫任何程式碼。 +- **Phase 1 — 骨架與 schema**:建立目錄結構、撰寫 AGENTS.md 第一版與兩個指標檔、config/models.yaml、index.md 與 log.md 模板、raw/manifest.json 結構。 +- **Phase 2 — 轉換管線**:實作 `tools/convert/` 全部轉換器與統一入口,附各格式的最小測試檔與轉換驗證。 +- **Phase 3 — 攝入管線**:實作 `tools/ingest.py`。含 SHA-256 登記、讀取 models.yaml、Ollama 呼叫、頁面產出、git branch + PR 準備。錯誤處理要完整——本地模型輸出不穩定是預期情況,需有格式驗證、重試、以及 fallback model 切換機制。 +- **Phase 4 — Lint agent**:實作 `tools/lint.py` 與報告格式,並準備 Gitea Actions workflow 草稿(cron 觸發)。 +- **Phase 5 — MCP 薄殼與 Copilot Agents**:FastMCP 實作 `search_wiki`(BM25,回傳 index 條目 + 相關度)與 `read_page`(回傳單頁全文 + frontmatter,依 models.yaml 的 token 上限截斷並附 source_ref);撰寫三個 `.agent.md`。 +- **Phase 6 — Pilot 驗收**:我會提供 10–20 份真實部門文件(去敏後,含 Word/Excel/PDF/PPT 混合格式)。跑完整轉換 + 攝入,產出品質報告:各格式轉換成功率、攝入成功率、frontmatter 合規率、交叉引用正確性、人工抽驗結果。以此決定是否擴大。 + +## 成功標準 + +- 四種 Office 格式 + 網頁皆能一鍵轉換入庫,manifest 可完整追溯原始檔 +- Pilot 文件攝入後,任一團隊成員透過 MCP 或 kb-query agent 問「某功能的歷史缺陷模式」,能得到有 source_ref 的綜合答案 +- 換一個 Ollama model tag 只需改 config/models.yaml,不動任何程式碼 +- lint 報告能抓出人為植入的矛盾頁(Phase 6 我會故意放) +- Copilot agents 全程只經手精簡結果,credit 消耗趨近於零 +- 全程無任何文件內容離開本機 +- 每個階段的產出,模糊處都有 ASSUMPTION 註解 + +現在從 Phase 0 開始。 diff --git a/raw/converted/.gitkeep b/raw/converted/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/raw/manifest.json b/raw/manifest.json new file mode 100644 index 0000000..27049a3 --- /dev/null +++ b/raw/manifest.json @@ -0,0 +1,4 @@ +{ + "version": 1, + "files": {} +} diff --git a/raw/originals/.gitkeep b/raw/originals/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tools/convert/.gitkeep b/tools/convert/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/wiki/concepts/.gitkeep b/wiki/concepts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/wiki/entities/.gitkeep b/wiki/entities/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/wiki/summaries/.gitkeep b/wiki/summaries/.gitkeep new file mode 100644 index 0000000..e69de29