feat: convert --verify 對帳 + 修復 CRLF 使 hash 失準 + raw/** .gitattributes (#1)

## 目的

`convert` 後檔案被手動刪除/就地改動時,提供正規的稽核與修復途徑;並修掉一個讓「還原後 re-hash 比對」在 Windows 失效的既有 bug。

## 變更

- **`convert.py --verify`(純唯讀對帳)**:re-hash 全部登記檔、掃未登記檔,回報 missing / mismatch / unregistered,不一致以退出碼 1 表示(可當 CI/排程閘門)。`converted/assets/*` 與 `.gitkeep` 正確略過。
- **修 CRLF 使 hash 失準**:`write_text` 在 Windows 把 `\n`→`\r\n`,但登記的 SHA-256 算在 `\n` bytes 上 → 磁碟 bytes 與帳本永遠對不上(converted md + web 快照原始檔)。改為 `write_bytes` 寫入所登記的那份 bytes。
- **`.gitattributes`(`raw/** -text`)**:`core.autocrlf=true` 下 checkout 會在 git 層重新引入 CRLF,抵銷上一項修復;關閉 raw 的換行正規化,把「登記 hash == 磁碟 bytes」不變式延伸到 git checkin/checkout。
- **selfcheck**:補 clean / missing / mismatch / unregistered 四情境(全程唯讀斷言;clean 案例含未入帳本的 assets,順帶證明不誤報)。
- **AGENTS.md**:新增 §14「raw 完整性與修復(對帳)」,並於 §1.4 補「登記 hash == 磁碟 bytes」不變式與 `.gitattributes` 機制。

## 驗證

`.venv/Scripts/python.exe tools/convert/selfcheck.py` → `ALL PASS`。

## 備註

`--verify` 是唯讀稽核工具,不改任何檔(含 manifest),符合 §7「lint 絕不擅自刪改」精神。修復決策(可衍生 vs 信任根、先 `git restore` 不改帳本、動 manifest 走 PR)詳見 AGENTS.md §14。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: LittleYellow <crazytea@gmail.com>
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-07-23 02:27:47 +00:00
parent cb16e8688f
commit 356ae9367c
4 changed files with 158 additions and 4 deletions

8
.gitattributes vendored Normal file
View File

@@ -0,0 +1,8 @@
# raw/ 是 hash 釘選的 provenance 帳本AGENTS.md §1.4 / §9 / §14
# git 一律不得正規化其換行,否則 checkout 後磁碟 bytes 會與 manifest 的
# SHA-256 不符,讓 --verify 對帳失準(本專案 core.autocrlf=true
# 轉換器已在寫入時以 write_bytes 固定為登記的那份 bytes此處把同樣的
# 保證延伸到 git 的 checkin/checkout。
raw/originals/** -text
raw/converted/** -text
raw/manifest.json -text