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
@@ -13,8 +13,12 @@ feature-branch-per-feature convention that SDD traceability depends on.
13
13
 
14
14
  ## Branch-to-Workflow Mapping
15
15
 
16
- Dflow only requires that every SDD feature / bug-fix lives on its own branch
17
- that links back to a spec. The *base branch* that feature branches are cut
16
+ Dflow only requires that SDD work is traceable from the branch it lands on. A
17
+ feature, and a defect that owns its own branch, each get a branch that links
18
+ back to what was recorded. Work picked up by a feature that is still in
19
+ progress stays on that host's branch — the host `_index.md` `branch:` field is
20
+ authoritative — and a T3 change is traced by its `_index.md` row, not by a spec
21
+ file of its own. The *base branch* that feature branches are cut
18
22
  from (e.g. `main`, `develop`, `trunk`) is a project-level decision that Dflow
19
23
  does not mandate.
20
24
 
@@ -24,8 +28,12 @@ main (or your project's base branch)
24
28
  ├─ feature/{SPEC-ID}-{slug} ← Full SDD workflow
25
29
  │ Gate: spec must exist BEFORE first commit
26
30
  │
27
- └─ bugfix/{BUG-ID}-{slug} ← Lightweight SDD workflow
28
- Gate: at minimum a lightweight spec
31
+ └─ bugfix/{BUG-ID}-{slug} ← a defect that owns its own branch
32
+ (a defect with no feature to host it opens a minimal zero-phase host
33
+ of its own — see references/modify-existing-flow.md Step 1.7)
34
+ Gate: whatever the cascade's tier calls for (T2: at minimum a
35
+ lightweight spec; T3: the host _index.md row only; T1: escalate —
36
+ it belongs on a feature/ branch)
29
37
  ```
30
38
 
31
39
  > If your project adopts Git Flow / GitHub Flow / trunk-based, the choice of
@@ -60,7 +68,9 @@ The branch slug follows the language the developer / AI discuss the
60
68
  feature in. **Both Chinese and English slugs are valid**; Dflow does not
61
69
  force translation in either direction. The same slug is reused for the
62
70
  feature directory name and the first phase-spec filename, so consistency
63
- across branch / dir / phase-spec is automatic.
71
+ across branch / dir / phase-spec is automatic. A **minimal (zero-phase)
72
+ host** has no phase-spec, so its slug is shared by the branch and the
73
+ directory only — the absent third name is the host's shape, not drift.
64
74
 
65
75
  Examples:
66
76
 
@@ -94,8 +104,13 @@ This is the one non-negotiable Git coupling Dflow enforces:
94
104
  - **Every SDD feature must have its own feature branch.** Branch name must
95
105
  match its SPEC-ID so that `git log`, PR titles, and spec documents can be
96
106
  traced back to one another.
97
- - **Every bug-fix (SDD-tracked) must have its own bugfix branch** following
98
- the same pattern.
107
+ - **A defect that owns its own branch uses a `bugfix/` branch** following the
108
+ same pattern — including a standalone defect whose own minimal host is what
109
+ owns it, and whose branch therefore carries a BUG-NUMBER rather than that
110
+ host's SPEC-ID. A defect picked up by a feature that is still in progress is
111
+ hosted work instead: it stays on that host's branch. Either way the host
112
+ `_index.md` `branch:` field is authoritative — every spec inside that host,
113
+ and every branch gate applied to it, takes its value.
99
114
  - Commits that span multiple specs (accidentally or deliberately) are
100
115
  discouraged; if you notice work on a new spec emerging mid-branch, stop
101
116
  and create a new branch off the correct base.
@@ -124,9 +139,34 @@ Both Git policies (`gitflow` / `trunk`, per `dflow/specs/shared/_conventions.md`
124
139
  project cuts features from — `main` / `develop` / `trunk`, or whatever your
125
140
  policy uses — or on an unrelated branch) — the AI offers to create and switch
126
141
  to the correct branch, switch to an existing matching one, or override and
127
- stay (recorded in the feature `_index.md` Checkpoint Log; three consecutive
128
- overrides → the AI suggests re-running `dflow init`, never changing the
129
- setting on its own).
142
+ stay (three consecutive overrides → the AI suggests re-running `dflow init`,
143
+ never changing the setting on its own).
144
+
145
+ **How "override and stay" is recorded, so closeout can honour it.** Write one
146
+ row in the feature `_index.md` Checkpoint Log:
147
+
148
+ | Timestamp | Checkpoint | Result |
149
+ |---|---|---|
150
+ | {YYYY-MM-DD HH:MM} | `branch-override` | `override ({branch-you-stayed-on})` |
151
+
152
+ The Result **names the branch you stayed on** — not the value of `branch:`,
153
+ which stays exactly as the host opened it. That name is what makes the record
154
+ usable, and it is exactly what closeout reads: **its branch check passes when
155
+ *any* `branch-override` row on this host names the branch `HEAD` is on** — not
156
+ only the most recent one, because a host may override onto different branches
157
+ in different phases and closeout fires no branch gate of its own, so it never
158
+ writes a newer row. A record that does not say *where* you stayed excuses
159
+ nothing.
160
+ ⚠ **This row is a record, not a lifecycle checkpoint.** It is not a commit and
161
+ it does not count toward the tier's checkpoint count.
162
+ ⚠ **Where it can appear at all: only on a phase-bearing host.**
163
+ `references/modify-existing-flow.md` withholds this override from every
164
+ **minimal host** (Step 1.6's follow-up variant, Step 1.7 standalone, Step 1.8
165
+ post-hoc), because those hosts assert branch equality against a `branch:` they
166
+ cut by change class. So `references/finish-feature-flow.md`'s closeout branch
167
+ check reads this row and honours it, while its minimal-host checkpoint count
168
+ is never looking at one — that count says so at the site rather than carrying
169
+ an exclusion for a row that cannot reach it.
130
170
 
131
171
  Dflow does not need to identify your base branch to evaluate the gate — it only
132
172
  checks whether you are on the right feature branch. The base branch matters only
@@ -136,7 +176,8 @@ project's decision (GitFlow → `develop`, Trunk / GitHub Flow → `main`).
136
176
  ### Commit checkpoints
137
177
 
138
178
  At lifecycle milestones the AI offers a commit checkpoint, folded into the
139
- existing Step Gate prompt (it does not add a separate question):
179
+ prompt the flow already shows there — a Step Gate, or the flow's closing
180
+ announcement (it does not add a separate question):
140
181
 
141
182
  ```
