dflow-sdd-ddd 0.14.0 → 0.16.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 (100) hide show
  1. package/CHANGELOG.md +915 -0
  2. package/CONTRIBUTING.md +11 -1
  3. package/README.en.md +160 -212
  4. package/README.md +93 -147
  5. package/TEMPLATE-COVERAGE.md +13 -6
  6. package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
  7. package/bin/dflow.js +90 -4
  8. package/docs/closeout-check.en.md +204 -0
  9. package/docs/closeout-check.md +204 -0
  10. package/docs/commands.en.md +112 -0
  11. package/docs/commands.md +103 -0
  12. package/docs/doctor-uncertainty.en.md +212 -0
  13. package/docs/doctor-uncertainty.md +212 -0
  14. package/docs/evaluating-dflow.en.md +29 -11
  15. package/docs/evaluating-dflow.md +8 -6
  16. package/docs/release-versioning-policy.md +6 -0
  17. package/docs/upgrading.en.md +196 -0
  18. package/docs/upgrading.md +197 -0
  19. package/docs/using-with-claude-code.en.md +13 -4
  20. package/docs/using-with-claude-code.md +13 -4
  21. package/docs/using-with-codex.en.md +13 -4
  22. package/docs/using-with-codex.md +13 -4
  23. package/docs/using-with-github-copilot.en.md +13 -4
  24. package/docs/using-with-github-copilot.md +13 -4
  25. package/lib/closeout-check.js +690 -0
  26. package/lib/doc-shapes.json +1195 -0
  27. package/lib/doctor-checks.js +2500 -24
  28. package/lib/init.js +2861 -143
  29. package/lib/render-diagrams.js +1474 -0
  30. package/lib/render.js +865 -49
  31. package/package.json +2 -2
  32. package/templates/brownfield/references/drift-verification.md +4 -0
  33. package/templates/brownfield/references/finish-feature-flow.md +648 -98
  34. package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
  35. package/templates/brownfield/references/finish-feature-minimal-host.md +427 -0
  36. package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  37. package/templates/brownfield/references/finish-feature-record-correction.md +45 -0
  38. package/templates/brownfield/references/git-integration.md +205 -26
  39. package/templates/brownfield/references/init-project-flow.md +23 -3
  40. package/templates/brownfield/references/modify-existing-flow.md +439 -88
  41. package/templates/brownfield/references/modify-existing-follow-up.md +122 -0
  42. package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +200 -0
  43. package/templates/brownfield/references/new-feature-flow.md +110 -37
  44. package/templates/brownfield/references/new-phase-flow.md +59 -9
  45. package/templates/brownfield/references/pr-review-checklist.md +328 -10
  46. package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +151 -34
  47. package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
  48. package/templates/brownfield/scaffolding/Git-principles-gitflow.md +85 -8
  49. package/templates/brownfield/scaffolding/Git-principles-trunk.md +88 -10
  50. package/templates/brownfield/scaffolding/_conventions.md +50 -28
  51. package/templates/brownfield/scaffolding/_overview.md +1 -0
  52. package/templates/brownfield/templates/_index.md +158 -10
  53. package/templates/brownfield/templates/analysis.md +79 -0
  54. package/templates/brownfield/templates/behavior.md +1 -0
  55. package/templates/brownfield/templates/context-definition.md +1 -0
  56. package/templates/brownfield/templates/context-map.md +2 -1
  57. package/templates/brownfield/templates/glossary.md +1 -0
  58. package/templates/brownfield/templates/lightweight-spec.md +154 -11
  59. package/templates/brownfield/templates/models.md +1 -0
  60. package/templates/brownfield/templates/phase-spec.md +9 -1
  61. package/templates/brownfield/templates/rules.md +1 -0
  62. package/templates/brownfield/templates/tech-debt.md +1 -0
  63. package/templates/common/references/ddd-modeling-guide.md +33 -16
  64. package/templates/{greenfield → common}/references/dflow-feedback-flow.md +2 -1
  65. package/templates/common/references/flow-rationale-registry.md +146 -0
  66. package/templates/common/skill/SKILL.md +13 -11
  67. package/templates/greenfield/references/drift-verification.md +4 -0
  68. package/templates/greenfield/references/finish-feature-flow.md +639 -100
  69. package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
  70. package/templates/greenfield/references/finish-feature-minimal-host.md +383 -0
  71. package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  72. package/templates/greenfield/references/finish-feature-record-correction.md +45 -0
  73. package/templates/greenfield/references/git-integration.md +193 -26
  74. package/templates/greenfield/references/init-project-flow.md +23 -3
  75. package/templates/greenfield/references/modify-existing-flow.md +395 -87
  76. package/templates/greenfield/references/modify-existing-follow-up.md +104 -0
  77. package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +200 -0
  78. package/templates/greenfield/references/new-feature-flow.md +116 -35
  79. package/templates/greenfield/references/new-phase-flow.md +58 -9
  80. package/templates/greenfield/references/pr-review-checklist.md +311 -8
  81. package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +146 -32
  82. package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
  83. package/templates/greenfield/scaffolding/Git-principles-gitflow.md +84 -8
  84. package/templates/greenfield/scaffolding/Git-principles-trunk.md +94 -14
  85. package/templates/greenfield/scaffolding/_conventions.md +50 -28
  86. package/templates/greenfield/scaffolding/_overview.md +6 -2
  87. package/templates/greenfield/templates/_index.md +145 -10
  88. package/templates/greenfield/templates/aggregate-design.md +1 -0
  89. package/templates/greenfield/templates/analysis.md +79 -0
  90. package/templates/greenfield/templates/behavior.md +1 -0
  91. package/templates/greenfield/templates/context-definition.md +1 -0
  92. package/templates/greenfield/templates/context-map.md +2 -1
  93. package/templates/greenfield/templates/events.md +4 -1
  94. package/templates/greenfield/templates/glossary.md +1 -0
  95. package/templates/greenfield/templates/lightweight-spec.md +154 -11
  96. package/templates/greenfield/templates/models.md +1 -0
  97. package/templates/greenfield/templates/phase-spec.md +9 -1
  98. package/templates/greenfield/templates/rules.md +1 -0
  99. package/templates/greenfield/templates/tech-debt.md +1 -0
  100. package/templates/brownfield/references/dflow-feedback-flow.md +0 -251
