跳至主要内容

證據保留:UAT 快照、report run 與原樣張

狀態:P2-6 設計與實作均已通過審閱;實作於 2026-10-20 通過第 2 輪(受審 revision r2-19ace3c868307bfa,審閱者 ada@leandev.io,見 §12)。ADR-023 現已 Accepted,含後續 P3 實作;retention 為提交參考,blocked 不構成新增交付閘門(§8)。既有證據原位保留,歷史缺件依各輪清冊明示;工具通過不代表資料已齊、已清理或 hook 已啟用,fleet 採用須依各次發布紀錄核對。 依據:ADR-023 D2/D4/D5、ADR-020 2026-10-10 修訂、文件解析與索引 §1、驗證類遷移;追蹤 FU-142。

1. 目標與範圍​

將 registry 的 referenced/referenced+latest 從標籤補成可重現的保留判定。查詢只回答指定工作樹中哪些資料被保留、哪些尚無已知引用、哪些無法判定;不代理 UAT/報表驗收,也不自動刪除或提交檔案。

本期納入本期不做
UAT 快照、來源 sidecar、結果及歷史承接的引用閉包P3 寫入 hook、FU-144 查詢效能改造
report 帳本全部歷史與 run 單位的保留判定新增刪除/apply 動詞、改寫 Git 歷史、LFS、儲存服務
原樣張保存與 ADR-020/D2 的明確一致性修訂外部採用 HTML 包登錄(FU-126)、還原確認自動化(FU-134)
原生唯讀引用匯出、共用保留查詢、audit 與提交前指引批次搬移、重錄、修改 schema 或重置既有真人接受
參考實作投影、文件/skills/rules/adapter 同批接線以 retention 取代現有展示副本清理、部署政策或 work 交付契約

採用選擇:UAT 與報表證據維持原位,不搬到 static;原生 snapshot、runs、history、manifest 的路徑與摘要責任保持不變。網站需要閱讀的原檔沿既有逐檔入口提供,不能掛出整個 testing 或 workspace。DR-EVIDENCE-IN-PAGE-TREE 不因此變成 error,也不要求為清除此提示搬檔。

2. 現況與判定風險​

九個 workspace 的本次唯讀描述盤點得到 3,954 個 UAT 快照,共 49,092,810 bytes;58 個報表帳本候選、274 個 run,共 251,884,295 bytes。投影未改,JSON 解析錯誤為 0。盤點僅涵蓋各站預設 docs 內容樹,不宣稱包括所有 project locate、Git 歷史或外部原件。

1,163 個快照名稱沒有直接出現在所掃目前 UAT JSON 的字串中。這不是可刪數量:快照內的舊 sidecar、歷史匯入、工作交付及其他文件可能再引用它們;本次字串盤點不是原生 schema 驗證,也沒有計算完整遞迴閉包。不預告可回收容量。

實作前提來自現行原始碼:

  • UAT stored_blob 依序查目前檔案、SHA-256 快照及 Git 歷史;AcceptanceSnapshot 會再讀當時 sidecar。來源快照也可能保存 JSON 原文,不能把每個 .txt 當獨立葉節點。
  • schema 6 場景帳本的過往 bindings、review/撤銷/承接紀錄仍是可追溯的來源;只保留目前 passed 場景會抹掉處置依據。
  • report record 將舊紀錄放進 history;carry-acceptance 必須重新取得舊接受 PDF 的完整 bytes。validate_history 接受歷史 metadata,不代表舊 PDF/XML 可以刪除。
  • report-evidence 的路徑目前涵蓋帳本、runs 及同層附件,不能把整個類型一律當待裁切的 run;uat-origin/equivalence 的 all 保留不得因本期順手縮減。

3. 判定單位與權威​

資料保留規則判定權威與單位
UAT 快照referencedSHA-256 定址的完整檔案;同一 docs 模組共享池,不按單一 US 或 target module 各自清理
UAT sidecar/結果、equivalence/archive、origin/匯入對應all/with-source 沿現行契約原生 schema、事件與來源帳本;本期不裁切事件或歷史原文
report 帳本與同層確認/來源/結果附件allPDF/HTML 帳本、還原確認及明示相依;保留完整 history、acceptanceHistory 與 carriedFrom
report runsreferenced+latest每個帳本 owner 的 runs/{runId}/ 整個目錄;一個成員被引用即保留整個 run
採用 HTML 包/原樣張來源all/with-source原生包與來源契約;不得為降低 run 數更改接受包指紋
PDF/還原展示副本regenerate既有 report 展示生命週期;進行中 URL 及來源 bytes 均須保留

registry 只提供類型、位置及政策,不解讀原生驗收語意。UAT 與 report 各提供唯讀引用匯出函式;docs.py 統一做閉包、彙整及位置/Git 狀態呈現,不另寫第二套驗收 verifier。不得執行下游或來源分支提供的 Python 程式來信任其 keep 清單;使用本次已核對的 canonical helpers,registry/inventory 屬資料輸入。

3.1 原生匯出契約​

建議兩個 helper 各新增純讀取的 retention-inventory 入口,共用輸出 schema 1:owner、roots、edges、units、latestUnits、pins、issues、complete。每筆 root/edge 帶來源路徑、JSON pointer/欄位或原生原因;路徑相對 workspace,digest 表示完整原檔或快照 SHA-256,不能混成 Git blob SHA。

  • UAT 接受既有來源 schema 5/6、結果 schema 1/3/5/6 與已支援的 origin/equivalence 格式,復用既有結構驗證及原生路由。不是藉 inventory 自動升級任何資料。
  • report 接受 PDF schema 1/2、HTML schema 1、既有還原確認 schema 1 及 evidence-location 描述;不自動下載外部資料。取不回者回 unavailable,不當成不存在或可刪。
  • 來源內容 stale、已撤銷或測試失敗,仍可提供有效結構的保留邊;原生 verifier 結論另列,不將舊接受變成 fresh,也不以 stale 省略歷史引用。
  • 未支援 schema/事件、同身分多候選、畸形檔名、循環的非法原生結構、越界、symlink、無法讀取或未知位置都使對應 owner 的 complete=false。共享快照池有任何無法排除的未知 owner,即整池不得產生完整性成立的「無引用」結果;仍可列已證實的局部 keep,並依 §8 交付本次有效成果。
  • 匯出不可呼叫 initialize/stamp/record、寫快照、建目錄、修復路徑、append event 或持久化 cache。所有入口皆 readOnly=true、writes=0。