142
183
  ✓ {milestone} complete
@@ -147,12 +188,47 @@ existing Step Gate prompt (it does not add a separate question):
147
188
 
148
189
  Tier sets how many checkpoints a change has: T1 three (spec / implementation /
149
190
  closeout), T2 two (spec+implementation merged / closeout), T3 a single commit.
191
+ **What a checkpoint carries follows from where its flow offers it.**
192
+ `references/modify-existing-flow.md` offers its checkpoint at the end of its
193
+ artifact step (Step 6), so a T2's merged commit — and a T3's single commit —
194
+ carries the change together with the documentation that step writes.
195
+ `/dflow:new-feature` and `/dflow:new-phase` offer the implementation checkpoint
196
+ at the gate into their completion step, so what that step writes rides the
197
+ host's next commit, whichever that is — for example the next phase's first
198
+ checkpoint, a hosted lightweight change's commit, or closeout.
199
+ "T3 = a single commit" means a single **implementation** commit. On a hosted T3
200
+ the entries that carry its hash ride the host's **next** commit (more work, or
201
+ closeout), as every checkpoint's do (below). If the host has no next commit
202
+ scheduled, one ledger-only tracking commit that references the T3 hash is
203
+ allowed. It is bookkeeping, not a lifecycle milestone: it adds no Checkpoint Log
204
+ row of its own (unlike closeout, which is a checkpoint and does get a row).
205
+ **Minimal host (zero-phase) exception — there, tier does not set the count.**
206
+ On a minimal host (`references/modify-existing-flow.md` Step 1.7 standalone, or
207
+ its Step 1.6 follow-up minimal variant) there is no later host commit for a row
208
+ to ride, so the count is **two for every tier** — implementation, or
209
+ `spec-baseline` for a baseline capture, then closeout — and every row, a T3's
210
+ included, is written into checkpoint 1 itself; only the entries that carry
211
+ checkpoint 1's hash ride the closeout commit.
212
+ Everything above about "T3 = a single commit" describes a **hosted** T3, the
213
+ case where a later host commit exists.
150
214
  Whether you choose Y or N, the AI records one row in the feature `_index.md`
