跳至主要内容

ADR-016: UAT 證據來源分層與變更後複核

ADR 編號: 016 狀態: 已採納 (Accepted) 提案日期: 2026-09-29 決策日期: 2026-09-29 最後修訂: 2026-09-29 決策者: 團隊 peer review:設計方向三輪通過;P0、P1、P2 各三輪、P3 兩輪成果審閱通過 範圍: /uat-script 來源指紋、/uat 驗收結果、/progress//work 的 UAT 證據閘門、變更管理

摘要​

UAT 指南的來源指紋目前對生成時讀過的每個檔案做整檔 SHA-256,任一 byte 改變就判定指南過期,並連帶讓已通過的人工驗收失效。框架升級、樣式調整或實作重構因此大量觸發重生與重驗,使用者習慣直接重蓋,真正需要重看的指南反而被淹沒。

本提案把一個指紋拆回兩個問題:「指南內容是否仍正確」與「先前的人工通過是否仍成立」。來源分為語意、脈絡與不列入三層;語意來源改變才判定 stale,脈絡來源改變則由真人複核,結論可以是保留、只重驗受影響場景,或回到重生。驗收結果改為逐場景綁定,讓規格的局部修改只作廢對應場景。

審閱結論​

2026-09-29 經三輪 peer review 通過設計方向。兩輪共 8 條意見(6 major、2 minor)皆已修訂處置,無不採納項目;各輪修訂內容見「變更歷史」。審閱者明示確認四個待決點皆採作者建議,裁決見「審閱裁決」節。

通過範圍僅限本 ADR 與文件站索引。 本次通過不解鎖任何規則、skill 或工具的修改:P0–P3 各階段實作須另行送審;m-change-management.md 等現行規則在對應階段實作通過前維持原狀,ADR 狀態維持 Proposed,P3 成果審閱通過後才改為 Accepted。

採納(2026-09-29):P0–P3 成果審閱全部通過,狀態改為 Accepted。設計方向在實作中的修訂分別記於「P1 實作裁決」「P2 實作裁決」「P3 實作裁決」與「相容與遷移」;其中最大的偏離是不提供 migrate(依 florae-g1 模擬數據,見「相容與遷移」)。

背景​

現行機制​

/uat-script 以 .claude/skills/uat/scripts/evidence.py stamp-guide 建立 schema 5 sidecar,自動納入 US、完整 SBE 集合、design language 與 test-data-seed.md,並依 skill 指示以 --extra-input 納入 E2E Coverage/spec、環境來源檔及生成時讀取的其他權威來源(uat-script/SKILL.md Step「穩定場景 ID 與來源指紋」)。

機制位置行為
新鮮度比對check_guide整份 manifest 相等才算 fresh;錯誤訊息只有 guide sources changed,不指出哪個來源改變
結果綁定verify_result結果綁定整份指南 guideSha256 與 sidecar sourceFingerprintSha256;重新 stamp 即使內容不變,也使人工通過失效
共用單檔current_source_manifesttest-data-seed.md 與每個 mockup 的 m-design-language.md 各為單一檔案,任一 US 的修改讓所有引用它的指南過期

下游實測證據​

下游專案 florae-g1 回報(2026-09):

  • 41 份 P.UAT 指南中只有 1 份 fresh。
  • 40 份過期指南中,31 份的 US 與 SBE 都沒有變更。
  • 過期原因次數:實作檔 193、環境檔(package.json、vite.config、lock)70、E2E spec 61、設計語言 31、測試資料 26、翻譯 14。
  • 一次頁級按鈕樣式調整讓 24 份指南需要重生,其中 21 份內容完全沒變,只是重蓋指紋。

最大一桶(實作檔)來自 generator 政策:skill 要求「生成時另讀原始碼也逐檔附加 --extra-input」,不是工具本身強制。

「回退」實際發生在哪裡​

指南過期不會自動改寫共享 Sprint 階段,影響出現在下一次需要 UAT 證據時:

位置行為
共享 /progress只在推進到某個 *.UAT 時呼叫 verify-result;已通過該階段的 US 不會被拉回
/work 分支進度每次重驗連續證據鏈;任一 UAT stale,有效階段退回最後有效的一步
/work merge 整合重驗UAT stale 則維持 pending,須 /uat-script → /uat 重做才能推送
推進到 ✅須重驗該軌道最後一次 UAT

所以重做 UAT 的成本集中在合併與完成節點,並會一次爆發。

根因​

同一個指紋同時回答兩個問題:

  1. 這份指南的內容還正確嗎?(文件問題)
  2. 先前的人工通過還適用於目前的產品嗎?(產品問題)