4. UAT 引用閉包​

4.1 根與跨檔相依​

完整列舉已定位 docs 模組中的指南 sidecar、所有模組專屬結果、equivalence(含 archive)、origins/mapping,以及 work request/progress/receipt/evidence 閉包。包含工作樹中未提交的有效資料。直接路徑與 legacy/project locate 仍依 P2-4 查詢契約,不能回退到單一 US 的預設檔案。

原生 exporter 須明列下列引用:目前 fragments;歷史 entries 的 semantic/context bindings、review bindings、convertedFrom、原始結果與 sidecar 指紋、匯入 used snapshot/mapping/receipt;以及這些指紋取回的舊 sidecar 內的下一層來源。不是只搜尋 digest 這個 key。

已登記其他類型的文件及工作交換若直接連結快照或 run,須作額外 pin;對已存在快照的完整 SHA-256 字串可作保守保留訊號,但不能用字串搜尋取代原生 exporter,也不能把未命中宣稱為完整無引用。專案型別可透過明示 --pin 補充來源,無法判讀的相關來源揭露為 incomplete,不能靜默忽略。

schema 3 source-correspondence 另包含同 US 的 docs 來源/複製指南及 historicalGuide Git proof;全部新增 commit/tree/blob 共用原預算並由 uat-equivalence owner 重驗與保留,未知 schema 保持 unsupported/完整保全。

4.2 演算法​

  1. 先凍結 workspace/docs inventory、registry 及工具身分,完整列舉 roots 與候選快照;共用池只建立一次索引。
  2. 由 roots 展開原生 edges;被取回的 JSON 快照依原生角色繼續展開。合法的內容圖重複拜訪以 (path, digest, role) 去重,不以任意深度截斷當成成功。
  3. 同一 SHA 被任一 US/stage/module/歷史事件/work pin 引用即 keep;撤銷、被取代或目前不通過的紀錄也不自動解除 pin。
  4. 有引用但快照缺失或摘要不符:列出原生取回結果與缺口。原生能以目前同 bytes 或 Git blob 取回,不代表可以把仍被引用的既有快照列為可清理;不把 fallback 可用等同清理授權。
  5. 完整性成立且閉包外者只列 unreferenced(在本次已知根下未引用),不刪除。共享池 incomplete 時列 blocked,不得用局部結果冒稱完整的保留/無引用清單。已證實引用的局部 keep 可列出,但須帶 complete=false 與缺口;本次有效成果依 §8 的原生契約精確提交,不等待歷史共享池修復。

uat-origin、equivalence、archive 仍 all;本期不重判為 referenced。不重造免重驗決定、不移除撤銷或 pending repair,也不改變 /progress 的閘門。

5. Report run 與 latest​

以實際帳本路徑的 parent 為 owner;同一 RPT 的自訂位置由 P2-4 原生路由定位。三層集合:

  • 根:全部 PDF/HTML 帳本及其 history、acceptanceHistory、還原確認與歷史、來源/結果附件、work/文件 pin。
  • 引用:pdfs、junit、sources 中指向 run 的成員、接受收據的 PDF、carriedFrom.pdf/recordedAt 所指原紀錄與舊 PDF、嵌入 HTML 接受快照的相依。保留整個 run 的所有成員,不只帳本列出的 PDF。
  • latest:每個 owner 最新一次成功完成 record 的頂層紀錄所指 run 單位;即使尚未取得人的接受亦保留。頂層可能指多個 run,全部保留。recordedAt 只核對原生紀錄及歷史次序,不從目錄名、mtime、Git commit 日期或字典排序猜最新。

最後的 keep 是歷史引用、目前引用、latest 與額外 pins 的聯集。多 owner 不互相競爭 latest;若同 RPT 有歧義帳本或無法判讀頂層,保守 blocked,不任選一份。

從未 record 的 run(含失敗、中斷、只有部分成員)、未列入原生契約的 metadata/附加檔、未知 owner,均列 unmanaged/blocked,不推定較舊便可刪。blocked 限制完整 retention 判定,不阻擋同 owner 或同專案本次原生驗證有效的帳本、run 與快照交付(§8)。既有格式沒有可靠完整 run 名冊,因此本期不假裝能為每個未登錄 run 選 latest;先保存完整失敗證據,另由原流程或明確人工處置。被引用的 run 所含額外檔仍整包保留。

既有 ledger 保留所有 history,可能使大部分已登錄 run 都需要保留。接受此結果,不為達到估算的節省量縮減歷史。已追蹤的無引用檔列為 trackedUnreferenced,不自動從 HEAD 刪除;刪除目前檔案不會縮小既有 Git 物件。

6. 原樣張與 D2 修訂​

採用Git 共享為預設,保留既有來源契約明示不能提交之原件/證據包的窄例外。不把「全部素材可供團隊存取」重新解讀成每份原件必須能進 Git;也不新增讀者、存取控制、公開性或部署批准關卡。

