Commit Graph

6 Commits

Author SHA1 Message Date
LittleYellow
d41cb49a45 fix: 加 .gitattributes 對 raw/** 關閉換行正規化
core.autocrlf=true 下,已 commit 的 raw/converted/*.md 於 Windows checkout
會被 git 轉成 CRLF,使磁碟 bytes 與 manifest 登記的 LF-hash 不符、--verify
誤報 mismatch——在 git 層抵銷了轉換器的 write_bytes 修復。以 `raw/** -text`
把「登記 hash == 磁碟 bytes」的不變式延伸到 git 的 checkin/checkout。
AGENTS.md §1.4 補記此機制。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:23:04 +08:00
LittleYellow
f9a0cd2369 feat: convert 新增 --verify 對帳模式 + 修復 Windows CRLF 使 hash 失準
- convert.py --verify:純唯讀 re-hash 全部登記檔並掃未登記檔,
  報 missing/mismatch/unregistered,不一致退出碼 1(供刪除/竄改後稽核)
- 修 write_text 在 Windows 轉 \n→\r\n 使磁碟 bytes 與登記 SHA-256 不符
  (converted md 與 web 快照原始檔),改 write_bytes 寫入所登記的那份 bytes
- selfcheck 補 clean/missing/mismatch/unregistered 四情境(全程唯讀斷言)
- AGENTS.md §14 raw 完整性與修復流程 + §1.4 hash==磁碟 bytes 不變式

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 08:21:39 +08:00
LittleYellow
3c1b268074 修復含空格/括號檔名的圖片連結失效,自檢改驗連結可 render
來源檔名含空格或不平衡括號時,convert 產出的 Markdown 圖片連結會失效——
圖檔明明存在於磁碟,整行卻退化成純文字(CommonMark 對未包住的空格與不平衡
括號視為分隔符)。用真 CommonMark parser 驗過:中文與成對括號正常,空格與
落單括號會壞。

- convert.py / from_docx.py / from_pdf.py / from_pptx.py:四處圖片連結目標
  一律以 <> 包住(![name](<rel>)),同時涵蓋空格與不平衡括號。
- selfcheck.py:新增 assert_links_ok()——以 markdown_it 真 render,斷言圖片
  連結數 == <img> 數且目標檔存在,取代原本只檢查 "![" 字串在不在的表面斷言。
  測資補內嵌圖片(docx/pdf/pptx 各一路徑)、檔名改含空格與不平衡括號。
- requirements.txt:明確宣告 markdown-it-py(原為 fastmcp 傳遞依賴,自檢直接
  使用,宣告以免上游調整依賴樹後自檢失效)。
- AGENTS.md §13.4:新增「斷言要驗結果可用,不是驗字串存在」規則。

驗證:四個自檢全通過;移除任一處 <> 修法,assert_links_ok 即失敗。
ingest / lint / search 在含括號檔名下全鏈路已另行驗證正常(source_ref 走
YAML 純量,不受影響)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 06:12:47 +08:00
LittleYellow
b2eb4fbfa3 docs: 清除 markdown lint 警告(MD040 補語言標註、MD060 關閉)
- MD040:AGENTS.md 四處與 README.md 一處的 fenced code block 補上語言標註
  (目錄樹與格式範例用 text,index.md / log.md 的範例用 markdown)。

- MD060:本專案文件表格一律按終端顯示寬度對齊(CJK 佔 2 欄),而 MD060 以
  字元位置比對管線符號,對 CJK 無感,兩者不可能同時滿足。選擇保留顯示寬度
  對齊(人類在編輯器裡讀得順),以 .markdownlint.jsonc 關閉該規則並註明理由。
  順帶修正 AGENTS.md §3.1 表格 entity 列的對齊——該列混入 ASCII 的 API,
  原本比其他列短 1 欄。

未處理 MD013(行長 > 80):VS Code 的 markdownlint 擴充預設不啟用此規則,
且 §3.1 表格在維持顯示對齊的前提下無法壓到 80 字元以內。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 07:35:44 +08:00
LittleYellow
0b4c2bbb15 修復中文路徑 preflight 與 BM25 核心詞落空,測資改照現實建
兩個 bug 同源於自檢測資「照能過建、不照現實建」:

- ingest preflight:git status --porcelain 預設會把含中文或空格的路徑加引號
  轉義,raw/ 白名單比對因此失效,中文檔名的 convert 產出被誤判為 raw/ 以外的
  未提交變更而中止攝入。舊測資用 ASCII 檔名,整條路徑從未被走過。

- search:BM25Okapi 的 idf 在 df >= N/2 時 <= 0(rank_bm25 對負 idf 的替代值
  epsilon x average_idf 在 average_idf 為負時同樣為負),與 search() 的 s > 0
  過濾相乘,會讓「每頁都提到的核心詞」查詢全數落空——知識庫愈小、詞愈核心
  愈嚴重,MCP 的 search_wiki 一併受害。改用 Lucene 式恆正 idf。
  舊測資每個查詢詞都只出現在一頁(df=1),恰好避開此配置。

變更:
- tools/ingest.py:preflight 比對前剝除 git 的轉義引號
- tools/search.py:_BM25 子類覆寫 _calc_idf 為 log(1 + (N-df+0.5)/(df+0.5))
- tools/selfcheck_ingest.py:新增 preflight 中文檔名放行 / 非 raw 擋下的檢查
- tools/selfcheck_search.py:新增與既有頁共用核心詞的測資,鎖住 idf 退化
- tools/convert/selfcheck.py、tools/selfcheck_lint.py:測資檔名改中文+空格
- AGENTS.md §13.4:新增「測資照現實建,不是照能過建」規則
- README.md §3.2:補 convert 產出應保持未提交、由 ingest 一併 commit 的流程

驗證:四個自檢全數通過;分別移除兩個修法後對應檢查會失敗。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 07:21:45 +08:00
LittleYellow
59c16ea393 Phase 1: 骨架與 schema — 目錄結構、AGENTS.md 正本、指標檔、models.yaml、index/log 模板、manifest 結構
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 07:42:45 +08:00