交換文件規格
狀態:P1 設計已通過審閱(20261015-docs-exchanges-p1,第 3 輪,受審 revision r3-6940c07d011ead6f;6 條 major 均處置)。P1 實作已通過審閱(20261016-docs-exchanges-p1-impl,第 4 輪,受審 revision r4-3b0c6db130f8a561;9 條意見均處置);實作與審閱中確認的修訂見 §15 依據:ADR-023 的 D1、D2、D6、D7 與實作分期 P1;文檔 Registry 規格;追蹤項目 FU-142 本頁定義:AI 與人類交換的文件(審閱簡報與證據、Sprint 交付紀錄)在 docs 模組中的位置、生命週期、提交與確認方式,以及
docs.py的寫入動詞publish/close。
1. P1 範圍
| 做 | 不做 |
|---|---|
/peer-review 的簡報與證據移入 docs 模組(D1),不提交、結案刪除(§15 審閱報告不提交) | /report 與 /uat 證據的保留篩選(屬 P2 retention;P1 不改變它們的提交時點) |
/work 新工作的交付紀錄移入 docs 模組 | 進行中的 /work 工作改路徑(沿舊位置到結案,見 §11) |
docs.py publish/close:revision、發布紀錄、確認綁定(D6)、基線固定與分類(D2) | resolve/create/register、PreToolUse hook(P2/P3) |
| preview-only 在標準建置的編譯前排除與產物掃描(D7) | handoff.md 的位置(ADR 待決 1,見 §14) |
| 證據的用途篩選與被引用證據保留(交付交換另檢查可提交)、結案前結論落點檢查 | ADR-020 原樣張與 git 的對齊(ADR 待決 2) |
| 參考實作現有 20 個舊審閱證據孤兒依用途處置 | 下游專案的孤兒(由各專案在套用 P1 時自行處置) |
2. 目錄與 registry 變更
2.1 位置
| 交換 | 給人讀的文件(docs 樹,渲染成頁面) | 證據與附件(static 樹,不編譯) |
|---|---|---|
審閱 reviews | {docsRoot}/docs/exchanges/reviews/{id}/brief.md | {docsRoot}/static/exchanges/reviews/{id}/evidence/** |
交付 work | {docsRoot}/docs/exchanges/work/{id}/request.md、progress.md、integration.md | {docsRoot}/static/exchanges/work/{id}/evidence/** |
證據放 static 樹的理由:證據常含 md、HTML 與程式碼,放在 docs/ 會被 Docusaurus 當成頁面編譯;任何壞連結都會因 onBrokenLinks: 'throw' 讓整站建置失敗,而證據的內容本來就不該受站台連結規則約束。static 樹只複製、不編譯,並由交換頁的附件索引(§10)提供導覽。這也落實 ADR 待決 3「證據移出 docs/ 正文樹」中交換證據的部分;報表與 UAT 證據仍待 P2 決定。
2.2 registry 變更(共用層)
| 類型 | 變更 |
|---|---|
peer-review-exchange | 容器維持 {docsRoot}/docs/exchanges/reviews/{id}/**;錨點維持新簡報與舊簡報 |
peer-review-evidence | paths 改為 {docsRoot}/static/exchanges/reviews/{id}/evidence/**;舊位置不變 |
新增 peer-review-static | {docsRoot}/static/exchanges/reviews/{id}/** 的 temporary 容器(R11 要求 static 側也有容器) |
新增 review-record | {docsRoot}/static/exchanges/reviews/{id}/publish.json、confirmations.json:發布紀錄與確認紀錄(§5),role data、exchangeKind: peer-review、隨審閱交換結案移除 |
work-request、work-progress | 新增 integration.md 的 work-receipt 類型;位置維持新路徑,舊路徑保留為 legacy |
work-evidence | paths 改為 {docsRoot}/static/exchanges/work/{id}/evidence/**;容器改由新增的 work-exchange({docsRoot}/docs/exchanges/work/{id}/**)擔任,錨點不變 |
review-display(deprecated) | 保留至參考實作與下游的 static/reviews/ 清空後移除 |
2.3 證據連結格式
文件引用證據一律用 Docusaurus 的 pathname:// 連結,路徑從 static 根開始:
[測試輸出](pathname:///exchanges/reviews/{id}/evidence/test-docs.txt)
| 面向 | 規則 |
|---|---|
| 網站 | pathname:// 連結不走前端路由、不受建置連結檢查,Docusaurus 自動加上 baseUrl(@docusaurus/core 的 Link 已核對);部署時 docs-host 的 basename 替換同樣適用 |
docs.py 解析 | pathname:///X → {docsRoot}/static/X;只接受落在同一交換的 static/exchanges/{kind}/{id}/evidence/ 下的目標,其他目標(含 ..、絕對網址、其他交換)列為錯誤 |
| 其他寫法 | 指向 evidence/ 的相對連結、/exchanges/... 一般連結一律列為錯誤,不猜測轉換 |
| 程式碼 | fenced 與 inline code 中的連結是示例,不解析、不列入閉包 |
2.4 證據保留閉包
證據目錄只放下列檔案的閉包;交付交換只提交這個閉包:
- 入口:交換文件(簡報;work 為 request、progress、integration)以 §2.3 格式引用的檔案。
- 相依:入口與相依檔中,HTML 的
src、href、srcset,以及 CSS 的url()、@import所指向、位於同一evidence/目錄下的相對路徑,遞迴展開。 - 紀錄檔:
publish.json、confirmations.json(審閱交換)。
相依指向不存在的檔案、逃出 evidence/、或是符號連結,一律列為錯誤。外部網址(http(s)://、data:)不屬閉包、不檢查。
3. 審閱交換(/peer-review)
| 步驟 | P1 之後 |
|---|---|
draft | 簡報寫在 docs/exchanges/reviews/{id}/brief.md;證據放 static/exchanges/reviews/{id}/evidence/;記錄審閱基線 reviewBase;執行 docs.py publish(§9) |
| 呈現 | 簡報直接由站台渲染成頁面,不再產生 static/reviews/ 展示副本;審閱期間用審閱預覽(start:docs-only)閱讀 |
review/respond/verdict | 寫入簡報的欄位所有權與寫前重讀紀律不變;結論另寫入確認紀錄(§5.3);寫入後執行 publish |
sync | 處置意見後執行 publish;publish 產生新 revision |
close | 執行 docs.py close(§9.3):結論落點已確認、無 open 的 blocking/major、推送祖先守衛無違規,才刪除交換目錄;成果之後由作者依 01-commit.md 提交與推送 |
m-peer-review.md 的「簡報不進 git、不進 docs/」改寫為:簡報放 docs 模組但不提交(gitignored),結案刪除;.claude/peer-review/ 只在舊審閱結案前沿用(§11)。
交換 id:審閱交換的 id 為 {YYYYMMDD}-{slug};去掉數字前綴後的路由形式必須含 -(slug 至少兩個詞),docs.py 拒絕其他 id,讓建置後的 id 掃描不與一般文字混淆(§7)。
簡報結構:docs.py 依標頭鍵名與章節表格欄名解析,不依欄序。標頭引言區塊必須有 輪次、狀態、審閱基線(完整 SHA)、成果範圍(、 分隔的 workspace 相對路徑)與 展示;章節表格為「基線後提交」(提交|分類|說明)、「意見」(編號|嚴重度|…|狀態|處置)、「審閱紀錄」(輪次|…|結論)、「結論落點」(結論|落點|狀態)。完整範本在 m-peer-review.md。簡報以 CommonMark 呈現,站台需 markdown.format: 'detect'。
4. 交付交換(/work)
- 新工作:
start把request.md、progress.md建在docs/exchanges/work/{workId}/,整合端的integration.md同目錄;測試輸出等證據放static/exchanges/work/{workId}/evidence/。 - 送審與整合契約不變:delivery commit 仍「只修改本工作
request.md」;最初 draft 取證、sourceSHA 邊界與整合 receipt 的 git 驗證,只是把{requestRel}換成新路徑。 - 網站呈現:work 為 persistent、
distribution: site,交付紀錄隨標準建置出現在站台,取代現行「沒有網站入口」的缺口。 - 不受 D2 審閱提交守衛約束:work 本來就是在工作分支提交成果、審閱後合併(
m-work.md);D2 只適用於/peer-review的共享工作樹審閱。 - 證據守衛同樣適用:
/work的start、advance、submit在提交任何交付紀錄或證據前,執行docs.py evidence --exchange work/{workId}(§9.4);閉包以外的證據檔、缺檔或越界相依都會讓該步驟停止。整合端寫integration.md時同樣執行。
5. 呈現版本與確認(D6)
5.1 revision
revision = r{round}-sha256( 受確認內容投影 ‖ 成果清冊 ‖ 呈現環境 )[:16]
| 部分 | 內容 |
|---|---|
| 受確認內容投影 | 簡報全文,扣除標頭的「狀態」、「展示」欄、審閱紀錄表的「結論」欄(鏡像欄位),以及結論落點表的資料列(作者在通過後填寫的結案紀錄,見 §15) |
| 成果清冊 | 審閱範圍內每個檔案的路徑與 SHA-256(依 §6 的成果範圍),以及 evidence/ 每個檔案的路徑與 SHA-256 |
| 呈現環境 | docs 模組中所有影響呈現的實際檔案內容雜湊(依路徑排序的路徑與 SHA-256):根目錄的 docusaurus.config.ts、site.project.ts、sidebars*.ts、package.json、package-lock.json、docs-registry*.json;scripts/**、src/**(元件、主題覆寫、CSS)。不使用 .docs-site.json 的記錄值 |
publish 先執行 /docs-site 的受管檔核對(update.py audit):結果不是 aligned(受管檔有本機漂移或 bundle 落後)時拒絕發布,先修復站台再審閱。專案自有的呈現擴充(site.project.ts 引用的 CSS、元件、外掛版本)由上表的實際內容雜湊涵蓋,任何一項改變都產生新 revision。
5.2 發布紀錄 publish.json
docs.py publish 寫入 static/exchanges/reviews/{id}/publish.json:revision、round、受確認內容投影雜湊、成果清冊、呈現環境、頁面 URL、核對結果。頁面本身在簡報標頭顯示 revision 與輪次(由「展示」欄提供)。
核對:publish --verify-url {baseUrl} 指向審閱預覽(start:docs-only),在 --verify-timeout(預設 60 秒)內重試,全部成立才記 verified: true:
- 預覽的
docs-site-exchanges外掛在審閱模式把已載入簡報「展示」中的 revision 與 bytes 雜湊寫成{baseUrl}__docs-site/exchanges/reviews/{id}.json(存於node_modules/.cache,不進 git、不進標準建置);兩者必須等於本次 revision 與目前簡報。 - 簡報頁的編譯結果必須含本次完整的「展示」值
{revision} / src {簡報來源雜湊}(來源雜湊涵蓋「展示」以外的全部 bytes,所以確認、鏡像與結論落點的更新也會被核對):依.docusaurus/registry.js找出@site/docs/exchanges/reviews/{id}/brief.md的 chunk,取回{baseUrl}{chunk}.js檢查。開發服務的 HTML 是客戶端渲染的固定模板,外掛重新載入也不保證頁面已重新編譯(見 §15),所以只看第 1 點不足以證明頁面是本版。 - 頁面 URL 取自預覽產生的文件 metadata(
.docusaurus/docusaurus-plugin-content-docs/中source為該簡報者的permalink),且回應 200;找不到 metadata 即視為路由不存在。逐一取回evidence/與紀錄檔比對 SHA-256。
請求一律帶 Accept: text/html,*/*(開發服務的 SPA fallback 只回應宣告接受 HTML 的請求)。沒有給 --verify-url 或逾時時,發布紀錄的 verified 為 false,/peer-review 不得宣稱已可審閱。
5.3 確認紀錄 confirmations.json
{"confirmations": [
{"revision": "r3-4d58c60ef77aecc0", "by": "reviewer", "verdict": "approve", "at": "2026-10-15T12:00:00Z", "note": "…"}
]}
- 審閱結論與人工確認一律在此附加一筆,寫明確認的 revision;確認紀錄不在 revision 雜湊範圍內,所以寫入確認不會讓所確認的 revision 失效。
- 簡報中的狀態欄與結論欄是鏡像,必須與最新一筆一致;
docs.py status(§9.2)檢查不一致。 - 只有
revision等於目前計算值的確認才算數;舊 revision 的確認保留在紀錄中,不被當成目前版本的確認。
6. 審閱基線與推送邊界(D2)
6.1 審閱基線與成果範圍
draft記錄reviewBase(當下 HEAD 完整 SHA)與成果範圍路徑,寫在簡報標頭。首次publish把兩者寫入publish.json而固定(不得手改):之後改寫基線即拒絕(BC-REBASE),範圍只能增加、不能移除(BC-SCOPE);需要前移基線就另開審閱。- 成果差異=
git diff {reviewBase} -- {成果範圍}(含之後的提交與工作樹變更),一律排除交換目錄(docs 與 static 兩側)。
6.2 基線後的提交
publish 列出 reviewBase..HEAD 中、觸及交換目錄以外檔案的每個提交,要求在簡報「基線後提交」表分類:
| 分類 | 處理 |
|---|---|
| 本成果 | 留在成果範圍,照常審閱;通過前不得推送到共享分支 |
| 外部(不重疊) | 只觸及成果範圍以外:從範圍排除並列出 |
| 外部(重疊) | 觸及成果範圍內的檔案:publish 停止,由人決定重新起審或拆分成果 |
有未分類的提交時,publish 拒絕產生新 revision,close 拒絕結案。
6.3 不提交
審閱交換不提交:registry 把審閱交換類型設為 git: ignored,/docs-site 在 docs 模組 .gitignore 維護忽略區塊;docs.py 任何動詞都不 stage、不提交。被追蹤的審閱交換檔案讓 publish/close 拒絕、status 列違規(EX-TRACKED)。被審成果依 m-peer-review.md 不變量二在通過後才提交。
6.4 審閱範圍:共享工作樹、審閱期間不推送
- 審閱交換沿用
/peer-review的定位:共享工作樹(同一台電腦或同步檔案系統,見m-peer-review.md)。審閱者直接讀作者工作樹中未提交的成果;這不是 P1 新增的限制。跨 clone 的交付本來就由/work處理(成果隨分支提交、審閱後合併)。 - 不推送:
docs.py的動詞都不推送;成果的提交與推送在close之後,由作者依01-commit.md處理。 - 推送祖先守衛:
docs.py status檢查reviewBase..HEAD中被分類為「本成果」的提交是否已出現在目前分支的遠端追蹤分支;已出現即回報違規(exit 1),close也拒絕結案,直到由人處理。
7. preview-only 的編譯前排除(D7)
| 層 | 做法 |
|---|---|
| docs 編譯 | docs-site.cjs 讀 registry,把 distribution: preview-only 的 docs 路徑加入 docs plugin 的 exclude;只有 DOCS_SITE_REVIEW=1 時不排除 |
| 導覽、搜尋、sitemap | 排除的文件不產生路由,自然不進側欄、搜尋索引與 sitemap;llms.txt 不列交換文件(app-docs 11-llms-txt-sync 規則同步註明) |
| static 檔與產物掃描 | 由 bundle 新增的 scripts/docs-site-finalize.cjs 在 docusaurus build 整個程序結束後執行:先從輸出目錄刪除 preview-only 的 static 路徑(exchanges/reviews/**、既有的 reviews/**、reports/restorations/**),再掃描整個輸出目錄(HTML、JS chunk、搜尋索引、sitemap、llms.txt),找到任何 preview-only 來源路徑或交換 id 即以非零 exit 結束 |
為何不放 postBuild | Docusaurus 3.10 的 executePluginsPostBuild 以 Promise.all 並行執行各外掛的 postBuild,搜尋外掛也在自己的 postBuild 寫索引;外掛內的掃描可能早於其他外掛完成,不是最後一步 |
| 建置與部署入口 | docs 模組 package.json 中每一個會產生或發布建置產物的 script 都必須經過 finalize,由 /docs-site 補建並由 /docs-site audit 檢查:・含 docusaurus build 者:改為 … docusaurus build && node scripts/docs-site-finalize.cjs(保留既有前置命令),涵蓋 build、build:docs-only。・含 docusaurus deploy 者:docusaurus deploy 預設在程序內自行 build(@docusaurus/core 3.10 deploy.js 已核對),會繞過 finalize;改為 npm run build && docusaurus deploy --skip-build,finalize 失敗時 && 讓部署停止。・ docusaurus serve --build:同樣在程序內 build,不允許;serve 只能服務既有輸出。docs-host 的 copyDocsBuild 經由 npm run build 取得產物,一併涵蓋 |
| 不在契約內的入口 | 直接在命令列執行 npx docusaurus build/deploy 不經 package.json scripts,無法由 audit 攔截;/docs-site 的說明與 m-docs-site.md 明定一律使用 npm scripts,host 與 CI 也只呼叫 npm scripts |
| docs-host | copyDocsBuild 的排除保留作為第二道防線,不再是唯一防線 |
交換 id 去數字前綴後可能與正式文件同名。finalize 仍掃完整交換 id、來源/路由路徑及獨立短代號;
僅在比對短代號時排除可核對的正式文件引用,不把同名視為全域豁免。
引用取自 docs-site-routes schema 1 的 command=build 紀錄,設定輸入及該文件來源 SHA 必須仍吻合,
且來源不得屬於 registry 的 preview-only 路徑。只豁免完整 permalink(含 baseUrl)、同站絕對 URL、
來源路徑及 Docusaurus 記錄的 slug、文件 id/HTML class 與 editUrl 引用;未知前綴、子路徑與其他獨立值仍掃描。
根文件的裸 id 與短代號無法區分,仍須掃描,不因同名正式頁而豁免獨立值。
缺少、過期或僅由 preview/start 產生的紀錄不提供豁免。JSON/JS 跳脫的斜線先正規化,
完整交換 id/路徑永不因正式文件引用而豁免;同一字串兼具完整 id 與短代號時採完整 id 的嚴格比對。
8. 證據條件與結案條件
證據檢查(docs.py evidence,§9.4;publish 與 /work 各步驟內建呼叫):
- 用途篩選:
evidence/中每個檔案都必須在 §2.4 閉包內。閉包外的檔案列為錯誤,由作者移到{workspace}/output/(scratch,不進 git)、刪除,或在文件中補上引用。交付交換在提交前必須沒有錯誤;已追蹤但不再被引用的檔案也列出,必須在同一次提交中移除或重新引用。 - 被引用證據保留:閉包內每個檔案都必須存在、是一般檔案(非符號連結);交付交換另要求不被 gitignore(已追蹤或會在本次 stage)。
- 大小提示:新增或變更的檔案中,單檔超過 5 MB 或合計超過 20 MB 時列為警告,要求作者確認用途;不自動拒絕。
docs.py close 移除交換目錄之前檢查:
- 最新確認為
approve,且確認的 revision 等於目前計算值。 - 意見表沒有 open 的 blocking/major,也沒有未分類的基線後提交;推送祖先守衛(§6.4)沒有違規。
- 結論落點:簡報「結論落點」表的每一列都有落點(ADR、rules、文檔、follow-up 編號或 commit body),且標成已完成;任何一列空白即拒絕。
9. docs.py 寫入動詞
沿用 P0 的 JSON 外層與 exit 規則;寫入動詞的 readOnly 為 false,writes 列出實際寫入或 stage 的路徑。
P1 的 publish/status/close 只支援審閱交換(--exchange reviews/{id})。work 交換的版本與確認沿 m-work.md 既有的 sourceSHA 與整合 receipt 契約,不另加 revision;對 work 只提供證據檢查(§9.4 evidence)。
9.1 publish
docs.py publish --workspace {ws} --exchange {kind}/{id} [--verify-url {baseUrl}] [--verify-timeout {seconds}]
交換路徑符號連結檢查 → 受管檔核對(§5.1)→ 基線固定與分類(§6)→ 計算 revision → 寫 publish.json → 更新簡報「展示」欄 →(有 --verify-url)取回頁面與附件核對 → §8 證據檢查(回報,不阻擋發布)。不 stage、不提交、不推送。
9.2 status(唯讀)
docs.py status --workspace {ws} --exchange {kind}/{id}
回報目前計算的 revision 與 publish.json 是否一致、最新確認是否對應目前 revision、鏡像欄位是否一致、未分類的基線後提交,以及推送祖先守衛(§6.4)的結果。有違規時 exit 1。
9.3 close
docs.py close --workspace {ws} --exchange {kind}/{id}
執行 §8 結案條件 → 刪除交換目錄(docs 與 static 兩側)。審閱交換不提交,簡報不留在 git 歷史;持久的是結論落點。
9.4 evidence(唯讀)
docs.py evidence --workspace {ws} --exchange {reviews|work}/{id}
依 §2.3、§2.4 解析連結與閉包,回報:閉包清單、閉包外檔案、已追蹤但不再引用的檔案、缺檔、越界或符號連結、大小警告;交付交換另檢查被 gitignore 的引用。有錯誤時 exit 1。審閱與 work 都可用,供 publish 與 /work 各步驟呼叫。
9.5 舊位置
三個動詞遇到舊位置(.claude/peer-review/)的交換時拒絕,並提示依舊流程結案(§11)。
10. 導覽
- docs-site 共同分類新增「審閱與交付」(目錄
exchanges)。 - 每個交換頁的底部由 docs-site 外掛自動附上附件索引:列出該交換在
static/exchanges/下對應目錄的檔案、大小、SHA-256 與連結,以及publish.json的 revision 與核對結果。人類從導覽進入交換頁,即可讀到全部附件,不需另給連結。資料由獨立外掛docs-site-exchanges以 global data 提供,頁尾(DocItem/Footer)依目前文件的來源路徑查詢,不依賴特定的文件元件(部分站台的文件路由使用 openapi 主題的ApiItem)。 - 標準建置只呈現 work;審閱交換只在審閱預覽出現(§7)。
11. 遷移與相容
| 對象 | 處理 |
|---|---|
| 進行中的審閱(舊位置) | 沿舊流程到結案;/peer-review 依簡報所在位置選擇流程 |
進行中的 /work 工作(舊位置) | 沿舊路徑到合併;新工作才用新路徑。不搬移既有 request,以免破壞最初 draft 取證 |
| 參考實作的 20 個舊審閱孤兒 | 逐一核對其結論已落點(ADR、rules、commit 均已存在)後,列出清單請人確認刪除;確認前不刪 |
static/reviews/ 舊展示副本 | 隨對應審閱結案刪除;全部清空後移除 review-display 類型與 docs-host 排除中的 reviews/** |
| 下游專案 | 經 /methodology publish、/docs-site plan/apply 取得新版;各專案自行處置舊孤兒,P1 不寫入下游 |
12. 測試
| 類別 | 測試 |
|---|---|
| revision | 寫入確認與鏡像欄位後 revision 不變;改動實質段落、成果檔、證據檔或呈現環境後 revision 改變;舊 revision 的確認不算數 |
| 基線 | 成果被意外提交後仍在範圍內;外部提交不重疊時排除並列出、重疊時停止;有未分類提交時 publish 與 close 拒絕 |
| 不提交 | publish/close 不改變 HEAD 與使用者暫存區;--commit 選項不存在;被追蹤的審閱交換檔案讓動詞拒絕 |
| 證據連結與閉包 | pathname:// 有效連結解析到 static;相對連結、/exchanges/... 一般連結、其他交換或越界目標列為錯誤;HTML 引用的 CSS、圖片與 CSS url() 遞迴納入閉包;相依缺檔、越界、符號連結報錯;外部網址不檢查 |
| 證據 | 未引用證據列為錯誤、補引用後通過;審閱證據可被 gitignore,交付證據被 ignore 時報錯;大小警告 |
| work 證據 | start/advance/submit 與整合端寫 receipt 時,閉包外證據讓步驟停止 |
| 結案 | 結論落點有空列、最新確認非目前 revision、有 open blocking/major 時拒絕;通過時只刪除交換目錄 |
| D7 | 標準建置的輸出不含任何 preview-only 路徑或交換 id;審閱預覽包含;在測試站台加一個於 postBuild 延遲寫出洩漏檔的外掛,finalize 仍能抓到並讓 npm run build 失敗 |
| D7 入口 | /docs-site audit 對下列 script 報錯:docusaurus build 後沒接 finalize、docusaurus deploy 沒有 --skip-build 或前面不是 npm run build、docusaurus serve --build;/docs-site plan 會把三個 docs 模組現有的 deploy: docusaurus deploy 改寫為 npm run build && docusaurus deploy --skip-build;finalize 失敗時 npm run deploy 不執行部署步驟 |
| 呈現環境 | 只改 src/ 的 CSS、只改自訂元件、只改 package-lock.json 的外掛版本,revision 都改變;受管檔有本機漂移時 publish 拒絕 |
| 推送邊界 | 本成果提交已出現在遠端追蹤分支時,status 回報違規、close 拒絕;docs.py 任何動詞都不推送 |
| work | 新路徑下的最初 draft 取證、ready-only commit、receipt 驗證與舊路徑相容 |
| 舊位置 | 動詞遇到 .claude/peer-review/ 交換時拒絕 |
13. 會修改的檔案
| 檔案 | 變更 |
|---|---|
.claude/rules/m-peer-review.md、/peer-review SKILL.md | 不變量一改寫(放 docs 模組、不提交、結案刪除);位置、publish/close、確認紀錄、基線後提交、結論落點表 |
.claude/rules/m-skill-execution.md | 暫時展示副本段改為交換文件直接呈現;確認綁定 revision |
.claude/rules/m-work.md、/work SKILL.md 與 references | 新工作的路徑;證據放 static 樹 |
.claude/rules/m-docs-site.md、/docs-site(docs-site.cjs、新增 docs-site-finalize.cjs、update.py 的 scripts 補建與檢查——build/build:docs-only 接 finalize、deploy 改為先 npm run build 再 --skip-build、禁止 serve --build——docs-registry.json、docs.py、測試) | D7 編譯前排除、建置後 finalize 與產物掃描、「審閱與交付」分類、附件索引、registry 變更、publish/status/close/evidence |
app-docs/.claude/rules/11-llms-txt-sync.md(docs practices) | 交換文件不列入 llms.txt |
appfuse-docs/docs-methodology/project-documentation.md | 團隊指南改寫審閱呈現段落 |
.claude/rules/m-methodology.md | 索引 |
| ADR-023 | 變更歷史;待決 3 的交換證據部分已決 |
14. 待決與審閱重點
待決:
審閱提交是否推送:第 1 輪審閱後決定審閱期間不推送(§6.4);/peer-review本來就以共享工作樹為定位,跨 clone 由/work處理。handoff.md(ADR 待決 1):本設計維持現狀。- 大小門檻:§8 的 5 MB/20 MB 警告值。
請特別看:
- 證據放 static 樹、文件放 docs 樹的切分(§2.1),以及它對 ADR 待決 3 的部分決定。
- revision 的雜湊範圍與確認紀錄分離(§5)是否能同時滿足「寫入確認不失效」與「實質改變必重新確認」。
- D7 的建置後 finalize(刪除 preview-only 輸出加產物掃描),是否足以取代「只靠 host 排除」。
- 用途篩選以「簡報是否引用」作為唯一準則(§8)是否太嚴或太鬆。
/work只對新工作換路徑、進行中工作沿舊路徑(§11)是否會讓兩種路徑並存太久。
15. 實作中確認的修訂
設計通過後,實作、實際站台驗證與 P1 實作第 1 輪審閱(20261016-docs-exchanges-p1-impl)發現下列設計需要補正;均以測試與隔離副本中的實際 Docusaurus 驗證,隨 P1 實作一併送審。
| 項目 | 原設計 | 修訂 | 理由 |
|---|---|---|---|
| 投影範圍(§5.1) | 只扣除三個鏡像欄位 | 另扣除「結論落點」表的資料列 | 結論落點在通過後才由作者填寫;若納入投影,填寫就讓通過的 revision 失效,close 永遠無法同時滿足「目前 revision 已通過」與「結論落點已完成」 |
| 預覽核對(§5.2) | 取回頁面檢查 revision | 外掛狀態檔+編譯 chunk 雙重檢查,限時重試 | 開發服務回應的 HTML 不含頁面內容;實測 Rspack 漏接初次編譯期間的檔案變更時,外掛已讀到新簡報、頁面卻仍是舊編譯結果 |
| 結案前提(§9.3) | 結案條件成立即 git rm | 審閱交換不提交,結案直接刪除兩側目錄;被追蹤的檔案拒絕 | 依「審閱報告不提交」決定(見下列);原先「須已提交」的修訂隨之撤回 |
| 頁面 URL(§5.2) | 由檔案路徑推算 | 取自預覽產生的文件 metadata 的 permalink | Docusaurus 會去掉路徑段的數字前綴,20261016-… 的簡報實際路由不含日期;開發服務對任何路徑都回 200,推算錯誤也不會被發現 |
| 頁面版本指紋(§5.2,第 1 輪審閱 R1-02) | 編譯頁只比對 revision | 「展示」寫成 {revision} / src {簡報來源雜湊},編譯頁必須含整個值 | 確認、鏡像與結論落點不改 revision;只比 revision 時,頁面停在「審閱中」也會核對通過 |
| 符號連結(§9,R1-01) | 未規定 | 交換目錄、簡報、紀錄檔及其祖先為符號連結時,任何動詞在讀寫前拒絕 | 否則 publish 會改寫交換目錄外的檔案 |
| 基線固定(§6.1,R1-03) | 「審閱期間不得修改」只是約定 | 首次發布寫入並固定,改寫或縮小範圍即拒絕 | 否則前移基線就能讓應分類的提交從清單消失 |
| 部署輸出目錄(§7,R1-04) | 未規定 | deploy 的輸出目錄必須等於 build script 的輸出,否則列衝突 | 否則可能建置並 finalize build/,卻發布另一個舊目錄 |
| 交換 id 掃描(§7,R1-05、R2-02) | 只掃完整路徑 | 另掃交換 id 的來源與路由形式(去掉數字前綴),前後不得緊接 id 字元;審閱 id 的路由形式必須含 -(slug 至少兩個詞),否則 docs.py 拒絕 | 其他外掛可能只寫出 id;單字路由 id(如 20261016-demo → demo)與一般文字混淆,以命名限制排除,finalize 仍掃描(fail closed) |
| 既有 finalize 的目錄(§7,R2-01) | 看見既有 finalize 就略過 | 既有 finalize 的 --out-dir 必須等於所屬 docusaurus build 的輸出,不一致時 plan 改寫 | 否則 build 寫到 custom-out,finalize 卻掃描乾淨的 build/,洩漏留在要部署的目錄 |
| 程式碼示例(§2.3,R1-06) | 全文解析連結 | 略過 fenced/inline code | 規則文件中的連結示例不是引用,不該阻擋發布 |
| 審閱報告不提交(§3、§6、§9,2026-10-16 使用者決定) | 審閱期間提交交換目錄(不推送),結案以提交移除、歷史保留 | 審閱交換 git: ignored、.gitignore 忽略區塊;publish/close 不再有 --commit,結案直接刪除 | 審閱報告是過程產物,不進版控;持久的只有結論落點。交付交換(/work)不受影響,仍隨 git 追蹤 |