項目保存契約
可提交的原件/還原來源依既有來源位置明確追蹤,於 docs 模組內保存;原定位置已在 docs 內時不重複製造第二份權威
既有契約明示不能提交的原件/證據包維持原定 controlledRoot/evidence-location;Git 保存位置基準、來源版次、相對檔案清單、完整 SHA-256、取回說明及確認附件,不保存憑證
網站入口同一內部專案文檔站提供本輪完整固定副本及對照,維持原樣張→還原→採用→PDF 三個不同確認命題;不另建第二網站
ignored 展示副本report-restoration/report-preview 仍 derived/regenerate,不能成為唯一原件;來源不可取得或 hash 不符時揭露不可重建,不得宣稱安全清理
原生能力缺口不藉 metadata 宣稱 helper 已支援外部/ignored 採用 HTML 包;FU-126/FU-134 仍獨立

本次通過設計已由 D2 增補上述窄例外,ADR-020 補上現行保存契約與交叉引用;舊受控獨立網站等段落保留為歷史,2026-10-10 的本站入口要求繼續有效。採用例外不自動搬移或下載既有原件,不把原圖、字型或 PDF 重新產製成「相同來源」。

原樣張來源尚無明確共用分類者,實作時新增 report-source:慣用位置 {docsRoot}/sources/reports/{report}/{sourceId}/**,registry paths 使用 {docsRoot}/sources/reports/**,category=source、role=data、authority=source、lifecycle=persistent、retention=all、presentation=hidden、distribution=workspace、git=tracked、downstream=exclude(不帶入 scaffold),由 /report 保存可提交原件/還原來源及 metadata。來源不放入 Docusaurus docs 編譯樹或採用 HTML 包;人類從既有還原對照的逐檔固定副本讀取,完整 bytes/SHA 核對與同站入口照原契約,不把 hidden 當免除展示。以來源附件維持原始版次與 bytes,搬入新位置視為明確遷移,不自動改寫舊指紋;既有來源不因新型別自動搬移。不能提交的 bytes 仍留於例外儲存,這個類型只保存其 locator/摘要,不將 URL 當已驗證取回。

以上設計已通過;本期實作將 canonical 與參考實作投影增為 89 類,report-source 已接入分類,實作仍須另輪審閱。report-source 不新增檔案生成範本,成員/sourceId 由原樣張契約與 /report 決定,不把 locator 當網路下載命令。

7. 共用唯讀介面與 audit​

本期實作提供下列唯讀介面(實作另輪審閱):

docs.py retention --workspace {workspaceRoot} [--docs-module {moduleKey}]
[--type uat-snapshot|report-evidence] [--pin {workspaceRelativeFile} ...]
[--format json|md] [--fail-on none|error|warning]
  • 不給 type 就查兩類;未知類型/不安全路徑 exit 2。--pin 只加保留根,不排除引用、不縮小政策;明確檔案不存在或無法判讀即 incomplete,不能默默忽略。無候選、無根是有效空集合,不能藉此建空目錄。
  • 輸出沿 docs.py envelope:schemaVersion=1、readOnly=true、writes=0,另含 contextToken、owners、roots、keep、unreferenced、unmanaged、blocked、issues、bytes、inputs。清單逐檔或逐 run 完整輸出,不用 audit 的 20 路徑展示截斷作提交清單。
  • 每筆都含 owner/unit/相對路徑/bytes/SHA(缺檔另列)、Git tracked/staged/untracked/ignored 狀態、保留原因與引用來源。bytes 是工作樹完整檔案大小,不是 Git 物件大小或可回收量。
  • contextToken 綁定完整來源集合及 bytes、候選集合/檔名/bytes、project.json、兩層 registry、canonical exporter/閉包工具、Git HEAD 與 index 身分;結束前重讀核對。任何新增、刪除、移位、摘要或位置改變使計畫失效,寫入後不得沿用舊清單。
  • Git index 與工作樹相關資料不同時,回 RT-INDEX-DIVERGED 及 blocked,不提供聲稱完整且適用於該 index 的保留清單,不讓已還原工作樹遮蔽 staged 引用。這包含尚未同步到 index 的本次新檔/修改:不得要求先 stage 才准產生本次成果;原生操作仍依 §8 辦理。無 Git 環境可唯讀列舉,但不宣稱可對某個 index 作完整判定。
  • 同一交易內凍結原生 roots/候選集合與 index;UAT exporter 對已存在的 uat-results 目錄取得協作鎖,使用不 mkdir 的唯讀分支。缺目錄且無候選是空集合;有相關資料卻無法取得所需鎖時 blocked。所有 stamp/snapshot/帳本 writers 須納入同一協作鎖,不宣稱只鎖讀者就能排除未協作 writer。report 本期為 owner 目錄補同一把原生讀/寫協作鎖(唯讀不建目錄),涵蓋 record/accept/carry 與 exporter;多 owner 按正規化路徑排序取鎖,避免死鎖。鎖不可取得、檔案集合、index 或 root bytes 改變時,整個受影響池 blocked;完成前重驗全部輸入,不能以兩次局部清單相同冒充完整交易鎖。
  • 不 stage/unstage、不寫 .gitignore、不回復或刪檔,不新增 apply/force。無引用檔如何另行清理須由人明確指示;查詢結果本身不等於刪除授權。

7.1 audit 及失敗分流​

代碼等級行為
RT-UNSUPPORTED/RT-INCOMPLETEwarning根格式/事件/位置無法完整判讀;blocked,不給完整 retention 清單,仍保留 §8 的本次交付出口
RT-REFERENCE-MISSING/RT-DIGEST-MISMATCHerror必需 bytes 無法依原生規則取得或摘要不符;只揭露原生缺口,不改驗收狀態
RT-UNREFERENCEDinfo完整閉包外候選;可供提交前檢視,不能自行刪除
RT-UNMANAGEDwarning未登錄/未知 owner run 或原件;保守保留待處置
RT-INDEX-DIVERGED/RT-CONTEXT-CHANGEDwarning不提供適用該 context/index 的完整 retention 清單;依 §8 保留本次成果,完成 stage 後可重新查詢

docs.py audit 引用同一計算器,不另估一套 retention;輸出保留 status 與問題來源。--fail-on 依現有規則回 exit 1,不將 warning 假裝成成功候選;registry/使用方式錯誤仍 exit 2。retention 的 blocked、不完整輸出或查詢 exit code 均不自動作為 /uat、/report、commit/work 交付的新閘門;不能直接把查詢命令以 && 串成必須通過才交付的步驟。若專案另有已明示的 CI audit 政策,依該政策處理並揭露,不能冒稱是本期新增的預設要求。這不把 audit 變成新的 UAT 撤銷器,也不改原生接受收據。

8. 提交前接線與既有資料​

retention 是保留/提交範圍的參考,並非提交、進度或交付閘門。 /uat、/report 現行不自行 commit,本期不新增自動 stage/commit,也不要求完整 retention 查詢成功後才能保存或交付成果。查詢完整時,以 keep 原因輔助核對;incomplete/blocked 時,不刪除或排除未知資料,也不要求先修完整個歷史池。

8.1 本次成果的精確保存與交付​

不論 retention 是否 complete,本次原生操作須依既有契約明列實際產生/修改且已核對的帳本/sidecar/事件、其引用的 run 整包及必要來源快照。快照以本次帳本及來源指紋綁定的 SHA/完整 bytes 核對;run 以本次原生輸出、帳本引用及成員清單核對,不能從 blocked 的全域推測清單猜取。all 類帳本/原文/歷史仍完整保存,必要相依不因 retention 未列入而省略。

使用者另行要求 commit 或既有 work 流程已授權提交時,由操作者精確 stage 上述本次路徑並檢查實際 index;不用 git add 整個 snapshots/runs,也不修改其他人的 staged 項目。只有本次新增或修改的相依需納入當次差異;已追蹤且未變的必要檔繼續保留。既有 work 分派、進度保護、delivery commit、peer-review 及人工驗收閘門均照原流程,retention 不授權繞過。

8.2 blocked 的出口​

retention 狀態/本次成果原流程處置
全域 complete,本次原生契約有效使用本次明確路徑+keep 原因核對;有原授權時正常提交
舊 UAT schema/未知 owner/舊失敗或中斷 run 使池 blocked,本次原生契約有效保存全部既有資料,精確提交本次帳本、其引用的 run 與必要新快照;在本次操作結果或提交說明列出 RT 問題及待處置範圍,不等待全池修復、不強迫另開待辦作交付前置
本次正常新增/修改使 index 與工作樹不同,或其他 staged root 引起 RT-INDEX-DIVERGEDretention 不提供適用該 index 的完整判定;有原授權時只核對/stage 本次明確成果,保留其他 staged 項目;stage 完可重查,仍 blocked 亦不阻斷既有交付流程
本次缺少必要 bytes、摘要不符、原生 verifier/人工接受或原交付閘門未通過依原生契約修復或停止其原本不允許的推進;不能用 retention 的參考定位豁免既有驗證,不能宣稱 passed/accepted

局部 keep 須明標 complete=false,不可假稱完整清單或可清除集合。查詢問題保留原 code/來源與影響範圍,不為通過提交而改輸出、藏 warning、裁切 history 或強制轉換舊 schema;後續修復或另開 follow-up 依既有授權辦理。有人明確要求額外保留已知無引用資料時,將用途/pin 記入持久來源後再查,不手改查詢結果。

retention 不決定是否可提交敏感原件,沿已存在來源契約處理;不新增讀者核對。引用到的工作證據是保留根,不把本命令當自動 submit。原生接受、批准、生命週期與有效階段不變。

既有 tracked 檔案不批次刪除,snapshots、runs、result/sidecar、HTML/PDF/restoration 帳本不改 schema 或 digest。unsupported 歷史資料先揭露,不能為得到 complete 強制轉換、丟 history 或重新要求真人驗收。有效原件及證據不因本期方法論更新失去接受。

9. 實作檔案與驗收​

範圍預期變更
docs-siteretention 共用計算器與 CLI、audit、輸出契約與測試;新增 report-source 共用型別
UAT 原生純讀取引用匯出,完整 schema/歷史/快照遞迴、鎖與跨模組池;保留現有 CLI
report 原生帳本/歷史/承接/整 run/latest 匯出及所有原生 writer 的 owner 交易鎖;缺原件與 unsupported 的明確出口
文字接線uat/report/docs-site skills、doc-locations、m-peer-review/m-work 中相關提交引用及必要共用 rule;明示 retention 為參考與 blocked 的本次成果交付出口,不新增 commit/進度/交付關卡或改 work 交付提交模型
持久文件ADR-023 D2 窄例外、ADR-020 現行保存補充、報表指南及範本、FU-142、本站導覽/索引
投影/adapter參考實作以 docs-site plan/apply 投影;canonical adapter audit/sync/validate;全部 P2 通過前不下行

驗收至少涵蓋:

  1. UAT 同 SHA 跨 US/stage/module 共用、僅歷史事件引用、convertedFrom 舊 sidecar 再引用的多層快照、origin/equivalence/archive/work pin、循環去重、schema 1/3/5/6、畸形/未知事件拒絕、不改任何 ledger bytes。
  2. report schema 1/2、HTML 歷史及嵌入接受快照、carriedFrom 舊 PDF、acceptanceHistory、整 run 額外成員保留、多 owner 不混 latest、頂層多 run、未知/失敗/中斷 run 保守 blocked、不按 mtime/目錄排序選最新;existing native status/carry-acceptance 結果保持。
  3. Git staged roots 與工作樹不同(含工作樹已還原)、根刪除/新增/改名、symlink/越界/缺投影、查詢中 root/候選集合變動、鎖競爭、無 Git 不宣稱對 index 的完整判定;所有命令零寫入、零 stage。
  4. 原件可提交/既有契約不能提交、locator 不含憑證、不可取得及摘要錯誤、ignored 展示副本缺來源不可重建、採用包外保存、既有三個真人確認不變。不得宣稱 FU-126/FU-134 已完成。
  5. 提交出口 fixtures:舊版 UAT 使共享池 blocked、歷史失敗/中斷 run、未知 owner、正常新檔尚未 stage、staged root 與工作樹不同等情境,均不得因 retention 結果阻擋本次有效成果依原授權精確 stage/提交;本次必要相依完整保留、未知歷史不刪、RT 問題揭露、其他 staged 項目不受改動。反例驗證本次原生 bytes/摘要/既有閘門不合格仍不得宣稱通過;不能把參考定位變成 verifier 豁免。
  6. schema 3 us-rest 的 docs inventories/指南/US/引用集合及 scope 原件重算、缺錨點/跨 US/降讀拒收、去除 framework binding 的正常 stamp/retain-context 全出口、schema 1/2 回歸與原子發布。
  7. 全套 UAT/report/docs-site 回歸;新增 retention fixtures、九 workspace 唯讀影響盤點、候選 bytes 與原始來源 SHA;docs-only 建置、索引/實際頁面與必要附件核對。

10. 採納決策​

  • 保留判定以目前及完整歷史閉包為根,即使因此大部分已登錄 run 無法減少;不以儲存節省目標裁切接受來源。
  • 本期提供確定性唯讀判定與提交前參考接線,不新增提交/交付閘門;blocked 時依 §8 精確保存及交付本次有效成果。不新增自動刪除/apply,未知 run 不冒充可清理。
  • 證據維持原位;ADR-023 D2 對已有「不能提交」來源契約採窄例外,維持 ADR-020 最新本站入口及三關確認。
  • report-source 為可提交原件/locator 的持久類型,89 類的變更只在設計通過後實作。

第 1 輪審閱方明示上述四項命題全部採用;第 2 輪已確認 R1-01 的提交參考與 blocked 出口修訂,整體設計通過。

設計通過並完成結案後才開始實作,實作另送審。ADR-023 維持 Proposed,P3 與各獨立 backlog 不因本稿而完成;沒有清理、下行或部署。

11. 設計審閱結論(2026-10-20)​

P2-6 設計通過第 2 輪審閱,受審 revision r2-87cfce29bd2c9c8c,審閱者 ada@leandev.io。1 項 major、1 項 minor 均已處置,無 open/declined。

  • R1-01:retention 為提交參考;完整歷史引用不因本次有效成果交付而省略。共享池 blocked、未知舊 run 或 index 不一致時,依 §8 精確保存本次有效帳本、引用 run 整包與必要快照,揭露 RT 問題,不新增交付閘門;原生 verifier/人工接受/work 原有閘門仍照常。§9 已列對應正反例驗收。
  • R1-02:標的為 methodology;設計通過及結案後僅進入 P2-6 實作與另輪審閱,不解鎖產品 US 的 /impl//progress,也不立即下行。全部 P2 通過後才可統一 methodology publish。
  • 四項決策:完整歷史閉包、唯讀不刪除、證據原位與 D2 既有不能提交來源的窄例外、report-source 持久來源分類均採用。ADR-023 D2 與 ADR-020 保存說明承接決策;設計結案時 registry 為 88 類,89 類候選、CLI/exporter、原生協作鎖及提交出口 fixtures 當時待實作(本期進度見 §12),不宣稱已完成 retention 功能或清理。

既有九站盤點為描述資料,未直接命中的快照不是可刪清單;原生 schema、歷史接受及資料 bytes 保留。兩站 docs-only 建置、llms lint、7 個候選分類路徑與網站版本核對通過,只證明本次設計可檢視;完整原生回歸、零寫入/並行/index 對抗驗收仍在實作階段完成。FU-126/FU-134、FU-144 與 P3 各自待辦,ADR-023 維持 Proposed;本輪不 commit/push、部署或下行。

12. P2-6 實作對照與審閱結論(2026-10-20)​

P2-6 實作於 2026-10-20 通過第 2 輪審閱(受審 revision r2-19ace3c868307bfa,審閱者 ada@leandev.io)。R1-01/R1-02 兩項 major 與 R1-03 minor 已處置;R2-01 的既有帳本資料欠帳另記 FU-145,不在本輪改寫原生資料。

  • 共用 CLI/audit 使用 docs-site/scripts/retention.py;UAT 與 report 由各自的 scripts/retention.py 提供 schema 1 原生 roots/edges/units/latestUnits/issues 匯出,兩個 evidence.py 的 retention-inventory 入口共用同一唯讀交易。只載入 canonical 工具,不執行目標 workspace 的 helper。
  • UAT 沿全部歷史事件、bindings/contextDigests、convertedFrom 舊 sidecar 遞迴展開;完整 SHA 及工作文件直接引用只加 pin。型別篩選不能隱藏跨原生引用;額外 JSON pin 沒有已驗證的原生角色或無法判讀時列 incomplete,不以局部搜尋冒充完整閉包。schema 不明、原生取回缺口與未知 owner 揭露,不能從部分 keep 推論可清理。非必要舊指南區塊指紋無法取回時列 incomplete,不將其冒充產品驗收撤銷。
  • report 維持完整 history/接受來源,引用任一成員即保留整個 run;latest 取頂層 record 所指全部 run,不依目錄名或 mtime。未登錄 run 即使另有 pin 仍列 unmanaged/blocked。原件/locator 不自動下載,無法核對受控來源或只剩展示副本時列 incomplete。
  • 交易鎖為既有 UAT 目錄及排序後的 report owner 目錄;唯讀不建鎖檔或空目錄。來源/候選 membership、設定/工具雜湊、HEAD/實際 index 及 staged bytes 均綁定 contextToken,完成前重驗。原生 writer 共同使用該鎖。
  • 新型別 report-source 為 persistent/all/hidden/workspace/tracked/downstream exclude,無生成 template;只在參考實作以 plan/apply 投影。scaffold-module/scaffold-template 在複製前依分類把原件與 locator 加入精確排除,來源不改寫;native equivalence 與 PDF 接受結構沿原生 validator,展平 history 的承接仍查回完整原始紀錄。skills 與共用契約明列 §8 的精確交付出口,不新增 stage/commit 或修改原 verifier/接受收據。

本輪審閱處置:

  1. R1-01:型別篩選與 JSON 根辨識。額外原生 JSON 根啟發式限於未分類或原生快照位置;另一池的已分類根只辨識角色,不展開其閉包或混入候選。design-language manifest(含明示 pin)不再誤擋,跨型別 pin 及未知 JSON 的保守案例保留;實際報表型別篩選 complete。
  2. R1-02:歷史 sidecar 閉包。schema 6 帳本依原生路由解析 sidecar;未記 targetModule 的舊帳本沿原生唯一指南規則定位,歧義維持 blocked。回取佇列保留 originalPath,能沿 Git 歷史遞迴取回多層 sidecar 與葉來源;已自含完整快照時不新增現行指南前置。實際資料已取回並展開 3 份舊 sidecar。
  3. R1-03:協作鎖排序。report writer 的 decorator/CLI 與 retention 查詢統一按解析後路徑字串排序;以標點目錄 fixture 核對實際取鎖順序。
  4. R2-01:既有移植資料欠帳。參考實作 51 份 schema 6 帳本中,47 份 resultPath 仍指向來源專案。另由 FU-145 承接原生 repair-result-path、verifier 與 retention 核對;本輪保留原帳本、歷史接受與相關快照,不以直接改 JSON、補 digest 或刪除資料消除 blocked。

作者本輪重跑 retention 42、report 34、docs-site Python 191+Node 27,共 294 案;審閱者另確認 retention 42、report 34、UAT 346 案通過。兩站 docs-only、llms lint/finalize 與網站核對通過;app 首次因持久正文含暫時審閱代號而被 finalize 拒絕,改為正式規格引用後重建通過。九站唯讀盤點期間原生資料、投影、index、HEAD 未變;5 站 complete、4 站因歷史缺口或 index 差異 blocked,未列可刪容量。原生路由矛盾與 unknown schema 仍揭露,錯誤數下降不代表舊資料已修復。

P2-1~P2-6 設計與實作均已通過;方法論下行仍須另行授權及依發布流程執行。ADR-023 維持 Proposed,P3 待完成;FU-126/FU-134、FU-143/FU-144/FU-145 各自承接既有欠帳。本輪不改寫原生 schema/接受紀錄,不清理資料、部署或下行;完整含 server 同步 build 未重跑。

FU-145:純位置維護與驗收新鮮度分離(2026-10-21)​

使用者採用純位置維護方案 A。UAT 6.13.0 的 repair-result-path 不再以來源 fresh 為位置更正前置,仍要求唯一且身分正確的現存指南、登錄且符合 stage 的 target、安全路徑、既有 surface 綁定與合法 schema/序列。操作持帳本目錄鎖,以讀取前 SHA 核對並行變動,明示舊路徑、操作者與原因;只更正 resultPath、追加帶前後位置與原帳本摘要的 result-relocation、推進 nextSequence。原事件、未知欄位、來源綁定及快照不變,不補造舊帳本缺少的 surface 綁定;重跑為 no-op。

此例外僅限帳本目前存放位置。新的通過、來源保留處置及整合閘門沿用原生要求;位置事件不把 stale/pending/failed/revoked 轉為驗收有效,也不補出缺失來源。retention 已識別此事件,修復前帳本 SHA 為操作溯源,不自動成為新的原文快照需求。未 stage 的位置更正仍須揭露 RT-INDEX-DIVERGED,不能提前提交或隱藏它來宣稱完整。

參考實作 FU-145 已透過公開 native CLI 修復 47 份 resultPath,各追加一次位置事件並重跑確認 no-op;原 920 筆事件與全部 1,962 份快照保留,其他 2,093 份原生檔案 bytes 未變。355 項 UAT 與 43 項 retention 回歸通過。修復後 201 次原生命令仍揭露舊來源不存在,路由由 ledger 不符改為 sidecar 不符;48 份 stage-status 仍 pending。retention 的 keep 1649/edges 2042 未增減,既有 98 INCOMPLETE、51 UNSUPPORTED、5 REFERENCE-MISSING 仍在,另有一項 index 警告涵蓋 47 帳本及 3 份本次文件。此實作於 2026-10-21 通過第 1 輪審閱(ada@leandev.io 核准 r1-d3f8b9a3bef96245,無意見),使用者確認結論落點後已結案;FU-145 保留歷史來源承接的後續欠帳,不能宣稱閉包已完整展開;未提前 stage/提交、修改原接受或下行。

FU-145:已複製前端的來源路由維護(2026-10-21)​

UAT 6.14.0 新增 repair-source-route:限定 schema 6 P.UAT、來源與目前 inventory 都為 web-mockup,固定來源指南/sidecar 與可達 copy commit 證明複製關係;未移植 Server、現存另一模組、孤兒、歧義及原件不符均拒絕。預設 plan 唯讀,write 明示 token 並持原生帳本目錄鎖重算;token 綁指南、sidecar、帳本、原件、inventory、registry、工具與 Git 狀態。只替換 sidecar 外層 targetModule,保留 source、guideSha256、generator、stage、指南與原接受,不能自動 stamp 或推導語意 keep。

交易先以原生內容定址快照保存前/後 sidecar、吻合舊摘要的完整指南、目前指南與準備前帳本,再以同一 operationId 追加 guide-source-relocation prepared、替換 sidecar、追加 completed。帳本只增 entries/nextSequence。首次 write 保持全工作區 token 查核;prepared 後以 --operation-id 核對收據、快照及目前帳本/sidecar bytes 的 CAS 恢復或中止,不再依賴來源 workspace、HEAD、無關 diff 或目前 runtime 摘要。resume 要求目前指南 bytes 未變;abort 可在指南正文變動後核對原件、回復 sidecar 並追加 aborted。不刪舊紀錄、不覆寫並行修改。每個檔案的原子寫入不構成跨檔原子交易。

新計畫 schema 2 不自動保存本機絕對路徑:來源以 Git 根提交及 workspace 前綴導出的 sourceRepositoryId 與固定 commit 識別;registry、工具及原生位置使用相對識別。schema 1 舊收據仍可讀取與恢復;schema 2 帶 sourceWorkspace 或絕對工具/registry 識別時拒絕。此可攜契約不改原有 append-only 原則。

validator/reader/writer/stamp 對未完成交易 fail closed。retention 識別新事件、展開收據內 before/after 的原件快照與其傳遞來源;pending 仍保全原件並回報 RT-INCOMPLETE,畸形交易為 RT-UNSUPPORTED。舊 exporter 維持未知事件 unsupported;混用工具不作安全保證。操作不新增一般掃描根外取回能力、不擴張 report、不改 stage gate。路由修復後 freshness、接受與 retention complete 仍各自核對;未 stage 的差異照常揭露,不以提前提交來消除警告。

來源路由工具與 US-003 P.UAT 單筆試點於 2026-10-21 通過第 2 輪實作審閱(ada@leandev.io 核准 r2-fe7afe7b5f33fc23),使用者確認四項結論落點後已結案。R1-01 交易自身 CAS、R1-02 可攜收據與經核准的未提交試點重做、R1-03 兩階段合併提交安排均已核實;382 項 UAT、44 項 retention、兩站 docs-only 建置及 adapter 驗證通過。原 11 事件、1,962 舊快照與五份試點原件保留,路由 resolved 仍不改指南 stale/stage pending;retention keep 1658/edges 2431,歷史缺件與 unsupported 仍由 FU-145 承接。本輪未正常重生指南、stamp、寫入新的接受或語意處置、清理、下行、commit/push。

FU-145:受限 context 來源對應(UAT 6.15.0,2026-10-22)​

UAT 6.15.0 的 reconcile-context-sources 沿既有 uat-equivalence 型別擴充 schema 2、 source-correspondence transform,不新增帳本 mapping 事件或第二套對應來源。 通用請求明列已完成來源路由的 operationId 與逐 key 綁定;實際資料範圍另行明示確認。 完整 surface 包含 US、stage、target、guide/result 路徑與後綴、routeOperationId; 只有 context tier、同 kind/selector 及接受時摘要相符的來源可取得路徑對應。 semantic 與 context 綁定使用分開的換算回呼;沒有完整片段身分的 file/text 查詢只保有 原 reference-rewrite 能力,新紀錄不得進入 blob trace/text_history 或把變內容判為等價。

可攜見證保存指定 source/copy commit 的 sidecar、inventory 與來源路徑證明, 以及匹配舊片段的必要祖先 parent 鏈。以內容定址快照保存 raw commit/tree/blob, 載入時重算物件 id、SHA-256、tree mode/路徑、parent 關係與原生片段摘要; publication 的檔案、指南與 inventory 綁定工作樹或引入紀錄的 commit。 不依賴外部 clone,不執行來源 helper 或自動 fetch。

見證只保留所需物件,64 commit/256 物件、單物件 1 MiB、整組 raw 8 MiB、 紀錄及快照序列化聯集 12 MiB、路徑 32 元件為硬上限,超限即 blocked。 必要原始 tree 會帶入同層名稱/mode/id,commit 會帶入作者資訊、提交訊息及可能簽章; 須先確認本次資訊取捨,plan 再列出精確物件與原文清單,不能遮蔽後假稱符合原 Git id。 完整請求、欄位及上限契約由 .claude/skills/uat/references/context-source-correspondence.md 維護。

write 持原生鎖重算 token,先完整保存並驗見證,最後原子發布不可變紀錄。 發布前中斷保留鬆散原件,原 gate 不變,重跑重新查核後補發;不新增 prepared 帳本交易。 retention 在既有 uat-equivalence owner 驗證 schema 2,保留直接證明與全部 Git 物件快照; 舊 exporter 對新 schema 維持 unsupported 並保全未知閉包,不降讀成 reference-rewrite。 仍須正常 stamp/retain-context 及 verifier/stage gate,對應本身不代表驗收、整合或 retention complete;歷史欠帳與 index 差異繼續揭露。本小節記錄 UAT 6.15.0 的工具契約;真實資料維護範圍另以各次原生紀錄與維運文件為準。

同 US docs us-rest 的窄幅擴充(UAT 6.16.0)​

本組實作於 2026-10-23 通過審閱並結案(revision r2-93adc40be8b21f55);不代表已 fleet 發布。

schema 3 沿同一 owner/loader/reconciler,只增加同 US 的 docs 複製關係與引用集合證明。 docsProof 保存 source/copy 指南 Git 路徑;每個 us-rest binding 的 historicalGuide 與 historical US 同 commit,來源及歷史指南須吻合 before sidecar 的 guideSha256。 source/copy/publication inventories 各唯一 docs 關係、四組指南/US 的錨點及場景範圍皆重算, 引用必須非空且完全相同;用原生 text_without_sections 取得餘文,不能取整份 US 或取得 semantic 能力。 所有新增物件與直接快照都在 §4 閉包內、共用原物件與 byte 上限;未知 schema 必須 unsupported 並保全,不降讀或因局部工具成功宣稱全池 complete。

schema 1/2 與 exact beforeDigest 核心規則保持;不新增歷史多摘要/basis sequence grant, 不改 alias 分支。有效 framework 基準等於目前內容時可省略該 binding、沿原內容身分承接, context 基準保留接受時/完整處置綁定的合法換算;未換算 key 先摺疊既有保留,再換算最終摘要, 避免留下已被取代的舊 key。後續不同摘要不沿用先前 grant,新路徑的合法保留更新已換算基準; 仍須正常 stamp/retain-context 與 check-guide/verify-result/stage-status 全部出口。 本補充只記錄工具契約;原生資料範圍須另按已核准方案逐筆 plan,整組以 methodology 審閱, 通過結案才解鎖提交;不自動 fleet 發布,不改 ADR-019 D2/D3 或人工舉證責任。

宣告、有效基準與歷史原件(UAT 6.17.0,2026-10-23)​

本節為 UAT 6.17.0 的實作補充(2026-10-23);不追溯改寫 schema 2/3 的既有契約。 schema 4 的 basisLedger 是發布前完整原帳本 bytes,必須是當前帳本的 exact prefix; retention 沿原生 result owner 保留它及其中引用。 每個 binding 的四角色宣告原件、可證明的 registry 缺席及事件限定 basis 共用原 Git 物件閉包與上限; 原生擷取器重算 tier/kind/selector/scenarios,consumer 只授予該場景/形成事件身分的 context 路徑換算。 有效摘要不等於 beforeDigest 時,其 Git 歷史投影須另外證明;不是放寬 exact digest、一般 alias 或 semantic 能力。

來源搬移仍為 prepared 時拒絕原件回復,不追加收據或破壞其精確前綴恢復能力。 restore-evidence-snapshots 只接受原帳本及其來源 SHA 圖可達的原生 owner/JSON pointer。 producer 自行推導角色、原 SHA、key 與來源路徑,依序使用已存在原件、所選原生指南/sidecar、 原生 guide SHA 可達的保存指南、relocation 固定 copy commit,以及固定來源 Git 歷史。 全部只接受完全相同 bytes;使用 Git 時,指南與片段投影須為同一可達 commit。 所有原件、直接 snapshot 與 proof 聯集遵守原固定大小上限。 plan 列完整 references、objectDisclosure、proof、writeSet 與輸入 CAS;write 持原生鎖重算, 核對帳本、指南/sidecar、inventory/registry、runtime、HEAD/index、來源集合及既有 snapshot 狀態。 相同原件不覆寫,未知 bytes 拒收;全部已存在時零寫入且不依賴來源 checkout。 先寫易變原生輸入及 owner/ledger 前綴,再寫 proof、不可變物件及回復原件,最後追加 source-evidence-restoration 收據。

收據的 operationId、references、作者/理由須吻合其 proofSha256 所指 immutable proof。 restoration proof schema 2 保存 ledgerBefore、可達 ownerSnapshots、逐引用 origin、必要的固定 inventory/指南與 Git 原物件。 此 schema 與 source fingerprint/context correspondence 分開;source 標記使舊 reader 對未知 proof 保守拒絕。 retention 重驗收據、原帳本前綴及 portable witness,沿這些邊保存整組閉包,不以 output 或交換附件充當永久依據。 重複操作 no-op;proof 已落地但收據未追加時,自動尋找唯一匹配的 native proof,或明示其 SHA 重新 plan。 重驗已保存輸入;缺少不可變物件只按固定 OID 從原生池、本 checkout 或明示唯讀來源補讀,全部重驗後補收據。 尚無收據的 proof 也是原生保存根並明示 RT-INCOMPLETE;部分缺件、未知格式或中斷鬆散原件均保全,不刪歷史。 不支援的舊 reader 對未知事件/proof 明示 unsupported、保持未知閉包。 這是證據維護,既有接受、指南、sidecar、語意處置與進度均不變,來源 stale/pending-repair 不因原件回復而豁免。

原接受區塊補綁的保存(UAT 6.18.0,2026-10-23)​

upgrade-bindings --from-accepted-snapshots 只讀原帳本 binding.block 所指的 exact-SHA 原生快照; 缺少原件時先走既有 restore-evidence-snapshots,不以目前指南、一般文件或人工補寫取代。 真人確認的計畫綁完整 surface、sidecar、帳本、原事件/區塊、目前命題及 runtime,寫入仍只追加 binding-upgrade。 acceptedBlock 沿既有 text 引用邊保存;bindingSource/extraction/planToken 是補綁來源及確認紀錄,不是新的驗收通過或 semantic grant。

原接受事件與其來源基準照常保留,真正改變的命題、語意、撤銷與重驗仍由原生 verifier 判定。 舊明確「人工驗收」段落的命題對應須由人核對,不能把其他敘述升成命題;詳細契約見 ADR-019 的原接受區塊補充。 此模式不消除其他歷史缺件、不減少未知原件的保存義務,也不新增提交或進度閘門。

正常 stamp-guide 替換既有 sidecar 時,依 ADR-019「指紋 sidecar 替換前的保存」保存完整舊原件;既有帳本仍以 sourceFingerprintSha256 邊取回,不新增保存角色或人工接受事件。同名 exact-SHA 快照內容不符時停止替換。僅改說明或指紋版本亦須維持這項原件保存。