非規格變更通常不影響第一題,但可能影響第二題。UAT 只驗 E2E 證明不了的命題(操作手感、視覺辨識、真實外部依賴、非功能感受),而這些正是框架升級容易悄悄改變的地方。因此「指南仍適用」不等於「先前通過仍成立」;兩題需要不同的來源與不同的處置,不能用同一個整檔指紋判定。

決策​

D1:兩個問題分開判定​

問題依據不成立時
指南內容是否仍正確語意來源stale:重生指南,受影響場景重驗
先前通過是否仍成立脈絡來源 + 真人複核review-needed:由人依 D5 判斷

指南狀態從二元(fresh/stale)擴為三態:fresh、review-needed、stale。/uat 遇到 stale 阻擋;遇到 review-needed 先引導複核(D5),不直接要求重生。

D2:來源分三層​

層級來源變更時的效果
語意來源US 中被場景引用的段落;UAT-only 的 SBE;Coverage Header 解析結果(場景 → E2E/UAT-only/Deferred);指南使用的測試資料段落;環境啟動命令及其解析定義;宣告為命題依據的權威來源(例如作為命題依據的 BR 原文、框架文件)的宣告段落,未宣告段落時為整檔stale
脈絡來源有效 Design Language;US 中未被引用的段落;E2E/UI 合約 spec 本體;旅程涉及的頁面與元件;旅程宣告的翻譯 key 值(或 D6 旅程的翻譯檔 fallback);框架版本(取自依賴宣告中框架套件的版本值);宣告為參考脈絡的其他來源;無法機械抽取定義的環境來源檔review-needed
不列入lock 檔、建置設定全檔、未被任何旅程宣告的翻譯 key、與旅程無關的實作檔無

兩條適用於所有來源的原則:

  • 層級屬於片段,不屬於檔案。 同一個檔案可以同時提供多個片段、分屬不同層級,並分別比對。例如 package.json 中 scripts.{name} 的值是語意來源,框架套件的依賴版本是脈絡來源,其餘內容不列入;只升級框架、scripts 不變時,指南變成 review-needed,而不是因整檔被排除而漏掉。指南狀態取所有已變片段中最嚴的一個。
  • 權威來源依用途分類,不依檔案類型。 /uat-script 以 --extra-input 納入的每個來源,都必須宣告用途:直接決定指南命題或操作內容者為「命題依據」(語意來源),只提供背景者為「參考脈絡」(脈絡來源)。未宣告用途者視為命題依據。作為命題依據的 BR 原文沿用 ADR-014 的邊界,以 bytes 摘要其宣告段落,不以 BR semantic digest 替代。

與原提案的差異及理由:

  • E2E spec 本體列為脈絡,不是不列入。 UAT 會跳過「E2E 已證明的命題」;assertion 被刪除或放寬時,原本由 E2E 負責的命題會無人驗證。Coverage Header 的分類結果屬語意來源,spec 其餘內容由人複核是否仍證明相同命題。
  • US 未被引用的段落列為脈絡,不是忽略。 段落綁定由 generator 宣告,漏宣告會造成漏報;未被引用段落的變更至少要讓人看過。
  • 環境命令摘要的是解析定義,不是指南中的字串。 指南中的命令字串不會因 package.json 改變而改變;應摘要實際解析到的定義,例如 package.json 的 scripts.{name} 值。無法機械抽取時,該來源檔整檔列為脈絡來源。
  • 翻譯以 key 為單位追蹤,不整檔列入,也不整檔排除。 翻譯檔整檔列入會重現誤報(任何文案修改都讓所有指南過期);整檔排除則會漏掉「只改入口文字、頁面與元件檔案不變」的情況,而入口文字正是辨識性類旅程要判斷的東西。規則如下:
    • 指南引用畫面文字(按鈕、選單、欄位標籤)時,generator 宣告對應的翻譯 key;工具摘要這些 key 在 UAT 使用語系下的值,列為該旅程的脈絡來源。
    • D6 宣告 UI 入口依賴、但未宣告任何翻譯 key 的旅程,改以目標模組的翻譯檔整檔作為該旅程的脈絡來源(保守 fallback,只影響這類旅程)。
    • 宣告的 key 在翻譯檔中不存在時 stamp 失敗,避免以錯誤 key 規避追蹤。

