14 KiB
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. 硬性約束(不可協商,違反即為缺陷)
- 資料落地:受 FSC 法遵限制,所有文件內容的 LLM 處理一律走本地 Ollama,
任何情況下不得將文件內容送往雲端 API。格式轉換一律使用本地程式庫,
禁止任何雲端轉換服務。禁止使用任何
:cloud後綴的 Ollama model(在遠端執行, 內容會離開本機)。 - 模型設定外部化:所有 Ollama 連線資訊與 model tags 一律讀取
config/models.yaml,不得寫死在程式碼中。程式不接受環境變數以外的其他覆寫來源; 設定缺欄位時報錯,而非使用隱含預設值。 - 供應鏈限制:禁止引入任何中國團隊開發或有中國關聯的模型與框架 (含 bge、Qwen、GLM、MiniMax、Jina 系列)。未來若需 embedding,預設候選為 EmbeddingGemma(Google)或 snowflake-arctic-embed(Snowflake)。
- raw 層不可變:
raw/內的文件只讀不改。原始檔與轉換後 Markdown 皆登記 SHA-256 至raw/manifest.json(結構見 §9),轉換檔條目必須回指原始檔 hash。 wiki 頁面引用來源必須帶source_ref(格式見 §3.3)。 - HITL 閘門:所有 wiki 層的變更以 git branch + PR 形式提交,經人工審核後才 合併至 main。攝入腳本永遠不直接 commit 到 main。lint 絕不擅自刪檔,一律標記 待人工核准。
- Copilot 成本紀律:Copilot agents 是薄編排層——文件內容的 LLM 處理一律委派給
本地 Ollama 腳本(shell out 至
tools/),Copilot 只讀取腳本回傳的精簡結果 (狀態、統計、報告路徑),不將文件全文拉進 context。 - 最小詮釋原則:遇到模糊需求時採取最小合理詮釋,並將所有假設以
<!-- ASSUMPTION: ... -->註解標註在產出物內,不擅自擴大範圍。 - 語言: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 檢查)
---
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 格式
<repo 相對路徑>#<sha256 前 8 碼>
例: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 工作流
- 轉換:
tools/convert/convert.py將原始檔轉為 Markdown,原始檔與轉換檔 皆登記raw/manifest.json(含 SHA-256 與對應關係)。 - 建分支:
ingest/<YYYYMMDD>-<slug>,絕不在 main 上工作。 - 讀來源:讀取
raw/converted/下的 Markdown(超過limits.ingest_chunk_max_chars時分段)。 - 寫 summary:每份來源產出一頁
wiki/summaries/,status 為draft。 - 更新 entity / concept:依 §4 判斷開新頁或就地編輯;單一來源可能觸及多頁。
- 更新 index.md:每個新頁 / 改頁同步一行條目(格式見 §10)。
- 追加 log.md:格式見 §10。
- 開 PR:推分支至 Gitea remote,PR 描述列出:來源檔案 + hash、 新增/修改的頁面清單、LLM 使用的 model tag。人工審核後合併。
7. Lint 工作流
tools/lint.py 檢查項目:
- schema 完整性:frontmatter 欄位齊全、值合法、source_ref 在 manifest 中存在。
- 過期主張(staleness):頁面 timestamp 過舊、或其 source 對應的原始檔已有 更新版本攝入。
- 覆蓋缺口:manifest 中已轉換但沒有對應 summary 頁的來源。
- 孤兒頁:不被 index.md 或任何其他頁連結的頁面。
- 重複頁:title / description 高度相似的頁面對。
產出 markdown 報告;絕不擅自刪檔或改檔,一律列為「待人工核准」項目。 排程:Gitea Actions cron(Phase 4)。
8. Query 工作流
- 先讀
index.md定位候選頁,最多 10 頁。 - 只讀取候選頁內文(透過
tools/search.pyBM25 排序輔助)。 - 綜合回答,必附 source_ref。
- 禁止全庫掃描(遍歷 wiki/ 全部頁面或 raw/ 全文)。
9. raw/manifest.json 結構
{
"version": 1,
"files": {
"raw/originals/<檔名>": {
"kind": "original",
"sha256": "<64 hex>",
"media_type": "docx | xlsx | pdf | pptx | html",
"added_at": "<ISO-8601>",
"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": "<ISO-8601>"
}
}
}
10. index.md 與 log.md 格式
index.md — 目錄式導航,依頁面類型分節,每頁一行:
- [標題](wiki/entities/payment-gateway.md) — 一句摘要 | #payment #gateway
log.md — append-only 操作日誌,新條目追加於檔案末尾,不修改既有條目:
## [YYYY-MM-DD] <op> | <title>
op ∈ bootstrap / ingest / edit / lint / review。
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 行為紀律
13.1 先想再寫(Think before coding)
不假設、不隱藏困惑、主動揭露權衡。
- 明確陳述假設。
- 詮釋真正分歧時,只問一個釐清問題;否則採最小詮釋、以行內註解標註假設、 繼續前進——不要停滯。
- 存在更簡單的做法時要說出來;該反駁就反駁。
13.2 寫最少能動的程式碼(the ladder)
動手前,停在第一個能解決問題的階梯:
- Skip it — 這功能真的需要嗎?(YAGNI)
- Stdlib — 標準函式庫是否已提供?
- Native — 平台/執行環境是否內建?
- Existing dependency — 已安裝的依賴能否勝任?
- One line — 能不能一行解決?
- 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:)
而非沉默的。