151
215
  Checkpoint Log — every checkpoint is accounted for (`committed` / `skipped` /
152
- `failed`), even when no commit happens. A commit hash is written only after the
153
- commit succeeds; a hook rejection or failed commit is recorded as `failed`
154
- (never a fake hash). **Exception — the closeout row**: the closeout commit
155
- cannot contain its own hash, so the closeout row is written before the commit
216
+ `failed`), even when no commit happens.
217
+ **No checkpoint commit can contain its own hash.** The entries that carry a
218
+ checkpoint's hash — its Checkpoint Log Result `committed ({hash})`, and any
219
+ Lightweight Changes `Commit` cell holding that hash — are written after the
220
+ commit succeeds and ride the host's **next** commit. A hook rejection or failed
221
+ commit is recorded as `failed` (never a fake hash).
222
+ **One further Result value — `reconciled ({merged-hotfix-hash})`.** It records
223
+ that this checkpoint documents a change that was **already merged** before any
224
+ ceremony ran, and it is written only on a post-hoc hotfix host's implementation
225
+ row (`references/modify-existing-flow.md` Step 1.8). The hash in the parentheses
226
+ belongs to the **merged hotfix**, not to this host's own documentation commit —
227
+ that one goes in the Lightweight Changes row's `Commit` cell, and the two have
228
+ different provenance and must never be swapped. On every other host the three
229
+ values above are the whole vocabulary.
230
+ **Exception — the closeout row**: no later commit of this host's lifecycle
231
+ carries it, so the closeout row is written before the commit
156
232
  as `closeout | committed` with **no hash** (see
157
233
  `references/finish-feature-flow.md` Step 4); trace that commit via
158
234
  `git log -1 -- dflow/specs/features/completed/{SPEC-ID}-{slug}` or the optional
@@ -275,17 +351,35 @@ heavily enough that git's similarity index dropped below the rename
275
351
  threshold; consider using `git mv` for the move, then making content
276
352
  edits in a follow-up commit).
277
353
 
278
- ### CI / hook automation (future)
354
+ ### CI / hook automation
279
355
 
280
- A pre-commit hook can refuse commits where `dflow/specs/features/active/` or
281
- `dflow/specs/features/completed/` show paired `D` + `A` instead of `R` for
282
- the same feature directory. Not part of Dflow today, but compatible
283
- with the rule.
356
+ Dflow ships `dflow check-closeout`, a gate for the closeout commit. For each
357
+ feature directory newly archived to `dflow/specs/features/completed/` it checks
358
+ that `_index.md` and every spec say `status: completed`, that nothing is left
359
+ under `active/`, that the Checkpoint Log has a real `closeout` row reading
360
+ `committed` or `skipped`, and — with `--staged` — that nothing under the
361
+ archived directory is left unstaged; it exits 1 when one fails. A project wires
362
+ it into a pre-commit hook (`--staged`) or a CI job (`--range <base>..<head>`)
363
+ itself — Dflow installs neither. `dflow check-closeout --help` names the page
364
+ with the hook and CI templates. When the hook refuses a closeout commit, handle
365
+ it as `references/finish-feature-flow.md` Step 4 instruction 3 says.
366
+
367
+ Passing it is not a clean closeout: the post-commit verification in
368
+ `references/finish-feature-flow.md` Step 4 still applies in full.
369
+
370
+ A hook that refuses paired `D` + `A` instead of `R` for the same feature
371
+ directory is compatible with the `git mv` rule, but it is not part of
372
+ `check-closeout`.
284
373
 
285
374
  ## Gate Checks by Branch Type
286
375
 
287
376
  ### feature/ branch — Before Creating
288
377
 
378
+ This is the **phase-bearing** (T1) list. A **minimal (zero-phase) host** cuts a
379
+ `feature/{SPEC-ID}-{slug}` branch too and takes the short list under it: it has
380
+ no phase-spec *by definition*, so every item that reads one is not merely unmet
381
+ but unmeetable, and demanding them would block the change the branch exists for.
382
+
289
383
  AI should verify:
290
384
  - [ ] Feature directory exists at `dflow/specs/features/active/{SPEC-ID}-{slug}/`
291
385
  with `_index.md` and at least one phase-spec inside
@@ -294,7 +388,33 @@ AI should verify:
294
388
  - [ ] At least one Given/When/Then scenario is defined in the first phase-spec
295
389
  - [ ] Domain concepts are identified (even if not yet in models.md)
296
390
 
391
+ **Minimal (zero-phase) host — this list instead**
392
+ (any route in `references/modify-existing-flow.md` that opens a zero-phase host
393
+ — Step 1.7 standalone, Step 1.6's follow-up variant, Step 1.8's post-hoc
394
+ hotfix, or one added later; a baseline capture uses the same shape):
395
+ - [ ] Feature directory exists at `dflow/specs/features/active/{SPEC-ID}-{slug}/`
396
+ with a minimal `_index.md` — all seven sections, Phase Specs table
397
+ **empty**, and no `phase-spec-*` file
398
+ - [ ] `_index.md` has status: `in-progress`, and its `branch:` equals the branch
399
+ being cut — that field is authoritative for everything in this host
400
+ - [ ] The tier's artifact is ready to be written into the first commit: a
401
+ lightweight-spec for a **T2**, a Lightweight Changes row for a **T3**, a
402
+ `Tier = baseline` row for a baseline capture — in every case with the
403
+ paths it declares named. For a **T2 / T3** those are the implementation
404
+ paths; a **baseline capture** is observation-only and declares the
405
+ **documents it wrote** instead — that is its counterpart
406
+ (`references/modify-existing-flow.md` Step 1.7). Do not ask a capture for
407
+ implementation paths: `references/finish-feature-flow.md` Step 1 blocks a
408
+ baseline commit that carries implementation source at all
409
+ - [ ] Bounded Context is identified **only if this change has one**; a no-BC
410
+ host records `none` and must not acquire a context to pass this gate.
411
+ **A baseline capture is never no-BC** — it sets `BC:` to the context it
412
+ captured, because capturing that context is the whole point of the host
413
+
297
414
  If any are missing, guide the developer through creating them BEFORE the branch.
415
+ On the minimal-host list that governs the `_index.md` items; the tier's artifact
416
+ only has to be *decided and ready to write*, because Step 1.7 records it after
417
+ the branch is cut, not before.
298
418
 