D3:語意來源以段落摘要,錨點缺失即 stale​

  • 單位:Markdown 標題區段(以標題路徑定位);需要更細的粒度時,於來源文件加入明確錨點標記。不以清單項目序號定位,避免插入一項就讓後續項目全部位移。
  • 正規化:只做換行符統一、行尾空白去除、連續空行合併;不處理同義改寫,不宣稱能判斷語意等價。
  • 錨點找不到(標題改名、段落刪除)時判 stale,寧可誤報不漏報。
  • 綁定下限:UAT-only 的 sbe: 場景由工具自動綁定其 SBE 檔;us:、ux: 等補充場景必須至少宣告一個 US 錨點,否則 stamp 失敗。
  • BR 已有語意 projection digest 前例(ADR-014),但兩者輸入語意不同;本決策只共用 bytes hash helper,不共用 projection 或 serializer,沿 ADR-014 的邊界。

D4:驗收結果逐場景綁定​

每個 uat-scenario-id 的結果只綁定:

  1. 該場景在指南中的區塊摘要;
  2. 指南共用前言(使用前準備、身分與測試資料)的摘要;
  3. 該場景宣告的語意來源摘要;
  4. 取得通過時的脈絡來源摘要,以及可取回當時內容的引用(供 D5 複核比對,保存方式見 D5「差異證據的保存」)。

結果不再綁定整份指南與整份 sidecar 的 hash;只為一個場景重生指南時,其他場景的通過保留。verify-result 通過條件改為:目前指南的每個場景都有一筆有效的通過結果(區塊、前言、語意來源皆吻合),且其脈絡來源已吻合或已被複核為「保留」。

D5:變更後複核的三種結論​

脈絡來源改變時,指南變為 review-needed。工具列出變更的來源、差異摘要,以及可能受影響的場景(依 D6 的宣告與涉及元件推導),由真人對每個受影響場景選擇:

結論適用情況處理對進度的影響
保留變更不影響該場景的人工判斷命題寫入複核紀錄,保留原通過無
部分重驗指南仍正確,但該場景的體驗可能已改變不重生指南;該場景結果標為待重驗,/uat 只走這些場景只影響被標記的場景
轉為 stale複核發現指南本身已不正確回到 /uat-script 重生,受影響場景重驗依變更管理處理

複核紀錄的要求:

  • 只能由真人做出:/uat 以明示確認取得結論,Agent 不得自行寫入「保留」。
  • 內容:複核者、時間、檢視過的來源與差異、各場景結論與理由。
  • 綁定所複核的脈絡摘要:同一批來源之後再改變,就要重新複核。
  • 存放位置獨立:不寫入 sidecar 中會被結果綁定的部分,避免寫入複核紀錄反過來讓結果失效。
  • 批次複核必須顯示差異:不得只列檔名讓人一鍵確認,避免複核退化成新的「習慣重蓋」。
  • 複核不是驗收通過:「保留」只延續既有通過;沒有通過結果的場景不能經複核取得通過。

差異證據的保存​

現行 sidecar 只記來源 hash,無法還原舊內容;驗收當時來源若尚未 commit,Git 也不一定能還原。沒有舊內容就無法顯示差異,「保留」就只剩人的記憶。因此在記錄通過結果與寫入複核紀錄時,同時保存每個脈絡來源的可取回引用:

當時來源狀態保存方式
內容與記錄當下 HEAD 的同路徑 blob 相同記錄該 commit 與路徑;結果檔之後提交在此 commit 之上,取得結果檔的 clone 通常也取得該 commit(若因 squash 或 rebase 而不可達,依下方「無法取得」處理)
內容尚未 commit,或不符合上列條件以內容 SHA-256 為名,存成隨 Git 追蹤的快照(位於 docs/testing/uat-results/ 下,同內容只存一份);翻譯 key 只存宣告的 key 值

取回時必須驗證取回內容的 SHA-256 等於結果記錄的摘要,不符視同無法取得。

舊內容無法取得時(快照遺失、commit 不可達、schema 5 遷移而來且 Git 歷史中找不到相符版本),該場景的複核結論只能是「部分重驗」或「轉為 stale」,不得選「保留」。

D6:依賴畫面體驗的旅程宣告 UI 入口​

評估畫面體驗的旅程(例如「入口是否容易辨識」)可在指南中宣告所依賴的 UI 入口或元件,以及入口文字對應的翻譯 key(未宣告 key 時適用 D2 的翻譯檔 fallback)。這些入口相關的脈絡來源改變時,該旅程一定列入 D5 的受影響清單,並預設建議「部分重驗」,不預設「保留」。

D7:失效原因分兩類,回退時有條件保留​

