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.
- package/CHANGELOG.md +824 -1
- package/CONTRIBUTING.md +16 -10
- package/README.en.md +156 -200
- package/README.md +89 -144
- package/TEMPLATE-COVERAGE.md +15 -8
- package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
- package/bin/dflow.js +36 -4
- package/docs/commands.en.md +110 -0
- package/docs/commands.md +101 -0
- package/docs/doctor-uncertainty.en.md +212 -0
- package/docs/doctor-uncertainty.md +212 -0
- package/docs/evaluating-dflow.en.md +29 -11
- package/docs/evaluating-dflow.md +8 -6
- package/docs/npm-publish-checklist.md +3 -1
- package/docs/release-versioning-policy.md +8 -2
- package/docs/upgrading.en.md +196 -0
- package/docs/upgrading.md +197 -0
- package/docs/using-with-claude-code.en.md +25 -10
- package/docs/using-with-claude-code.md +20 -7
- package/docs/using-with-codex.en.md +18 -6
- package/docs/using-with-codex.md +16 -5
- package/docs/using-with-github-copilot.en.md +25 -10
- package/docs/using-with-github-copilot.md +21 -8
- package/lib/doc-shapes.json +997 -0
- package/lib/doctor-checks.js +2654 -0
- package/lib/init.js +3583 -107
- package/lib/render-diagrams.js +1474 -0
- package/lib/render.js +865 -49
- package/package.json +2 -2
- package/templates/brownfield/references/drift-verification.md +4 -0
- package/templates/brownfield/references/finish-feature-flow.md +635 -88
- package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
- package/templates/brownfield/references/finish-feature-minimal-host.md +406 -0
- package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/brownfield/references/git-integration.md +160 -15
- package/templates/brownfield/references/init-project-flow.md +26 -4
- package/templates/brownfield/references/modify-existing-flow.md +412 -87
- package/templates/brownfield/references/modify-existing-follow-up.md +121 -0
- package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +82 -0
- package/templates/brownfield/references/new-feature-flow.md +61 -6
- package/templates/brownfield/references/new-phase-flow.md +57 -7
- package/templates/brownfield/references/pr-review-checklist.md +303 -10
- package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +158 -34
- package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
- package/templates/brownfield/scaffolding/Git-principles-gitflow.md +75 -6
- package/templates/brownfield/scaffolding/Git-principles-trunk.md +82 -8
- package/templates/brownfield/scaffolding/_conventions.md +50 -28
- package/templates/brownfield/scaffolding/_overview.md +1 -0
- package/templates/brownfield/templates/_index.md +151 -7
- package/templates/brownfield/templates/analysis.md +79 -0
- package/templates/brownfield/templates/behavior.md +1 -0
- package/templates/brownfield/templates/context-definition.md +1 -0
- package/templates/brownfield/templates/context-map.md +2 -1
- package/templates/brownfield/templates/glossary.md +1 -0
- package/templates/brownfield/templates/lightweight-spec.md +154 -11
- package/templates/brownfield/templates/models.md +1 -0
- package/templates/brownfield/templates/phase-spec.md +9 -1
- package/templates/brownfield/templates/rules.md +1 -0
- package/templates/brownfield/templates/tech-debt.md +1 -0
- package/templates/common/references/ddd-modeling-guide.md +33 -16
- package/templates/{greenfield → common}/references/dflow-feedback-flow.md +2 -1
- package/templates/common/references/flow-rationale-registry.md +130 -0
- package/templates/common/skill/SKILL.md +13 -11
- package/templates/greenfield/references/drift-verification.md +4 -0
- package/templates/greenfield/references/finish-feature-flow.md +625 -89
- package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
- package/templates/greenfield/references/finish-feature-minimal-host.md +363 -0
- package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/greenfield/references/git-integration.md +148 -15
- package/templates/greenfield/references/init-project-flow.md +28 -8
- package/templates/greenfield/references/modify-existing-flow.md +378 -85
- package/templates/greenfield/references/modify-existing-follow-up.md +103 -0
- package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +82 -0
- package/templates/greenfield/references/new-feature-flow.md +67 -4
- package/templates/greenfield/references/new-phase-flow.md +56 -7
- package/templates/greenfield/references/pr-review-checklist.md +287 -8
- package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +153 -32
- package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
- package/templates/greenfield/scaffolding/Git-principles-gitflow.md +74 -6
- package/templates/greenfield/scaffolding/Git-principles-trunk.md +88 -12
- package/templates/greenfield/scaffolding/_conventions.md +50 -28
- package/templates/greenfield/scaffolding/_overview.md +6 -2
- package/templates/greenfield/templates/_index.md +137 -7
- package/templates/greenfield/templates/aggregate-design.md +1 -0
- package/templates/greenfield/templates/analysis.md +79 -0
- package/templates/greenfield/templates/behavior.md +1 -0
- package/templates/greenfield/templates/context-definition.md +1 -0
- package/templates/greenfield/templates/context-map.md +2 -1
- package/templates/greenfield/templates/events.md +4 -1
- package/templates/greenfield/templates/glossary.md +1 -0
- package/templates/greenfield/templates/lightweight-spec.md +154 -11
- package/templates/greenfield/templates/models.md +1 -0
- package/templates/greenfield/templates/phase-spec.md +9 -1
- package/templates/greenfield/templates/rules.md +1 -0
- package/templates/greenfield/templates/tech-debt.md +1 -0
- package/templates/brownfield/references/dflow-feedback-flow.md +0 -251
|
@@ -6,6 +6,7 @@ created: {YYYY-MM-DD}
|
|
|
6
6
|
branch: feature/{SPEC-ID}-{slug}
|
|
7
7
|
# follow-up-of: {原 SPEC-ID} # 選用:本 feature 為某個已 completed feature 的 follow-up 時填入
|
|
8
8
|
---
|
|
9
|
+
<!-- dflow-shape: greenfield/_index.md 1 — keep this line: dflow doctor reads it -->
|
|
9
10
|
|
|
10
11
|
<!--
|
|
11
12
|
Template note (for AI):
|
|
@@ -43,7 +44,20 @@ Template note (for AI):
|
|
|
43
44
|
Minimal usage:
|
|
44
45
|
For a 1-commit / 1-phase feature this template can be ~30 lines —
|
|
45
46
|
fill metadata + a short Goals & Scope + one row in Phase Specs +
|
|
46
|
-
|
|
47
|
+
Resume Pointer, and the BR Snapshot **only when this host carries a BR
|
|
48
|
+
delta** — a phase-bearing host whose phase-specs establish none leaves it
|
|
49
|
+
empty, and that section states the rule. The other sections can stay empty.
|
|
50
|
+
|
|
51
|
+
Minimal HOST usage (zero-phase) — a different shape, not a smaller one:
|
|
52
|
+
A minimal host (references/modify-existing-flow.md Step 1.7 standalone, or
|
|
53
|
+
its Step 1.6 follow-up minimal variant, or Step 1.8's post-hoc hotfix, whose
|
|
54
|
+
linkage resolves to one of those two) carries NO phase-spec, and its
|
|
55
|
+
Phase Specs table stays EMPTY. Its record lives in Lightweight Changes
|
|
56
|
+
instead — at least one row, written before the first commit. Do NOT add a
|
|
57
|
+
Phase Specs row or create a phase-spec to make the "1-phase" wording above
|
|
58
|
+
fit: a host that carries a phase is certified as phase-bearing whatever it
|
|
59
|
+
was intended to be, and closeout then checks it as one
|
|
60
|
+
(references/finish-feature-flow.md Step 1).
|
|
47
61
|
-->
|
|
48
62
|
|
|
49
63
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
@@ -79,24 +93,91 @@ Template note (for AI):
|
|
|
79
93
|
> 歷史由各 phase-spec 的「Delta from prior phases」段串接閱讀;feature
|
|
80
94
|
> 完成時 `/dflow:finish-feature` 把本表推進到對應 BC 的 `rules.md` /
|
|
81
95
|
> `behavior.md`(延續 Step 5.3 既有 sync 機制)。
|
|
96
|
+
>
|
|
97
|
+
> ⚠ **這張表在範本裡是空的(只有表頭),那是對的 —— 不要為了讓它看起來有東西而造一列。**
|
|
98
|
+
> 只有這個 host 真的帶著 BR delta 時才會有列(`/dflow:new-feature` 會拿第一個 phase
|
|
99
|
+
> 規劃中的 BR 初始化它;phase-specs 沒有帶出 BR delta 的 host 就留空);**BC-bearing
|
|
100
|
+
> 的 follow-up host** 另外會從 `rules.md` 繼承 in-scope 的列
|
|
101
|
+
> (見 references/modify-existing-follow-up.md)。
|
|
82
102
|
|
|
83
103
|
| BR-ID | Current Rule | First Seen (phase) | Last Updated (phase) | Status |
|
|
84
104
|
|---|---|---|---|---|
|
|
105
|
+
|
|
106
|
+
<!--
|
|
107
|
+
欄位範例(**這不是資料,是給 AI 看的範例**;它在註解裡,所以不會被當成本表的列):
|
|
108
|
+
|
|
85
109
|
| BR-01 | {規則描述} | phase-1 / inherited from rules.md | phase-N | active / removed |
|
|
86
110
|
|
|
111
|
+
⚠ 本區塊不是規範。`First Seen` / `Last Updated` / `Status` 的權威語義在既有
|
|
112
|
+
flow 規則裡:
|
|
113
|
+
`First Seen` 的 `inherited from rules.md` 見 references/modify-existing-follow-up.md;
|
|
114
|
+
`Status` 的 `active` / `removed` 見 references/finish-feature-flow.md Step 3 與
|
|
115
|
+
references/new-phase-flow.md。有衝突時以那些檔為準。
|
|
116
|
+
-->
|
|
117
|
+
|
|
87
118
|
<!-- dflow:section lightweight-changes -->
|
|
88
119
|
## Lightweight Changes
|
|
89
120
|
|
|
90
121
|
> T2 行:描述含「見 `lightweight-{date}-{slug}.md`」外連
|
|
91
122
|
> T3 行:inline 完整描述一句話 + 標籤(如 `[cosmetic]` / `[text]` /
|
|
92
|
-
> `[
|
|
123
|
+
> `[appearance]`);T3 不產獨立 spec 檔
|
|
124
|
+
>
|
|
125
|
+
> **minimal(zero-phase)host 的每一列都要能指出這次變更碰到的原始碼路徑**
|
|
126
|
+
> (寫到能和一個 commit 比對的粒度即可,不是貼 diff)。T2 由它的
|
|
127
|
+
> lightweight-spec `## Implementation Paths` 段承載,row 只要外連過去;**T3 沒有
|
|
128
|
+
> spec 檔,路徑就直接寫在 Description 裡**,接在一句話描述與標籤後面。
|
|
129
|
+
> `/dflow:finish-feature` 會拿 checkpoint 1 的 diff 和這些路徑比對;
|
|
130
|
+
> **一個路徑都沒宣告會擋下 closeout**,不會當成通過。
|
|
131
|
+
> **掛在 phase-bearing feature 底下的列不受此限**——closeout 對它們不跑這項檢查
|
|
132
|
+
> (`references/finish-feature-flow.md` Step 1 明寫此例外,理由是 hosted row 本來
|
|
133
|
+
> 就沒有被要求宣告路徑)。寫上去仍是好習慣,但那裡沒有 gate、也不會擋。
|
|
93
134
|
>
|
|
94
|
-
>
|
|
135
|
+
> **post-hoc hotfix 的 T3 列**(見 references/modify-existing-flow.md Step 1.8):
|
|
136
|
+
> Description 另外標明這是 hotfix,並寫出識別依據(PR/incident/tracker 編號)
|
|
137
|
+
> ——沒有依據的 hash 會擋下 closeout。此時路徑指的是**已合併的那個 hotfix**
|
|
138
|
+
> 碰到的檔案;本列 `Commit` 欄填的是**補文件那個 commit** 的 hash,不是 hotfix
|
|
139
|
+
> 的 hash(後者記在 Checkpoint Log 的 `reconciled (...)` 列)。兩者來源不同,
|
|
140
|
+
> 不可互填。
|
|
141
|
+
>
|
|
142
|
+
> Tier 判準見 AI-AGENT-GUIDE.md § Ceremony Scaling 的 ordered cascade(步驟 0–4,先命中者勝)。
|
|
95
143
|
|
|
96
144
|
| Date | Tier | Description | Commit |
|
|
97
145
|
|---|---|---|---|
|
|
98
146
|
| {YYYY-MM-DD} | T2 | bug fix XYZ — 見 [`lightweight-{date}-{slug}.md`](./lightweight-{date}-{slug}.md) | {hash} |
|
|
99
|
-
| {YYYY-MM-DD} | T3 | 按鈕顏色從藍改綠 `[cosmetic]` | {hash} |
|
|
147
|
+
| {YYYY-MM-DD} | T3 | 按鈕顏色從藍改綠 `[cosmetic]` — `src/Web/Checkout/PayButton.cs` | {hash} |
|
|
148
|
+
|
|
149
|
+
> ⚠ **`Commit` 還沒填就留空 —— 不要寫佔位字串。** 上面的 `{hash}` 是**範本佔位符**
|
|
150
|
+
> (代表「這裡放一個 commit hash」),不是可以留在真實 `_index.md` 裡的值。
|
|
151
|
+
> 自己發明 `{pending}`、`(待 commit)` 這類字樣會讓那一格變成**非空**,而
|
|
152
|
+
> **凡是照「空/非空」判的規則都會把它讀成已經填好**。在 phase-bearing host 上更徹底:
|
|
153
|
+
> `_index.md` 對 checkpoint 1 的那些證據檢查全都標明「minimal host(zero-phase)限定」,
|
|
154
|
+
> 所以**關帳(closeout)那條線上**沒有任何檢查會去看那一格 —— 要到下面說的回填與
|
|
155
|
+
> PR review 才有人真的去讀它。
|
|
156
|
+
> ⚠ **抓得到它的判準是「那條檢查會不會去解析這個值」**,不是照空/非空判的那些。
|
|
157
|
+
> 目前這樣的檢查有:`references/finish-feature-flow.md` **Step 1**(minimal host 的
|
|
158
|
+
> 關帳檢查:把佔位字串判為「**從未填入**」,與「空」和「填錯 hash」分成三種不同訊息,
|
|
159
|
+
> 一律**擋**)、同檔 **Step 4 指令 1**(hosted 列回填:unfilled 指「空**或**放著佔位
|
|
160
|
+
> 字串」,兩者以同一種方式回填)、以及 `references/pr-review-checklist.md` 的**兩項**
|
|
161
|
+
> ——存在性那項要 `git cat-file -t` 逐個 resolve,hosted identity 那項再用
|
|
162
|
+
> `git show --stat` 確認那個 hash 真的是該列自己的實作 commit(該檔明寫這兩項
|
|
163
|
+
> 「不可互換」)。⚠ 另有數處**複述**同一條規則但把執行交給上面那些檢查(例如
|
|
164
|
+
> `references/modify-existing-flow.md` 的「Commit evidence goes to two surfaces」),
|
|
165
|
+
> 那些是指標、不是額外的關卡。**日後新增的檢查照同一個判準算,這裡列幾項不是重點。**
|
|
166
|
+
> 別把它們的存在讀成「所以放佔位字串沒差」:在它們之前,每一條機械規則都已經把
|
|
167
|
+
> 那一格當成填好了。
|
|
168
|
+
> **留空是有名字的狀態;佔位字串不是。**
|
|
169
|
+
|
|
170
|
+
> **post-hoc hotfix 的列自成一個 host,不會和上面的一般列並存**
|
|
171
|
+
> (見 references/modify-existing-flow.md Step 1.8):上面兩列的 checkpoint 1
|
|
172
|
+
> **必須**碰到它們宣告的實作路徑,而 post-hoc host 的 checkpoint 1 是**補文件那個
|
|
173
|
+
> commit**、按約定**不得**碰任何已宣告的實作路徑,同一個 commit 不可能兩者兼具
|
|
174
|
+
> (`references/finish-feature-flow.md` Step 1);Checkpoint Log 的實作列 Result
|
|
175
|
+
> 也只能二擇一(`committed (...)` 或 `reconciled (...)`)。post-hoc host 本身仍
|
|
176
|
+
> **可以是 compound**——多個 post-hoc 列共用同一個補文件 commit——不能混的是一般列:
|
|
177
|
+
>
|
|
178
|
+
> | Date | Tier | Description | Commit |
|
|
179
|
+
> |---|---|---|---|
|
|
180
|
+
> | {YYYY-MM-DD} | T3 | 首頁公告錯字修正 `[text]` — `src/Web/Home/Notice.cs`;post-hoc hotfix,識別依據 INC-2031 | {hash} |
|
|
100
181
|
|
|
101
182
|
<!-- dflow:section checkpoint-log -->
|
|
102
183
|
## Checkpoint Log
|
|
@@ -104,18 +185,64 @@ Template note (for AI):
|
|
|
104
185
|
> 生命週期 checkpoint 的 commit / skip 時間線(讓三週後回溯不必手動重建)。
|
|
105
186
|
> 每個 checkpoint 無論 commit 或 skip 都記一列。Tier 決定 checkpoint 數:
|
|
106
187
|
> T1 三點(spec 完 / impl 完 / closeout)、T2 兩點(spec+impl 合併 / closeout)、
|
|
107
|
-
> T3
|
|
188
|
+
> T3 單一實作 commit(其 inline row 與本列的 hash 由 host 的下一個 commit 一併帶進;
|
|
189
|
+
> host 若沒有後續 commit,允許一個只動 ledger 的 tracking commit 收尾,該 commit 不另成列)。
|
|
190
|
+
> ⚠ **上面那些「點」在本表 `Checkpoint` 欄各有固定的字面值**:spec 里程碑寫
|
|
191
|
+
> **`spec-baseline`**、實作寫 **`implementation`**、關帳寫 **`closeout`**(下表的
|
|
192
|
+
> `spec-baseline` / `implementation` / `closeout` 三列就是這幾個值;表中另有一列
|
|
193
|
+
> `branch-override`——本例排在最前——是紀錄列、不是生命週期 checkpoint,見下方說明)。散文裡的
|
|
194
|
+
> 「spec 完」是在說那個里程碑,**不是欄位值** —— 不要照著它造一個 `spec` 出來。
|
|
195
|
+
> ⚠ 這條只管**本表的 `Checkpoint` 欄**。`references/git-integration.md` 的選配 trailer
|
|
196
|
+
> `Dflow-Checkpoint: {SPEC-ID} {spec|impl|closeout}` 有它自己的三個角色名(其中就有
|
|
197
|
+
> `spec`)——那是另一個地方的詞彙,**不要拿本條去「修正」一個寫對的 trailer**。
|
|
198
|
+
>
|
|
199
|
+
> **Minimal host(zero-phase)例外**——見 references/modify-existing-flow.md
|
|
200
|
+
> Step 1.7(standalone)、Step 1.6 的 follow-up minimal 變體,或 Step 1.8 的
|
|
201
|
+
> post-hoc hotfix(其 linkage 落在前兩者之一):這種 host 之後
|
|
202
|
+
> 沒有別的 commit 可以收攏 T3 的 row,所以**不分 tier 一律記兩個 checkpoint**
|
|
203
|
+
> (implementation,然後 closeout),而且 T3 的 inline row 要**寫進 checkpoint 1
|
|
204
|
+
> 本身**、不是等下一個 commit 帶進來。上一段「T3 單一實作 commit / 由下一個
|
|
205
|
+
> commit 帶進」講的是**掛在既有 feature 底下的** T3,不適用於 minimal host。
|
|
206
|
+
>
|
|
207
|
+
> Result 的合法值是 `committed ({hash})` / `skipped` / `failed`,外加
|
|
208
|
+
> **`reconciled ({merged-hotfix-hash})`**——只給 post-hoc hotfix(Step 1.8)的
|
|
209
|
+
> implementation 列用,意思是「本 checkpoint 記錄的是一個已經合併的變更」。
|
|
210
|
+
> 括號裡是**那個 hotfix 的 hash**,不是本 host 補文件那個 commit 的 hash
|
|
211
|
+
> (後者填在 Lightweight Changes 該列的 `Commit` 欄)。完整詞彙見
|
|
212
|
+
> references/git-integration.md § Commit Checkpoints, Branch Gate & AI Commits。
|
|
213
|
+
>
|
|
214
|
+
> **`branch-override` 是紀錄列,不是生命週期 checkpoint。** 在 branch gate 選了
|
|
215
|
+
> 「override and stay」時記一列(references/git-integration.md § Branch gate
|
|
216
|
+
> 定義形狀):Checkpoint 寫 `branch-override`、Result 寫
|
|
217
|
+
> `override ({你留下來的分支})`。它**不是 commit**、**不計入 tier 的 checkpoint
|
|
218
|
+
> 數**。closeout 的分支檢查會看**有沒有任何一列**指名你現在所在的分支(不是只看最近
|
|
219
|
+
> 一列——一個 host 可能在不同 phase override 到不同分支,而 closeout 自己不觸發 branch
|
|
220
|
+
> gate、不會補寫新列)。括號裡必須是**分支名**,沒寫分支的紀錄豁免不了任何東西。
|
|
221
|
+
> `branch:` 欄位本身永遠不因 override 而改寫。
|
|
222
|
+
> ⚠ **只會出現在 phase-bearing host。** references/modify-existing-flow.md 對
|
|
223
|
+
> **minimal host**(Step 1.6 follow-up 變體/Step 1.7 standalone/Step 1.8
|
|
224
|
+
> post-hoc)**不提供**這個選項——那些 host 正是拿 `branch:` 當權威來斷言分支相等的。
|
|
108
225
|
>
|
|
109
226
|
> commit hash 只在 commit 實際成功後填入;pre-commit hook reject 或 commit
|
|
110
227
|
> 失敗記 `failed`、不寫假 hash。**例外:closeout 列不填 hash**——closeout
|
|
111
228
|
> commit 無法自含自身 hash,該列於 commit 前寫入、隨歸檔目錄一起進 commit;
|
|
112
229
|
> 溯源用 `git log -1 -- completed/{SPEC-ID}-{slug}` 或選配的
|
|
113
230
|
> `Dflow-Checkpoint` trailer(見 references/git-integration.md)。
|
|
231
|
+
>
|
|
232
|
+
> ⚠⚠ **下表示範的是欄位值,不是這張表的起始狀態——一列都不要預先放。** 每一列
|
|
233
|
+
> 都在它那個 checkpoint **實際走到的當下**才新增(`branch-override` 在 branch gate
|
|
234
|
+
> 選了 override 時;`closeout` 由 references/finish-feature-flow.md Step 4 指令 1
|
|
235
|
+
> 在關帳當下寫入)。
|
|
236
|
+
> ⚠ **尤其不要預先放一列空的 `closeout` 佔位**:minimal host(zero-phase)的關帳
|
|
237
|
+
> 檢查要求 Checkpoint Log 在關帳前**恰好一列**
|
|
238
|
+
> (references/finish-feature-minimal-host.md Step 1),預先放下的那一列會**擋下**
|
|
239
|
+
> 關帳。
|
|
114
240
|
|
|
115
241
|
| Timestamp | Checkpoint | Result |
|
|
116
242
|
|---|---|---|
|
|
243
|
+
| {YYYY-MM-DD HH:MM} | branch-override | override ({branch-you-stayed-on}) |
|
|
117
244
|
| {YYYY-MM-DD HH:MM} | spec-baseline | committed ({hash}) / skipped / failed |
|
|
118
|
-
| {YYYY-MM-DD HH:MM} | implementation | committed ({hash}) / skipped / failed |
|
|
245
|
+
| {YYYY-MM-DD HH:MM} | implementation | committed ({hash}) / skipped / failed / reconciled ({merged-hotfix-hash}) |
|
|
119
246
|
| {YYYY-MM-DD HH:MM} | closeout | committed / skipped / failed |
|
|
120
247
|
|
|
121
248
|
## Resume Pointer
|
|
@@ -125,7 +252,10 @@ Template note (for AI):
|
|
|
125
252
|
> 下方四個 cursor 欄位是 workflow 進度的**存放層(宣告,claim)**:
|
|
126
253
|
> 進入 flow 時設 Active Workflow;**每過一個 step gate** 更新 Current Step /
|
|
127
254
|
> Gates Passed / Awaiting(與該 gate 既有的 `_index.md` 更新合併,不另加儀式);
|
|
128
|
-
>
|
|
255
|
+
> `/dflow:cancel` 時 Active Workflow 設回 `none`;closeout 也設回 `none`,但**是在
|
|
256
|
+
> 歸檔那一步**——`finish-feature-flow.md` Step 4 的 `git mv` 之後緊接著寫,**不是**
|
|
257
|
+
> closeout 一開始就寫。在那之前 closeout 本身仍是進行中的 workflow,後面還有 step
|
|
258
|
+
> gate 要過。
|
|
129
259
|
> `/dflow:status` 讀 cursor 後會與推導證據(Checkpoint Log、phase-spec
|
|
130
260
|
> status、git log)交叉,不一致會明確報 mismatch——cursor 是宣告、證據優先。
|
|
131
261
|
> Phase 粒度進度由上方 Phase Specs 表承載;cursor 只補 workflow step / gate
|
|
@@ -3,6 +3,7 @@ aggregate: {AggregateName}
|
|
|
3
3
|
bounded-context: {ContextName}
|
|
4
4
|
created: {YYYY-MM-DD}
|
|
5
5
|
---
|
|
6
|
+
<!-- dflow-shape: greenfield/aggregate-design.md 1 — keep this line: dflow doctor reads it -->
|
|
6
7
|
|
|
7
8
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
8
9
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/analysis.md 1 — keep this line: dflow doctor reads it -->
|
|
2
|
+
<!-- Seeded by Dflow. -->
|
|
3
|
+
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
4
|
+
<!-- Placement: this template fills two paths. Cross-Context Flows and Function / Role Index are always written in the domain-root copy, `dflow/specs/domain/analysis.md`, whoever owns what they describe, and left as they are in a per-context copy - including in a project that has only one context. A hotspot row goes in the copy that holds the knowledge it is stuck on, and a question row in the copy that will hold its answer, as Open Questions and Hotspots says. For every other entry, ask who owns what the entry describes. A status field is owned by the context whose entity stores it - the entity that context's models.md defines, or will define. A derived figure is owned by the context that computes it, not the ones it reads from. A mechanism is owned by the context whose behavior it explains. One context owns it: the entry goes in that context's `dflow/specs/domain/{context}/analysis.md`, and it stays there even when another context reads the field, triggers a transition or supplies data it reads. No one context owns it - two contexts own it equally, or a mechanism explains behavior in several contexts equally: it goes in the domain-root copy. -->
|
|
5
|
+
<!-- Entry ids: every entry carries one. The prefix is the section's - `FL` flows, `LC` lifecycles, `RM` read models, `MX` mechanisms, `FN` function rows, `HS` hotspot rows - and the number is sequential within this copy and never reused; an entry keeps its id for as long as it stays in this copy. A subsection carries its id in its heading (`### LC-01: {name}`); in the two tables that have an ID column, each row carries it there. Cite an entry in this file by its id alone. Cite one in the other copy, or from any other document, as path then id: `domain/{context}/analysis.md LC-01`. Until what a citation points at has an entry of its own, write its name instead of an id; whenever you update this file, replace any such name whose entry now exists. An entry that moves to the other copy takes a new id there: update whatever cited the old one - search for its path and id together, and for the bare id in the file it left. -->
|
|
6
|
+
<!-- Referring to a rule: a cell that names what a business rule decides refers to that rule and holds nothing else; a cell decided by no rule holds the value itself. Refer to a rule by its BR-ID alone only from the copy of the context whose rules.md holds it; anywhere else - always in the domain-root copy - write its path then its id: `domain/{context}/rules.md BR-001`. A cell holding a BR-ID, alone or after its path, is a reference; anything else is a recorded value. Until a rule has a BR-ID, write the rule's name; whenever you update this file, replace any rule name whose BR-ID now exists. -->
|
|
7
|
+
<!-- Evidence convention: every entry carries its evidence in the form `{code | data | confirmed by {role} | document | inferred | assumed} - {what to open to re-check} ({date})`. A subsection ends with one line that reads `Evidence: ` followed by it; a table row puts it in its Evidence column. For `data`, the middle slot also carries the counting rule the number used. `document` is a written source outside the code - a regulation, an internal policy, a ticket, an existing spec. When you take a claim from one of these rather than re-checking it yourself, the date is the one that source gives, not the day you copied it. `inferred` is a conclusion drawn from code or data rather than read off either one: name what it was drawn from. A question nobody has answered yet is not an entry: record it where the Open Questions and Hotspots section says. A value that rests on nothing a reader can open is `assumed`: a guess, or a fact whose only home is a private note, a chat log, or one person's AI memory. Say what it rests on, and record the question of confirming it where the Open Questions and Hotspots section says. -->
|
|
8
|
+
|
|
9
|
+
# Domain Analysis
|
|
10
|
+
|
|
11
|
+
> System-level knowledge that no single bounded-context document holds: flows
|
|
12
|
+
> that cross contexts, the lifecycle a status field moves through, how derived
|
|
13
|
+
> figures are computed, the mechanisms behind observed behavior, who reaches
|
|
14
|
+
> which function, and the spots in them this project keeps working around.
|
|
15
|
+
> Where an entry relies on a rule, a model, or a context relationship, link it
|
|
16
|
+
> by BR-ID, model name, or section instead of restating it. Where this project
|
|
17
|
+
> has already written one of these somewhere else, leave that text where it is
|
|
18
|
+
> and give it a row or a subsection here that says where to read it.
|
|
19
|
+
|
|
20
|
+
## Cross-Context Flows
|
|
21
|
+
|
|
22
|
+
<!-- Global file only. One subsection per ordered flow whose steps are owned by more than one context; the table is the record, one row per step in order. A flow that stays inside one context is not recorded here: its scenarios belong in behavior.md. A statement about two contexts that holds without an order - which one is upstream, how they integrate, what data passes between them - belongs in context-map.md: link it instead of repeating it. A derived figure is not a flow, however many contexts it reads from - it goes in Read Models and Derived Figures. Keep one row per step and no branches: where the flow genuinely forks, either write the fork as its own flow or record the condition as a rule in rules.md and link it. -->
|
|
23
|
+
|
|
24
|
+
### FL-01: {流程名稱}
|
|
25
|
+
|
|
26
|
+
| # | From | To | Handed over | State change | Evidence |
|
|
27
|
+
|---|---|---|---|---|---|
|
|
28
|
+
| 1 | {Context A} | {Context B} | {交出去的是什麼:欄位、識別鍵或事件} | {造成什麼狀態變化} | {code|data|confirmed by {role}|document|inferred|assumed} - {複查入口} ({date}) |
|
|
29
|
+
|
|
30
|
+
## Lifecycles
|
|
31
|
+
|
|
32
|
+
<!-- One subsection per status field: name the field and where it is stored, list every value it can hold, then one row per transition. List the values even when the code admits more than the workflow uses: a value seen only in stored data is still a state. A transition triggered from another context stays here - name that flow in Cross-Context Flows and cite it rather than restating the handover (from a per-context copy: `domain/analysis.md FL-01`). Whether a single transition is allowed to happen is a business rule: it belongs in rules.md and the Guard cell carries its BR-ID. One scenario played out end to end belongs in behavior.md. The entity that stores the field is defined in models.md. The Means cell says what the state allows or blocks next; when the value's name is also a term the business uses elsewhere, its definition belongs in glossary.md and this cell stays short. Evidence sits on the transitions, not on the state list. -->
|
|
33
|
+
|
|
34
|
+
### LC-01: {狀態欄位名稱}(`{存放位置:資料表.欄位,或 Aggregate 屬性}`)
|
|
35
|
+
|
|
36
|
+
| State | Means |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `{狀態值}` | {這個狀態允許或擋住接下來的什麼} |
|
|
39
|
+
|
|
40
|
+
| From | Trigger | To | Guard | Evidence |
|
|
41
|
+
|---|---|---|---|---|
|
|
42
|
+
| `{原狀態}` | {誰做了什麼} | `{新狀態}` | {決定它的 BR-ID;沒有規則決定就寫必須成立的條件,都沒有就留空} | {code|data|confirmed by {role}|document|inferred|assumed} - {複查入口} ({date}) |
|
|
43
|
+
|
|
44
|
+
## Read Models and Derived Figures
|
|
45
|
+
|
|
46
|
+
<!-- One subsection per figure or read model: its definition, which records or states it counts, and the point at which an amount moves from one figure to another. A stored entity or value object is defined in models.md; this section holds what is computed from them. Say what a missing, duplicated or stale record does to the figure. -->
|
|
47
|
+
|
|
48
|
+
### RM-01: {數字或 read model 名稱}
|
|
49
|
+
|
|
50
|
+
{定義、計入條件、切換點}
|
|
51
|
+
|
|
52
|
+
Evidence: {code | data | confirmed by {role} | document | inferred | assumed} - {要開哪一支才能複查} ({date})
|
|
53
|
+
|
|
54
|
+
## Mechanisms
|
|
55
|
+
|
|
56
|
+
<!-- One subsection per mechanism: how the system produces a behavior that no single rule explains - versioned records, deferred updates, recalculation on read. A behavior that one rule or one Given/When/Then scenario can state belongs in rules.md / behavior.md instead. The Affects line lists what this mechanism changes the meaning of - BR-IDs and entry ids, each cited as Entry ids and Referring to a rule say. -->
|
|
57
|
+
|
|
58
|
+
### MX-01: {機制名稱}
|
|
59
|
+
|
|
60
|
+
{運作方式與影響}
|
|
61
|
+
|
|
62
|
+
Affects: {BR-ID 與 FL-/LC-/RM- 編號(照檔頭的引用規則帶路徑;還沒有編號的寫名稱),逗號分隔;沒有就寫 none}
|
|
63
|
+
Evidence: {code | data | confirmed by {role} | document | inferred | assumed} - {要開哪一支才能複查} ({date})
|
|
64
|
+
|
|
65
|
+
## Function / Role Index
|
|
66
|
+
|
|
67
|
+
<!-- Global file only. One row per function: which roles reach it and the data scope each one sees. When a business rule decides who may use the function or what a role sees, that rule is the source of truth: write its BR-ID in that cell instead of restating the rule. Write roles or a data scope directly only where no rule decides them - a menu entry every role sees, a report anyone can run. -->
|
|
68
|
+
|
|
69
|
+
| Function | ID | Entry point | Bounded Context | Roles | Data scope | Evidence |
|
|
70
|
+
|---|---|---|---|---|---|---|
|
|
71
|
+
| {功能名稱} | FN-01 | `{route / page / job}` | {Context name} | {角色,或決定它的 BR-ID(帶路徑)} | {看得到的資料範圍,或決定它的 BR-ID(帶路徑)} | {code|data|confirmed by {role}|document|inferred|assumed} - {複查入口} ({date}) |
|
|
72
|
+
|
|
73
|
+
## Open Questions and Hotspots
|
|
74
|
+
|
|
75
|
+
<!-- One row per hotspot: a spot in the knowledge above this project keeps working around until a domain decision settles it. It goes in whichever copy of this file holds the knowledge it is stuck on - or, when that is a business rule or knowledge not recorded yet, the copy the Placement question gives it - and the Affects column names that knowledge by id, cited as Entry ids and Referring to a rule say. Also one row per question that comes up while writing an entry here and whose own answer will be a cross-context flow, a lifecycle, a derived figure, a mechanism or role reach. A question the current feature must answer before it can finish stays in that feature's spec, and a question whose answer belongs to another document's subject stays in that document's own Open Questions section - a term in glossary.md, a business rule in the owning context's rules.md, and a context boundary, an integration responsibility or the question of which context owns a rule in context-map.md. A question that stays in this file goes in the copy that will hold its answer - the copy Placement gives that answer - whichever copy the entry that raised it is in. When a code change would settle an item - a missing check, a known shortcut - it is tech debt: record it in tech-debt.md instead. A hotspot whose pending decision is recorded elsewhere links to it. A settled item stays as a resolved row that says what settled it, with the settling decision in its Evidence cell. -->
|
|
76
|
+
|
|
77
|
+
| Item | ID | Affects | Why it matters | Status | Evidence |
|
|
78
|
+
|---|---|---|---|---|---|
|
|
79
|
+
| {待確認事項或熱點} | HS-01 | {FL-/LC-/RM-/MX-/FN- 編號或 BR-ID(照檔頭的引用規則帶路徑;還沒有編號的寫名稱)} | {影響} | open / resolved | {code|data|confirmed by {role}|document|inferred|assumed} - {複查入口} ({date}) |
|
|
@@ -4,6 +4,7 @@ chinese-name: {中文名稱}
|
|
|
4
4
|
owner: {負責的開發者或團隊}
|
|
5
5
|
created: {YYYY-MM-DD}
|
|
6
6
|
---
|
|
7
|
+
<!-- dflow-shape: greenfield/context-definition.md 1 — keep this line: dflow doctor reads it -->
|
|
7
8
|
|
|
8
9
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
9
10
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/context-map.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
|
|
29
30
|
## Integration Notes
|
|
30
31
|
|
|
31
|
-
- {
|
|
32
|
+
- {沒有先後順序也成立的跨 context 資料交換、contract、ACL 或 integration event 設計;有先後順序的跨 context 交手流程記在 analysis.md}
|
|
32
33
|
|
|
33
34
|
## Open Questions
|
|
34
35
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/events.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|
|
@@ -14,7 +15,9 @@
|
|
|
14
15
|
## Event Flow Notes
|
|
15
16
|
|
|
16
17
|
- {事件發生時序、交易邊界、重試或一致性注意事項;跨 aggregate 的 async(eventual
|
|
17
|
-
consistency)event chain
|
|
18
|
+
consistency)event chain 在這裡只記上述注意事項,鏈上各步的情境寫在 behavior.md
|
|
19
|
+
(步驟分屬多個 context 的有序交手流程記在 analysis.md);handler 重試耗盡
|
|
20
|
+
的最終失敗若造成 business-visible 後果
|
|
18
21
|
(補償/權益/金流/庫存/合規/人工對帳)→ 升級為 BR/EC 寫進 behavior.md 與 spec,
|
|
19
22
|
best-effort 副作用(通知/logging)記這裡或 tech-debt 即可;多步驟且失敗需補償
|
|
20
23
|
→ 見 ddd-modeling-guide 的 Long-Running Processes 段(process 判準與階梯)}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/glossary.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
id: BUG-{NUMBER} # bug-type T2 only; a non-bug T2 (lightweight-{date}-{slug}.md) carries no id — the filename identifies it
|
|
3
3
|
title: {簡述問題}
|
|
4
4
|
status: in-progress # in-progress | completed
|
|
5
|
-
bounded-context: {ContextName}
|
|
5
|
+
bounded-context: {ContextName} # or `none` when the host has no meaningful bounded context
|
|
6
6
|
created: {YYYY-MM-DD}
|
|
7
|
-
branch: bugfix/BUG-{NUMBER}-{slug}
|
|
7
|
+
branch: bugfix/BUG-{NUMBER}-{slug} # must equal the host _index.md `branch:` value (that field is authoritative) — a non-bug T2 therefore carries the host's feature/{SPEC-ID}-{slug} branch
|
|
8
|
+
# hotfix-branch: hotfix/{name} # ADD (uncomment) only for a post-hoc T2 — references/modify-existing-flow.md Step 1.8. The already-merged emergency fix's own branch, kept even after that branch was deleted.
|
|
9
|
+
# hotfix-identity: {PR / incident / tracker reference} # ADD only for a post-hoc T2 — the source the asserted `reconciled ({merged-hotfix-hash})` identity rests on; an uncited hash blocks closeout. Keep it adjacent to hotfix-branch.
|
|
8
10
|
---
|
|
11
|
+
<!-- dflow-shape: greenfield/lightweight-spec.md 1 — keep this line: dflow doctor reads it -->
|
|
9
12
|
|
|
10
13
|
<!--
|
|
11
14
|
Template note (for AI):
|
|
@@ -16,7 +19,7 @@ Template note (for AI):
|
|
|
16
19
|
- T1 Heavy → use templates/phase-spec.md instead
|
|
17
20
|
- T2 Light → THIS template; produces an independent file
|
|
18
21
|
- T3 Trivial → no independent file; just one inline row in _index.md
|
|
19
|
-
Lightweight Changes with a tag like [cosmetic] / [text] / [
|
|
22
|
+
Lightweight Changes with a tag like [cosmetic] / [text] / [appearance]
|
|
20
23
|
|
|
21
24
|
Instance file location and naming:
|
|
22
25
|
Place the instantiated file inside the corresponding feature directory:
|
|
@@ -24,17 +27,136 @@ Template note (for AI):
|
|
|
24
27
|
or, when the lightweight change is a tracked bug:
|
|
25
28
|
dflow/specs/features/active/{SPEC-ID}-{slug}/BUG-{NUMBER}-{slug}.md
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
A standalone change not yet attached to any existing feature needs a
|
|
31
|
+
minimal host feature directory (with a minimal _index.md) to hold this
|
|
32
|
+
instance — the structure invariant is that every spec file lives under
|
|
33
|
+
some feature directory. That minimal host has a defined create / record /
|
|
34
|
+
close-out lifecycle: references/modify-existing-flow.md Step 1.7 for a
|
|
35
|
+
standalone change, or its Step 1.6 minimal variant when the change is a
|
|
36
|
+
follow-up on a completed feature; a post-hoc hotfix reaches the same
|
|
37
|
+
lifecycle through Step 1.8, which resolves its linkage to one of those two.
|
|
38
|
+
Follow that lifecycle rather than
|
|
39
|
+
improvising one, and do not leave an empty host behind.
|
|
40
|
+
|
|
41
|
+
No-BR variants (a T2 that carries no BR delta at all):
|
|
42
|
+
The default shape below is the classic BR-delta form (Behavior Delta with
|
|
43
|
+
BR-NN entries + Root Cause). It stays valid and is the right shape whenever
|
|
44
|
+
the change does have a BR delta.
|
|
45
|
+
A change can reach T2 carrying no BR delta at all. These families describe
|
|
46
|
+
how to write a spec the cascade has ALREADY placed at T2; none of them
|
|
47
|
+
makes a change T2, and none of them overrides an earlier cascade step. Do
|
|
48
|
+
NOT invent a BR-NN and do NOT write a fake root cause. Pick the matching
|
|
49
|
+
family, put its BR line under `## Behavior Delta` in place of the
|
|
50
|
+
ADDED / MODIFIED / REMOVED / RENAMED subsections, and replace `## Root Cause`
|
|
51
|
+
with that family's evidence section:
|
|
52
|
+
|
|
53
|
+
(a) presentation — any copy / appearance change T3 would not take: a sweep
|
|
54
|
+
beyond the local unit, a whole-screen rewrite, a local edit to
|
|
55
|
+
high-consequence content (a security warning, a password hint,
|
|
56
|
+
consent text, a payment or legal notice), or one that changes what the output *means* (an
|
|
57
|
+
instruction reversed from "company email only" to "any email", a
|
|
58
|
+
danger / status colour flipped)
|
|
59
|
+
BR line: `BR: none — presentation`
|
|
60
|
+
Evidence: `## Output Footprint` — which screens / outputs the change
|
|
61
|
+
actually reaches, and **what it now says or signals** whenever the
|
|
62
|
+
meaning moved or the content is high-consequence
|
|
63
|
+
(b) contract change — non-breaking structured-log / export / API / event
|
|
64
|
+
field or semantics change
|
|
65
|
+
BR line: `BR: none — contract change`
|
|
66
|
+
Evidence: `## Contract Delta`, including a `**Downstream consumers**:`
|
|
67
|
+
line naming who reads it
|
|
68
|
+
(c) operational — CVE / security dependency bump, or a behavior-preserving
|
|
69
|
+
refactor on an auth / payment / resilience / compliance path
|
|
70
|
+
BR line: `BR: none — operational`
|
|
71
|
+
Evidence: `## Operational Rationale`, including a `**Trace**:` line
|
|
72
|
+
(advisory / ticket / audit reference; a self-initiated case with nothing
|
|
73
|
+
to cite records `**Trace**: none — self-initiated` — the line is never
|
|
74
|
+
omitted)
|
|
75
|
+
(d) performance — a runtime performance / resource / SLA change, including
|
|
76
|
+
one no audience perceives
|
|
77
|
+
BR line: `BR: none — performance`
|
|
78
|
+
Evidence: `## Performance Delta`, including an
|
|
79
|
+
`**SLA / resource context**:` line
|
|
80
|
+
(e) implementation defect — the rule is unchanged; the implementation was
|
|
81
|
+
wrong
|
|
82
|
+
BR lines: `BR Delta: none — implementation defect` AND
|
|
83
|
+
`Governing BR-IDs: {BR-NN, BR-NN | none}`
|
|
84
|
+
Evidence: keep `## Problem` / `## Root Cause` / `## Fix Approach`, plus a
|
|
85
|
+
regression task
|
|
86
|
+
(f) intentional change — a planned, non-normative functional or interaction
|
|
87
|
+
change with no rule in the catalogue (default tab, redirect target,
|
|
88
|
+
ordering, a presentation / interaction control)
|
|
89
|
+
BR line: `BR: none — intentional change`
|
|
90
|
+
Evidence: `## Change Rationale`, including `**Before**` / `**After**`
|
|
91
|
+
behavior lines and a `**Regression**:` line
|
|
92
|
+
|
|
93
|
+
More than one family can fit — a behaviour-preserving payment-retry refactor
|
|
94
|
+
that also shifts runtime SLA is both (c) and (d). Do not pick one and drop
|
|
95
|
+
the other's evidence: write the BR line of the family with the higher
|
|
96
|
+
consequence (order: (e) → (c) → (b) → (d) → (f) → (a)) and include **every**
|
|
97
|
+
matching family's evidence section. A reviewer needs the operational trace
|
|
98
|
+
and the SLA context, not whichever one the author chose first.
|
|
99
|
+
|
|
100
|
+
Family (e) keeps two fields on purpose: "no BR delta" is not "no governing
|
|
101
|
+
rule". `Governing BR-IDs:` lists the rules the defect sits under, so the rule
|
|
102
|
+
the fix answers to stays traceable; a genuinely uncatalogued defect records
|
|
103
|
+
`none`. Never collapse the pair into a single `BR: none`.
|
|
104
|
+
Family (f) is non-normative only. A new normative constraint (permission /
|
|
105
|
+
eligibility / threshold / approval / required outcome) is a new BR — take it
|
|
106
|
+
back to the cascade rather than filing it here, even when the catalogue has
|
|
107
|
+
no BR-ID for it yet.
|
|
108
|
+
|
|
109
|
+
Legacy shapes are accepted, never migrated. Readers and gates take both the
|
|
110
|
+
classic BR-delta form and the older single `BR:` line bug form (written
|
|
111
|
+
before the `BR Delta:` / `Governing BR-IDs:` split) as they are; leave
|
|
112
|
+
existing specs alone and use the shapes above for new ones.
|
|
113
|
+
|
|
114
|
+
After drafting this lightweight-spec, AI must:
|
|
34
115
|
1. Add an outbound-link row to the feature's _index.md Lightweight Changes table
|
|
35
|
-
(Tier = T2; description includes the link to this file)
|
|
116
|
+
(Tier = T2; description includes the link to this file).
|
|
117
|
+
TIMING — do this BEFORE the implementation commit, not after. On a
|
|
118
|
+
minimal (zero-phase) host the row must already be inside checkpoint 1,
|
|
119
|
+
and closeout's allow-list admits only the row's `Commit` cell
|
|
120
|
+
afterwards, so a row added later blocks. "Drafting", not the Step 1.7
|
|
121
|
+
"Finalize + close" sub-step, which runs after that commit and only fills
|
|
122
|
+
the cell in.
|
|
36
123
|
2. Refresh the feature's _index.md Current BR Snapshot table to reflect
|
|
37
124
|
any BR ADDED / MODIFIED / REMOVED / RENAMED in this lightweight-spec
|
|
125
|
+
(a no-BR family has nothing to refresh — leave the snapshot as it is)
|
|
126
|
+
|
|
127
|
+
Implementation Paths:
|
|
128
|
+
The `## Implementation Paths` section below names the source paths this
|
|
129
|
+
change touches. Paths, not a diff — enough to compare a commit against.
|
|
130
|
+
REQUIRED on a minimal (zero-phase) host — standalone or follow-up:
|
|
131
|
+
`/dflow:finish-feature` asserts that checkpoint 1's diff touches them, so a
|
|
132
|
+
spec declaring none leaves that check nothing to compare and a missing
|
|
133
|
+
declaration BLOCKS closeout rather than passing vacuously
|
|
134
|
+
(references/finish-feature-flow.md Step 1; written at
|
|
135
|
+
references/modify-existing-flow.md Step 1.7, before the first commit).
|
|
136
|
+
On a HOSTED T2 — one recorded under a phase-bearing feature — closeout runs
|
|
137
|
+
no such check and nothing blocks on it, so the section is good practice
|
|
138
|
+
there, not a gate. Do not read the "blocks" above as applying to a hosted
|
|
139
|
+
spec; it does not.
|
|
140
|
+
Keep the paths OUT of `## Implementation Tasks`: the completion checklist
|
|
141
|
+
may collapse or remove that section once the tasks are done, and the paths
|
|
142
|
+
must still be readable at closeout.
|
|
143
|
+
|
|
144
|
+
Post-hoc hotfix fields — T2 only, references/modify-existing-flow.md Step 1.8:
|
|
145
|
+
`hotfix-branch:` records the already-merged emergency fix's own branch
|
|
146
|
+
(keep the value even when that branch has been deleted); `hotfix-identity:`
|
|
147
|
+
cites what the identity claim rests on — the PR, incident, or tracker
|
|
148
|
+
reference. Both live in the frontmatter, adjacent, so the trace and the
|
|
149
|
+
thing it rests on stay together. They ship COMMENTED OUT: an ordinary
|
|
150
|
+
(non-post-hoc) T2 leaves them commented and they are inert. Uncomment them
|
|
151
|
+
only in post-hoc mode — never fill them with `none`, and never leave them
|
|
152
|
+
live on an ordinary T2, which would claim a hotfix branch that never
|
|
153
|
+
existed on a record nothing else re-checks.
|
|
154
|
+
In post-hoc mode `## Implementation Paths` names the paths the MERGED
|
|
155
|
+
HOTFIX touched: closeout compares them against the `reconciled ({hash})`
|
|
156
|
+
commit, and blocks if this host's own documentation commit touches any of
|
|
157
|
+
them (that would be re-implementation, not reconciliation). Closeout tests
|
|
158
|
+
plausibility only and blocks on an uncited hash; the identity itself is
|
|
159
|
+
confirmed by references/pr-review-checklist.md.
|
|
38
160
|
-->
|
|
39
161
|
|
|
40
162
|
# {問題簡述}
|
|
@@ -46,6 +168,8 @@ Template note (for AI):
|
|
|
46
168
|
## Behavior Delta
|
|
47
169
|
|
|
48
170
|
> 精簡 delta 格式:bug fix 多數只需 MODIFIED;若確實是新增規則可改用 ADDED、移除用 REMOVED、改名用 RENAMED。多項變更時照類別列。
|
|
171
|
+
>
|
|
172
|
+
> 完全沒有 BR delta 時改用 no-BR 家族形(見檔首 Template note 的 No-BR variants):本段只留該家族的 BR 行(例如 `BR: none — presentation`;家族 (e) 是 `BR Delta:` + `Governing BR-IDs:` 兩行),不要為了填滿 delta 子段捏造 BR-NN。
|
|
49
173
|
|
|
50
174
|
### MODIFIED - behavior modified in this fix
|
|
51
175
|
#### Rule: BR-NN {規則名稱}
|
|
@@ -58,12 +182,31 @@ Template note (for AI):
|
|
|
58
182
|
|
|
59
183
|
## Root Cause
|
|
60
184
|
|
|
185
|
+
> classic BR-delta 形與 no-BR 家族 (e) 保留本段;家族 (a)–(d)、(f) 以該家族的 evidence 段取代本段(見檔首 Template note 的 No-BR variants)。
|
|
186
|
+
|
|
61
187
|
{為什麼會這樣?是邏輯錯誤?資料問題?還是需求理解有誤?}
|
|
62
188
|
|
|
63
189
|
## Fix Approach
|
|
64
190
|
|
|
65
191
|
{怎麼修?有沒有抽到 Domain 層的機會?}
|
|
66
192
|
|
|
193
|
+
## Implementation Paths
|
|
194
|
+
|
|
195
|
+
> The source paths this change touches — paths, not a diff, at a granularity a
|
|
196
|
+
> commit can be compared against. **Required on a minimal (zero-phase) host**:
|
|
197
|
+
> `/dflow:finish-feature` asserts checkpoint 1's diff touches them, and
|
|
198
|
+
> declaring none **blocks** closeout instead of passing. On a **hosted** T2 —
|
|
199
|
+
> recorded under a phase-bearing feature — closeout runs no such check, so this
|
|
200
|
+
> is good practice there rather than a gate. Do not move the list into
|
|
201
|
+
> `## Implementation Tasks`: that section may be collapsed once the tasks are
|
|
202
|
+
> done, and these paths must still be readable at closeout.
|
|
203
|
+
>
|
|
204
|
+
> **Post-hoc hotfix (Step 1.8)**: list what the **already-merged hotfix**
|
|
205
|
+
> touched. This host's own documentation commit must **not** touch any of them.
|
|
206
|
+
|
|
207
|
+
- `{src/path/touched}`
|
|
208
|
+
- `{src/another/path/touched}`
|
|
209
|
+
|
|
67
210
|
<!-- dflow:section implementation-tasks -->
|
|
68
211
|
## Implementation Tasks
|
|
69
212
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/models.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|
|
@@ -7,6 +7,7 @@ created: {YYYY-MM-DD}
|
|
|
7
7
|
author: {developer-name}
|
|
8
8
|
branch: feature/{SPEC-ID}-{slug}
|
|
9
9
|
---
|
|
10
|
+
<!-- dflow-shape: greenfield/phase-spec.md 1 — keep this line: dflow doctor reads it -->
|
|
10
11
|
|
|
11
12
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
12
13
|
|
|
@@ -17,7 +18,14 @@ Template note (for AI):
|
|
|
17
18
|
This is the **phase-spec** template - one phase-spec captures one full
|
|
18
19
|
"Kickoff -> Domain -> Design -> Build -> Verify" cycle inside a feature directory.
|
|
19
20
|
A feature can have 1..N phase-specs; the feature-level dashboard lives in
|
|
20
|
-
the sibling `_index.md` (see templates/_index.md).
|
|
21
|
+
the sibling `_index.md` (see templates/_index.md).
|
|
22
|
+
Exception — a **minimal (zero-phase) host** has **0**: it records a small
|
|
23
|
+
standalone or follow-up change and is defined by carrying no phase-spec at
|
|
24
|
+
all (references/modify-existing-flow.md Step 1.7, or its Step 1.6 minimal
|
|
25
|
+
variant). Such a host never uses this template. If you are about to create a
|
|
26
|
+
phase-spec for one, stop: adding a phase makes it a phase-bearing feature,
|
|
27
|
+
and closeout will then check it as one.
|
|
28
|
+
The instance file name is
|
|
21
29
|
`phase-spec-YYYY-MM-DD-{slug}.md` placed at
|
|
22
30
|
`dflow/specs/features/active/{SPEC-ID}-{slug}/`.
|
|
23
31
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/rules.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- dflow-shape: greenfield/tech-debt.md 1 — keep this line: dflow doctor reads it -->
|
|
1
2
|
<!-- Seeded by Dflow. -->
|
|
2
3
|
<!-- Formatting convention: keep table cells concise. When one cell holds multiple short items (invariants, rules, steps), separate them with <br> so each renders on its own line - never chain them into one line with ;/; separators. Long narrative detail does not belong in a table cell: keep the cell to a concise summary and put extended detail in an existing section of this document when one fits, or give each item its own row. -->
|
|
3
4
|
|