@@ -0,0 +1,122 @@
1
+ # Step 1.6: Create Follow-up Feature — Brownfield Progressive Extraction
2
+
3
+ Branch file of `references/modify-existing-flow.md`. It **adds** the
4
+ follow-up-specific rules; it does not restate or override anything in that flow.
5
+
6
+ **You are here because** that flow's Step 1.6 dispatched you — it owns whether
7
+ this route applies, and what has already been decided by the time you arrive.
8
+
9
+ Build the follow-up feature using the same machinery as
10
+ `/dflow:new-feature` (see `new-feature-flow.md` Steps 3.5 and 4), with
11
+ these follow-up-specific differences. **Use the tier Part A already decided.**
12
+ This is the same change Part A classified, and re-running the cascade on it can
13
+ return a second answer to one question. Re-enter Part A **only** when the
14
+ Step 1.5 A/B/C discussion materially changed the scope (work added or dropped);
15
+ say so explicitly when you do, and let that re-run **replace** the earlier tier
16
+ rather than stand beside it. On that tier: a **T1** follow-up
17
+ takes the full new-feature machinery below; a **T2 / T3** follow-up — or a
18
+ **baseline capture**, which is **tier-exempt** (observation-only, no cascade
19
+ tier, and reaches here via Part A's observation-only routing rather than the
20
+ Step 1.5 A/B/C prompt) — takes the **minimal (zero-phase) variant** described
21
+ after the reverse-link step, which does **not** delegate new-feature Step 4's
22
+ unconditional first phase-spec. A **post-hoc hotfix** whose host linkage
23
+ Step 1.8 resolved to *follow-up* also arrives here (likewise without the
24
+ Step 1.5 prompt, and always T2 / T3, so always the minimal variant); its
25
+ first checkpoint keeps the `implementation` name but carries Result
26
+ `reconciled (...)` per Step 1.8.
27
+
28
+ - **New SPEC-ID** (today's date sequence — do NOT reuse the original
29
+ SPEC-ID): e.g. original `SPEC-20260201-003-訂單折扣` → follow-up
30
+ `SPEC-20260424-002-訂單折扣-匯率擴充` (or any new slug)
31
+ - **New slug**: not required to equal the original slug; pick whatever
32
+ best describes the follow-up scope
33
+ - **`_index.md` Metadata**: `follow-up-of: {原 SPEC-ID}` is REQUIRED
34
+ (uncomment the optional line in the template; can be a YAML array if
35
+ the follow-up spans multiple originals)
36
+ - **`_index.md` Goals & Scope** auto-prepended note:
37
+ ```
38
+ > 本 feature 為 `{原 SPEC-ID}-{原 slug}` 的 follow-up,原 feature
39
+ > 完成於 `{date}`,詳見 `completed/{原 SPEC-ID}-{原 slug}/_index.md`。
40
+ ```
41
+ - **`_index.md` Current BR Snapshot baseline** (**BC-bearing follow-up only**):
42
+ if the follow-up touches a bounded context, AI reads the BC's
43
+ `dflow/specs/domain/{context}/rules.md` and inherits the BRs that are
44
+ in-scope for this follow-up. Mark each inherited row with First Seen
45
+ = `inherited from rules.md` and Last Updated = (empty until the new
46
+ feature's first phase Delta — or, for a minimal follow-up, its
47
+ lightweight-spec's delta — touches it). For a **no-BC follow-up** (the
48
+ minimal variant on a completed no-BC host), leave the Current BR Snapshot
49
+ **empty** — do not read or fabricate a BC's `rules.md`.
50
+ **A baseline capture is the other exception**, and it names a real bounded
51
+ context, so state it rather than leaving it to the BC-bearing rule: a
52
+ completed-only baseline host is tier-exempt and observation-only — it carries
53
+ no BR delta, and the capture may be the very thing that creates that BC's
54
+ `rules.md`. Leave its Current BR Snapshot **empty**, exactly as the
55
+ no-feature baseline route does (Step 1.7 step 3, "fill it only if the change
56
+ carries a BR delta"). The capture writes the BC layer directly, so the host's
57
+ snapshot is not its record and closeout has nothing to sync. **Both baseline
58
+ routes behave identically here** — lineage decides the host shape, never the
59
+ snapshot policy.
60
+
61
+ **Reverse-link into the old `_index.md`**: AI also updates
62
+ `dflow/specs/features/completed/{原 SPEC-ID}-{原 slug}/_index.md` —
63
+ uncomment the Follow-up Tracking section (if not already present) and
64
+ add a row. When `follow-up-of` names **more than one** original (it may be a
65
+ YAML array), do this in **every** one of them; a parent left without its row
66
+ never gets the `absent → in-progress → completed` transition the contract
67
+ requires, and on a **minimal** follow-up host finish-feature Step 1 blocks
68
+ closeout on it (that check is scoped "Minimal host (zero-phase), follow-up
69
+ only" and proves the *opening* half; on a phase-bearing follow-up Step 6 still
70
+ flips and verifies the closing half, but nothing checks that the row was ever
71
+ opened as `in-progress`):
72
+
73
+ ```
74
+ | {新 SPEC-ID} | {新 slug} | {today} | in-progress |
75
+ ```
76
+
77
+ This update is **part of the same change set** as opening the host. For a
78
+ **T1** follow-up the AI may offer to commit the new host and this initial
79
+ `absent → in-progress` reverse-link together (commit message should mention
80
+ "Add follow-up reference to `{新 SPEC-ID}`"). For the **minimal (T2 / T3, or
81
+ baseline) variant** the AI does **not** offer a separate host-open commit — the
82
+ initial reverse-link edit rides along in the first host checkpoint
83
+ (implementation, or `spec-baseline` for a baseline follow-up; see the variant
84
+ paragraph below), keeping the follow-up at exactly two host checkpoints. The reverse link is a derived index — the new feature's
85
+ `follow-up-of` field is the authoritative source.
86
+
87
+ After a **T1** follow-up feature is set up, this flow hands off to the
88
+ `/dflow:new-phase` flow (or stays in this flow at Step 2 for the first
89
+ phase's content).
90
+
91
+ **Minimal (zero-phase) follow-up variant (T2 / T3 / baseline).** When the
92
+ follow-up change is itself lightweight — or is an observation-only **baseline
93
+ capture**, which is tier-exempt rather than lightweight and reaches this
94
+ variant from Step 1.6's opening paragraph — do **not** delegate new-feature
95
+ Step 4 (which would create an unconditional first phase-spec). Instead treat
96
+ the follow-up host exactly like a standalone minimal host — open it via
97
+ **Step 1.7's
98
+ mechanics, steps 2–4 only** (assign identifiers + collision check, create the
99
+ minimal `_index.md` with an empty Phase Specs table, branch gate **by change
100
+ class**: `bugfix/BUG-{NUMBER}-{slug}` for a functional bug,
101
+ `feature/{SPEC-ID}-{slug}` otherwise — this **overrides** new-feature's
102
+ hardcoded `feature/` branch). Step 1.7's **step 1 does not apply**: it is the
103
+ standalone-classification gate, and this caller has already been classified as
104
+ a follow-up. Everything Step 1.7 states **after** step 4 *does* apply
105
+ unchanged — every artifact's row written before checkpoint 1, the
106
+ implementation-path declaration, the finalization before checkpoint 1 and
107
+ "Finalize + close" after it, and the two
108
+ commit-evidence surfaces — because finish-feature reads for all of it on a
109
+ follow-up host exactly as on a standalone one. Then record the change's
110
+ artifacts — a T2 lightweight-spec, one
111
+ or more T3 inline rows, or both for a compound follow-up (Step 1.7's "minimal
112
+ means zero-phase, not one-artifact") — or, for a **completed-only baseline
113
+ capture**, record it per Step 1.7's baseline mechanics (the `spec-baseline`
114
+ checkpoint and a `Tier = baseline` row) — and close with
115
+ `/dflow:finish-feature`. The lifecycle is **two host checkpoints**
116
+ (implementation — or `spec-baseline` for a baseline follow-up — then closeout)
117
+ **plus one post-closeout reverse-link flip tracking commit** — the flip (the original feature's Follow-up Tracking row
118
+ `in-progress → completed`, done by `/dflow:finish-feature` Step 6) is a
119
+ **sanctioned post-completion mutation, not a host checkpoint**, and is
120
+ recorded in **neither** the follow-up host's Checkpoint Log **nor** the
121
+ original feature's. Option C of Step 1.5 ("a follow-up containing only one
122
+ T3 row") lands here.
@@ -0,0 +1,200 @@
1
+ # Step 1.8: Hotfix T2 / T3 Post-Hoc — Brownfield Progressive Extraction
2
+
3
+ Branch file of `references/modify-existing-flow.md`. It **adds** the
4
+ post-hoc-specific rules; it does not restate or override anything in that flow.
5
+
6
+ **You are here because** that flow's Step 1.8 dispatched you — it owns whether
7
+ this route applies, and what has already been decided by the time you arrive.
8
+
9
+ Sometimes an urgent fix is merged, pushed, and its branch cleaned up
10
+ **before** any Dflow ceremony runs. When you come back to record it,
11
+ declare **post-hoc mode** and reconcile rather than re-implement.
12
+
13
+ **Admission condition — T2 / T3 only.** This step builds a *minimal
14
+ (zero-phase)* host, so it admits only a post-hoc change Part A classified
15
+ **T2 or T3**. A **T1** post-hoc keeps the normal phase-bearing route
16
+ (`/dflow:new-phase` / `/dflow:new-feature`) and documents the merged work
17
+ there — it is not routed here, and giving it a zero-phase host would be wrong.
18
+ If you arrived here with a T1, go back to Part A's routing.
19
+
20
+ 1. **Host-linkage choice first.** A post-hoc hotfix is **already merged on the
21
+ mainline**, so no in-flight feature branch can host it: documenting it into
22
+ an unmerged `feature/...` host would strand the production fix's record on a
23
+ branch the mainline cannot see — possibly for weeks — and would let that
24
+ feature's Integration Summary claim work it never did. The hotfix therefore
25
+ always gets a host of its own, and the only question is whether that host is
26
+ linked:
27
+ - **A related completed feature** → run it as a **follow-up** (Step 1.6
28
+ minimal variant — keep `follow-up-of` and its two reverse-link
29
+ transitions). A hotfix on a completed feature filed as an unlinked
30
+ standalone loses its lineage.
31
+ - **Otherwise** → open a **standalone** minimal host (Step 1.7). "Otherwise"
32
+ includes *a related feature that is still in flight* — see above for why
33
+ it cannot be the host.
34
+
35
+ Make the choice here, and **act on it only after item 2's branch-base
36
+ check**: on either route, nothing is opened, linked or cut before that
37
+ check.
38
+
39
+ Do not skip this choice. If a feature that was in flight turns out to have
40
+ touched the same code, that is a **merge** question, settled when the
41
+ branches actually meet — see `finish-feature-flow.md` Step 5.
42
+ 2. **Reconcile, do not re-run.** The implementation already happened on the
43
+ (now often deleted) hotfix branch. Do **not** reopen an implementation
44
+ branch for it or redo the work. The documentation is recorded on **this
45
+ host's own branch**, cut by change class at Step 1.7 step 4 (or at Step
46
+ 1.6's delegation to it) like any other minimal host — that branch *is* the
47
+ **post-hoc branch** the rest of this step names, and the value `_index.md`
48
+ `branch:` records.
49
+
50
+ **Branch-base check — run it before Step 1.7 step 3 creates anything**
51
+ (on the follow-up route: before Step 1.6 opens the host and writes the
52
+ reverse link). It settles which base branch this host's branch is cut
53
+ from. Closeout requires the commit item 3 records to be an ancestor of
54
+ this branch, so a branch cut from a base that does not contain that commit
55
+ yet passes every step until closeout and is blocked there. Settle that
56
+ commit with the developer first (item 3), then:
57
+ 1. Settle the base branch and fetch it. The developer decides which
58
+ branch is the base — Dflow does not know it, though the project may
59
+ record it under `_conventions.md` § Git Policy — and it is the branch
60
+ Step 1.7 step 4 cuts from anyway. `{base-ref}` is that branch's latest
61
+ ref (for example `origin/develop`). Fetch the remote it belongs to
62
+ (`git fetch origin` for `origin/develop`; `git fetch --all` when
63
+ unsure): a bare `git fetch` updates only the default remote, so a base
64
+ on another remote stays stale and the steps below misjudge it. The fix
65
+ is merged and pushed by now, and it often reached the base on the
66
+ server — a PR merge or a squash — that this clone has not fetched yet.
67
+ 2. Run `git cat-file -t {hash}`. It must print `commit`. If it prints
68
+ anything else or fails, and step 1's fetch failed, the commit may only
69
+ be missing from this clone: stop, say the check needs the fetch, and
70
+ run it again once the remote is reachable. Otherwise the hash is
71
+ mistyped, names an object that is not a commit, or names a commit that
72
+ remote does not have — stop and ask the developer. Do not guess.
73
+ 3. Run `git show --stat {hash}`. At least one path it lists must be an
74
+ implementation path this record will declare. If none is, stop and
75
+ settle the commit with the developer — closeout's (c) would block it.
76
+ A last commit that touches only tests does this. Then run
77
+ `git rev-list --parents -n 1 {hash}`: more than two hashes means a
78
+ merge commit — for example the one a PR page shows as its merged
79
+ commit. Item 3 never records one, and a merge usually passes the path
80
+ check above, so stop here and settle the commit with the developer.
81
+ 4. Run `git merge-base --is-ancestor {hash} {base-ref}`:
82
+ - **Exit `0`** — cut this host's branch from `{base-ref}` at Step 1.7
83
+ step 4. Do **not** let the new branch track the base: run
84
+ `git checkout -b {branch} --no-track {base-ref}`, or update the local
85
+ base branch the way the project normally does and cut from that. A
86
+ branch that tracks `origin/develop` can, under some push settings,
87
+ push its documentation commits straight to `develop`.
88
+ - **Exit `1`** — the fix is not in that base yet. Tell the developer
89
+ both causes. **The fix has not been merged back yet**: merge it back
90
+ first (under GitFlow, into `develop`). **The recorded commit is not
91
+ the one item 3 names**: under a squash or rebase merge, or a
92
+ cherry-pick into the base, the fix's own commits never reach it —
93
+ record the commit the fix landed as (item 3).
94
+ ⚠ Do **not** cut from `main` instead to make the check pass: the
95
+ documentation branch would carry `main`'s merge commits into
96
+ `develop` when it merges, and its documents would start from
97
+ `main`'s older Domain documents and conflict there.
98
+ - **Any other exit code** — a mistyped ref or a failed command. Stop
99
+ and show the developer the output.
100
+ - **If step 1's fetch failed** (offline): exit `0` is still
101
+ trustworthy — the ref you cut from does contain the commit. Exit `1`
102
+ may only mean the local ref is behind; treat it as provisional and
103
+ say so.
104
+ 3. **Implementation checkpoint Result = `reconciled ({merged-hotfix-hash})`.**
105
+ In the host's Checkpoint Log the implementation row's Result is
106
+ `reconciled (...)` — the value meaning "this checkpoint documents an
107
+ already-merged change" — carrying the hash of **one of the fix's own
108
+ commits**, or of **the commit the fix landed as** when it reached the base
109
+ branch by a squash, a rebase or a cherry-pick — a commit on the base
110
+ branch this host's branch is cut from (item 2).
111
+ It sits alongside the usual `committed` / `skipped` / `failed` Results (see
112
+ `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI
113
+ Commits). That hash belongs to the **hotfix**, so it is **not** evidence
114
+ that this host's own first commit landed — the documentation work still owes
115
+ checkpoint 1 a real commit of its own (item 4), made **before** closeout.
116
+ Committing the documentation together with closeout collapses the host to
117
+ one commit and fails finish-feature Step 1.
118
+
119
+ **Which commit that is depends on how the fix reached the base branch:**
120
+
121
+ | The fix reached the base branch by | Record |
122
+ |---|---|
123
+ | a merge (under GitFlow, merging the hotfix branch back into `develop`) or a fast-forward | the last of **the fix's own commits** that touches a declared implementation path — never a merge commit, and under GitFlow never the tagged merge commit on `main`, which the back-merge does not bring into `develop` |
124
+ | a squash merge | the squash commit on the base branch |
125
+ | a rebase merge or a cherry-pick | the last of the fix's commits **as they landed on the base branch** that touches a declared implementation path |
126
+
127
+ When the fix's own commits are on the base branch, record one of them even if
128
+ a copy of the fix got there first. Closeout accepts a commit that touches only
129
+ some of the declared paths: it asks for at least one. The hotfix branch's own
130
+ name still goes in `hotfix-branch:` (item 4).
131
+
132
+ **You are asserting this hash, not deriving it.** Nothing in the repository
133
+ records which commit was the hotfix, so no check in this flow can confirm
134
+ it — finish-feature's reconciliation gate is explicit that it tests
135
+ plausibility only. So state the identity
136
+ and **cite what it rests on**: the PR, incident, or tracker reference that
137
+ identifies this fix. **Cite the source, not the hash** — a corrected hash
138
+ (item 6) then never has to touch the citation. Record the citation
139
+ alongside the per-tier trace
140
+ (item 4). An **uncited** hash blocks closeout —
141
+ `references/pr-review-checklist.md` is what confirms the identity, and it
142
+ needs something to confirm against.
143
+ 4. **Per-tier trace.** A **T2** records the merged-hotfix branch in its
144
+ lightweight-spec `hotfix-branch:` field; a **T3** marks its `_index.md`
145
+ Lightweight Changes row Description as a hotfix (no new field, no T3 spec
146
+ file). Item 3's identity citation goes in the same place — beside
147
+ `hotfix-branch:` for a T2, in the row Description for a T3 — so the trace
148
+ and the thing it rests on stay together. In **both** tiers the host's
149
+ Lightweight Changes row carries a `Commit` value, and that value is the
150
+ **post-hoc documentation commit**
151
+ hash (the row is produced by the documentation work) — **not** the
152
+ merged hotfix hash, which already lives in the `reconciled (...)` checkpoint
153
+ above; the two have different provenance and must not be conflated. This
154
+ row hash is what finish-feature Step 1 reads to prove the documentation
155
+ commit exists separately from closeout, so fill it in as soon as that
156
+ commit lands.
157
+ 5. **Branch equality** for the host is asserted against the **post-hoc
158
+ documentation branch** (the `_index.md` `branch:` value), never the deleted
159
+ hotfix branch.
160
+ 6. **Closeout: (b) fails on the `reconciled (...)` hash.**
161
+ `references/finish-feature-minimal-host.md`'s `Minimal host, hotfix
162
+ post-hoc only` check sends you here. Report which cause it is — never only
163
+ "not an ancestor" — and give the developer the repair for that cause. First
164
+ fetch the remote `{base-ref}` belongs to (item 2 step 1) and find the
165
+ commit item 3 says to record, then test where it is. If the fetch fails, a
166
+ result that depends on `{base-ref}`, or on a commit this clone does not
167
+ have, is provisional — say so, as item 2 does:
168
+ - **It is already on this branch** (`git merge-base --is-ancestor
169
+ {its-hash} HEAD` exits `0`) — the record names the right fix but the
170
+ wrong commit — for example the tagged merge commit on `main`. Correct
171
+ only the Checkpoint Log hash. The citation (item 3 cites the source, not
172
+ the hash), `hotfix-branch:` and the declared paths stay as they are, so
173
+ the correction rides the closeout commit — closeout's closed list admits
174
+ Checkpoint Log rows. Checkpoint 1 is not touched.
175
+ - **It is on the base branch but not on this branch** (`git merge-base
176
+ --is-ancestor {its-hash} {base-ref}` exits `0`) — this branch was cut
177
+ before the fix reached the base, so correcting the hash is not enough.
178
+ Merge `{base-ref}` into this branch — or, if nothing is pushed yet,
179
+ rebase this branch onto it and refill every Lightweight Changes row's
180
+ `Commit` cell — then record that commit. Set closeout's uncommitted
181
+ finalization edits aside first with `git stash push --include-untracked`
182
+ (a plain `git stash` leaves newly created files behind), check that
183
+ `git status --porcelain` prints nothing, and restore them afterwards
184
+ with `git stash pop`: `git rebase` refuses to run over uncommitted
185
+ edits, and `git merge` refuses when the base changed the same files. If
186
+ `git stash pop` reports a conflict — it can when the base changed the
187
+ same part of a file those edits touch — resolve it before closeout
188
+ continues.
189
+ - **It is not on the base branch either** — the fix was never merged back.
190
+ Merge it back first (under GitFlow, into `develop`), then take the case
191
+ above.
192
+ - ⚠ **Never merge `main` or the tag into this branch to make (b) pass.** It
193
+ lets the wrongly recorded commit pass unchanged, and it carries `main`'s
194
+ commits into `develop` when this branch merges.
195
+ - **The record names a different fix** (the citation, the hotfix branch and
196
+ the declared paths are all wrong) — checkpoint 1's own record is wrong,
197
+ and closeout cannot repair that. Follow
198
+ `references/finish-feature-record-correction.md`: it says when
199
+ checkpoint 1 can be amended and when to stop for the developer, and it
200
+ covers `reconciled (...)`, which names the wrong fix too.
@@ -12,7 +12,7 @@ Crossing any step gate above also updates the host feature's `_index.md` Resume
12
12
 
13
13
  All other step transitions are **step-internal**: announce "Step N complete, entering Step N+1" and proceed without waiting. See AI-AGENT-GUIDE.md § Workflow Transparency for the full transparency protocol and confirmation signals.
14
14
 
15
- **Ceremony**: this flow always defaults to **T1 Heavy** — the first phase of a brand-new feature is by definition a full SDD cycle. Tier judgement (T1 / T2 / T3) only applies to `/dflow:modify-existing` (see `references/modify-existing-flow.md` and AI-AGENT-GUIDE.md § Ceremony Scaling).
15
+ **Ceremony**: this flow always defaults to **T1 Heavy** — the first phase of a brand-new feature is by definition a full SDD cycle. Tier judgement (the ordered cascade — T1 / T2 / T3 / below workflow) applies to `/dflow:modify-existing` and `/dflow:bug-fix`; the criteria live in AI-AGENT-GUIDE.md § Ceremony Scaling, and `references/modify-existing-flow.md` is where they are applied.
16
16
 
17
17
  ## Step 1: Intake — Understand the Request
18
18
 
@@ -25,7 +25,26 @@ Ask these questions (naturally, not as a checklist dump):
25
25
 
26
26
  1. **What's the feature?** Get a plain-language description.
27
27
  2. **Who needs it?** Identify the stakeholder or user role.
28
- 3. **Why now?** Understand priority and urgency (affects ceremony level).
28
+ 3. **Why now?** Understand priority and urgency.
29
+
30
+ > **`/dflow:new-feature` is always T1 — it does not re-run the cascade.**
31
+ > Entering here declares "genuinely new work" (a new capability, page, or
32
+ > navigable surface). If the request is really a **modification** of existing
33
+ > behaviour — a tweak, a bug fix, an appearance change, or anything that would
34
+ > land at T2 / T3 / below-workflow — it belongs in `/dflow:modify-existing`,
35
+ > whose Step 1 cascade (step 0) is the only place a misroute is caught. So
36
+ > sanity-check at intake: if this looks like a small change to something that
37
+ > already exists, redirect to `/dflow:modify-existing` rather than minting a T1
38
+ > feature. ⚠ **Do not redirect a request that already came from there.** A
39
+ > `/dflow:modify-existing` or `/dflow:bug-fix` request the cascade landed at T1
40
+ > — including one a project convention escalated to T1, which the overlay may
41
+ > only ever raise — is routed here **by** step 0 and has already been caught;
42
+ > sending it back is a loop, because step 0 provably returns the same answer.
43
+ > `AI-AGENT-GUIDE.md` § Ceremony Scaling's T1 row says so directly. The guard
44
+ > is for a request that arrived at `/dflow:new-feature` **without** passing the
45
+ > cascade. (A follow-up to a *completed* feature is the one new-feature-shaped
46
+ > case that may still be lightweight — it arrives through `modify-existing`
47
+ > Step 1.6's minimal variant, not here.)
29
48
 
30
49
  Then check existing assets:
31
50
  - Search `dflow/specs/domain/` for related concepts
@@ -99,8 +118,11 @@ Walk through these questions:
99
118
  - **What are the key nouns?** → Potential Entities or Value Objects
100
119
  - **What are the key verbs?** → Potential Domain Services or Entity behaviors
101
120
  - **What are the rules/constraints?** → Business Rules to document
102
- - **What are the states/statuses?** → State machines to model
121
+ - **What are the states/statuses?** → State machines to model, recorded in `analysis.md`
103
122
  - **What external data is needed?** → Interfaces to define
123
+ - **What crosses a bounded context, and what does each step hand to the next?** → An ordered cross-context flow (always the domain-root copy)
124
+ - **Which figures are derived rather than stored?** → A read model definition
125
+ - **Who reaches this feature, and what data scope does each role see?** → A role × function entry (always the domain-root copy)
104
126
 
105
127
  If one concept gathers rules / invariants that must hold together — **a state
106
128
  machine over its lifecycle, or invariants spanning several of its fields /
@@ -128,6 +150,8 @@ For each new concept:
128
150
  2. Check if it already exists in models.md — extend if needed
129
151
  3. If entirely new, add to the appropriate context's models.md
130
152
 
153
+ For each of the system-level answers above — the state machines included: record it in `dflow/specs/domain/{context}/analysis.md` when one context owns what it describes and in `dflow/specs/domain/analysis.md` when no one context does, creating the file from `templates/analysis.md` the first time there is something to record. That template's sections carry the notation.
154
+
131
155
  If foundational domain docs are missing, create them from templates before writing content:
132
156
  - `dflow/specs/domain/glossary.md` → `templates/glossary.md`
133
157
  - `dflow/specs/domain/{context}/models.md` → `templates/models.md`
@@ -137,7 +161,7 @@ If foundational domain docs are missing, create them from templates before writi
137
161
  **→ Step Gate: Step 3 → Step 3.5**
138
162
 
139
163
  Announce to developer:
140
- > "Domain concepts captured. Before I create any files, let me confirm the SPEC-ID, slug, directory name, and branch name with you (Step 3.5). `/dflow:next` to proceed."
164
+ > "Domain concepts captured. Before I create the feature directory or branch, let me confirm the SPEC-ID, slug, directory name, and branch name with you (Step 3.5). `/dflow:next` to proceed."
141
165
 
142
166
  Wait for confirmation before entering Step 3.5.
143
167
 
@@ -186,7 +210,31 @@ If the developer asks to change the slug, re-propose and re-confirm.
186
210
 
187
211
  ## Step 4: Write the Spec
188
212
 
189
- Create the **feature directory** + **`_index.md`** + **first phase-spec**:
213
+ > **Minimal hosts do not come here (defensive guard).** Step 4 creates a first
214
+ > phase-spec, which only a genuinely **T1** new feature has. A **minimal host**
215
+ > is zero-phase and is recorded through its own path in `modify-existing-flow.md`,
216
+ > **not here**: Step 1.6 explicitly does **not** delegate to this step. If you
217
+ > reached Step 4 while handling a minimal / zero-phase host, **stop and re-enter
218
+ > `modify-existing-flow.md` at Step 1** — *not* at Step 1.6, 1.7 or 1.8.
219
+ >
220
+ > Those steps each assume work Step 1 has already done: Part A has decided the
221
+ > tier (or routed an observation-only **baseline capture**, which is tier-exempt
222
+ > and has its own two routes), and Part B has done the host linkage. An entry
223
+ > that arrived *here* ran neither, so recovering into one of them skips the
224
+ > authoritative cascade and the completed-feature scan — which is how a change
225
+ > that should have been a follow-up gets archived as an unlinked standalone.
226
+ > Step 1 routes it from there, and its Part B hotfix callout is what sends a
227
+ > **T2 / T3 post-hoc** to Step 1.8 — the only route that attaches `reconciled
228
+ > ({merged-hotfix-hash})`, the identity citation, and the per-tier hotfix
229
+ > trace, all of which a host recovered straight into 1.6 / 1.7 would silently
230
+ > lack. (A **T1** post-hoc is not a minimal host and is not this guard's
231
+ > business.)
232
+ >
233
+ > Either way, do not create a phase-spec, and do not treat this step as a
234
+ > zero-phase execution path.
235
+
236
+ Create the **feature directory** + **`_index.md`** + **first phase-spec** (T1
237
+ new feature):
190
238
 
191
239
  ```
192
240
  dflow/specs/features/active/{SPEC-ID}-{slug}/
@@ -194,6 +242,8 @@ dflow/specs/features/active/{SPEC-ID}-{slug}/
194
242
  └── phase-spec-{YYYY-MM-DD}-{slug}.md
195
243
  ```
196
244
 
245
+ > **Table-cell formatting**: keep table cells concise — separate multiple short items with `<br>` (never chain them into one line with ;/; separators), and move long narrative detail out of the cell into a document section (full convention: the formatting comment at each spec doc's head).
246
+
197
247
  1. **Create the directory**: `dflow/specs/features/active/{SPEC-ID}-{slug}/`
198
248
  2. **Create `_index.md`** using `templates/_index.md`:
199
249
  - Metadata: fill `spec-id`, `slug`, `status: in-progress`, `created`, `branch`
@@ -366,7 +416,7 @@ During implementation, continuously check:
366
416
  **→ Step Gate: Step 7 → Step 8**
367
417
 
368
418
  Announce to developer:
369
- > "Implementation appears complete. Ready to run the completion checklist (verify against spec, update domain docs, archive the spec)? `/dflow:next` to proceed."
419
+ > "Implementation appears complete. Ready to run the completion checklist (verify against spec, update domain docs, complete the phase)? `/dflow:next` to proceed."
370
420
 
371
421
  > Commit checkpoint (T1 milestone 2 of 3): offer to commit the implementation, then record the result in the `_index.md` Checkpoint Log. Milestone 3 (closeout) is the `/dflow:finish-feature` checkpoint.
372
422
 
@@ -386,7 +436,7 @@ AI reports `✓` / `✗` for every item before touching docs. Items marked *(pos
386
436
  - [ ] Every `EC-*` edge case is handled
387
437
  - [ ] Domain layer has **no** delivery-framework references (grep `src/Domain/`)
388
438
  - [ ] *(post-8.3)* `dflow/specs/domain/{context}/behavior.md` contains a section anchor for every `BR-*` introduced by this spec (mechanical input for `/dflow:verify`)
389
- - [ ] *(post-8.3)* `dflow/specs/domain/{context}/rules.md` `last-updated` is later than this spec's `created` date (mechanical drift guard)
439
+ - [ ] *(post-8.3)* for **every `BR-*` this spec introduced or changed**, that rule's row in `dflow/specs/domain/{context}/rules.md` carries a `Last updated` not earlier than this spec's `created` date (mechanical drift guard). ⚠ Quantified per-BR on purpose, like the item above: a T1 may legitimately introduce **no** BR (§ Ceremony Scaling step 0 admits it), and this then passes vacuously rather than blocking. `rules.md` has no document-level `last-updated` — it is a column in the Rule Index, which is what 8.3 sub-step B4 updates.
390
440
 
391
441
  If any item fails, report the gap and pause — don't proceed to 8.2.
392
442
 
@@ -404,42 +454,65 @@ Ask these one-by-one; do not dump all five at once.
404
454
 
405
455
  ### 8.3 Documentation updates
406
456
 
457
+ > **Table-cell formatting**: keep table cells concise — separate multiple short items with `<br>` (never chain them into one line with ;/; separators), and move long narrative detail out of the cell into a document section (full convention: the formatting comment at each spec doc's head).
458
+
407
459
  - [ ] `dflow/specs/domain/glossary.md` — new terms added
460
+ - [ ] `dflow/specs/domain/analysis.md` — ordered cross-context flows, role reach, or anything else no one context owns, that this feature introduced, found or altered; any spot this feature worked around pending a domain decision, in those or in unrecorded knowledge that belongs here; and any open row there this feature settled (created from `templates/analysis.md` the first time there is something to record)
408
461
  - [ ] `dflow/specs/domain/{context}/models.md` — model definitions updated
462
+ - [ ] `dflow/specs/domain/{context}/analysis.md` — lifecycles, derived figures or mechanisms no single rule explains this feature introduced, found or altered, in the owning context's copy, which may not be this host's; any spot this feature worked around pending a domain decision, in those or in a rule or unrecorded knowledge that belongs there; and any open row there this feature settled (created from `templates/analysis.md` the first time there is something to record)
409
463
  - [ ] `dflow/specs/domain/{context}/rules.md` — business rules updated
410
464
  - [ ] `dflow/specs/domain/{context}/behavior.md` — merge completed spec's Given/When/Then scenarios into consolidated behavior. Sub-steps:
411
465
  - Promote any Activity 3 (Spec Writing) draft sections (from B3 mid-sync) to formal sections
412
466
  - Update the corresponding `rules.md` anchor's `last-updated` date (B4)
413
467
  - [ ] `behavior.md` draft cleanup — if the spec was abandoned mid-way, keep the `## 提案中變更` section's history or explicitly REMOVE it
468
+ - [ ] `analysis.md`, at either of its two paths — re-check every entry this feature recorded before building: an entry for what the feature was to add or change against what was built (corrected where the build differs, removed where nothing was built for it), and an entry for something already in the system against the system as it now stands (corrected where this feature changed it, never removed because this feature built nothing for it). Read the entries in the file, not in a diff: a checkpoint may already have committed them.
414
469
  - [ ] `dflow/specs/migration/tech-debt.md` — tech debt discovered during implementation recorded
415
470
 
416
- ### 8.4 Archival
417
-
418
- For a single-phase feature, this is the closeout point. If the feature has
419
- later phases still ahead, this phase is complete but the feature is not —
420
- don't archive yet; run `/dflow:new-phase` to start the next phase, not
421
- `/dflow:finish-feature` yet. For a multi-phase feature, the developer
422
- typically reaches this point at the end of the final phase — at which time
423
- `/dflow:finish-feature` is the recommended trigger (it bundles steps 8.1 /
424
- 8.2 verification, BC sync, and archival into one explicit ceremony). Either
425
- path is acceptable; pick the one that matches the developer's habit.
426
-
427
- - [ ] `_index.md` `status` field changed to `completed`
428
- - [ ] All `phase-spec-*.md` files in the feature directory have `status:
429
- completed` in their frontmatter
430
- - [ ] **Whole feature directory** moved from `dflow/specs/features/active/`
431
- to `dflow/specs/features/completed/` using `git mv` (preserves rename
432
- tracking — see `references/git-integration.md` § "Directory Moves
433
- Must Use git mv"):
434
- ```
435
- git mv dflow/specs/features/active/{SPEC-ID}-{slug} \
436
- dflow/specs/features/completed/{SPEC-ID}-{slug}
437
- ```
438
-
439
- > **Recommended path for multi-phase features**: instead of doing
440
- > 8.1–8.4 manually at the end of every phase, run `/dflow:finish-feature`
441
- > once the feature's last phase is complete. It executes the same checks
442
- > + BC sync + `git mv` + emits an Integration Summary. See
443
- > `references/finish-feature-flow.md`.
444
-
445
- Only announce "feature complete" after 8.4 is done.
471
+ ### 8.4 Phase completion and handoff
472
+
473
+ This step completes the phase and hands the feature on. It does not close the
474
+ feature out: `/dflow:finish-feature` is the only closeout path — it flips the
475
+ `_index.md` `status`, moves the feature directory to `completed/`, and takes
476
+ the closeout commit checkpoint.
477
+
478
+ **Complete this phase** — all four items, whether or not another phase
479
+ follows:
480
+
481
+ - [ ] This phase-spec's frontmatter `status` changed from `in-progress` to
482
+ `completed`
483
+ - [ ] This phase's row in the `_index.md` Phase Specs table changed from
484
+ `in-progress` to `completed`
485
+ - [ ] `_index.md` Current BR Snapshot reconciled against this phase-spec's
486
+ **Business Rules** section — this is the feature's first phase, so it
487
+ has no Delta from prior phases. If implementation changed a rule, update
488
+ the phase-spec first, then reconcile. Touch only this phase's rows: a
489
+ row that another change in this host wrote — a lightweight change
490
+ hosted under this feature, for example — stays as it is. Where this
491
+ phase and such a change both changed the same rule, keep the later
492
+ change's text; if the host's record does not show which change came
493
+ later, ask the developer which text is current instead of choosing.
494
+ - [ ] `_index.md` Resume Pointer: rewrite **both** narrative lines — Current
495
+ Progress says this phase is completed, and Next Action names the
496
+ command the handoff below picks. Step 4 wrote "phase-1 in progress:
497
+ drafting phase-spec." and "finish phase-spec, then implement …" into
498
+ these two lines; either one left standing reads as open work.
499
+
500
+ `/dflow:finish-feature` relies on these four whenever the feature reaches it,
501
+ next or after later phases. Its Step 1 checks the phase-spec `status`, the
502
+ Phase Specs row and the Resume Pointer, and stops closeout on a stale one.
503
+ Its Step 3 syncs the Current BR Snapshot into the bounded context as it
504
+ stands, without re-deriving it from the phase-specs.
505
+
506
+ `Implementation Tasks` is not on this list: 8.1 verified it, and 8.2 may have
507
+ collapsed or removed it by team convention. BC document sync is not on it
508
+ either: 8.3 did it.
509
+
510
+ **Hand off:**
511
+
512
+ - Another phase is still ahead → run `/dflow:new-phase` next.
513
+ - No further phase — a single-phase feature, or this was the last phase →
514
+ run `/dflow:finish-feature` next. It is the only closeout path.
515
+
516
+ Announce that this phase is completed and name the next command. Do not
517
+ announce the feature as complete: `/dflow:finish-feature` announces that once
518
+ its closeout is complete.