現行 m-change-management.md 規定 /progress --rollback 以 invalidate-result 作廢回退目標之後的整份 UAT 結果,重新推進時不得重用舊驗收結果。這與 D4「只作廢對應場景」衝突。

但只比對語意來源,不足以決定回退後保留哪些通過。因實作缺陷或先前驗收誤判而回退時,規格可能完全沒變,摘要全部吻合,舊通過卻已經不可信。因此失效原因分兩類,處理規則不同:

失效類別觸發範圍能否因摘要吻合而恢復
來源變更語意來源改變;/progress --rollback 且原因為規格變更語意來源不吻合的場景可以:摘要吻合的場景保留,重新推進時可重用
明示撤銷/progress --rollback 且原因為實作缺陷或驗收誤判;/uat 中發現先前通過有誤由人選定的場景,預設為全部不行:撤銷紀錄永久有效,只能以新的 /uat 驗收取代
  • /progress --rollback 必須取得回退原因;原因未知或未回答時,視為明示撤銷全部場景(寧可多驗,不可誤留)。
  • 撤銷紀錄保存原因、撤銷者、時間與場景範圍;與來源變更造成的失效一樣,不刪除舊紀錄。
  • Sprint 階段的回退語意不變。

此項推翻 m-change-management.md 現行明文規則,已由第 3 輪審閱裁決採用(見「審閱裁決」Q1);規則本身於 P3 實作通過後才修訂。

相容與遷移​

P3 修訂(2026-09-29):不提供 migrate。 下方「原遷移設計」保留作為歷史,不實作。

現行做法:雙讀+重生升級。

  • schema 5 指南與其結果持續以原本的整檔指紋判定與驗證(P1 起的雙讀),/progress、/work 不受影響。
  • 指南重生時由 /uat-script 產生 schema 6 版本;新指南的驗收結果為 schema 6 帳本,須重新驗收。schema 5 的通過紀錄不帶入帳本。
  • 回退時 schema 5 結果整份失效(見 D7 與 m-change-management.md)。

不做 migrate 的理由:以 florae-g1 真實資料依下方遷移表唯讀模擬 58 份指南(其中 21 份有 passed 結果):

模擬結果指南其中有 passed
無法遷移(schema 4 以前,工具本來就拒絕)235
規格已變,判 stale147
除非真人逐檔確認 extra 用途,否則 stale156
可自動轉為 review-needed53
須從 Git 歷史取回舊內容才能判定10

migrate 能自動保住的通過只有 3 份,全部人工確認後最多再 6 份;實作卻須為「沒有來源宣告的指南」另建推導模式並取回 Git 歷史內容,成本與出錯風險都最高。這些指南多半已因來源變更過期、遲早要重生,重新驗收的代價小於維護一套遷移邏輯。

重生前須處理的資料問題(florae-g1 實測,追蹤於 FU-99):depends_on 中對不上實際標題的 test-data-seed 錨點(約 36 處)、UI 合約 spec 重複帶 Coverage Header(11 支);兩者都會讓 schema 6 stamp 拒收,須在重生前修正。

差異快照不做清理:快照以內容摘要為檔名、同內容只存一份,且被帳本中的通過與複核紀錄引用;刪除快照會讓之後的複核因舊內容取不回而無法選「保留」。若日後體積成為問題,另以「不被任何帳本引用」為條件設計清理。

原遷移設計(P3 決定不實作,保留歷史)​

  • schema 5 sidecar 視為舊版:check-guide 回報需升級,但不直接判定整份過期。
  • 提供一次性 migrate 指令,只遷移可證明未變的部分。原則:schema 5 只保存整檔 hash;整檔未變即可證明其中任何片段未變;整檔已變時,先嘗試從 Git 歷史取回舊內容(沿該路徑歷史逐版計算 SHA-256,找到與記錄相符的版本),取回後再依 D2 比對對應片段;取不回就無法證明,語意來源一律維持 stale。
  • 依 schema 5 的來源角色逐類處理:
