dflow-sdd-ddd 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +824 -1
  2. package/CONTRIBUTING.md +16 -10
  3. package/README.en.md +156 -200
  4. package/README.md +89 -144
  5. package/TEMPLATE-COVERAGE.md +15 -8
  6. package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
  7. package/bin/dflow.js +36 -4
  8. package/docs/commands.en.md +110 -0
  9. package/docs/commands.md +101 -0
  10. package/docs/doctor-uncertainty.en.md +212 -0
  11. package/docs/doctor-uncertainty.md +212 -0
  12. package/docs/evaluating-dflow.en.md +29 -11
  13. package/docs/evaluating-dflow.md +8 -6
  14. package/docs/npm-publish-checklist.md +3 -1
  15. package/docs/release-versioning-policy.md +8 -2
  16. package/docs/upgrading.en.md +196 -0
  17. package/docs/upgrading.md +197 -0
  18. package/docs/using-with-claude-code.en.md +25 -10
  19. package/docs/using-with-claude-code.md +20 -7
  20. package/docs/using-with-codex.en.md +18 -6
  21. package/docs/using-with-codex.md +16 -5
  22. package/docs/using-with-github-copilot.en.md +25 -10
  23. package/docs/using-with-github-copilot.md +21 -8
  24. package/lib/doc-shapes.json +997 -0
  25. package/lib/doctor-checks.js +2654 -0
  26. package/lib/init.js +3583 -107
  27. package/lib/render-diagrams.js +1474 -0
  28. package/lib/render.js +865 -49
  29. package/package.json +2 -2
  30. package/templates/brownfield/references/drift-verification.md +4 -0
  31. package/templates/brownfield/references/finish-feature-flow.md +635 -88
  32. package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
  33. package/templates/brownfield/references/finish-feature-minimal-host.md +406 -0
  34. package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  35. package/templates/brownfield/references/git-integration.md +160 -15
  36. package/templates/brownfield/references/init-project-flow.md +26 -4
  37. package/templates/brownfield/references/modify-existing-flow.md +412 -87
  38. package/templates/brownfield/references/modify-existing-follow-up.md +121 -0
  39. package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +82 -0
  40. package/templates/brownfield/references/new-feature-flow.md +61 -6
  41. package/templates/brownfield/references/new-phase-flow.md +57 -7
  42. package/templates/brownfield/references/pr-review-checklist.md +303 -10
  43. package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +158 -34
  44. package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
  45. package/templates/brownfield/scaffolding/Git-principles-gitflow.md +75 -6
  46. package/templates/brownfield/scaffolding/Git-principles-trunk.md +82 -8
  47. package/templates/brownfield/scaffolding/_conventions.md +50 -28
  48. package/templates/brownfield/scaffolding/_overview.md +1 -0
  49. package/templates/brownfield/templates/_index.md +151 -7
  50. package/templates/brownfield/templates/analysis.md +79 -0
  51. package/templates/brownfield/templates/behavior.md +1 -0
  52. package/templates/brownfield/templates/context-definition.md +1 -0
  53. package/templates/brownfield/templates/context-map.md +2 -1
  54. package/templates/brownfield/templates/glossary.md +1 -0
  55. package/templates/brownfield/templates/lightweight-spec.md +154 -11
  56. package/templates/brownfield/templates/models.md +1 -0
  57. package/templates/brownfield/templates/phase-spec.md +9 -1
  58. package/templates/brownfield/templates/rules.md +1 -0
  59. package/templates/brownfield/templates/tech-debt.md +1 -0
  60. package/templates/common/references/ddd-modeling-guide.md +33 -16
  61. package/templates/{greenfield → common}/references/dflow-feedback-flow.md +2 -1
  62. package/templates/common/references/flow-rationale-registry.md +130 -0
  63. package/templates/common/skill/SKILL.md +13 -11
  64. package/templates/greenfield/references/drift-verification.md +4 -0
  65. package/templates/greenfield/references/finish-feature-flow.md +625 -89
  66. package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
  67. package/templates/greenfield/references/finish-feature-minimal-host.md +363 -0
  68. package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  69. package/templates/greenfield/references/git-integration.md +148 -15
  70. package/templates/greenfield/references/init-project-flow.md +28 -8
  71. package/templates/greenfield/references/modify-existing-flow.md +378 -85
  72. package/templates/greenfield/references/modify-existing-follow-up.md +103 -0
  73. package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +82 -0
  74. package/templates/greenfield/references/new-feature-flow.md +67 -4
  75. package/templates/greenfield/references/new-phase-flow.md +56 -7
  76. package/templates/greenfield/references/pr-review-checklist.md +287 -8
  77. package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +153 -32
  78. package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
  79. package/templates/greenfield/scaffolding/Git-principles-gitflow.md +74 -6
  80. package/templates/greenfield/scaffolding/Git-principles-trunk.md +88 -12
  81. package/templates/greenfield/scaffolding/_conventions.md +50 -28
  82. package/templates/greenfield/scaffolding/_overview.md +6 -2
  83. package/templates/greenfield/templates/_index.md +137 -7
  84. package/templates/greenfield/templates/aggregate-design.md +1 -0
  85. package/templates/greenfield/templates/analysis.md +79 -0
  86. package/templates/greenfield/templates/behavior.md +1 -0
  87. package/templates/greenfield/templates/context-definition.md +1 -0
  88. package/templates/greenfield/templates/context-map.md +2 -1
  89. package/templates/greenfield/templates/events.md +4 -1
  90. package/templates/greenfield/templates/glossary.md +1 -0
  91. package/templates/greenfield/templates/lightweight-spec.md +154 -11
  92. package/templates/greenfield/templates/models.md +1 -0
  93. package/templates/greenfield/templates/phase-spec.md +9 -1
  94. package/templates/greenfield/templates/rules.md +1 -0
  95. package/templates/greenfield/templates/tech-debt.md +1 -0
  96. package/templates/brownfield/references/dflow-feedback-flow.md +0 -251
package/CHANGELOG.md CHANGED
@@ -6,7 +6,826 @@
6
6
 
7
7
  ---
8
8
 