299
419
  ```
300
420
  "Before we create the branch, let's set up the spec.
@@ -310,24 +430,83 @@ AI should verify:
310
430
  - [ ] All `phase-spec-*.md` in the feature directory have `status: completed`
311
431
  - [ ] `_index.md` Current BR Snapshot has been synced to BC layer
312
432
  (`rules.md` / `behavior.md`) — typically by `/dflow:finish-feature`
313
- - [ ] Whole feature directory ready to `git mv` to `dflow/specs/features/completed/`
314
- (or already moved if `/dflow:finish-feature` ran)
433
+ - [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
434
+ complete for this host — its Local-closeout gate is satisfied (the
435
+ closeout commit landed and passed post-commit verification) and, if
436
+ the host carries `follow-up-of`, the Step 6 tracking commit has also
437
+ landed and been verified. `status: completed` or a directory already
438
+ under `completed/` does not show this on its own.
315
439
  - [ ] All new business logic is in `src/Domain/` (not delivery/entrypoint code — presentation/UI layer, controllers, handlers, jobs, message consumers, data pipelines, or stored procedures)
316
440
  - [ ] New terms added to `glossary.md`
317
441
  - [ ] `rules.md` and `models.md` updated if applicable
318
442
  - [ ] Tech debt recorded for any shortcuts taken
319
443
  - [ ] Domain layer code has no delivery-framework references
320
444
 
445
+ > **On a minimal (zero-phase) host**, split this list by what each item reads.
446
+ > Items about **this host's own record** — `_index.md` status, **Closeout
447
+ > complete**, and the phase-spec check, which passes vacuously on an empty
448
+ > table — apply **unchanged**: they are what stops a host merging with its
449
+ > record still open. Every item that names a **Domain or bounded-context
450
+ > artifact**, the BR-Snapshot sync included, applies only to what this change
451
+ > **actually touched**: a **no-BC** host has no bounded context to sync or
452
+ > document, a **T3** does no Domain work at all, and a **baseline capture** has
453
+ > already written Domain documents directly rather than syncing to them — so for
454
+ > those they read N/A. **Bounded-context-scoped only** — `glossary.md` and
455
+ > `migration/tech-debt.md` belong to no bounded context, stay in a no-BC host's
456
+ > sweep, and are a baseline capture's own capture destinations, so they are
457
+ > **not** N/A for either. **Code invariants are not artifacts** — the items
458
+ > here that state a rule about the **source** rather than name a document to
459
+ > update are **never N/A**: they hold for any change that touches code at all,
460
+ > and a host wrongly claiming to be no-BC is exactly what they catch. Record
461
+ > the N/A — do not invent a context, a Domain document, or a BR row to tick
462
+ > one.
463
+
321
464
  ### bugfix/ branch — Before Creating
322
465
 
466
+ > **A `bugfix/` branch is always a minimal (zero-phase) host**, so the
467
+ > minimal-host list above applies here **in full** — the `_index.md` shape, the
468
+ > authoritative `branch:` field, and the artifact's declaration of the paths it
469
+ > touches, which is what closeout blocks on. Every route that cuts one opens the
470
+ > host through `references/modify-existing-flow.md` **Step 1.7's mechanics** —
471
+ > its own numbered **step 4**, "Branch gate — by change class". The known routes
472
+ > are Step 1.7 directly, Step 1.6's minimal follow-up variant, and Step 1.8's
473
+ > post-hoc hotfix; the latter two delegate to that same step (steps 2–4), and a
474
+ > route added later reaches it the same way.
475
+ > Not the top-level `## Step 4`, which cuts no branch. A **T1**
476
+ > escalates to `feature/`, a defect hosted under a phase-bearing feature never
477
+ > gets a branch of its own, and a baseline capture is not a functional bug so it
478
+ > cuts `feature/`. This matters because a functional bug walks **this** gate and
479
+ > never the `feature/` one. The items below are what `bugfix/` adds on top.
480
+
323
481
  AI should verify:
324
- - [ ] Lightweight spec exists or is created during this session
325
- - [ ] Root cause is documented
482
+ - [ ] **The tier's artifact** exists or is created during this session — a
483
+ **lightweight spec** for a T2; for a **T3**, the host `_index.md`
484
+ Lightweight Changes row and *no* spec file, exactly as the branch map
485
+ above says. A T3 spec file does not exist in Dflow, so asking for one
486
+ blocks the change instead of documenting it. A **T1** does not belong on
487
+ a `bugfix/` branch — escalate it to `feature/`.
488
+ - [ ] Root cause is documented — a T2's `## Root Cause`, or the evidence
489
+ section its no-BR family substitutes for it; for a **T3** the row
490
+ Description is the whole record and there is no separate root-cause
491
+ artifact
326
492
  - [ ] Fix approach is noted
327
493
 
328
494
  ### bugfix/ branch — Before Merging (Pre-PR / Pre-Integration)
329
495
 