schema 5 角色D2 歸屬整檔未變整檔已變,取回舊內容整檔已變,取不回
us語意(遷移期間為整份,見下)freshstale(schema 5 指南沒有段落宣告,無法判斷改變的段落是否被引用)stale
sbe語意fresh逐檔比對 hash(不需取回內容):SBE 集合增減,或 UAT-only 場景的 SBE 改變,則 stale;只有 E2E 或 Deferred 場景的 SBE 改變則 fresh。場景分類以 Coverage 為準,且 Coverage 必須已依下方 E2E spec 列證明未變,否則 stale同左
test-data-seed語意(遷移期間為整份,見下)freshstale(理由同 us)stale
design-language脈絡fresh(以目前內容作為脈絡基線)review-neededreview-needed,且不得「保留」(D5)
extra:含本 US Coverage Header 的 E2E specCoverage 為語意,本體為脈絡fresh比對 Coverage:不同則 stale;只有本體不同則 review-neededstale
extra:環境來源檔命令定義為語意、框架套件版本為脈絡,其餘不列入(同檔多片段)fresh分別比對:命令定義不同則 stale;否則框架版本不同則 review-needed;兩者都相同則 fresh。命令定義無法解析時,整檔視為脈絡,review-neededstale
extra:翻譯檔依 D2 以 key 追蹤freshreview-needed(schema 5 指南未宣告 key,無法定位受影響場景,全部列入複核)review-needed,且不得「保留」
extra:BR 原文(位於 requirements/business-requirements/)命題依據(語意)freshstale(schema 5 未宣告段落,無法判斷改變的段落是否為依據)stale
extra:其他(實作檔、框架 README 等)schema 5 未記錄用途,無法判定freshstale;migrate 可請真人逐檔確認用途,確認為「參考脈絡」者改為 review-needed,確認紀錄保存於遷移結果stale;真人確認為「參考脈絡」者改為 review-needed,且不得「保留」
  • 用途只能由真人確認,Agent 不得自行判定為參考脈絡;未確認者一律依「命題依據」處理。這條避免遷移把規格變更降級為可複核保留。
  • schema 5 指南沒有 US 錨點、測試資料段落與翻譯 key 的宣告。遷移後,每個場景暫以整份 US 與整份 test-data-seed 作為語意來源,並以原本納入的翻譯檔整檔作為所有場景的脈絡來源;下次以 /uat-script 重生指南時,才依 D3 細分到段落。遷移只換 schema,不降低對規格的把關。
  • 既有通過結果:只有結果綁定的 sourceFingerprintSha256 等於被遷移的 sidecar,且 guideSha256 等於目前指南時,才轉為逐場景通過;否則不保留。
  • 已經被重新 stamp 而作廢的舊結果,遷移無法恢復;如需恢復,須從 Git 歷史取回當時的 sidecar,並經真人確認。
  • 遷移不得把目前的來源直接標為「已複核」。原提案的「依現有來源標為已複核」會把 US/SBE 真實變更的指南洗成 fresh(florae-g1 中有 9 份屬此情況),不採用。

考量的方案​

方案內容不採用或保留的理由
A. 維持現狀整檔指紋,任一改變即 stale誤報淹沒真實過期,已造成習慣性重蓋,把關失效
B. 只收緊 extra-input不再納入實作檔與翻譯檔可消除最大一桶,但只是降低把關,沒有提供「產品已改變」時的複核路徑;可作為過渡,但不單獨採用
C. 只改善診斷check-guide 回報具體變更來源無 schema 變更、風險最低,但不減少重做;作為 P0 先行
D. 完全排除非規格來源只看 US/SBE/Coverage無法覆蓋「指南正確但體驗改變」的情況,框架升級後的 UAT-only 命題無人把關
E. 三層來源 + 逐場景 + 三結論複核(本案)見 D1–D7採用

影響範圍​

類別項目
工具uat/scripts/evidence.py(stamp-guide、check-guide、verify-result、invalidate-result 區分來源變更與明示撤銷、新增 review 相關指令、脈絡來源快照的寫入與取回驗證;P3 決定不做 migrate);uat/scripts/test_evidence.py;schema 5 → 6
Skillsuat-script/SKILL.md(來源宣告、--extra-input 用途宣告(命題依據/參考脈絡)、場景錨點、翻譯 key 宣告);uat/SKILL.md(review-needed 流程、部分重驗、驗收中發現誤判時的撤銷);progress/SKILL.md(--rollback 取得回退原因;第 372 行仍寫 schema 2,已與實作不符);progress/scripts/update.py(證據 inventory);progress/execution-contract.json
/workwork/references/progression.md、integration-revalidation.md(逐場景有效性、review-needed 在合併時的處理)
BRm-business-requirements.md 第 226、233 行與 ADR-014 明定「保留 schema 5」「BR hash 不替代 UAT 全檔指紋」,須同步修訂;br/SKILL.md;br/scripts/test_boundaries.py(直接 import evidence)
Rulesm-change-management.md(stale 描述、只影響脈絡來源的變更類型、D7 回退語意);m-methodology.md(/uat-script、/uat 描述)
發布工具與 skills 同屬 methodology 命名空間,須同批 /methodology publish;下游不需遷移,既有 schema 5 指南以雙讀繼續運作,重生時升級