9
- ## 0.13.0 — 2026-07-10 — dflow render(specs 人讀化)+ init 預設安裝 skill(day-one 自動觸發)
9
+ ## 0.15.0 — 2026-09-27 — 分級改為順序判定、analysis.md 與 render 畫圖、doctor 看不準就直說
10
+
11
+ **Proposals**:PROPOSAL-077(A1 — spec 人讀可讀性:render 長欄位排版)、PROPOSAL-078 phase 1(formatting convention 投遞與偵測)、PROPOSAL-079(render index completed/ 年度分頁)、PROPOSAL-081(README 瘦身重組+防過度設計特點露出)、PROPOSAL-082(Tier 邊界語意改為順序 cascade)、PROPOSAL-083(standalone minimal host 生命週期)、PROPOSAL-084(`doctor` 誠實揭露不確定性)、PROPOSAL-085(flow reference 執行期體積)、PROPOSAL-086(受限標頭比讀者窄)、PROPOSAL-087(finish-feature 罕見路徑抽離)、PROPOSAL-090(`Git-principles-*.md` 的 canonical 區改為可刷新)、PROPOSAL-091(`doctor` 的兩條 false-clean 路徑)、PROPOSAL-093(closeout 尾巴的 cursor 矛盾)、PROPOSAL-095(BR Snapshot 範例列移出資料面)、PROPOSAL-096(closeout baseline 的鑰匙改為可推導)、PROPOSAL-099(系統級知識的落點)、PROPOSAL-100(render 把生命週期與流程畫成圖)、PROPOSAL-101(render 首頁改成分組目錄)、PROPOSAL-092(規格文件的形狀版號)
12
+
13
+ ### 從 `0.14.0` 升上來
14
+
15
+ 照 [`docs/upgrading.md`](docs/upgrading.md) 升級:先升 CLI,在專案根目錄跑 `dflow configure-agents`,再跑 `dflow doctor`。這一版另外要注意:
16
+
17
+ 1. **分級結果與 Dflow 自己出現的時機都會變**(P-082):同一個改動,升級前後可能分到不同的 tier。
18
+ 要跑 `dflow configure-agents --skills` 換新 skill;root shim 若你改過、又沒有 Dflow 的 marker,
19
+ 照 doctor 的提示手動換掉 routine 那一段(升級說明頁 § `0.15.0` 另外要做的事)。
20
+ 2. **有幾件要你自己補**:`_conventions.md` 少的 `### SPEC-ID Format`、`### Slug Conventions` 兩節
21
+ (P-083;⚠ 只有 `### SPEC-ID Format` doctor 會直接點名,`### Slug Conventions` 沒有指紋,要自己對照);trunk 專案若在 `Git-principles-trunk.md` 的 §2/§3 填過合併策略,
22
+ 改記到 `## 6.` 底下(P-090);`_index.md` 若照抄了範本的範例列——Current BR Snapshot 的範例列、
23
+ 預先放下的 Checkpoint Log `closeout` 列——刪掉那一列(P-095、dist issue #11)。
24
+ 3. **doctor 會多出幾條提示,多半不代表專案壞了**:沒有形狀標記的文件(P-092;補法見升級說明頁
25
+ § 形狀標記,可以之後再做,還沒關帳的 minimal host 先別補)、`Git-principles-*.md` 還沒採納
26
+ marker(P-090;互動式 `configure-agents` 會問,預設否)、表格缺排版註解(P-078)。
27
+ 出現 `uncertain` 時 doctor 不會印 `All checks passed`(P-084),照它連到的說明頁處理;
28
+ 以前會靜默通過的幾種狀態現在會報(P-091)——那些狀況本來就存在。
29
+ 4. **沒有自動遷移**:Dflow 不改寫你寫的 spec;舊的 lightweight-spec 寫法照舊合法(P-082)。
30
+
31
+ ### 各項變更
32
+
33
+ - **規格文件有了形狀版號(PROPOSAL-092)**:
34
+ 每一支範本的第一行(有 frontmatter 就在它後面)多一行
35
+ `<!-- dflow-shape: {軌別}/{範本} {號碼} — keep this line: dflow doctor reads it -->`(號碼後面的說明可有可無),
36
+ 記下照它寫的文件是哪一軌、哪一支範本的第幾號形狀——就像紙本表單角落的版號。兩軌 26 支範本
37
+ (系統層、feature 層與 `_overview.md`)都加上了,目前全部是第 1 號。照範本建立的文件會帶著
38
+ 這一行:`dflow init` 寫的文件一定有;AI 照範本建的文件通常會一起帶上,**但沒有保證**,
39
+ 掉了的話 doctor 會照實說(見下面「沒有標記」)。
40
+ `dflow doctor` 拿它跟你裝的 CLI 裡同一支範本的現行號碼比:**同號不報**(文件跟範本不同的地方
41
+ 都當成你自己的決定);比現行舊 → 一條 `info`,列出兩號之間變了什麼,**新增**的可以照補,
42
+ **改名/拆分/搬移/移除**的只報、由你判斷,**說明與順序**(`>` 說明、HTML 註解、段落的先後)
43
+ 標明不影響結構、由你和 AI 判斷要不要同步;比現行新 → 一條 `warn`(先升級 CLI);看不準——
44
+ 標記不在它的位置、格式不對,或文件裡不只一行含 `dflow-shape:`(當例子引用、被註解掉的也算,
45
+ doctor 不去判斷哪一行才是有效的標記)→ 一條 `uncertain`(`unreadable-shape-marker`),列出
46
+ 行號與處理方式;**沒有標記 → 一條 `info`,doctor 不判讀它們的形狀**。
47
+ 專案的 bundle 比 CLI 新時,這項檢查會跳過並說明原因。
48
+ - **升級要做的事**:這一版之前建立的文件都沒有標記,升級後 doctor 會多一條提示。照
49
+ `docs/upgrading.md` § 形狀標記 的一次性補法,交給 AI 逐份比對、由你判斷每個差異之後蓋號;
50
+ 還沒關帳的 minimal host(只掛一個小改動的 feature 目錄)先不要補,doctor 會把它們分開列;
51
+ Phase Specs 表是空的、目錄裡卻有 phase spec 的 feature,doctor 判不出是不是 minimal host,
52
+ 也分開列、兩種處理方式都附上。
53
+ **沒有自動遷移**,doctor 也不會改你的文件。
54
+ - 帶著標記的 feature `_index.md` 改由標記判讀,不再逐段比對 H2;沒有標記的照舊。
55
+ - 「表格排版註解」那條提示改成**只抄那一行**,不要把範本檔頭整段抄過去——檔頭帶著範本的標記。
56
+ - 刻意接受、寫在說明頁上的殘餘風險:形狀以外的改動(固定標籤、詞彙表的列、`####` 以下、
57
+ frontmatter 的 `#` 註解,以及 `>` 說明與 HTML 註解之外的說明文字)不會讓號碼變;合法但錯誤的
58
+ 號碼偵測不到;同號不報也會蓋掉 AI 不小心刪掉的段落;標記被當例子引用或被註解掉時會報看不準。
59
+ - tutorial:init 寫的文件與範例裡 AI 建的文件,照一次性補法判斷過差異後蓋上第 1 號
60
+ (`features/completed/` 不動);其中 11 支開頭還是舊範本的註解,換成現行範本開頭的兩行
61
+ (`Seeded by Dflow.` 與表格排版慣例),範例自己的說明照原樣保留;brownfield 範例進行中的 phase-spec,把現行範本已不用的
62
+ `id: …-P1` 改成 `spec-id:`。
63
+ - 維護者:範本的形狀(`##`/`###` 與它們的先後、表頭、frontmatter 欄位、`>` 說明、HTML 註解;
64
+ 只是重新折行不算)一變就要加號並登記在 `lib/doc-shapes.json`,`test/doc-shapes.mjs` 會擋;`TEMPLATE-COVERAGE.md` 寫明這個契約,
65
+ 並把兩列過時的路徑對齊 flow(`context.md`、feature 目錄裡的 `aggregate-design.md`)。
66
+
67
+ - **minimal host 關帳不再擋下「把任務打勾」(dist issue #16 的第一個缺口)**:
68
+ minimal host(只記一筆小改動、不分階段的 feature 目錄)關帳時,有一份**封閉**清單規定哪些
69
+ 還沒 commit 的修改可以跟著進關帳 commit。它對 lightweight/BUG spec 只收 `status:` 翻成
70
+ `completed`,以及開發者同意時整段收掉 `Implementation Tasks`。但 `modify-existing` 的完成檢查
71
+ (brownfield Step 6.1、greenfield Step 5.1)要求任務全部打勾、沒勾的標成 follow-up,而在
72
+ minimal host 上這一步一定發生在第一個 commit 之後,flow 前面也沒有叫 AI 邊做邊勾 ——
73
+ **照著每一條指示做完,關帳照樣被擋**,AI 只能違規放行,或多開一個 commit。
74
+ 清單現在收下完成檢查命令的那幾種編輯:把完成的任務打勾、把沒勾的標成 follow-up,以及同意時
75
+ 的整段收掉或移除;spec 其他內容的修改照舊擋下。
76
+ 兩軌對稱。既有專案再跑一次 `dflow configure-agents` 即取得;**沒有遷移動作**。
77
+ ⚠ #16 的第二個缺口(`_overview.md` 與 `features/backlog/` 不在清單 (iii) 裡)沒有動,
78
+ 它與 #15 是同一件事,一起處理。
79
+
80
+ - **tutorial 跟上出貨內容**:
81
+ - 閱讀指南(`tutorial/how-to-read-dflow-specs.md`)的系統層與 BC 文件表補上 `analysis.md`。
82
+ - 兩支範例產出的 `Git-principles-*.md` 跟上現行範本:「AI commit authorship」一節改成
83
+ init 時三選一、記在 `_conventions.md`(不再寫「建議、不強制」);greenfield 那支另外跟上
84
+ hotfix 一節(post-hoc 模式)與一行套件相依的措辭。這幾段都在可刷新區(§§ 1–5)之外,之前
85
+ 的範本改動沒有帶進範例。
86
+ - 兩軌 `walkthrough-06` 說某句話「在 Step 3、Step 5 與 `Git-principles-*` 都寫了」,改成它
87
+ 實際所在的位置:兩軌 `finish-feature-flow.md` 的 Step 3。
88
+
89
+ - **README**:兩份 README 的功能介紹補上 `analysis.md`(P-099)與 render 把生命週期、流程畫成圖
90
+ (P-100);文件模型的系統層加上 `analysis.md`,並註明它不由 init 建立。主要特點的 render 那一列
91
+ 把畫圖放到前面、講出圖讓人看出什麼;render 那一節補一張生命週期圖的對照截圖(Expense 範例的
92
+ `LC-01`:左是狀態表與轉移表,右是 render 畫出的圖)。
93
+
94
+ - **README 改成「你不用先學指令」,指令目錄搬到 `docs/commands.md`**:
95
+ 讀者原本得先讀過兩輪指令表——「開始使用」列 7 條、「主要 Flow」整節再把 11 條分四類列一次,
96
+ 外加一張各 AI 工具怎麼打斜線的表——才會讀到「AI 會判斷該走哪一條」。**順序本身就在教人「先學指令」**,
97
+ 而實際使用不需要學:講出要做的事,AI 就會判該走哪一條 workflow、要寫多少規格。
98
+ 現在主要特點之後新增一節「你不用先學指令」,先給三個「你說什麼 → AI 走哪條」的例子
99
+ (新功能走完整規格、欄位算錯多半是輕量規格、按鈕改顏色只在 `_index.md` 記一行),
100
+ 再放一張流程圖:從「你講需求」開始,AI 判定要多少規格、分流到新功能或改既有/修 bug,
101
+ 接著沿 T1 完整路徑走過 `/dflow:new-feature` 的四個 Step Gate 與兩個 commit 檢查點,
102
+ 最後回到 `/dflow:new-phase`,或交給 `/dflow:finish-feature` 走它自己的兩個 Step Gate、
103
+ 在歸檔那一步做第三個 commit 檢查點之後凍結歷史。**AI 停下來等你確認的每一格都標出來**;
104
+ commit 標記落在綠色那一格,代表那個 Step Gate 同時問你要不要 commit;落在藍色那一格,
105
+ 代表那一步單獨問——**它一樣會停,只是不是 Step Gate**(收尾那一個就是這種)。
106
+ commit 檢查點的數量由 tier 決定(T1 三個、T2 兩個、T3 一個;zero-phase 的 minimal host
107
+ 不論 tier 都是兩個);**你會遇到幾個 Step Gate,由 flow 與 tier 一起決定**——不同 flow 不同,
108
+ 同一條 flow 裡輕的 tier 還會跳過一些關(`/dflow:modify-existing` 判成 T3 就不跑 DDD
109
+ 影響評估那一關),判成 T1 則可能整條升到 `/dflow:new-feature`/`/dflow:new-phase`。
110
+ 「主要 Flow」整節與各工具叫法表都移到新的
111
+ [`docs/commands.md`](docs/commands.md)/[`.en.md`](docs/commands.en.md)——一般使用不需要那一頁,
112
+ 它是給「想直接指定某條 flow、想糾正 AI 選錯的那一條、或想盤點 Dflow 涵蓋哪些情境」的人看的。
113
+ 「completed feature 是凍結歷史」留在 README,移到文件模型段末(它講的是核心保證,不是指令)。
114
+ Workflow 模型的三層表把「自然語言進入(預設)」排到「命令進入」前面,
115
+ 取代原本「自動偵測安全網」那個把自然語言寫成備援的講法。兩份 README 逐節對等。
116
+
117
+ - **`dflow render` 把生命週期與流程畫成圖(P-100,dist issue #6)**:
118
+ `analysis.md` 裡填好的 `### LC-nn`(一個狀態欄位的生命週期)與 `### FL-nn`(跨 context 的流程)小節,
119
+ 現在會在卡片上方多一張內嵌 SVG 圖:生命週期畫成狀態與轉換,流程畫成參與者與依序的交手;出處是 `inferred`/`assumed` 的箭頭畫成虛線。
120
+ **卡片一字不改,表格仍是正本。** 表格還是範本原封不動(只有佔位列)的小節跟以前一樣不畫;畫不出來的(缺表、缺欄、值對不上、超過大小上限)改成一行說明為什麼沒畫,
121
+ 不畫半張圖,也不會讓整次 render 失敗。參與者超過 4 個的流程在螢幕上左右捲動,列印時改印一行提示。
122
+ 有圖或提示時,標準輸出多一行 `diagrams: N drawn, M not drawn`。不新增相依套件,頁面照舊不帶 JavaScript;其他頁面不變。
123
+
124
+ - **`dflow render` 的首頁改成分組目錄(P-101)**:
125
+ specs 一多,舊首頁是一條照路徑排序、全部展開的檔名清單,第一屏被 `domain/` 佔滿。
126
+ 現在 `--src` 是 Dflow 的 specs 根目錄(有 `shared/_conventions.md`)時,首頁分成 Features、Domain、架構與遷移、共用文件、其他五組:
127
+ 每組是瀏覽器原生的收合區塊,第一次打開全部收起(只有一組時直接展開),標題列帶目錄、文件數與一句用途,展開後有預設收起的「怎麼讀這些文件」。
128
+ Domain 的跨 context 文件一列、其餘一個 context 一列;feature 一個目錄一列、一個檔一行(`_index.md` 在最前,其餘照檔名裡的日期);
129
+ 兩種 `analysis.md` 分別標「跨 context 分析」「context 分析」。`completed/` 的年度頁也改成同樣的 feature 列,並多一句說明。
130
+ 頁面照舊不帶 JavaScript,也不記得上次展開了哪一組;列印時收起的組只印出標題列。
131
+ `--src` 指到別處(例如只轉 `domain/`)時,首頁與年度頁維持原本的目錄樹。
132
+ 另修一個舊缺陷:檔名或目錄名含 `%`、`#`、`?` 時,首頁與年度頁的連結會連錯或斷掉,現在這三個字元會編碼。各文件轉出的頁面不變。
133
+
134
+ - **系統級知識有了落點:`analysis.md`(P-099,dist issue #6)**:
135
+ 跨 context 的有序流程、一個狀態欄位走過的生命週期、算出來而不是存下來的數字、單一規則解釋不了的機制、
136
+ 哪些角色碰得到哪個功能——這幾類知識以前沒有任何一支 domain 文件收,結果不是只留在對話裡,
137
+ 就是寫進 feature 產物、隨 feature 收尾一起凍結;這幾類知識裡一直被繞過、要等一個領域決定才解得掉的地方,也一樣沒有地方記。
138
+ 新檔有**兩個落點**:由某一個 bounded context 擁有的,記在 `dflow/specs/domain/{context}/analysis.md`;
139
+ 跨 context 的流程、整張角色索引,以及沒有任何一個 context 擁有的條目,記在 `dflow/specs/domain/analysis.md`;
140
+ 卡在某一條已記下的條目上、要等領域決定的地方,跟著那一條記在同一份。
141
+ 現在 `/dflow:modify-existing`、`/dflow:new-feature`、`/dflow:new-phase` 碰到它們時會記進去,完成與收尾時跟著維護;
142
+ 沒有指令在跑時,guide 也會把它路由過去,並提議把那一筆單獨 commit;PR review 多一項,提醒回頭複查一條出處。
143
+ **⭐ 純觀察也收**:「只看不改」的路由現在也會把發現記進 `analysis.md`。
144
+ brownfield 修改一個還沒有規格的功能時,另會順便把那一塊的系統現況成批盤點進來——中途採用 Dflow 的專案,系統現況就是這樣補齊的。
145
+ **init 不建它**,第一次有東西要記時才從 `templates/analysis.md` 建立;每一條都帶出處
146
+ (`code`/`data`/`confirmed by {role}`/`document`/`inferred`/`assumed`)。
147
+ 流程與生命週期用**表格**記——表格是 AI 讀寫的正本,也是人直接讀得懂的形式。
148
+ 範本的每一節寫明哪些東西該記去既有的鄰居文件;已經寫在別處的分析內容留在原處、連過去就好;
149
+ `context-map.md` 範本的 `Integration Notes` 也改成只收沒有先後順序的資料交換。
150
+ 既有專案不需遷移:重跑 `dflow configure-agents` 就會拿到新範本、更新後的 flow 檔,以及 guide canonical 區裡的新路由
151
+ (guide 還沒有 canonical marker 的專案,照舊由 `dflow doctor` 回報)。
152
+ `dflow render` 把這些表格轉成一列一張卡片;填好的流程與生命週期另外畫成圖(P-100,見上方)。
153
+
154
+ - **`doctor` 補掉兩條「靜默通過」路徑:值缺席不再關掉下游檢查,adapter/skill 層第一次被看(P-091)**:
155
+ 兩條都是 P-084 定義的**最糟**方向——doctor 說 `All checks passed`,而東西其實已經壞了或漂了。
156
+
157
+ **(一) 缺一個值就靜默關掉一整段檢查,共四支 check、七個 gate。**
158
+ 最貴的一個是 `checkInitOnlyStarters` 的 `if (policy)` **沒有 else**:`_conventions.md`
159
+ 少了 `## Git Policy` 段,整個 `Git-principles-*.md` 區塊就消失——**而那正是 P-090 修好的
160
+ 66 行漂移唯一的偵測管道**。實測:同一份專案只加一行 `Selected Git policy:`,
161
+ findings 從 7 條變 8 條;使用者原本看到的 7 條,實際上是 8 條。
162
+ 修法**不是統一補一段字**,七個 gate 各自判過:
163
+ 值只是「專案形狀的事實」的走**不確定就全查**(policy 缺席 → 把磁碟上實際存在的
164
+ `Git-principles-*.md` 逐一比對;edition 推不出來 → 兩軌都比,**兩軌都不像才報**);
165
+ 檢查真的做不下去的走**揭露**(讀不到套件內的範本 = 你的安裝壞了,不能沉默——
166
+ 這條是 `checkWorkflowBundleSourceAndOrphans` 的「NOTHING GATES THE PACKAGE CHECK」
167
+ 已經判死的既有判例)。`.dflow-bundle-manifest.json` 則分兩態:**沒有** manifest 是
168
+ 合法狀態、保持沉默;**壞掉**要報。
169
+ ⚠ 連帶修掉一個會誤導人的措辭:政策沒記錄時 `configure-agents` 其實**拒絕**碰任何
170
+ Git principles 檔,所以那幾條 finding 的建議會先叫你把 `## Git Policy` 補回來,
171
+ 不會叫你去跑一個必定拒絕的指令。
172
+
173
+ **(二) adapter 與 skill 兩層以前一條 check 都沒有。** `p097-y1` 的受控實測:
174
+ 同一棵樹刪掉整個 `.claude/`(11 支指令檔 + 1 份 `SKILL.md`),doctor 輸出**逐位元組相同**。
175
+ 新增 `checkAdapterAndSkillState`,採 **R3——只判已經存在的東西**:
176
+ 指令檔只裝了一部分會報(copilot 判 `dflow-*` glob,不判 `.github/prompts/` 目錄——
177
+ 那是共用命名空間)、`0.5.0` 舊檔名殘留會報、帶 Dflow marker 而內容落後的 `SKILL.md` 會報
178
+ (**三份都判,含 Codex 的 `.agents/skills/dflow/SKILL.md`**;Codex 沒有指令檔是
179
+ P-037 已核准的決定,但它**有** skill)。沒有 marker 的 `SKILL.md` 是使用者的檔,不報。
180
+ ⚠⚠ **「一支都沒有」刻意不報**:doctor 分不出「我本來就沒要」和「我有過、掉了」,
181
+ 而 P-037 **建議**採用者把這些衍生檔 gitignore 掉、clone 後重生成——照建議做的人
182
+ 「一支都沒有」是正常的。這條偵測被規格化三次、三次都被找到會誤報無辜專案的路徑
183
+ (其中一版連**每一次全新 `dflow init`** 都會被報)。**這筆殘餘風險已寫進
184
+ `docs/doctor-uncertainty.{md,en.md}`**,含失敗情境/為什麼不防/誰承擔/什麼條件重看。
185
+ 上位解(command adapter 改預設安裝)另案追蹤。
186
+
187
+ ⚠ **同批修掉一個「假的髒」——它是假的乾淨的鏡像。** edition 推不出來、而**其中一軌**的
188
+ packaged 範本讀不到時,`checkGuideCanonicalState` 會拿活下來的那一軌單獨比對,
189
+ 把一份**原封不動、正好屬於讀不到那一軌**的專案檔報成漂移——而同一份報告的上一條
190
+ finding 才剛說「因此本報告無法判斷它是不是最新」。漂移宣稱的前提是「和**所有**出貨軌都不像」,
191
+ 少一軌讀不到就不成立。`checkFeatureIndexShape` 是逐字同型,一併修(它今天觀察不到,
192
+ 因為兩軌 `_index.md` 的 H2 集合恰好相同——**latent 不是 absent**)。
193
+ ⚠⚠ **同一批還修掉一整類「值讀不到」的靜默**,那是七個 gate 全都沒問到的一問:
194
+ 它們一律只問「值**缺席**」,而 `catch(() => '')` / `catch(() => null)` / `catch { return }`
195
+ 把「檔不存在」與「檔在、內容完好、只是鎖住或被目錄佔位」併成同一態。結果包括:
196
+ 完好的 `AI-AGENT-GUIDE.md` 被說成「不具 Dflow guide 形狀」並叫你重建它、
197
+ 完好的 `_conventions.md` 被說成 `is empty` 並叫你重填答案、
198
+ `features/active/` 讀不到時整批 feature 一個字都不報。現在三者都分開講。
199
+ 同理,套件內那份 skill 範本改用**嚴格 UTF-8 解碼**(其他每一支 packaged 檔本來就這樣讀)——
200
+ 否則毀損內容會變成 U+FFFD、非空、有 marker,**兩道可用性檢查都騙得過**,
201
+ 然後 doctor 會對你三份完好的 `SKILL.md` 說它們過期了。
202
+ 另外,packaged guide 分類前補上 `toLf`:CRLF checkout 的套件不再被誤報成損壞。
203
+
204
+ 另外三處措辭誠實化:存在但讀不到的 `SKILL.md` 不再被當成「不存在」而靜默;
205
+ `null Git policy` 的後果改成分別講清楚(`init` fallback 到 `trunk`,`configure-agents` 則是拒絕動作);
206
+ `dflow doctor --help` 補上新增的三類覆蓋。
207
+
208
+ **(三) doctor 現在會說出自己判不了什麼。** 每次執行的報告結尾多一段:它不判斷這個專案
209
+ 「該不該」有指令檔與 skill 檔(那是意圖,沒有任何地方記錄),並指名由使用 Dflow 的 AI
210
+ 接手確認。⚠ **措辭刻意寫成「這是委派,不是保證」**——沒有任何機制強制它發生,也沒有
211
+ 任何檢查驗證它做過。把委派描述成 gate 是本 repo 付過學費的缺陷。
212
+ 落點只在 doctor 輸出 + 揭露頁,**不進 flow 檔、不進 guide**(那兩處每次執行/每 session 付費)。
213
+
214
+ - **closeout 的 baseline 現在**定址得回來**,而且偵測搬到了還能回頭的位置(P-096,dist issue #10 的殘餘)**:
215
+ `#10` 修好了「baseline 的**內容**讀不回來」(Step 1 的 `git hash-object` 補上 `-w`),
216
+ 但**定址那些內容的 `path → blob` 清單**仍然只被「講在對話裡」——
217
+ 而同一段文字兩句之後就宣告對話不可靠,且 `_index.md` 的 Resume Pointer **自述**
218
+ 「開新對話接續工作時,從這裡讀起」、Step 2 明文預期「下一個 session」會接手。
219
+ **跨對話是這棵樹自己寫在紙上的正常路徑**,一跨過去,那批 blob 就成了無人能定址的垃圾。
220
+ 現在 Step 1 把清單本身也寫成一顆 blob,錨在 **`refs/dflow/closeout-baseline/{SPEC-ID}-{slug}`**
221
+ —— 名字從 host 自己的 SPEC-ID **重算得出來**,所以**不需要任何東西撐過對話**;
222
+ 驗證全過之後才 `git update-ref -d` 釋放。
223
+ 同批還修了三件:擷取集合改用 `git ls-files --cached --others --exclude-standard`
224
+ (**那正是 `git add {dir}` 自己工作的集合** —— 舊寫法會把 ignored 檔種進 baseline 造成無解假擋,
225
+ 而只收 tracked 又會漏掉未 commit 的新檔、同樣誤擋);**`git mv` 之前**先確認 baseline
226
+ 讀得回來(原本這道驗證整個跑在 commit 之後,失敗時**沒有修復程序**);
227
+ 空 `Commit` cell 的措辭改成明說「本檢查不判它、`pr-review-checklist.md` 判」,
228
+ 維持既有分工而不再假裝自己在擋。
229
+ ⚠ **`degraded` 這個值仍未定義**,那是 `#10` 留下的另一半 —— 五輪 review 證明定義它需要
230
+ 先給它一個持久落點(現在的記錄裡沒有任何欄位放得下),已另案追蹤。
231
+
232
+ - **`Git-principles-{policy}.md` 的 §§ 1–5 改為可刷新,既有專案不再永遠停在 init 當時的版本(P-090,走 B3)**:
233
+ `Git-principles-{gitflow|trunk}.md` 是 **init-only starter** —— `configure-agents` 從不重投影它,
234
+ 但 `finish-feature` / `modify-existing` / `new-feature` 三支主幹 flow 都讀它。所以 `0.9.0` 之後
235
+ init 的專案,**分支命名、commit 規範、Gate Checks 這些 canonical 規則一路凍結在 init 那天**,
236
+ 而每次升級都在刷新「讀它的那些 flow」。實測落差:greenfield trunk **87 行**、brownfield trunk **65 行**,
237
+ 而且不是潤飾——是 hotfix 分支命名改成依嚴重度分流、post-hoc 記錄規則整段新增這一類。
238
+ 現在四份 starter 都插了一組**新的** marker `git-principles-canonical`
239
+ (⚠ **刻意不沿用 guide 那組**:`GUIDE_CANONICAL_SECTION_START` 同時被 `AI-AGENT-GUIDE.md` 的
240
+ section 邊界掃描當終止條件,共用同一個字串等於把兩個不相干的機制綁在一起)。
241
+ 區域邊界是 **`## 1. Branch Structure` 起、`## 6. AI Collaboration Rules (Project Policy)` 前止**。
242
+ ⚠⚠ **檔頭刻意留在區外**:它有 `> Created: {YYYY-MM-DD}`,那是專案填的值,包進去每次刷新都會蓋掉。
243
+ **`configure-agents` 的處置與 guide 同一張決策表**(skip + warn + offer,never rewrite unasked):
244
+ marker 完整 → 就地刷新 §§ 1–5、marker 外的內容不碰(換行統一見下);**沒有 marker 但認得出**(兩個標題錨各出現恰好一次)
245
+ → skip + warn,**互動式執行才提問**是否採納(預設**否**),非互動一律不問也不改;認不出或 marker 壞掉 → skip + warn。
246
+ ⚠ 採納提問的範圍比 guide 那個**窄得多**:只換 §§ 1–5,**檔頭與 `## 6.` 以下(含你的 CI/CD 段)內容原封保留**。
247
+ ⚠ 精確講:全檔會做一項既有的正規化——換行符統一成該檔原本佔多數的那一種——所以
248
+ **混合**換行的檔案是「內容保留」而非「逐位元組保留」。這個行為 guide 那半一直如此
249
+ (`detectDominantEol` + `applyEol`),不是本案引進的;本條先前把它寫成「逐位元組」
250
+ 是**過度宣稱**,由收工輪 `p090-b3-y1` 用混合換行的 fixture 實測推翻。
251
+ ⚠ 讀不到 `_conventions.md` 的 `## Git Policy` 時**明確 warn**,不是靜默 return——靜默正是這條線要消滅的形狀。
252
+ **`dflow doctor` 的 starter drift 改成只比 canonical 區**,四種狀態分開報:還沒採納(info)/
253
+ 區內不同(info)/marker 壞掉(warn)/**安裝的套件自己那份 starter 不堪用(warn)**。
254
+ ⚠ `malformed` **不得**折進「還沒採納」——否則一個被改壞的檔會讀成「從來沒有 marker」,
255
+ 採納提問就會去改寫沒有人重讀過的 §§ 1–5。
256
+ ⚠⚠ **那條「套件自己那份 starter 不堪用」的檢查不因專案檔不見而跳過。** 第一版把它
257
+ 放在「專案檔存在嗎」的 `else` 裡,於是**刪掉專案的 `Git-principles-*.md` 就會讓套件損壞
258
+ 整條靜音**,只剩一句「檔不見了,去 scratch 目錄跑一次 `dflow init` 撿回來」——而在那個
259
+ 套件上,那次 init 會原封不動地把同樣的損壞交給你,還看起來像你自己的錯。
260
+ 現在兩條都報,而且「檔不見了」那條的處置在套件已知損壞時會**先叫你重裝**。
261
+ ⚠ 這是本檔第四次有人在套件檢查外面猜邊界;前三次記在
262
+ `checkWorkflowBundleSourceAndOrphans` 上,結論只有一句:**出貨來源無條件驗**。
263
+
264
+ ⚠ 舊的**整檔**比對是這條 doctor 訊號長年沒人讀的原因:每個填過 CI/CD 段的專案都會亮燈,
265
+ 而那是**正常狀態**。現在區外的編輯不再被報成 drift。
266
+ ⚠⚠ **gitflow 兩軌的 CHANGELOG 範例日期改成 `{2026-04-21}`,不再是 `{YYYY-MM-DD}`。**
267
+ 這不是措辭調整,是上面那套機制的**前提**:canonical 區是以**出貨原始位元組**比對與刷新的,
268
+ 而 `{YYYY-MM-DD}` 是 `init` 會代換的 placeholder。它就落在 gitflow 的 §§ 1–5 之內,
269
+ 於是**剛 init 完的 gitflow 專案立刻被 doctor 判 canonical drift**,而
270
+ `configure-agents` 的「刷新」會把採用者檔案裡真實的日期**改回 `{YYYY-MM-DD}` 這串佔位字**。
271
+ 兩軌都會發生,收工輪 `p090-b3-x1r` 端到端重現。⚠ 這兩個檔裡有**兩個** `{YYYY-MM-DD}`,
272
+ 而只有一個被想過(檔頭 `> Created:`,刻意留在區外);區內那個曾經因為**另一個理由**
273
+ 被寫在註解裡(不可以拿它當節標題錨),沒有人把兩件事接起來。
274
+ ⚠ 對既有 gitflow 專案的影響:下一次 `configure-agents` 會把這個範例日期一併刷新,
275
+ 這正是 canonical 區該做的事。
276
+ 現在有一道 guard 守著它(`test/upgrade-drift.mjs`):**四份 starter**(兩軌 × 兩 policy)
277
+ 剛投影出來的 canonical 區,都必須與出貨檔逐位元組相同。⚠ 用「與新投影檔比對」而不是
278
+ 「grep 目前的 placeholder 清單」,是因為前者連未來新增的代換機制都擋得住。
279
+ **兩份 tutorial `outputs/` 的 Git-principles 也跟著更新**(user 決定 2026-08-28:
280
+ 流程與樣板有改,`outputs/` 就跟著改)。它們是「跑完 `dflow init` 長什麼樣」的對照證據,
281
+ 而 tutorial 在 `include_paths` 裡、會出貨。做法**不是手改**,是套用本案自己的機制:
282
+ 插入 marker、canonical §§ 1–5 換成本版出貨內容,**檔頭與 `## 6.` 以下保留**(這兩份是純 LF,實測逐位元組相同)
283
+ ——實測兩份的 `> Created: 2026-04-28` / `2026-04-29` 與 §6+ 都原封不動,
284
+ 而 `dflow doctor` 對更新後的兩份**不再有任何 Git-principles finding**。
285
+ ⚠ 這一併補掉了它們自 P-083/085/087 以來累積的落後(各約 21–22 個 hunk)。
286
+ ⚠⚠ **trunk 兩軌的 5 處「採用者填空」移出 canonical 區(收工輪 `p090-b3-y3` 抓到)。**
287
+ greenfield trunk 的 `## 3. Merge Strategy Options` 有三處 `**This project uses**:
288
+ {Yes / No / Default — fill in}`、brownfield trunk 的 `## 2` 與 `## 3` 各一處
289
+ (後者的節標題**自己就叫 `Merge Strategy (Project Chooses)`**)——它們全都落在
290
+ §§ 1–5 之內,也就是**每次刷新都會被蓋掉的那一段**。實測:採用者填成 `**squash**`,
291
+ 跑一次 `configure-agents` 就被換回 `{squash | rebase | fast-forward}`,沒有任何提示。
292
+ **這正是本案要防的事,卻由本案的邊界造成。**
293
+ ⚠ 根因是邊界建立在**節編號**(§§ 1–5)而不是**內容歸屬**。真正的分界是
294
+ **「Dflow 說的規則 → canonical;專案的選擇 → 不碰」**。
295
+ 修法(user 2026-08-28 拍板走 c 案):**取捨說明留在原處**(那是 Dflow 維護的內容),
296
+ **「本專案選哪個」移到 `## 6.` 底下新的一小節**(那裡本來就是專案自有區)。
297
+ gitflow 兩軌本來就沒有這個問題,未動。
298
+ 新增一道 guard:canonical 區內不得出現採用者填空的形狀(`{a / b}`、`{a | b}`、
299
+ `fill in`、`Delete the unused…`),⚠ 且用 `maskCodeBlocks` 排除 fenced 範例。
300
+ ⚠⚠ **既有採用者請注意**:新的 `## 6.` 小節在 canonical 區**外**,所以
301
+ `configure-agents` **不會**幫你加上它——你只會看到 §3 那幾行填空消失。
302
+ 若你曾在那裡填過選擇,升級後請自行在 `## 6.` 記一行。
303
+ (在此之前那個值本來也是每次刷新都會被清掉,所以不是新的損失,但補救位置變了。)
304
+ ⚠ **doctor 對「認不出來的 starter」不再建議一個不會出現的提問**(收工輪 `p090-b3-z1`)。
305
+ 兩個標題錨不完整時 `configure-agents` **不會**提出採納提問,而 doctor 先前照樣說
306
+ 「去接受採納提問」——對另一個指令的假宣稱。現在分成三種:讀不到(warn)/
307
+ 真的 pre-marker 且認得出(給採納建議)/認不出(說明為什麼不會有提問)。
308
+ ⚠ 順帶:**讀不到的檔**先前會被歸成「沒有 marker」,等於對沒讀到的內容下判斷,一併分開。
309
+ 新增三道 guard:**tutorial fixture 的 canonical 區必須與出貨檔逐位元組相同**
310
+ (它在 `include_paths` 裡、會出貨,而先前沒有任何東西在看它,實測同一場三個 commit 內就漂掉)、
311
+ **marker 位置必須釘在兩個標題錨上**(先前把 START 移到 `## 1.` 之下——等於讓 §1 不再被刷新
312
+ ——整套測試全綠)、以及上面那條 doctor 措辭。
313
+ ⚠⚠ **明知蓋不到、繼續漂的部分已列冊**(`planning/opt-in-backlog.md` 的
314
+ `p090-b3-outside-region-drift`,owner = maintainer):B3 的單區 marker 蓋不到排在專案自有段
315
+ **之後**的 canonical 內容——greenfield trunk 的 `## 7. Hotfixes under Trunk-based`(**這一筆是實際
316
+ 漂移中的**)、四份的 `## Related Documents`、greenfield trunk 的 `## 8. Release & Versioning`。
317
+ 這是 B3 對 B2(多區 marker)換來的代價,user 2026-08-28 拍板時已知並接受。
318
+ 升級說明見 `docs/upgrading.md` + `.en.md`。
319
+
320
+ - **`finish-feature` 的 baseline 現在真的取得回內容(dist issue #10)**:
321
+ Step 1 叫執行者對 host 目錄每個檔跑 `git hash-object {path}`、把 `path → blob` 清單當
322
+ baseline,Step 4 再拿它判「差異恰為 Step 2、Step 4 終局 Resume Pointer 寫入、Step 4
323
+ 指令 1 所命令的 edit,別無其他」。**但沒有 `-w` 的 `hash-object` 不寫物件庫**,baseline
324
+ 的**內容**事後取不回(`git cat-file -p` 回 `fatal: Not a valid object name`),而一份
325
+ hash 清單只答得出「相同/不同」—— 在正常路徑上「不同」正是**預期**答案,因為那三步
326
+ 本來就會改 `_index.md`。Step 4 又明文禁止退回用 `HEAD^`(理由正確:此時工作區還帶著
327
+ 未提交的 finalization edit 與 documentation sweep delta),所以沒有替代基準。
328
+ **那條檢查用它自己指定的證據執行不了。**
329
+ Step 1 現在改用 `git hash-object -w {path}`,並在旁邊寫明 `-w` 是強制的。Step 4 改成
330
+ 真的去 diff:與 baseline 不同的檔用 `git diff {baseline blob} HEAD:{completed path}`
331
+ 讀真正的 delta,拿那個 delta 去對推導條件;與 baseline 相同的檔只在「沒有任何一步
332
+ 命令過改它」時才算滿足 —— 命令過而沒動,就是那個 edit 沒落地,擋。degraded 條款也
333
+ 擴及「baseline blob 讀不回來」。
334
+ ⚠ **同一批另修掉一個既有缺陷**:Step 4 原本**斷言** baseline 與 committed span
335
+ 「line up entry for entry」而沒有去比。span 來自 `git ls-tree`(commit 側),所以
336
+ **Step 1 之後被刪掉的 host 檔永遠不會被比到**,之後新增的檔**沒有 baseline blob
337
+ 可 diff**;而另一半的 spill check 是整個 host 目錄照收,也擋不住 —— 兩半都放過的是
338
+ edit fallout 裡最粗的一種。現在先比兩個路徑集合、再比 blob,兩種不一致各自給裁決。
339
+ 兩軌對稱。既有專案再跑一次 `dflow configure-agents` 即取得修正後的 flow 檔;
340
+ **沒有遷移動作**。
341
+
342
+ - **`_index.md` 的 Current BR Snapshot 範例列移出資料面(P-095,dist issue #14)**:
343
+ 這張表的範例列 `| BR-01 | {規則描述} | phase-1 / inherited from rules.md | phase-N |
344
+ active / removed |` 五格裡有三格不是值。它與 issue #11 是同一個缺陷類(範例被當成
345
+ 起始狀態照抄),**但後果相反**:#11 會被關帳擋下,**這一個會通過** —— 關帳的 Step 1
346
+ 只檢查「這張表非空嗎」,接著 Step 3 把**每一列**推進 bounded context 的 `rules.md`。
347
+ **live 表現在只留表頭**,範例移進一段 HTML 註解、明標「這不是資料」並指回既有 flow
348
+ 規則(`First Seen` / `Last Updated` / `Status` 的權威語義本來就在
349
+ `modify-existing-follow-up.md` 與 `finish-feature-flow.md` / `new-phase-flow.md`
350
+ 裡,這裡不再抄一份)。
351
+ 表上方另加一句可見的規則:**本表起始為空,只有這個 host 真的帶著 BR delta 時才會有
352
+ 列;BC-bearing 的 follow-up host 另外會從 `rules.md` 繼承 in-scope 的列。**
353
+ ⚠ **為什麼不是加一道關帳檢查**:那會為一個**沒有量測、也沒有已知案例**的風險,讓
354
+ **每一次關帳**付費,而且會誤擋三種合法情境(`inherited from rules.md` 的繼承列、
355
+ 合法的空表、一條還沒進 `rules.md` 的新 BR)。移除污染源比派人看守它便宜得多。
356
+ ⚠ 這個修法押著一個假設:**執行中的 AI 會讀 raw Markdown 註解當成 guidance**。本範本
357
+ 已有兩處同形狀的先例(`Template note (for AI)`、被註解掉的 Follow-up Tracking),
358
+ 但**沒有實測採用者行為**。
359
+ ⚠ **兩軌刻意不對稱**:brownfield 另有一句 —— `Tier = baseline` 的 capture host
360
+ 本表留空、而且**不繼承**,即使它是 BC-bearing 的 follow-up 也一樣。greenfield 不加,
361
+ 因為它**沒有 baseline capture 這種 host**。其餘新增內容兩軌逐字相同。
362
+ 既有專案再跑一次
363
+ `dflow configure-agents` 即取得修正後的範本;**沒有遷移動作** —— 已經照抄了那一列的
364
+ host,刪掉它即可(那一列本來就不該存在)。
365
+
366
+ - **`_index.md` 範本的 Checkpoint Log 範例表不再被照抄成起始狀態(dist issue #11)**:
367
+ 範例表四列俱全(`branch-override` / `spec-baseline` / `implementation` /
368
+ `closeout`),而註解只講「minimal host 一律記兩個 checkpoint」,**沒有一句說每一列
369
+ 是什麼時候才寫下**。照著實例化一個 minimal host(zero-phase)的人會把 `closeout`
370
+ 列也預先放上去,然後在**整個實作與 commit 週期之後**才被關帳檢查擋下 —— 那道檢查
371
+ 要求 Checkpoint Log 此刻**恰好一列**。回報者列過這張表**四列沒有一列可以照抄**的
372
+ 理由,而表上沒有任何標記能讓讀者推出這件事。
373
+ 範本因此在表前補一段:**下表示範的是欄位值,不是這張表的起始狀態,一列都不要預先
374
+ 放**;每一列在它那個 checkpoint 實際走到的當下才新增,`closeout` 列由
375
+ `references/finish-feature-flow.md` Step 4 指令 1 在關帳當下寫入。
376
+ ⚠ 同時修掉診斷訊息的另一半:`references/finish-feature-minimal-host.md` Step 1
377
+ 原本只列「多一個 `implementation`」「游離的 `spec-baseline`」「放棄嘗試的殘留」
378
+ 三種成因,**最可能的那一種——順著範本預先放下的 `closeout` 列——一項都沒對上**,
379
+ 而該處自己要求「report the one that is true」。現在改成一條**述詞**而不是一份清單:
380
+ 分辨兩種修法的是**這一列有沒有記錄一個這個 host 真的走到的 checkpoint**,不是那幾格裡
381
+ 放了什麼。記錄不到的就刪掉(`closeout` 列是一個,因為關帳還沒跑;從範例表抄下來的
382
+ 任何一列也是);記錄得到的才是生命週期問題,要跟開發者解決。剩下的成因寫成開放的
383
+ 一類,不是封閉清單。
384
+ 兩軌對稱。既有專案再跑一次 `dflow configure-agents` 即取得修正後的範本與 flow 檔;
385
+ **沒有遷移動作**,已經走到一半的 host 若已預先放下 `closeout` 列,刪掉那一列即可。
386
+
387
+ - **`finish-feature` 的終局 cursor 改在歸檔那一刻才寫,Steps 5/6 正名為確認點(P-093)**:
388
+ 舊流程在 **Step 2** 就把 Resume Pointer 寫成 `Active Workflow: none`(宣告 workflow
389
+ 已結束),但同一支 flow 在那之後**還有兩個 step gate 會叫開發者打 `/dflow:next`**,
390
+ 而 `AI-AGENT-GUIDE.md` 規定「沒有 active workflow 時 `/dflow:next` 必須被拒絕」——
391
+ 兩份出貨檔在一個具體動作上直接衝突。
392
+ **第一刀**:Step 2 改寫**誠實的進行中值**;終局值移到 **Step 4、緊接 `git mv` 之後**
393
+ 寫入,並定義成**不可中斷的一對**(Y/N 提示、對開發者提問、會等輸入的 tool call、
394
+ `git status` 都不得插入其間)。⚠ 中間隔一個等待點就會開一個窗口:host 已在
395
+ `completed/`、cursor 卻還宣告 `finish-feature` 進行中,`/dflow:cancel` 會在那裡生效。
396
+ **第二刀**:`Step 5 → Step 6` 移出開頭的 Step Gates 表,正名為
397
+ **post-Local-closeout confirmation** —— 它會停下來等,但**不是 step gate**、不更新
398
+ cursor、不吃 `/dflow:next` 與 `/dflow:cancel`;表後的 catch-all 一併改寫成三分割。
399
+ ⚠ **型別歸屬是無條件的,「會停等」才是有條件的**(只有帶 `follow-up-of` 的 host
400
+ 會走到)。兩者若一起條件化,非 follow-up host 會掉回 catch-all 並同時讀到
401
+ 「宣告進入 Step 6」與「跳過 Step 6」。
402
+ 兩軌對稱;連帶更新 `_index.md` 範本的 cursor 契約、rationale registry、五份走查與
403
+ 兩個 completed fixture 的終局 `Next Action`。
404
+ ⚠ **失敗路徑不還原 cursor** —— 這是刻意的能力收窄,不是漏做。
405
+
406
+ - **`finish-feature` 的 minimal host(zero-phase)檢查改為獨立檔(P-087)**:
407
+ `/dflow:finish-feature` 是**每個 feature 收尾都會跑**的指令,而它的 Step 1 檢查表
408
+ 裡有一大段只在 **minimal host(zero-phase,也就是 T2/T3 小改動開出來的 host)**
409
+ 上適用 —— 一個帶 phase 的 feature 每次收尾都要把那段讀完,一條都用不到。這批檢查
410
+ (加上 Step 3 的 sync input、Step 4 post-commit 的尾巴、Step 5 的欄位規則)搬進
411
+ 新檔 `references/finish-feature-minimal-host.md`(兩軌各一份),主幹在 Step 1 的
412
+ 選擇器後面留一句「開哪一支檔」,Step 3/4/5 各留一行指標。
413
+ **greenfield 1,048 → 739 行、brownfield 1,073 → 723 行(−29.5% / −32.6%)。**
414
+ 同時把 Step 5 那段「主線 hotfix 跟這個 feature 撞到」併進既有的
415
+ `references/finish-feature-post-hoc-hotfix.md`,那支檔現在依**進入時機**分成
416
+ § Before closeout / § After closeout 兩節(40 → 95 行)。
417
+ ⚠ **一行規則都沒有刪**,但**不是純搬移**:搬家會讓一批句子在原地變成假的
418
+ (`above`/`below` 跨了檔、指向 Step 1 的指標指到空的地方),這次逐處改寫了
419
+ **53 句**,四個方向都有 —— 主幹指向被抽內容、被抽內容指回主幹、既有分支檔指向
420
+ 即將搬進它的內容、`pr-review-checklist.md` 指進被抽走的區塊。
421
+ ⚠⚠ **收益是不對稱的,這是設計而不是缺陷**:省到的是 **phase-bearing** 的 host;
422
+ **minimal host 自己反而多讀 43 行(+4.1%)**,因為它要多載入一支檔。判準是
423
+ **context 壓力峰值** —— 峰值落在 phase-bearing 的 T1 收尾(同時扛著 aggregate
424
+ design、phase specs 與領域建模),minimal host 是低壓力那一側。
425
+ ⚠ 採用者實拿的**磁碟總量略增**(多兩支檔 + 指標句),下降的是**單次執行讀進
426
+ context 的量**。既有專案再跑一次 `dflow configure-agents` 即取得新結構,
427
+ 沒有遷移動作。
428
+
429
+ - **`finish-feature` 的四個檢查,標頭宣告的適用範圍比它真正的讀者窄(P-086)**:
430
+ `finish-feature-flow.md` 有數十個標頭自我限定的區塊(`Minimal host (zero-phase)
431
+ only` 那種)。其中四處**藏著一條其實不分 host 形狀都需要的規則** —— 一個帶 phase
432
+ 的 feature 收尾時永遠不會讀到它,**而且不會有任何指標告訴它漏了什麼**。
433
+ 具體會發生什麼:一個 T1 分幾個 phase 進行,中間夾一個 hosted `Tier = T2` 小改動,
434
+ 那個小改動改了某個 domain event 的欄位;收尾時 Step 3 只說「把 **phase-spec**
435
+ 引進的新 event 加到 `events.md`」,而那筆改動記在 **lightweight-spec** 裡 ——
436
+ **`events.md` 就少一筆,沒有人會發現。** 嚴重度是「靜默失敗」。
437
+ 四處都改成:不分 host 的那一半移到每個 host 都會讀的地方,受限的那一半留在原處
438
+ 並寫明它只證了什麼、誰接手剩下的。**greenfield 965 → 1,048 行、brownfield
439
+ 1,012 → 1,073 行**(brownfield 只有三處,第一處的欄位在 brownfield 不存在)。
440
+ `references/pr-review-checklist.md` 同時新增第 7 項承接「no-BC host 不得 commit
441
+ 進一個它沒有的 bounded context」的分支範圍舉證,並修掉一句沒有限定的宣稱
442
+ (greenfield 383 → 407、brownfield 437 → 465 行)。
443
+ ⚠ **沒有新指令、沒有遷移動作**:既有專案再跑一次 `dflow configure-agents` 即取得
444
+ 修正後的 flow 檔。
445
+
446
+ - **`modify-existing` 的兩條罕見路徑改為獨立檔,一次執行不再整份讀(P-085,第一批)**:
447
+ `/dflow:modify-existing` 與 `/dflow:bug-fix` 每跑一次,AI 都要把
448
+ `modify-existing-flow.md` 整份讀進 context,而其中兩條路多數執行根本不會走:
449
+ **Step 1.6**(把修改掛成某個已完成 feature 的 follow-up)與 **Step 1.8**
450
+ (補記錄一個已經緊急上線的修復)。這兩段搬進新檔
451
+ `references/modify-existing-follow-up.md` 與
452
+ `references/modify-existing-post-hoc-hotfix.md`,主幹留下標題與一句
453
+ 「開哪一支檔」的指標。**greenfield 819 → 662 行、brownfield 953 → 778 行
454
+ (約 −18%)。**
455
+ ⚠ **一行規則都沒有改**:搬移後把新舊檔重新組合回原檔,與搬移前**逐位元組相同**。
456
+ 留下來的 Step 1.5(問開發者這是不是 follow-up)與 Step 1.7(開最小 host)
457
+ **刻意不動** —— 判讀顯示漏掉這兩者會靜默做錯而下游無人接手,所以它們不得住在
458
+ 指標後面。
459
+ ⚠ **總 bytes 略增**(多兩支檔 + 指標句),下降的是**單次執行讀進 context 的量**
460
+ —— 這正是本案要優化的量。既有專案再跑一次 `dflow configure-agents` 即取得新結構。
461
+ 新增 dev-only 檢查 `scripts/check-flow-dispatch.mjs`:分支檔必須恰有一個
462
+ dispatcher 指向它、且兩軌對稱,避免主幹哪天不再指過去而罕見路徑靜默失去規則。
463
+
464
+ - **`finish-feature` 的兩條罕見路徑也改為獨立檔(P-085,第二批之一)**:
465
+ `/dflow:finish-feature` 是**每個 feature 收尾都會跑**的指令,而其中兩段多數
466
+ 執行不會用到:**post-hoc hotfix 的前置調解**(別人的緊急修復跟你這個 feature
467
+ 撞到)與 **Step 6 的 follow-up 反向連結翻轉**(只有 follow-up feature 才跑)。
468
+ 兩段分別搬進 `references/finish-feature-post-hoc-hotfix.md` 與
469
+ `references/finish-feature-follow-up.md`。**greenfield 1,160 → 1,082 行、
470
+ brownfield 1,211 → 1,133 行(約 −6.5%)。**
471
+ ⚠ **一行規則都沒有改**:Step 6 的本文逐位元組未動;hotfix 那段只做了一個**宣告
472
+ 過的機械轉換**(剝除一層 `>` 引用標記,因為它從主幹的 callout 變成獨立檔的本文),
473
+ 加回標記後與搬移前逐位元組相同。
474
+ ⚠ **主幹留下的 hotfix hook 是原文,不是新寫的**——「在下面任何檢查之前先處理重疊;
475
+ 檢查通過之後才記入本 host 的內容等於繞過了它們」這句本來就在,它自己就擋得住錯誤
476
+ 執行,所以只在後面接一句「細節見哪支檔」。
477
+
478
+ - **設計理由與維護歷史搬出 `finish-feature` 主幹(P-085,成分 2)**:
479
+ `finish-feature-flow.md` 裡有一批句子不是在告訴 AI 要做什麼,而是在解釋**這條規則
480
+ 為什麼長這樣**,或在講**文件自己**(「這一條沒有東西強制它」「上一版是什麼形狀」)。
481
+ 它們對執行沒有幫助,卻每一次 feature 收尾都被讀進 context。這批句子挑出來搬走:
482
+ **設計理由**進新的出貨查表檔 `references/flow-rationale-registry.md`
483
+ (單源於 `templates/common/`,逐字投影兩軌);**維護歷史與講文件自己的句子**進
484
+ dev-only 記錄,不出貨。**本次約 −11%;連同成分 1,greenfield 1,160 → 965 行
485
+ (−16.8%)、brownfield 1,211 → 1,012 行(−16.4%)。**
486
+ ⚠ **一條規則都沒有搬走。** 判準是「刪掉這句之後,AI 做對的機率是升還是降」——降就
487
+ 留下。所以「這個檢查判不了 X」「下游沒有東西接手 Y」這類**邊界宣告**全部留在主幹,
488
+ 即使它們讀起來跟設計理由一模一樣。
489
+ ⚠ **搬移無損,機器驗過**:把 registry 裡每一段從搬移前的原檔逐一刪掉、忽略空白比對,
490
+ 結果與現在的主幹**完全相同**(greenfield 32 段、brownfield 33 段)。除了三處宣告過的
491
+ 標點收尾(冒號改句號、拿掉一個開頭的 `But`)之外,沒有任何一句被改寫。
492
+ ⚠ **rationale registry 不要整份讀**:它是一個規則一行的查表檔。開發者問「這規定為什麼
493
+ 存在」時,用規則本身的字去 grep 那一行就好;`AI-AGENT-GUIDE.md` § Routing Non-Command
494
+ Input 多了一行告訴 AI 這個檔存在。既有專案再跑一次 `dflow configure-agents` 即取得。
495
+
496
+ - **`dflow doctor` 新增 `uncertain` 結果狀態 — 它會讓「乾淨」這個結論本身失效(P-084)**:
497
+ doctor 讀 `_conventions.md` 時靠 Markdown 區塊結構定位規則句,而那個讀取器有一批
498
+ **已知會讀錯的形狀**。過去這些缺口只寫在原始碼註解裡:使用者踩到了,拿到的仍然是
499
+ 一句 `All checks passed`,語氣與真正乾淨的專案一模一樣。現在只要偵測到這類形狀:
500
+ **(1)** 不會印出 `All checks passed`;**(2)** 受影響的檢查會被逐項列名,並明說
501
+ 「它們沒有出聲不代表通過」——因為 doctor 是有問題才講的工具,沉默平常就代表沒事;
502
+ **(3)** 印出穩定的偵測器 id 並連到說明頁。**exit code 不變,仍然是 0**:不確定不是
503
+ 建置失敗,doctor 從來沒有用非零 exit code 表達任何一條 finding。
504
+ 掃描 `_conventions.md` 與 `AI-AGENT-GUIDE.md` 這兩個「doctor 會針對其內容做出宣稱」
505
+ 的檔案,回報四種形狀:`inline-html-comment`(行中間才開始的註解——**靜默**把已關掉的
506
+ 規則讀成還在)、`comment-inside-container`(**容器裡面**的註解——清單項、引用區塊,
507
+ 以及 `<details>`/`<pre>` 這類 HTML 區塊都算——同樣靜默,而且**關不關起來都一樣**,
508
+ 問題出在它待的位置)、`unclosed-html-block`(文件層級沒關的區塊,雙向)、
509
+ 以及 `html-block-type-7`。
510
+ ⚠ **這份清單不是窮舉**,說明頁本身也這樣寫——沒被列出不等於已驗證安全。
511
+ 每個偵測器都是**對著出貨的 renderer 校準**的:形狀要實測到 doctor 與 renderer 讀法
512
+ 不同才會出聲,因為一個會在正確檔案上誤報的警告,會教會大家把所有警告都當耳邊風。
513
+ ⚠ 但**有一個刻意的例外,而且它是故意保守的**:`comment-inside-container` 對寫在
514
+ `<textarea>` 裡面的註解仍然回報,即使那裡讀者**看得到**該文字、兩邊讀法其實一致。
515
+ 豁免它試過三次,每次都反而造出「**真的**被藏起來的註解沒人回報」的情況,所以豁免被
516
+ 移除而不是再補一次;兩份說明頁都用整整一節說明遇到它該怎麼辦(保持那一行不變,但
517
+ 不要把整體的不確定結論當成通過)。乾淨的專案輸出完全不變。
518
+ ⚠⚠ **有兩個已知缺口刻意不回報,而第二個的理由值得寫下來。** 第一個是表格內的縮排
519
+ 續行:原型在 151 份真實檔案裡誤報 5 次,對它而言警告比缺口本身更糟。
520
+ 第二個是**畸形的表格分隔列**(格數與標題列不符)。它**真的**會害 doctor 讀錯節邊界,
521
+ 而且兩個方向都會——但為它寫的偵測器**連續六輪 review、每一輪都被找到一份會漏掉的
522
+ 文件**,而漏掉的方向一律是靜默:對已經漂移的檔案印出 `All checks passed`,比不回報
523
+ 更糟。收窄成「只報實測會讀錯的形狀」失敗五次;放寬成「任何格數不符都報」在第六次
524
+ 失敗,因為剩下的那份清單搬進了「怎麼認出一列分隔列」。其中一輪還量到**分隔列格數
525
+ 正確時**同樣的靜默失敗也會發生——也就是說這個偵測器的範圍本來就只是問題的一部分。
526
+ 耐久解是換工具而不是再寫一份更好的清單:`marked`(`dflow render` 用的那支 renderer)
527
+ 已經是本套件的相依套件,節邊界可以直接向它取得。那是另一項設計改動、要走自己的評估,
528
+ 所以本版**誠實地把它列為不檢查的缺口**,而不是留一個會靜默漏掉的檢查。
529
+ 兩份說明頁都寫明了這一條,殘餘風險記在 `planning/opt-in-backlog.md`
530
+ 的 `doctor-section-boundary-arbiter`。
531
+
532
+ - **新增說明頁 `docs/doctor-uncertainty.md` + `.en.md`(P-084)**:
533
+ 每個偵測器 id 一節,寫明形狀長什麼樣、為什麼讀不準、往哪個方向失敗(靜默漏報 vs
534
+ 大聲誤報)、以及怎麼改寫規避。CLI 連英文頁、中文頁一次語言切換可到,與升級指引的
535
+ 既有作法一致。**這個機制本身就是重點**:容器清單住在一個可以隨時修訂的頁面上,
536
+ 而不是住在改一次就要發一次版的 shipped 訊息裡。
537
+
538
+ - **`dflow doctor` 不再對一個裝壞的套件說「全部通過」**:
539
+ 安裝的 dflow 套件若少了工作流程 bundle 需要的來源檔(下載中斷、tarball 不完整、
540
+ 本機 checkout 被動過),doctor 過去會印出 `All checks passed`、exit 0——**而同一棵樹的
541
+ `dflow configure-agents` 在寫任何一個 byte 之前就硬失敗**。兩個指令對「這個套件能不能用」
542
+ 給出完全相反的答案,而使用者會先問 doctor。
543
+ 成因是套件完整性檢查的例外被無聲吞掉,連帶讓「退休 bundle 檔」那項掃描整個跳過。
544
+ 現在會回報一條 `[warn]`,**指名缺了哪支檔**,並明說**問題出在安裝的套件、不是你的專案**,
545
+ 處置是重裝。**在任何目錄裡都會驗,而且每一軌都驗**——包含工作流程 bundle 還沒投影
546
+ 或被刪掉的專案、doctor 判不出 track 的專案,以及**根本不是 Dflow 專案的目錄**。
547
+ ⚠⚠ **但要清楚它驗到哪裡為止,兩個維度都要講。**
548
+ **範圍**:只驗**工作流程 bundle 的來源樹**——`templates/{common,軌}/references/` 與
549
+ `templates/{軌}/templates/`。套件裡**其他**來源樹**不在範圍內**,例如
550
+ `templates/{軌}/scaffolding/` 與 `templates/common/skill/`:少掉其中一支
551
+ (實測 `scaffolding/AI-AGENT-GUIDE.md`、`common/skill/SKILL.md`)doctor 仍會說
552
+ 「全部通過」,而 `configure-agents` 會硬失敗。
553
+ ⚠ **這一句在 P-090 之後有一個例外**(見上方 P-090 那條):`scaffolding/Git-principles-{policy}.md`
554
+ 現在由 starter drift 檢查自己驗——它缺席或 marker 壞掉都會回報,
555
+ 且**不因專案自己那份檔不見而跳過,也不因 track 推不出來而跳過**:edition 推不出來時,
556
+ **選定 policy 底下的每一個候選軌都會驗**(全部候選都壞才說死「configure-agents 會失敗」,
557
+ 只壞其中一軌則說「取決於它解析到哪一軌」)。**其餘 scaffolding 檔仍不在範圍內。**
558
+ **深度**:驗的是來源檔的**清單**——哪些檔在不在、有沒有跨樹撞名、`references/` 與
559
+ `templates/` 是否都非空——**不是檔案的內容**。所以「檔在、但讀不到內容(權限)」
560
+ 「檔在、但是空的」「少了一支不在必要清單裡的檔」也驗不出來,而最後那類還會被
561
+ 誤判成你專案裡的「退休檔」。
562
+ ⚠ **以上全部是既有缺陷、不是本次引進的**(以變更前的程式逐條實測確認),已另行列冊
563
+ 追蹤,修法需要一份隨套件出貨的清單與雜湊,屬於獨立提案。**列在這裡是因為一份宣稱
564
+ 「不再說假話」的變更,不該對自己的覆蓋範圍說假話**——而第一版正是這樣:它把「內容」
565
+ 講成唯一的缺口、還把清單寫成窮舉,兩者都被收尾輪實測推翻。
566
+ ⚠ **「會擋到你」和「你的安裝壞了」是兩個問題,報告分開回答**:
567
+ - 壞的是**你這個專案會用到的**那部分(共用樹,或你這一軌)→ `[warn]`。
568
+ - 壞的是**你用不到的另一軌** → `[info]`,明寫它不會擋到你、為什麼,以及
569
+ **這個安裝是共用的**——同一台機器上用那一軌的別的專案還是會踩到。
570
+ 這種情況兩個指令**是一致的**、而且都是對的;報成 `warn` 會把原本的不一致往
571
+ 反方向重建(doctor 說壞、`configure-agents` 說好),等於拿一個假宣稱換另一個。
572
+ - ⚠ **只有在 doctor 與 `configure-agents` 對「這個專案屬於哪一軌」的判定一致時,
573
+ 才會說某一軌「用不到」。** 兩者的判定來源不同(doctor 優先看 manifest、
574
+ `configure-agents` 只看目錄結構),不一致時**一律當成兩軌都會用到**。
575
+ ⚠ **exit code 仍是 0**:doctor 從來不用非零 exit code 表達 finding,這條也不例外——
576
+ 改變的是它不再宣稱乾淨。**健康的套件輸出完全不變。**
577
+ ⚠ 訊息裡另外兩句話也只在成立時才出現:「退休檔掃描沒有跑過」只在該掃描本來會跑時
578
+ 附上(判得出 track、且 bundle 已投影),「`configure-agents` 也會失敗」只在兩個
579
+ 判定一致時才這樣斷言——**報告一個沒有發生的後果,跟這次要消滅的假宣稱是同一類。**
580
+
581
+ - **`dflow-feedback-flow.md` 收成單一來源 — 投影出來的內容除一句例句外不變**:
582
+ 這支 flow 原本兩軌各存一份,而兩份**只差一行**:可安全附在 issue 裡的證據清單中,
583
+ 那句「generic project type」的舉例。其餘逐字相同——也就是說它早就是 edition-neutral 的,
584
+ 只是被存成一對。現在它與 `ddd-modeling-guide.md` 一樣住在
585
+ `templates/common/references/`,投影到兩軌的目的地路徑完全不變
586
+ (`dflow/specs/shared/dflow-workflows/references/dflow-feedback-flow.md`)。
587
+ 那句例句改寫成不指涉任何 edition(同時列出「既有」與「新建」兩種形狀)。
588
+ **對採用者的實質影響只有那一句**;維護面則是上游 issue form 改版時的同步從兩份變一份,
589
+ 且 `check-repo-consistency.sh` 與 bundle collision guard 會擋住 per-track 複本重新出現。
590
+
591
+ - **Brownfield `dflow init` 不再承諾一個它永遠不會建的目錄 — 既有專案不需遷移**:
592
+ `Will defer:` 預覽原本對兩軌都列出 `dflow/specs/architecture/decisions/ADR-*.md`,
593
+ 但 Brownfield 建的是 `dflow/specs/migration/`、`architecture/` 從頭到尾不存在。
594
+ 成因是那一列住在名為「common」的清單裡。現在它與 `events.md` 一樣是 greenfield-only:
595
+ **Greenfield 的五列與順序完全不變,Brownfield 從四列變成三列。** 只影響 init 預覽
596
+ 的輸出文字,不影響任何已建立的檔案。
597
+
598
+ - **`dflow doctor` 新增 info 級偵測:guide 的 `## Project Context` 被 HTML 區塊藏住**:
599
+ 未關閉的 `<!--`(或其他 HTML 區塊)會讓那個標題變成區塊內容,於是
600
+ `configure-agents` 的 context 推斷靜默退回 `unknown` / `none`。舊訊息說「找不到這個
601
+ 段落、請補一個」——對一個明明就有那段的檔案是不可能執行的建議。新的 finding 會指出
602
+ 是哪一個區塊、開在第幾行,並說明「註解忘了關」與「刻意註解掉」同形、doctor 分不出來。
603
+ 同批把 `_conventions.md` 未關閉區塊那條 warn 的說明補成雙向:那個區塊**既會**造成
604
+ 誤報、**也會**壓掉本來該報的 finding。另外,原本那條「找不到 `## Project Context`
605
+ 段落」的 finding 也補上了第二個成因——**標題行本身不是那個標題**(`## Project Context###`
606
+ 這種右側 hash 前沒有空白的寫法、層級不是 `##`、或文字裡混進隱形字元),detail 與
607
+ action 兩處都給出路,不再只把人導向「請補一個段落」。
608
+
609
+ - **`_index.md` 範本的兩處指引修正 — 會隨 workflow bundle 投影到既有專案**:
610
+ 兩軌 `templates/*/templates/_index.md`(投影成
611
+ `dflow/specs/shared/dflow-workflows/templates/_index.md`,每次 `configure-agents`
612
+ 都會重新投影)。(1) 佔位字串警語原本有兩句已被同批 shipped 規則推翻——現在改成
613
+ 「凡照空/非空判的規則都會把佔位字串讀成已填」,並點名真正會去**解析**這個值的
614
+ 幾處檢查(判準是「會不會解析」,不是列了幾項)。(2) 新增 Checkpoint Log 的欄位值
615
+ 詞彙句:`spec-baseline` / `implementation` / `closeout` 是 `Checkpoint` 欄的字面值,
616
+ 散文裡的「spec 完」是里程碑名、不是欄位值;並註明 `git-integration.md` 的選配
617
+ trailer 有它自己的 `{spec|impl|closeout}` 角色名,不要拿這條去改寫對的 trailer。
618
+ **不需要採用者做任何事**——bundle 自己會重新投影。
619
+
620
+ - **Standalone / minimal(zero-phase)host 生命週期(P-083)— 新能力,既有專案不需遷移**:
621
+ 在此之前,**沒有所屬 feature** 的 T2/T3 改動沒有可執行的承接路徑——AI 只能回報
622
+ 缺口、與你商量記在哪。現在 `/dflow:modify-existing` 會開一個 **zero-phase host**:
623
+ 沒有 phase-spec,Lightweight Changes 的列在 checkpoint 1 **之前**寫好,依改動類別
624
+ 切分支(**功能性 bug** → `bugfix/BUG-{NUMBER}-{slug}`,其餘 standalone T2/T3 →
625
+ `feature/{SPEC-ID}-{slug}`),最後照常用 `/dflow:finish-feature` 收尾。涵蓋
626
+ standalone、follow-up、**post-hoc hotfix**(已合併到主線的緊急修復事後補記,
627
+ Step 1.8)三種情境;brownfield 另有 **baseline capture** host。
628
+
629
+ - **`_conventions.md` 補回兩個從未被投影出去的小節(P-083)— 既有專案需要手動補**:
630
+ `### SPEC-ID Format` 與 `### Slug Conventions (Project-Specific Fill-In)` 自
631
+ `v0.1.0` 起**從未**被 `dflow init` 寫進任何專案。模板一直正確地帶著它們,但兩節被
632
+ 放在 `## Prose Language` 底下,而 init 會整段替換該節、連帶吞掉底下的 `###` 子節。
633
+ 本版把兩節移到 `## Where Specs Live` 底下(它們原本的位置,語意上也對——ID 格式與
634
+ slug 慣例跟散文語言無關),新專案 init 即可拿到。
635
+
636
+ **既有專案不會自動取得**:`_conventions.md` 是你擁有的檔案,`dflow init` 與
637
+ `configure-agents` 都不覆寫它。若你依 `docs/upgrading.md` 的做法「用相同答案跑一次
638
+ 全新 init,再逐項分類差異」,會看到多出這兩節——**那是預期的**,把它們複製進你的
639
+ `_conventions.md`、放在 `## Prose Language` **之前**即可。特別注意
640
+ `### Slug Conventions` 裡的 `Project-specific term list` 是要你填的空格:因為這個
641
+ 缺陷,它從來沒有被問過任何人。
642
+
643
+ **`dflow doctor` 現在會替你發現這件事(P-082)**:它逐節檢查你的
644
+ `_conventions.md`,分兩種狀況報。**節整個不存在** → `info`(例如上面這兩節:沒有任何
645
+ 已發布版本投影過,所以每個既有專案都一樣缺,那是「你從沒被提供過的內容」、不是健康
646
+ 問題)。**節在、但少了現行規則** → `warn`(那是你自己的 convention 檔跟出貨流程當面
647
+ 矛盾,例如 Ceremony Scaling 少了 escalate-only 那條,表格就變成可以把 cascade 判高的
648
+ tier 調低)。檢查是**逐節**做的,不是整檔搜字串——規則出現在別節不算數。Dflow 一律
649
+ 只報告、不改寫你的檔案。
650
+
651
+ - **Tier 判定改為順序 cascade(P-082)— 會改變既有專案的分級結果,升級前請讀完本條**
652
+ (本條講的是**進入 workflow 之後**的分級;決定 Dflow 何時**自己出現**的觸發面見
653
+ 下一條——本版一併改了):
654
+ 原本的 T3「四準則 checklist」把 user-visible 的版面/文案修正和不可見的
655
+ code formatting、內部註解**並列在同一格**,導致同一份判準可以推出兩種答案。
656
+ 現在兩軌 `AI-AGENT-GUIDE.md` § Ceremony Scaling 與 `modify-existing-flow.md`
657
+ 改用**順序判定 cascade(步驟 0–4,先命中者勝)**,兩軌逐字一致:
658
+
659
+ - **步驟 0 scope**:cascade 只判「修改」。對**既有** surface 加呈現/互動控制
660
+ (copy 按鈕、日期 filter、排序、quick-view、補 `aria-label`)=修改分流;
661
+ 新 navigable surface、新獨立可消費產出/交付通道(Download-PDF、匯出、
662
+ 排程 email)、新 user-executable domain 操作才是 `/dflow:new-feature`。
663
+ - **不可見 ≠ 不追蹤**:machine-consumed contract(structured log/匯出欄位/
664
+ API/event)、操作語意面(security/safety/resilience/compliance/payment)、
665
+ runtime 效能/資源/SLA 變更**一律進 workflow**,即使產品受眾看不見;
666
+ 行為保持的 **routine** refactor 與 dependency bump 則落 below workflow,
667
+ **不論改動廣度**(廣度不是判準)。
668
+ - **T3 收窄且明確化**:限單一畫面/元件層級、語意保持的 copy/appearance
669
+ 修正;高後果內容(安全警告、密碼提示、同意書、付款/法律聲明)、語意
670
+ 翻轉的配色、影響可操作性/預設狀態/互動順序者(「只是 CSS」不豁免)、
671
+ 補齊缺漏的 accessible name、以及跨畫面掃改,一律升 T2。code formatting
672
+ 與內部註解**不再是 T3**,落 below workflow。
673
+ - **T3 tier-aware 路由**:判為 T3 後直接走 branch gate → 實作 → `_index.md`
674
+ inline 一行,明文 skip Domain/DDD 評估段(greenfield Step 2/3、
675
+ brownfield Step 2/3/4 的 baseline‧delivery‧extraction 段)——小修改不再
676
+ 被迫跑 T1/T2 級分析。
677
+ - **前門命令選擇表對齊**:installed guide 的「Use when」表與 machine command
678
+ registry、六份 `docs/using-with-*`、tutorial 命令面,new-feature/
679
+ modify-existing 兩列都改為與步驟 0 一致——避免 agent 在**進 flow 之前**
680
+ 就選錯命令、讓 cascade 根本不被觸達。
681
+
682
+ - **自然語言觸發面跟上 cascade(P-082 決策 1A)— 會改變 Dflow「什麼時候自己出現」,
683
+ 升級後要跑 `dflow configure-agents --skills`**:
684
+ 在此之前,skill `description` 與 root shim 的排除句是**無限定**的:「refactors、
685
+ renames、chores、formatting、dependency bumps」一律不觸發,shim 還額外明寫
686
+ 「你不需要先讀 guide」。但同一版的 cascade 判定 security/CVE 的 dependency bump、
687
+ 碰 payment 等操作語意面的 refactor、Domain/schema rename 都**要**進 workflow。
688
+ 兩邊直接打架:分類說要追蹤,進場那一關卻叫 agent 別來、順便叫它別去讀那份會告訴它
689
+ 該來的文件。而且這種失敗是**安靜**的——沒有任何測試看得見一個「決定不出現」的觸發器。
690
+
691
+ 現在 skill `description` 與 shim 的 routine 段都改成**具名的窄定義**:routine 只指
692
+ 行為保持、**產品觀眾看不到**、且不碰 architecture/data structure/machine-consumed
693
+ contract(log‧export‧API‧event,以及 env var‧CLI flag‧exit code 這類 inbound 契約)
694
+ /BR-ID/操作語意(security‧CVE、safety、resilience、compliance、payment)/效能‧
695
+ 資源‧SLA 的工作。碰到任一項就不是 routine,由 guide 的 § Ceremony Scaling 裁決
696
+ ——不再由 shim 自己複述一份會漂移的清單。
697
+
698
+ ⚠ **觀眾這一條是後補的**:shim 第一版把 cascade 的軸清單抄齊了,卻漏掉 guide 判準裡
699
+ 「沒有觀眾感知得到的輸出差異」那半句,於是換個按鈕文案、改個顏色這種碰不到任何一條
700
+ 軸、但看得見的改動,被 shim 判成 routine 並附帶一句「你不需要先讀 guide」。**大小不是
701
+ 判準**:單一元素的文案或外觀改動一樣算數。
702
+
703
+ **既有專案要做什麼**:skill 跑 `dflow configure-agents --skills` 換新。root shim
704
+ (`CLAUDE.md`/`AGENTS.md`/`.github/copilot-instructions.md`)若你**沒有自己編輯
705
+ 過**,`dflow configure-agents` 會就地重生——0.10.0–0.14.0 的舊 shim 一樣認得。若你
706
+ 編輯過、而且檔案裡沒有 Dflow 的 marker,Dflow 不會動它:`dflow doctor` 會點名,
707
+ routine 段要你手動換掉。
708
+
709
+ - **no-BR 的 T2 有了合法形狀,不必再捏造 BR(P-082)**:cascade 把跨頁 copy/
710
+ appearance 掃改、非 breaking contract 變更、security/CVE 工作、效能工作、
711
+ 實作缺陷、計畫性互動調整都收進 T2,但這些變更**沒有 BR delta 可填**。兩軌
712
+ `lightweight-spec.md` 新增 **no-BR 六家族**變體,每個家族各有自己的 BR 行與
713
+ 必填證據段:(a) presentation → `Output Footprint`;(b) contract change →
714
+ `Contract Delta` + `Downstream consumers`;(c) operational → `Operational
715
+ Rationale` + `Trace`;(d) performance → `Performance Delta` + `SLA / resource
716
+ context`;(e) implementation defect → `BR Delta: none` + **`Governing BR-IDs:`
717
+ 分欄**(「沒有 BR delta」不等於「沒有治理規則」——缺陷歸哪條規則管仍要留下
718
+ 追溯線)+保留 Problem/Root Cause/Fix Approach/regression;(f) intentional
719
+ change → `Change Rationale` + Before/After + Regression。兩軌
720
+ modify-existing 完成檢查與 `pr-review-checklist` 改為**依家族驗該家族的證據**,
721
+ BR/Domain 項對 no-BR spec 明記 N/A——既不 vacuous pass,也不逼 AI 生一條 BR
722
+ 或假的 Domain 更新來過檢。**既有 spec 一律不遷移**:classic BR-delta 形與舊的
723
+ 單欄 `BR:` bug 形都仍原生合法,readers 兩形容忍。
724
+
725
+ - **README 瘦身重組+「防過度設計」特點露出(P-081)**:兩語 README 重組——
726
+ 重複叢集收斂(skill/configure-agents/升級機制/why 論證的機制細節整併到各自的 canonical 段落)、
727
+ 「狀態」章收為四條、特點表 cell ≤2 句並新增「**防過度設計內建於引導**」
728
+ 列、why 兩章壓成 teaser+連結(證據語氣統一為第一方觀察)。升級 caveat
729
+ 與 marker 狀態矩陣下放新雙語頁 `docs/upgrading.md`/`docs/upgrading.en.md`
730
+ (含 ownership × flag 對照表、latest 標示與「先升 npm latest」提示);
731
+ `dflow doctor` 升級提示改指 canonical URL(`blob/main/docs/upgrading.en.md`,
732
+ 套件內附離線副本),測試鎖定 URL 組合與目標存在。
733
+
734
+ - **Formatting convention 從被動註解升級為主動投遞(P-078 phase 1)**:
735
+ concise-cell/`<br>` 慣例(P-072)原本只存在於模板檔頭 HTML 註解——
736
+ (1) 現在同一句 canonical 守則寫進兩軌 flow references 的**每個記錄型
737
+ doc 寫入點**(new-feature/new-phase/finish-feature/modify-existing/
738
+ drift-verification remediation,每軌 7 處、字串完全一致、可 grep 驗證
739
+ 同步);(2) `dflow doctor` 新增 **info 級**偵測:spec doc 有表格但缺
740
+ convention 註解(全檔搜尋、fence 內表格不算、`shared/` 與
741
+ `features/completed/` 不掃)→ 聚合報告 + 指引 AI 協助補註解,**不自動
742
+ 改寫 user-authored specs**。
743
+
744
+ - **`dflow render` 長欄位可讀性(P-077 A1)**:使用者把長 narrative 塞進
745
+ table cell 時(OBTS dogfooding 實證的「牆」),render 端純排版緩解——含
746
+ 200+ 字欄位的卡片自動撐滿整列並放寬行距;400+ 字欄位以純 CSS 摺疊為 6
747
+ 行、附「展開全文/收合」切換(無 JavaScript、checkbox 鍵盤可操作);列
748
+ 印一律全展開。cell 內容原樣輸出、不做任何語意拆分;source md 完全不變、
749
+ AI 讀取不受影響。
750
+ - **`dflow render` index 檔案樹樹狀視覺**(OBTS dogfooding 回饋):index.html
751
+ 的檔案樹加上導引線(含 └ 收尾)與資料夾/檔案圖示——純 CSS(mask SVG、
752
+ `currentColor` 隨明暗主題著色)、零 JS,HTML 結構與連結不變。
753
+ - **`dflow render` Gherkin 高亮補到實際寫法 + 關鍵字分色**(OBTS dogfooding
754
+ 回饋):高亮從「僅 \`\`\`gherkin fence」擴到三種情境——已標語言 fence、未標
755
+ 語言但 ≥2 行 keyword 開頭的 fence、以及**一般段落步驟**(OBTS behavior.md
756
+ 的主流寫法;每行都以 keyword 開頭才亮,避免英文敘述句誤上色)。關鍵字改
757
+ 分色:Given 綠、When 琥珀、Then 紫、And/But 灰、Scenario: 主色。
758
+ - **`dflow render` 標題色階**(OBTS dogfooding 回饋):h1/h2 深綠
759
+ (dark 模式轉亮青保對比)、h3/h4 主色 accent,強化內頁層級掃讀。
760
+ - **`dflow render` completed/ 年度分頁(P-079)**:`features/completed/`
761
+ 是只增不減的封存區,root index 不再攤開——改為 completed/ 一行年度連結
762
+ (新→舊、含件數),每年度一個**實體頁** `features/completed/index-<年>.html`
763
+ (年份取自 SPEC 目錄名前綴;不合規項目進「未分年」桶頁),頁內新→舊排
764
+ 序、附年度切換列。所有生成 index 頁納入撞名防護(來源若有同名 .md 於任
765
+ 何寫入前拒絕);年度清空時該頁由 manifest 差集自動回收。`features/active/`
766
+ 維持全列(工作集應一眼全見)。
767
+
768
+ ## 0.14.0 — 2026-07-12 — 升級健檢與 guide canonical 區可升級化
769
+
770
+ **Proposals**:PROPOSAL-058(升級期 user-owned 層 drift 偵測 + guide marker-guard)、PROPOSAL-076(configure-agents context inference 死源修正)、PROPOSAL-075(workflow 內容源單一化,內部)
771
+
772
+ 本版主線:讓「升級既有專案」從黑箱變成可診斷、可局部自動化——
773
+
774
+ 1. **`dflow doctor` 成為升級健檢**(058):偵測專案各層相對當前 CLI 版本的
775
+ drift,只報不改。
776
+ 2. **guide 的 Dflow 段落隨升級刷新**(058):`AI-AGENT-GUIDE.md` canonical 區包
777
+ marker、`configure-agents` 原地刷新;你的 `## Project Context` 與 marker 外
778
+ 內容一律保留。
779
+ 3. **context inference 讀真正的資料源**(076):修正 re-projection 時 tech
780
+ stack / migration context 恆退 `unknown` / `none` 的死源缺口。
781
+
782
+ ### 新功能(PROPOSAL-058)
783
+
784
+ - **guide-canonical marker-guard**:兩軌 `AI-AGENT-GUIDE.md` 模板的 canonical
785
+ 段包 `<!-- dflow-generated: guide-canonical START/END -->`;`configure-agents`
786
+ 對 marker 完好的 guide **原地刷新** canonical 區(canonical 區
787
+ substitution-free、刷新 byte-idempotent;保留檔案 EOL 與 marker 外全部內容)。
788
+ - **Consent-gated adoption offers**(互動式、預設 No;非互動一律 skip+warn、
789
+ 不佔 stdin slot):
790
+ - 無 marker 但可辨識的舊 guide → 詢問是否包 marker 並刷新(`## Project
791
+ Context` 保留、其餘替換);
792
+ - 引用 guide 但非 Dflow 管理的 root agent 檔(case 2d)→ 詢問是否附掛
793
+ marker 管理區塊(此後隨升級刷新;提示手動清舊 Dflow 措辭)。
794
+ - **`> Dflow Version:` 進位為 last-reconciled 語意**:`configure-agents` 成功
795
+ 套用後把 `_conventions.md` 的版本行推進到當前 CLI 版;任何 guarded skip 即
796
+ 放棄推進(不高估 reconciliation);行缺失不自動補(doctor 報告)。
797
+ - **doctor 升級 drift 偵測集**(全部 warn/info、exit 0、嚴格唯讀):版本行
798
+ stale/不可解析、政策段存在與機器格式、guide marker 態 + canonical byte 比
799
+ 對、workflow bundle 與 `_conventions` 的 `AI-AGENT-GUIDE.md §` dangling 參
800
+ 照、Git-principles 檔缺失/漂移、active feature `_index.md` 舊模板形狀(附
801
+ AI 協助遷移指引;completed/ 不掃)、root agent shim 態、bundle manifest 版
802
+ 本落後。
803
+ - docs:README(兩語)升級 caveat 段改寫——新升級行為 + doctor 健檢 +
804
+ 「fresh init 對比」保留為徹底驗證 SOP;六個 using-with 檔與 doctor help 同步。
805
+
806
+ ### 修正(PROPOSAL-076)
807
+
808
+ - **configure-agents 的 context inference 死源修正**:
809
+ `techStackSummary` / `migrationContext` 推斷原本讀 `_overview.md` 的
810
+ `| Tech stack |` / `| Migration / legacy context |` 表列——但任何版本的
811
+ packaged `_overview` 模板都從未有這兩列,推斷恆 fallback `unknown` / `none`。
812
+ 現改讀真正的機器可讀落點:guide `AI-AGENT-GUIDE.md` 的 `## Project Context`
813
+ 表(init 自始把 Q2/Q3 答案寫在這裡;只解析 Project Context 段內、段外同名列
814
+ 不遮蔽)。`dflow doctor` 新增 info 級檢查:可辨識/marker 管理的 guide 若缺
815
+ `## Project Context` 段、缺這兩列或列不可解析,會提示 inference 後果;fresh
816
+ init 專案不受影響(列本來就在)。同步校正兩軌 `init-project-flow.md` 把 Q3
817
+ 落點誤述為 `_overview.md` 的殘句。
818
+ - **解析與寫入加固**(076 實作 review 鏈產物,惠及既有 doctor 掃描):fence
819
+ 掃描補齊 CommonMark 閉合規則(fence 長度、info-string 行不算閉合、≤3 空白縮
820
+ 排);guide 可辨識性判準 fence-aware 且與 Project Context 定位一致(接受
821
+ adoption offer 不可能再因 fenced 假標題中止);BOM 容忍;init 把 Q2/Q3 答案
822
+ 寫入表格 cell 時跳脫 `|`,值經 inference 完整 round-trip。
823
+
824
+ ### 內部(PROPOSAL-075)
825
+
826
+ - workflow 內容源單一化:退役兩個歷史 skill-source 鏡像目錄,`templates/` 成
827
+ 唯一內容源(npm 包內容不變;README/docs 對應措辭同步、一致性 guard 防止
828
+ retired 路徑回流)。
10
829
 
11
830
  **Proposals**:PROPOSAL-072(表格 `<br>` 分行慣例)、PROPOSAL-073(`dflow render` 子指令)、PROPOSAL-074(init 預設安裝 project-level skill)
12
831
 
@@ -83,6 +902,10 @@
83
902
  mixed-state sentinel 回歸:flagless 不重生成既有 skill)、三家路徑全驗。
84
903
  `npm test` + `scripts/check-repo-consistency.sh` + `npm pack --dry-run` 全綠
85
904
  (dev 與 dist 兩側)。
905
+ - **Post-publish smoke(對公開 registry 套件,2026-07-10)**:
906
+ `npx dflow-sdd-ddd@0.13.0` 之 `--version` / `--help` 正確;init(非互動
907
+ 舊答案序列)exit 0、預設產出三家 skill 檔;configure-agents exit 0;
908
+ doctor 全過;render 30 md → HTML 成功。registry `latest = 0.13.0`。
86
909
 
87
910
  ### 升級提醒
88
911