330
- - [ ] Spec has the fix documented
496
+ - [ ] `_index.md` status: `completed`
497
+ - [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
498
+ complete for this host — its Local-closeout gate is satisfied (the
499
+ closeout commit landed and passed post-commit verification) and, if
500
+ the host carries `follow-up-of`, the Step 6 tracking commit has also
501
+ landed and been verified. `status: completed` or a directory already
502
+ under `completed/` does not show this on its own.
503
+ A `bugfix/` host closes out exactly like a `feature/` one; an
504
+ un-closed-out host must not merge.
505
+ - [ ] **The tier's artifact** has the fix documented — a **T2**'s lightweight
506
+ spec, or for a **T3** the host `_index.md` Lightweight Changes row, which
507
+ is its whole record. Do not ask a T3 for a spec file here either: the
508
+ Before-Creating item above says why, and this gate is the last place that
509
+ mistake can still block the merge.
331
510
  - [ ] Tech debt recorded if the underlying issue is broader (record in
332
511
  `dflow/specs/migration/tech-debt.md` if the bug reveals a systemic issue)
333
512
  - [ ] If business logic was touched, evaluate Domain extraction
@@ -381,7 +560,7 @@ Examples:
381
560
 
382
561
  These checks could eventually be automated in CI:
383
562
  - Verify no delivery-framework references in `src/Domain/` directory
384
- - Verify spec file exists for any branch with feature/ or bugfix/ prefix
563
+ - Verify a spec file exists for any branch with feature/ or bugfix/ prefix — except a host whose entire record is inline in its `_index.md` and therefore has no spec file by design (a T3-only host or a baseline-only capture today, and any later shape with that same property); check for the row instead
385
564
  - Verify glossary.md and rules.md were updated when Domain/ files change
386
565
  - Lint commit messages for spec ID format
387
566
 
@@ -236,8 +236,18 @@ Key Brownfield-track notes:
236
236
  - **`behavior.md` is NOT generated here.** Per F-05, per-context
237
237
  `behavior.md` files are created by `/dflow:new-feature` Step 8.3
238
238
  (completion flow) or by the P007a baseline-capture flow at the moment
239
- the first bounded context is established. Creating empty
240
- `behavior.md` files here would create stale placeholders.
239
+ the first bounded context is established.
240
+ - **`analysis.md` is NOT generated here**, at either of its paths. It holds
241
+ the system-level knowledge no single context document owns — an ordered flow
242
+ that crosses contexts (always the domain-root copy), the lifecycle a status
243
+ field moves through, a figure computed rather than stored, the mechanism
244
+ behind a behavior no single rule explains, which roles reach which function
245
+ (always the domain-root copy), and the spots in them this project keeps
246
+ working around until a domain decision settles them (each in the copy that
247
+ holds the knowledge it is stuck on). What one context owns is recorded in
248
+ `domain/{context}/analysis.md` and the rest in `domain/analysis.md`, each
249
+ created from `templates/analysis.md` the first time a session records
250
+ something that belongs there.
241
251
  - `domain/context-map.md` is **not** mandatory in the Brownfield track
242
252
  (contexts emerge organically during domain extraction; the Greenfield
243
253
  track makes this file mandatory because BCs are usually planned
@@ -288,13 +298,20 @@ skip, and wait for developer confirmation:
288
298
  > |---|---|
289
299
  > | `dflow/specs/domain/glossary.md` | already exists (47 lines) |
290
300
  >
291
- > **Not creating** (per F-05 decision):
301
+ > **Not creating**:
292
302
  > - No `dflow/specs/domain/{context}/behavior.md` files. These are created
293
303
  > later by `/dflow:new-feature` Step 8.3 or P007a when the first
294
304
  > bounded context is established.
295
305
  > - No `dflow/specs/domain/context-map.md`. Brownfield track treats BCs as
296
306
  > emergent from domain extraction; this file becomes relevant later,
297
307
  > typically when 2+ contexts coexist.
308
+ > - No `dflow/specs/domain/analysis.md` and no
309
+ > `dflow/specs/domain/{context}/analysis.md`. Each is created the first time
310
+ > one of these turns up and belongs there — an ordered cross-context flow
311
+ > (always the domain-root copy), the lifecycle of a status field, a derived
312
+ > figure, a mechanism no single rule explains, which roles reach which
313
+ > function (always the domain-root copy), or a spot in one of them this
314
+ > project keeps working around until a domain decision settles it.
298
315
  >
299
316
  > Looks good? Reply 'yes' to proceed with the writes, or tell me what to
300
317
  > adjust."
@@ -432,6 +449,9 @@ Init complete. Summary:
432
449
  Step 8.3 or P007a baseline capture
433
450
  - dflow/specs/domain/context-map.md — created organically when you have
434
451
  ≥2 bounded contexts
452
+ - dflow/specs/domain/{context}/analysis.md — needs a real bounded context
453
+ - dflow/specs/domain/analysis.md — created the first time a session records a
454
+ cross-context flow, role reach, or other knowledge no single context owns
435
455
  ```
436
456
 
437
457
  ### 5.2 Next-step recommendation