分階段實施​

階段內容schema
P0check-guide 回報變更來源(role/path);可獨立先行5
P1三層來源與段落摘要;fresh/review-needed/stale 三態6
P2逐場景結果、複核紀錄與三種結論;/uat 部分重驗6
P3/progress 回退原因(D7)、/work、BR consumers 與 rules 對齊;fleet publish(不做 migrate,見「相容與遷移」)6

驗收條件​

  • 框架版本升級、按鈕樣式調整、實作重構、翻譯修改,或未改變 Coverage Header 的 E2E spec 本體修改,都不會讓任何指南變成 stale。
  • 上述變更若涉及旅程的脈絡來源,指南變成 review-needed;複核結論為「保留」時,寫入一筆紀錄即恢復 fresh,全程不改指南內容、不重驗。
  • 只修改某旅程宣告的翻譯 key 值(頁面與元件檔案不變)時,該旅程變成 review-needed;D6 旅程未宣告 key 時,翻譯檔任何修改都讓它變成 review-needed。
  • 脈絡來源的舊內容無法取得或取回內容的摘要不符時,複核不能選「保留」。
  • 複核結論為「部分重驗」時,指南不重生,/uat 只要求重驗被標記的場景,其餘場景的通過保留。
  • US 修改一條驗收標準時,只有引用該段落的場景變 stale、其結果失效。
  • UAT-only 的 SBE 內容或 Coverage 分類改變時,指南變成 stale。
  • E2E spec 刪除或放寬 assertion 時,指南至少變成 review-needed。
  • 標題改名或段落刪除導致錨點找不到時,引用它的場景變成 stale。
  • Agent 無法在沒有真人明示確認的情況下寫入複核結論。
  • 只升級框架、package.json 的 scripts 不變時,指南變成 review-needed(一般情況與遷移皆同),不會 stale,也不會因為整檔排除而維持 fresh。
  • 宣告為命題依據的權威來源(例如 BR 原文)的宣告段落改變時,指南變成 stale。
  • (遷移未實作,下兩條改由雙讀保證:schema 5 判定不變)遷移不會讓下列指南變成 fresh:US 或 test-data-seed 已變更;SBE 集合增減;UAT-only 場景的 SBE 已變更。只有 E2E 或 Deferred 場景的 SBE 變更、且 Coverage 已證明未變時,才可 fresh。
  • 遷移時,E2E spec 或環境來源檔已變更、且無法從 Git 歷史取回舊內容證明 Coverage 與命令定義未變,指南維持 stale;用途未經真人確認的其他 extra 已變更,指南維持 stale。
  • 以實作缺陷或驗收誤判為原因的 /progress --rollback,即使所有摘要都吻合,被撤銷場景的舊通過也不會恢復;未提供回退原因時,全部場景視為撤銷。

非目標​

  • 不改變 E2E 與 UAT 的分工,也不改變 UAT-only 與延後場景的分類規則。
  • 不把複核當成人工驗收通過;複核只延續既有通過。
  • 不宣稱段落摘要能判斷同義改寫。
  • 不改變 /progress 的階段狀態機與 --force 不得略過 UAT 證據的規則。

審閱裁決​

第 3 輪審閱者明示確認,以下四項皆採作者建議:

編號問題裁決
Q1/progress --rollback 是否改為有條件的逐場景保留(D7)採有條件保留:規格變更造成的失效逐場景比對;實作缺陷或驗收誤判造成的明示撤銷,不因摘要吻合而恢復;未提供回退原因時視為全部撤銷;Sprint 階段回退語意不變
Q2「旅程涉及的頁面與元件」如何取得:由 generator 宣告,或從 E2E/UI 合約 spec 推導先由 generator 宣告 UI 依賴,工具驗證路徑存在;推導留待後續
Q3框架版本升級是否一律觸發 review-needed,或僅在 CHANGELOG 有 UI 行為變更時觸發一律觸發 review-needed,複核畫面附上 CHANGELOG 對應區段,降低判斷成本
Q4方案 B(收緊 extra-input)是否在 P1 完成前先行,作為過渡不先行;只有 P0(回報變更來源)先行,避免在沒有複核路徑時降低把關

P1 實作裁決​

P1(schema 6 來源分層與三態)於 2026-09-29 經三輪 peer review 通過。實作與 florae-g1 真實指南實測中定案的細節如下;權威操作說明見 uat-script/SKILL.md 的來源宣告表。

宣告方式:來源宣告以 HTML 註解寫在指南內。第一個 uat-scenario-id 之前為指南層級,之後為該場景層級。stamp 後修改指南(含宣告)即 stale。錨點採與 Docusaurus 相同的 heading slug,重複標題比照 github-slugger 遞增。

裁決內容理由
宣告來源消失一律 stale宣告的檔案、錨點、key 或 JSON 路徑消失時,不論語意或脈絡層都判 stale宣告已失效,重新 stamp 必被拒收;check 與 stamp 的有效性判定須一致
Coverage 以 Header 數量+正規化分類判定條目重排不影響;Header 增減、邊界變動或分類歧義為 stale;stamp 拒收同檔多個 Header 與分類歧義語意來源是「場景到分類的解析結果」,不是文字排列
非 JSON 環境與框架來源逐行摘要以宣告文字所在的行為片段(如 .env 的 port、Gradle 的 plugin 或依賴座標);寫 * 才整檔列為脈絡整檔追蹤會讓建置設定的任何修改都觸發複核
依賴 UI 但未宣告翻譯 key 的旅程必須宣告指南層級 uat-i18n-source(模組無翻譯時寫 none),其檔案整檔綁定到這些旅程以明確宣告落實 D2/D6 的翻譯 fallback,不以檔名啟發式猜測
design language 依目標模組定位web-mockup 用自身、web 用 {name}-mockup;server 目標不綁 design languageUS 未寫 module 時仍能唯一定位;S.UAT 驗收 API 消費者旅程,畫面設計不是其判斷依據
拒絕 node_modules 路徑框架行為依據改以 uat-framework 宣告版本P0 實測發現指南把套件內原始碼列為來源
review-needed 暫時處置P2 複核紀錄上線前比照 stale 阻擋,但以 guideStatus 區分沒有複核紀錄時不得放行
schema 5/6 雙讀generator 6.0.0 以前產生 schema 5,判定邏輯不變;驗收結果仍為 result schema 5既有驗收結果在 P3 遷移前須持續可驗證
發布時機P1、P2 各自審閱並 commit,不發布;P3 完成後一起 /methodology publish避免下游先看到沒有複核流程的 review-needed

P1 審閱裁決的待決點(審閱者採作者建議):

編號裁決
Q1 重複 Coverage Header維持嚴格拒收;florae-g1 有 11 支 UI 合約 spec 違規,須以 /e2e-script 修正後才能重生指南
Q2 失效的 seed 錨點維持嚴格;重生時改正 depends_on。florae-g1 約 36 處舊英文錨點,P3 遷移須另定處理方式
Q3 非 JSON 翻譯檔P1 維持整檔 fallback;P2 上線後依實際複核負擔再評估是否以 Node 抽取 key
Q4 server 目標的 design language採用:不綁 design language

P2 實作裁決​

P2(逐場景驗收帳本與變更後複核)於 2026-09-29 經三輪 peer review 通過(4 條 major 皆修正)。權威操作說明見 uat/SKILL.md Step 2.2a、2.4 與 5.x。

驗收帳本:結果檔升為 result schema 6,內容是只增不刪的 entries(場景紀錄、複核、撤銷、問題),以 sequence 定先後、不依賴時鐘;/progress、/work 仍只讀一個檔。場景紀錄綁定場景區塊、共用前言與適用於該場景的語意/脈絡片段摘要。場景區塊自 uat-scenario-id 起,涵蓋場景標題及其子段落;其餘內容(不含 frontmatter)為共用前言。所有寫入改由工具指令完成,不再由 Agent 手寫 JSON。

裁決內容理由
複核綁定呈現的版本review-status 回傳 reviewToken(綁 sidecar、帳本序號、受影響場景與每筆差異的前後摘要);record-review 必須帶回,不一致即拒寫並要求重新呈現差異;寫入沿用同一份已驗證狀態結論必須對應使用者實際看過的差異;來源在呈現後又改變時不得套用舊結論
帳本寫入持跨程序鎖所有寫入入口以 flock 鎖定 uat-results 目錄,涵蓋讀取、驗證、追加與保存;逾時報錯檢查與寫入分離時,並行操作可互相覆蓋,已成功的撤銷可能遺失
差異快照一律以片段摘要存檔取代 D5 表中「commit 引用或快照」的二擇一;快照位於 docs/testing/uat-results/snapshots/{sha256}.txt,stamp、記錄通過、複核時寫入,取回時驗證摘要片段常只是檔案的一部分,commit 引用須重新推導片段;摘要快照可自我驗證、同內容只存一份。代價是 repo 多出快照檔
真人確認以流程保證+留痕/uat 以 AskUserQuestion 逐場景取得結論與理由;紀錄保存操作者(預設 git user.name)與理由工具無法證明操作者身分,SKILL 如實寫明
首次驗收前也能複核review-needed 時 initialize-result 可建立不含通過紀錄的空帳本避免初始化與複核互相阻擋;複核不產生通過
撤銷目標須為已知場景目前指南的場景 ∪ 帳本曾記錄的場景;任一未知即整次拒寫拼錯名稱不得回報成功而讓原驗收仍有效
P3 前回退撤銷全部invalidate-result 對帳本寫入一筆撤銷全部場景的紀錄(rollback)與 m-change-management.md 現行規則一致;依回退原因逐場景保留屬 P3
重新 stamp 與複核指南層級的複核只適用於當時的 sidecar;場景層級的「保留」針對場景的通過紀錄,重新 stamp 後延續指南層級基準屬於特定 stamp;場景的保留判斷與 stamp 無關

P3 實作裁決​

P3(方法論對齊與回退原因)於 2026-09-29 經兩輪 peer review 通過(1 條 major、1 條 minor 皆修正);Q1–Q4 採作者建議。

裁決內容理由
不提供 migrateschema 5 指南與結果持續雙讀;重生時升為 schema 6 並重新驗收florae-g1 模擬:自動可保住的通過僅 3 份,人工確認後最多再 6 份;實作與出錯成本最高(見「相容與遷移」)
回退原因(D7)invalidate-result --cause:spec-change 只留紀錄、由來源摘要判定;defect/misjudgment 撤銷指定或全部場景;未提供原因撤銷全部;/progress --rollback 以 AskUserQuestion 取得原因規格變更的影響由摘要精確判定;缺陷與誤判與摘要無關,不得因吻合而恢復;原因不明時寧可多驗
恢復方式依原因分流/progress 閘門、/work 整合重驗與 evidence.py 錯誤訊息皆區分:stale 才重生、review-needed 先複核、needs-uat 只重驗受影響場景一律要求重生會讓逐場景保留失去作用,並重新引發「習慣重蓋」
快照不清理見「相容與遷移」快照被帳本引用,刪除會讓複核無法選「保留」
規則對齊範圍已修訂 m-change-management、m-business-requirements、m-doc-version、m-work、m-methodology、/progress 與 /work 的說明、ADR-014(部分取代註記);以詞表搜尋確認其餘命中為無關或歷史保留依 m-change-management.md「機制或架構前提變更的跨文件檢視」

相關文檔​

變更歷史​

日期內容
2026-09-29初稿:依下游實測提案整理;補入變更後複核的「部分重驗」結論、E2E spec 列為脈絡來源、環境命令改摘要解析定義、遷移只保留可證明未變的部分
2026-09-29第 1 輪審閱修訂:遷移改為依 schema 5 角色逐類定義並可從 Git 歷史取回舊內容;翻譯改以 key 追蹤並提供 D6 fallback;D7 區分來源變更與明示撤銷;D5 新增差異證據的保存與無法取得時的限制;修正驗收條件中 E2E spec 的矛盾
2026-09-29第 2 輪審閱修訂:D2 明定層級屬於片段、同檔可多角色(命令定義與框架版本分別比對);權威來源依用途分為命題依據與參考脈絡,未宣告視為命題依據;遷移表新增 BR 原文列,其他 extra 未經真人確認用途即 stale;統一 SBE 遷移範圍與驗收條件
2026-09-29第 3 輪審閱通過設計方向;Q1–Q4 依審閱裁決定案(「待決點」改為「審閱裁決」);狀態維持 Proposed,實作 P0–P3 另行送審
2026-09-29P0 實作經三輪 peer review 通過:check-guide 過期時逐筆回報變更來源(CLI 錯誤 JSON 附 sourceChanges,永不為空),schema 與判定不變;審閱決定 P0 單獨發布、錯誤訊息不截斷。狀態仍為 Proposed
2026-09-29P1 實作經三輪 peer review 通過(5 條 major 皆修正):新增「P1 實作裁決」節記錄宣告方式與實作細節裁決;狀態仍為 Proposed,未發布
2026-09-29P2 實作經三輪 peer review 通過(4 條 major 皆修正):新增「P2 實作裁決」節;差異快照改為一律以片段摘要存檔(修訂 D5 保存方式);狀態仍為 Proposed,未發布
2026-09-29P3 實作經兩輪 peer review 通過:新增「P3 實作裁決」節;狀態改為 Accepted