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
@@ -64,8 +64,8 @@ are not available in the current AI tool:
64
64
 
65
65
  | Workflow | Use when |
66
66
  |---|---|
67
- | `/dflow:new-feature` | A new user-visible capability or business behavior is requested. |
68
- | `/dflow:modify-existing` | Existing behavior needs to change. |
67
+ | `/dflow:new-feature` | A genuinely new feature, page, or capability — a **newly created** navigable surface (its own route and its own content tree), a new user-executable domain operation, or a new independently-consumable output. Adding a control to an existing surface — or a menu entry pointing at a route that already exists — is modify-existing. |
68
+ | `/dflow:modify-existing` | Existing behavior or an existing surface changes — including adding a presentation / interaction control (copy button, filter, sort, quick-view) to an existing screen. |
69
69
  | `/dflow:bug-fix` | A defect can be described with expected vs actual behavior. |
70
70
  | `/dflow:new-phase` | An active feature needs another implementation slice. |
71
71
  | `/dflow:finish-feature` | Implementation is complete and needs drift closure. |
@@ -81,8 +81,8 @@ Machine-readable source for rendering tool-specific thin wrappers:
81
81
  <!-- dflow-command-registry:start -->
82
82
  | id | label | description | arg-hint | scope |
83
83
  |---|---|---|---|---|
84
- | new-feature | /dflow:new-feature | Start a new user-visible feature or business behavior. | feature request | workflow |
85
- | modify-existing | /dflow:modify-existing | Change existing behavior. | change request | workflow |
84
+ | new-feature | /dflow:new-feature | Start a genuinely new feature, page, or capability (new navigable surface, domain operation, or consumable output). | feature request | workflow |
85
+ | modify-existing | /dflow:modify-existing | Change existing behavior, or add a control to an existing surface. | change request | workflow |
86
86
  | bug-fix | /dflow:bug-fix | Investigate a defect described by expected vs actual behavior. | expected vs actual | workflow |
87
87
  | new-phase | /dflow:new-phase | Add another implementation slice to an active feature. | feature id or phase goal | workflow |
88
88
  | finish-feature | /dflow:finish-feature | Close implementation with drift checks and archived feature state. | feature id | workflow |
@@ -103,16 +103,36 @@ input like this (supporting files live in the workflow bundle at
103
103
  - **"Quick question about..." / "How does X work?"** → check
104
104
  `dflow/specs/domain/` first and answer from the documented domain knowledge.
105
105
  If no spec exists yet, suggest documenting the answer as domain knowledge.
106
+ - **Knowledge that no single context document holds** — an ordered flow that
107
+ crosses contexts (always the domain-root copy), the lifecycle a status field
108
+ moves through, a figure computed rather than stored, the mechanism behind a
109
+ behavior no single rule explains, which roles reach which function (always
110
+ the domain-root copy), or a spot in one of these that this project keeps
111
+ working around until a domain decision settles it (in the copy that holds
112
+ the knowledge it is stuck on) → **record it in
113
+ `analysis.md`**: `dflow/specs/domain/{context}/analysis.md` when one context
114
+ owns what it describes, otherwise `dflow/specs/domain/analysis.md`. Create
115
+ the file from `templates/analysis.md` the first time there is something to
116
+ record. With no workflow running, offer to commit that record on its own.
106
117
  - **"What should I work on next?" / sprint planning** → review
107
118
  `dflow/specs/features/backlog/` and suggest work based on migration value.
108
119
  - **"I'm creating a branch"** → read `references/git-integration.md`; verify
109
- branch naming and ensure a spec exists before coding starts.
120
+ branch naming, and make sure the tier's own record exists before coding starts
121
+ (T1 / T2: a spec; T3: the host `_index.md` row — a T3 branch has no spec file).
110
122
  - **"I'm designing a domain model" / "How should I model X?" / building or
111
123
  reshaping an Aggregate** → read `references/ddd-modeling-guide.md` (DDD
112
124
  tactical patterns: aggregates, invariants, value objects, domain events). It
113
125
  is written with Greenfield artifact names; see its **Edition note** for where
114
126
  Brownfield records the same decisions (`models.md` / `rules.md` /
115
127
  `behavior.md` / `migration/tech-debt.md`).
128
+ - **"Why does this rule exist?" / "This rule seems wrong"** → look the rule up in
129
+ `references/flow-rationale-registry.md`. Grep the rule id when you have one
130
+ (`grep -E '^R-FF-BRANCH-02:'`), otherwise a **short** fragment of the rule —
131
+ four to eight words, because the flow files are hard-wrapped and a longer
132
+ phrase spans a line break. A lookup may return two lines tagged `gf ·` / `bf ·`;
133
+ take this project's edition, which the workflow bundle's
134
+ `.dflow-bundle-manifest.json` records in its `edition` field. **Do not read
135
+ that file whole** — it is a lookup table, not a document.
116
136
  - **"Turn the specs into HTML" / "make the specs easier to read"** → run the
117
137
  CLI command `dflow render` (a human-readability tool, not a `/dflow:*`
118
138
  workflow). It mirrors `dflow/specs/` into a browsable static HTML tree
@@ -121,10 +141,18 @@ input like this (supporting files live in the workflow bundle at
121
141
  - **"Dflow seems wrong" / "this template is confusing"** (or you notice Dflow
122
142
  guidance drift) → suggest `/dflow:report-dflow-feedback`; never submit
123
143
  anything upstream automatically.
124
- - **Anything else code-related** → assess whether it touches business logic. If
125
- it does, use the auto-trigger safety net (suggest the matching `/dflow:*`
126
- command and wait for confirmation — see § Workflow Transparency); if not, help
127
- directly with no ceremony.
144
+ - **Anything else code-related** → run it through § Ceremony Scaling's ordered
145
+ cascade rather than a business-logic yes/no. Only the cascade's step 2 sends
146
+ work outside Dflow, and it is narrower than "not business logic": a display
147
+ typo, an appearance change, a machine-consumed contract edit, security / CVE
148
+ work and a deliberate runtime performance change are all tracked. If the
149
+ cascade lands the request anywhere at or above T3, suggest the matching
150
+ `/dflow:*` command and wait for confirmation (see § Workflow Transparency);
151
+ only if it lands below workflow, help directly with no ceremony. If step 0
152
+ takes it out of the cascade instead — observation-only work — it is neither:
153
+ say so and record it, do not treat "no tier" as "no ceremony". This applies
154
+ once you are already reading this guide — what makes a tool load it in the
155
+ first place is that tool's own trigger configuration, which is narrower.
128
156
 
129
157
  ## Status / Control Commands
130
158
 
@@ -250,6 +278,8 @@ Dflow-owned project documents live under `dflow/specs/`.
250
278
  | System overview | `dflow/specs/shared/_overview.md` |
251
279
  | Domain glossary | `dflow/specs/domain/glossary.md` |
252
280
  | Context map | `dflow/specs/domain/context-map.md` |
281
+ | Domain analysis (cross-context) | `dflow/specs/domain/analysis.md` |
282
+ | Domain analysis (per context) | `dflow/specs/domain/{context}/analysis.md` |
253
283
  | Active feature specs | `dflow/specs/features/active/` |
254
284
  | Completed feature snapshots | `dflow/specs/features/completed/` |
255
285
  | Technical debt | `dflow/specs/architecture/tech-debt.md` or `dflow/specs/migration/tech-debt.md` |
@@ -265,10 +295,13 @@ dflow/specs/
265
295
  │ └── _conventions.md # Spec writing conventions
266
296
  ├── domain/ # Domain knowledge (DDD preparation)
267
297
  │ ├── glossary.md # Ubiquitous Language
298
+ │ ├── context-map.md # Bounded Context relationships (created when needed)
299
+ │ ├── analysis.md # Cross-context flows and role reach
268
300
  │ └── {bounded-context}/ # e.g., expense/, hr/, leave/
269
301
  │ ├── context.md # Context boundary & responsibilities
270
302
  │ ├── models.md # Entity, VO, Aggregate definitions
271
303
  │ ├── rules.md # Business rules index (BR-ID + one-line)
304
+ │ ├── analysis.md # Lifecycles, derived figures, mechanisms
272
305
  │ └── behavior.md # Consolidated behavior (Given/When/Then)
273
306
  ├── features/
274
307
  │ ├── active/ # Currently in development
@@ -297,29 +330,112 @@ dflow/specs/
297
330
  ## Ceremony Scaling
298
331
 
299
332
  Not everything needs full ceremony — match effort to impact. Dflow uses three
300
- tiers — **T1 Heavy / T2 Light / T3 Trivial** — chosen by the AI per change.
301
- `/dflow:new-feature` and `/dflow:new-phase` always default to T1 (no judgement
302
- needed). The criteria below apply when `/dflow:modify-existing` or
303
- `/dflow:bug-fix` decides which tier fits a modification.
304
-
305
- | Tier | Scenario | Output | Command / Trigger |
306
- |---|---|---|---|
307
- | **T1 Heavy** | New feature, new phase, architectural change, new BR | Independent `phase-spec-YYYY-MM-DD-{slug}.md` placed in the feature directory + `_index.md` Phase Specs row + refresh BR Snapshot | `/dflow:new-feature` / `/dflow:new-phase` |
308
- | **T2 Light** | Bug fix, UI input validation tweak, flow branch change — has BR Delta | Independent `lightweight-YYYY-MM-DD-{slug}.md` (or `BUG-{NUMBER}-{slug}.md`) inside the feature directory + `_index.md` Lightweight Changes row (outbound link) + refresh BR Snapshot | `/dflow:bug-fix` or `/dflow:modify-existing` (lightweight branch) |
309
- | **T3 Trivial** | Button colour, copy/text fix, typo, formatting, pure comments — **no BR change, no Domain concept change, no data structure change** | **Inline row in `_index.md` Lightweight Changes only** (no independent spec file) | `/dflow:modify-existing` (`_index-only` branch) |
310
-
311
- **T3 criteria** (the AI must satisfy **all four** before classifying T3):
312
-
313
- 1. No BR-ID change (no ADDED / MODIFIED / REMOVED / RENAMED business rule)
314
- 2. No Domain concept added or changed (Aggregate / Entity / VO / Event)
315
- 3. No data structure change (table, column, relation, index)
316
- 4. Only changes UI surface (colour, text, layout), pure comments, or pure formatting
317
-
318
- If any criterion fails → drop to T2; if Domain / BR / data structure is touched → escalate to T1.
319
-
320
- **Below T3 — Dflow doesn't track at all**: pure typo fixes, commit-message
321
- typos, pure formatting commits (e.g. `prettier` / `dotnet format` auto-runs).
322
- You can `git commit` directly without writing even a T3 inline row.
333
+ tiers — **T1 Heavy / T2 Light / T3 Trivial** — plus a **below-workflow** level
334
+ Dflow doesn't track at all. `/dflow:new-feature` and `/dflow:new-phase` are
335
+ always T1 (no judgement). For `/dflow:modify-existing` and `/dflow:bug-fix`,
336
+ classify the change with the **ordered cascade — the first step that matches
337
+ wins** (order matters: a later catch-all would otherwise swallow the trivial and
338
+ below-workflow cases):
339
+
340
+ 0. **Scope.** The cascade classifies a *modification*. Genuinely new work — a
341
+ new feature, page, or capability — is `/dflow:new-feature` (T1), even with no
342
+ new BR / Domain / schema. Adding a presentation or interaction control to an
343
+ **existing** surface (copy button, date-range filter, sort control, quick-view
344
+ drawer / tab, or filling a missing `aria-label`) is a *modification* (stays in
345
+ the cascade). A new user-executable domain operation (e.g. one-click return), a
346
+ new independently-consumable output or delivery channel (Download-PDF / export /
347
+ emailed report), or a **newly created** navigable surface (its own route and its
348
+ own content tree) **is** new-feature. Adding a menu entry or link that points at
349
+ a route that already exists is an access control on an existing surface —
350
+ a modification, not a new surface. **Unit of classification**: classify one
351
+ coherent requested change. Split a compound request into its atomic changes,
352
+ run each through the cascade, and let the highest tier govern the whole — each
353
+ lower-tier part still records its own artifact under the same host. Mechanical
354
+ fallout you did not ask for (formatter noise, lint churn) neither raises nor
355
+ lowers the result.
356
+ **Observation-only work is also outside the
357
+ cascade**: capturing existing behaviour as a baseline (Brownfield) changes no
358
+ output, so it carries no tier at all — record it and do not read step 2's
359
+ "below workflow" as permission to skip the record.
360
+ 1. **T1 — Heavy.** A **new** business rule or normative constraint (permission /
361
+ eligibility / threshold / approval / required outcome — regardless of whether a
362
+ BR-ID already exists). *New* means a rule that can be stated and broken on its
363
+ own: take the change away and the original rule still works exactly as before.
364
+ Changing an existing rule's parameters is **T2** — a different threshold value,
365
+ or adding to a set the rule already checks (one more allowed country, one more
366
+ approver role). Adding an independent condition the rule never had (an approver
367
+ predicate for a specific payment channel) is a new rule, and T1. A Domain concept (Aggregate / Entity / VO / Event)
368
+ **added or structurally changed** (identity, VO equality components, aggregate
369
+ boundary, or removing / renaming / redefining a spec-tracked member — a Domain
370
+ concept **rename** is T1); a persistent **data-structure** change (table /
371
+ column / relation / index added, removed, renamed, or its type / nullability /
372
+ constraint / logical definition changed); an **architectural** change
373
+ (inter-layer dependency direction, deployment / module boundary, runtime /
374
+ platform ownership, or overturning an architecture decision — behavior-
375
+ preserving still counts); or a **breaking** cross-consumer contract (API /
376
+ event). Contracts run **inbound** too — a required env var / deployment config
377
+ key, a CLI flag, an exit code, a scheduled-automation calling convention. What
378
+ breaks a caller is T1: removing or renaming one, changing what one means, or
379
+ adding a **required** key with no backward-compatible default (deployments must
380
+ act) — making an existing operation's parameter **required** breaks callers the
381
+ same way. Adding an *optional* key or parameter with a backward-compatible
382
+ default is non-breaking — T2 via step 4.
383
+ 2. **Below workflow — not tracked.** No audience-perceivable output delta **and**
384
+ no machine-consumed-contract or operational-semantics touch: auto-formatter
385
+ runs, whitespace, internal comments, internal-doc typos, commit messages, and
386
+ behavior-preserving **routine** refactors / dependency bumps. **Routine** =
387
+ touches no operational-semantics axis (security / safety / resilience /
388
+ compliance / payment) and is not architectural — **breadth is not the test** (a
389
+ behavior-preserving refactor across hundreds of call sites is still below
390
+ workflow; a single-file change that touches an operational axis is not). Never
391
+ below workflow, even when invisible: any BR-ID delta, any machine-consumed
392
+ structured-log / export / contract change, any deliberate runtime performance /
393
+ resource / SLA change, or any security / CVE / compliance work — those reach
394
+ step 1 or 4 by audience. `git commit` directly.
395
+ 3. **T3 — Trivial.** A **local, low-risk, meaning-preserving pure copy or
396
+ appearance change a product audience perceives** — display-text typo / wording
397
+ polish, colour, spacing, layout polish, or polishing existing alt / ARIA
398
+ wording — on a **single screen / component or single independently-consumed
399
+ page / file**, at the **element level**. **Excluded from T3**: high-consequence
400
+ content (security warnings, password hints, consent, payment / legal notices);
401
+ meaning-changing appearance (danger / status-colour semantics); anything
402
+ affecting operability, default state, interaction order, or task completion
403
+ ("just CSS" is no exemption); adding a **missing** accessible name (compliance
404
+ remediation); and text a machine consumes — an API error string or code a client
405
+ parses is contract, not display copy, so it is never T3: route it by the contract
406
+ axis instead (breaks the consumer → step 1, T1; otherwise → step 4, T2). **Locality is
407
+ the rendered audience footprint, not the number of source files**: one shared
408
+ component or localization key whose output appears on several screens is beyond
409
+ the local unit (T2), while edits to several files that surface in one place stay
410
+ T3. Anything beyond that unit is T2 — a typo swept across many screens, a
411
+ whole-screen visual rewrite, a cross-page sweep. The limit follows the whole
412
+ intent, so splitting one cross-screen typo sweep into per-screen requests does
413
+ not turn it into several T3s.
414
+ 4. **T2 — Light (catch-all — everything else).** Functional / semantic behavior
415
+ delta (logic, validation, interaction flow, display calculation, an
416
+ **existing** BR's delta, non-breaking contract semantics); performance-only
417
+ changes (perceivable or not); and copy / appearance sweeps escalated from step
418
+ 3. Functional bug fixes are T2 (root-cause + regression notes).
419
+
420
+ | Tier | Output | Command / Trigger |
421
+ |---|---|---|
422
+ | **T1 Heavy** | Independent `phase-spec-YYYY-MM-DD-{slug}.md` placed in the feature directory + `_index.md` Phase Specs row + refresh BR Snapshot | `/dflow:new-feature` / `/dflow:new-phase` — also where a `/dflow:modify-existing` or `/dflow:bug-fix` request goes when the cascade lands it at T1 |
423
+ | **T2 Light** | Independent `lightweight-YYYY-MM-DD-{slug}.md` (or `BUG-{NUMBER}-{slug}.md`) inside the feature directory + `_index.md` Lightweight Changes row (outbound link) + refresh BR Snapshot | `/dflow:modify-existing` or `/dflow:bug-fix` — the usual landing for a functional defect |
424
+ | **T3 Trivial** | **Inline row in the host `_index.md` Lightweight Changes only** (no independent spec file) | `/dflow:modify-existing` or `/dflow:bug-fix` (`_index`-only branch — e.g. a defect that is only a display-text typo) |
425
+
426
+ **Audience** = any human audience of the product perceives the output: UI
427
+ (including alt / ARIA read by assistive tech), email, exports. Public / adopter-
428
+ facing docs (product README, public API reference) and operator surfaces
429
+ (dashboard labels, alerts) are product-audience: pure wording = T3 (single page;
430
+ a cross-page sweep escalates to T2 at step 3), meaning change = T2. Raw internal
431
+ diagnostic logs / traces are internal (copy-only fixes are below workflow).
432
+ Structured logs / machine-readable exports a downstream consumer depends on are
433
+ contract: breaking cross-consumer = step 1 T1, non-breaking = step 4 T2.
434
+
435
+ **Project conventions can only escalate.** `_conventions.md` Ceremony (Project
436
+ Application) rows are a floor-raising overlay applied *after* the cascade: a
437
+ project may push a T2 up to T1, but may not lower a cascade T1, nor drop a
438
+ tracked class below workflow.
323
439
 
324
440
  **Lightweight spec** = Problem + Expected behavior + 1–2 Given/When/Then. The
325
441
  instantiated file is placed inside the feature directory (see
@@ -393,7 +509,8 @@ during the completion checklist, not via template section markers.
393
509
  - Did we discover scattered business logic? → Record in tech-debt.md
394
510
  - Are there duplicated calculations? → Record
395
511
  - Direct SQL in delivery/entrypoint code? → Record
396
- - Magic numbers or undocumented statuses? → Record and add to glossary
512
+ - Magic numbers? → Record and add to glossary
513
+ - Undocumented status values? → List them in their field's lifecycle in `analysis.md`
397
514
 
398
515
  ## Workflow Steps
399
516
 
@@ -411,7 +528,7 @@ directory first. For example:
411
528
  |---|---|
412
529
  | `/dflow:new-feature` | `dflow/specs/shared/dflow-workflows/references/new-feature-flow.md` |
413
530
  | `/dflow:modify-existing` | `dflow/specs/shared/dflow-workflows/references/modify-existing-flow.md` |
414
- | `/dflow:bug-fix` | `dflow/specs/shared/dflow-workflows/references/modify-existing-flow.md` (lightweight-ceremony branch) |
531
+ | `/dflow:bug-fix` | `dflow/specs/shared/dflow-workflows/references/modify-existing-flow.md` (same flow; tier comes from the cascade, not from the command) |
415
532
  | `/dflow:new-phase` | `dflow/specs/shared/dflow-workflows/references/new-phase-flow.md` |
416
533
  | `/dflow:finish-feature` | `dflow/specs/shared/dflow-workflows/references/finish-feature-flow.md` |
417
534
  | `/dflow:verify` | `dflow/specs/shared/dflow-workflows/references/drift-verification.md` |
@@ -114,7 +114,7 @@ AI 的完整決策樹、Workflow Transparency、Ceremony Scaling 三層判準
114
114
  - `/dflow:new-feature` — 新功能開發
115
115
  - `/dflow:new-phase` — 在 active feature 內新增階段
116
116
  - `/dflow:modify-existing` — 修改既有功能
117
- - `/dflow:bug-fix` — 輕量修復
117
+ - `/dflow:bug-fix` — Bug 修復
118
118
  - `/dflow:finish-feature` — feature 收尾
119
119
  - `/dflow:pr-review` — PR 審查
120
120
  - `/dflow:verify` — rules.md ↔ behavior.md 漂移檢查
@@ -17,6 +17,8 @@ trunk-based, GitHub Flow), use `Git-principles-trunk.md` instead.
17
17
 
18
18
  ---
19
19
 
20
+ <!-- dflow-generated: git-principles-canonical START -->
21
+
20
22
  ## 1. Branch Structure
21
23
 
22
24
  | Branch | Naming | Cut from | Merges to |
@@ -24,6 +26,7 @@ trunk-based, GitHub Flow), use `Git-principles-trunk.md` instead.
24
26
  | `main` / `master` | `main` | — | release / hotfix only |
25
27
  | `develop` | `develop` | — | integration branch for features |
26
28
  | feature | `feature/{SPEC-ID}-{slug}` | `develop` | `develop` |
29
+ | bugfix | `bugfix/{BUG-ID}-{slug}` | `develop` | `develop` |
27
30
  | release | `release/{version}` | `develop` | `main` + `develop` |
28
31
  | hotfix | `hotfix/{version}-hotfix{n}` | `main` | `main` + `develop` |
29
32
 
@@ -31,6 +34,17 @@ The `feature/{SPEC-ID}-{slug}` pattern is a **Dflow requirement** (not
31
34
  a Git Flow requirement). It ties each feature branch to its
32
35
  corresponding `dflow/specs/features/active/{SPEC-ID}-{slug}/` directory.
33
36
 
37
+ A **`bugfix/{BUG-ID}-{slug}`** branch is the same shape as a feature branch and
38
+ follows the same topology — cut from the same base, pushed the same way,
39
+ integrated the same way, and **closed out the same way**. It is used when a
40
+ defect owns its own host rather than being picked up by a feature already in
41
+ flight. Its host is a **minimal (zero-phase) host**, so it carries no
42
+ phase-spec: the SPEC-ID lives in the directory name while the branch name
43
+ carries the BUG-NUMBER, and the host `_index.md` `branch:` field is
44
+ authoritative for both. Closeout is not optional because the branch prefix
45
+ differs — `/dflow:finish-feature` runs and the directory is archived to
46
+ `completed/` before the branch merges, exactly as for `feature/`.
47
+
34
48
  ### Feature Branch Workflow
35
49
 
36
50
  ```bash
@@ -107,10 +121,22 @@ git branch -d hotfix/{version}-hotfix{n}
107
121
  ```
108
122
 
109
123
  **Hotfix spec requirement (team convention)**: Hotfixes often skip the
110
- upfront SDD cycle for speed. This project commits to writing a
111
- lightweight spec within **24 hours** after the hotfix lands, documenting
112
- root cause + fix + (if applicable) a tech-debt entry in
113
- `dflow/specs/migration/tech-debt.md` if the bug reveals a systemic issue.
124
+ upfront SDD cycle for speed. This project commits to documenting the fix
125
+ within **24 hours** after it lands. Run `/dflow:modify-existing` in
126
+ **post-hoc mode** (`references/modify-existing-flow.md` Step 1.8): it opens a
127
+ minimal host of its own for the fix, records the implementation checkpoint as
128
+ `reconciled ({merged-hotfix-hash})`, and reconciles rather than re-running work
129
+ that is already on the mainline. The hash it records is the hotfix's own
130
+ commit, **not** the tagged merge commit on `main` (step 3): the record is
131
+ never a merge commit, and step 4 merges the hotfix **branch**, so the tagged
132
+ commit does not come into `develop` with it.
133
+ `references/modify-existing-post-hoc-hotfix.md` item 3 has the rule.
134
+ What gets written is whatever the cascade's tier calls for — a **T2** lands a
135
+ lightweight spec (root cause + fix + a `dflow/specs/migration/tech-debt.md` entry
136
+ if the bug reveals a systemic issue); a **T3** lands one `_index.md` Lightweight
137
+ Changes row and no spec file. Step 1.8 admits **T2 / T3 only**: a **T1**
138
+ post-hoc keeps the normal phase-bearing route and documents the merged work
139
+ there.
114
140
  This is a **human-to-human commitment** — Dflow / AI cannot track the
115
141
  24-hour clock; the team enforces it in retros.
116
142
 
@@ -156,12 +182,19 @@ before making key Git operations:
156
182
  justification in the spec's notes section)
157
183
  - [ ] `_index.md` status reflects the current work (Phase Specs row
158
184
  updated, `Resume Pointer` refreshed if the commit reaches a meaningful
159
- checkpoint)
185
+ checkpoint). A **minimal (zero-phase) host** has no Phase Specs row to
186
+ update — its record is the Lightweight Changes row, and that row must
187
+ already be written **before** this commit, not after it. Refresh the
188
+ Resume Pointer as usual.
160
189
 
161
190
  ### Before merging a feature branch to `develop`
162
191
 
163
- - [ ] `/dflow:finish-feature` has run (or the equivalent Step 8.4
164
- manual archival is complete)
192
+ - [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
193
+ complete for this host — its Local-closeout gate is satisfied (the
194
+ closeout commit landed and passed post-commit verification) and, if
195
+ the host carries `follow-up-of`, the Step 6 tracking commit has also
196
+ landed and been verified. `status: completed` or a directory already
197
+ under `completed/` does not show this on its own.
165
198
  - [ ] `_index.md` status = `completed`, feature directory moved to
166
199
  `dflow/specs/features/completed/` via `git mv`
167
200
  - [ ] BC layer synced: `dflow/specs/domain/{context}/rules.md` and
@@ -170,6 +203,23 @@ before making key Git operations:
170
203
  - [ ] `dflow/specs/migration/tech-debt.md` updated with any debt discovered
171
204
  - [ ] Domain layer (`src/Domain/`) has no delivery-framework references
172
205
 
206
+ > **Minimal (zero-phase) host.** The items about this host's own record —
207
+ > **Closeout complete**, `_index.md` status `completed`, and the archival
208
+ > move — apply **unchanged**: they are what stops a host merging with
209
+ > its record still open. Every item naming a **Domain or bounded-context
210
+ > artifact** applies only to what this change **actually touched**: a **no-BC**
211
+ > host has no context to sync or document, a **T3** does no Domain work at all,
212
+ > and a **baseline capture** wrote Domain documents directly rather than syncing
213
+ > to them — so for those they read N/A. **Bounded-context-scoped only** —
214
+ > `glossary.md` and `migration/tech-debt.md` belong to no bounded context, stay
215
+ > in a no-BC host's sweep, and are a baseline capture's own capture
216
+ > destinations, so they are **not** N/A for either. **Code invariants are not
217
+ > artifacts** — the items here that state a rule about the **source** rather
218
+ > than name a document to update are **never N/A**: they hold for any change
219
+ > that touches code at all, and a host wrongly claiming to be no-BC is exactly
220
+ > what they catch. Record the N/A; do not create a context, a Domain document,
221
+ > or a BR row to tick a box.
222
+
173
223
  ---
174
224
 
175
225
  ## 4. Integration Commit Message Conventions
@@ -200,6 +250,31 @@ Related BR-IDs:
200
250
  Related SPEC-IDs: {SPEC-ID}{, follow-up SPEC-IDs if any}
201
251
  ```
202
252
 
253
+ **Zero-phase (minimal host) form.** A minimal host has no phases and may have
254
+ no bounded context, so its Change Scope block carries the values that are
255
+ actually true rather than padded ones:
256
+
257
+ ```
258
+ Change Scope:
259
+ - BC: none # or the real context, when the change has one
260
+ - Phase Count: 0
261
+ - Lightweight Changes: 1 T2 + 0 T3 # at least one row, always
262
+
263
+ Related BR-IDs: {empty, or the per-family no-BR marker this change carries}
264
+ ```
265
+
266
+ `none` and `0` are the honest values here, not placeholders waiting to be
267
+ filled. **`Related BR-IDs` is the exception — never force it to `none`.**
268
+ It reports what this change's own record carries, not what was synced, so it
269
+ takes the same values a BC-bearing host would: empty, or the per-family no-BR
270
+ marker when the T2 carries one. Writing `none` there erases the marker the
271
+ zero-phase shape requires (`references/finish-feature-flow.md` Step 5 states
272
+ the rule, and a baseline host leaves the field empty). A minimal host that genuinely touches a bounded context reports that
273
+ context and its real BR delta exactly as a phase-bearing feature would — the
274
+ zero is the **phase count**, not the significance. A **baseline capture** is
275
+ the one variant that always reports a real `BC:` — capturing it is the whole
276
+ point of the host.
277
+
203
278
  ### Concrete example
204
279
 
205
280
  ```bash
@@ -252,7 +327,7 @@ release.
252
327
  Example entry:
253
328
 
254
329
  ```markdown
255
- ## [1.2.3] — {YYYY-MM-DD}
330
+ ## [1.2.3] — {2026-04-21}
256
331
 
257
332
  ### Added
258
333
  - {SPEC-20260421-001}: JPY currency support in Money value object
@@ -266,6 +341,8 @@ Example entry:
266
341
 
267
342
  ---
268
343
 
344
+ <!-- dflow-generated: git-principles-canonical END -->
345
+
269
346
  ## 6. AI Collaboration Rules (Project Policy)
270
347
 
271
348
  Three categories:
@@ -22,6 +22,8 @@ and long-lived release branches.
22
22
 
23
23
  ---
24
24
 
25
+ <!-- dflow-generated: git-principles-canonical START -->
26
+
25
27
  ## 1. Branch Structure
26
28
 
27
29
  | Branch | Naming | Cut from | Merges to |
@@ -35,6 +37,17 @@ happens on short-lived feature / bugfix branches cut from `main` and
35
37
  merged back into `main` quickly (ideally within a day, always
36
38
  within a week).
37
39
 
40
+ A **`bugfix/{BUG-ID}-{slug}`** branch is the same shape as a feature branch and
41
+ follows the same topology — cut from the same base, pushed the same way,
42
+ integrated the same way, and **closed out the same way**. It is used when a
43
+ defect owns its own host rather than being picked up by a feature already in
44
+ flight. Its host is a **minimal (zero-phase) host**, so it carries no
45
+ phase-spec: the SPEC-ID lives in the directory name while the branch name
46
+ carries the BUG-NUMBER, and the host `_index.md` `branch:` field is
47
+ authoritative for both. Closeout is not optional because the branch prefix
48
+ differs — `/dflow:finish-feature` runs and the directory is archived to
49
+ `completed/` before the branch merges, exactly as for `feature/`.
50
+
38
51
  The `feature/{SPEC-ID}-{slug}` pattern is a **Dflow requirement** (not
39
52
  a trunk-based requirement). It ties each feature branch to its
40
53
  corresponding `dflow/specs/features/active/{SPEC-ID}-{slug}/` directory.
@@ -76,8 +89,8 @@ Commits must tie back to a SPEC-ID:
76
89
 
77
90
  ### Conventional Commits style (recommended, optional)
78
91
 
79
- This project {does / does not} require Conventional Commits. When
80
- adopted, the format is:
92
+ Conventional Commits is optional. **Record whether this project requires it
93
+ in § 6, under "Commit and merge choices".** When adopted, the format is:
81
94
 
82
95
  ```
83
96
  {type}({scope}): {short description}
@@ -103,9 +116,9 @@ Example: `feat(expense): add JPY currency support` with
103
116
  ## 3. Merge Strategy (Project Chooses)
104
117
 
105
118
  Trunk-based strategies typically pick **one** merge style and stick to
106
- it. This project uses: **{squash | rebase | fast-forward}**. Delete
107
- the two unused options once decided, or keep all three in the table
108
- and circle the chosen one.
119
+ it. The table below gives the trade-offs; **record this project's choice
120
+ in § 6, under "Commit and merge choices"** — that section is yours, this
121
+ one is not.
109
122
 
110
123
  | Strategy | How the feature lands on `main` | When to prefer |
111
124
  |----------|--------------------------------|----------------|
@@ -120,12 +133,19 @@ and circle the chosen one.
120
133
  justification in the spec's notes section)
121
134
  - [ ] `_index.md` status reflects the current work (Phase Specs row
122
135
  updated, `Resume Pointer` refreshed if the commit reaches a meaningful
123
- checkpoint)
136
+ checkpoint). A **minimal (zero-phase) host** has no Phase Specs row to
137
+ update — its record is the Lightweight Changes row, and that row must
138
+ already be written **before** this commit, not after it. Refresh the
139
+ Resume Pointer as usual.
124
140
 
125
141
  ### Gate Checks — Before merging a feature PR to `main`
126
142
 
127
- - [ ] `/dflow:finish-feature` has run (or the equivalent Step 8.4
128
- manual archival is complete)
143
+ - [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
144
+ complete for this host — its Local-closeout gate is satisfied (the
145
+ closeout commit landed and passed post-commit verification) and, if
146
+ the host carries `follow-up-of`, the Step 6 tracking commit has also
147
+ landed and been verified. `status: completed` or a directory already
148
+ under `completed/` does not show this on its own.
129
149
  - [ ] `_index.md` status = `completed`, feature directory moved to
130
150
  `dflow/specs/features/completed/` via `git mv`
131
151
  - [ ] BC layer synced: `dflow/specs/domain/{context}/rules.md` and
@@ -136,6 +156,23 @@ and circle the chosen one.
136
156
  - [ ] CI green
137
157
  - [ ] PR has at least one review approval
138
158
 
159
+ > **Minimal (zero-phase) host.** The items about this host's own record —
160
+ > **Closeout complete**, `_index.md` status `completed`, and the archival
161
+ > move — apply **unchanged**: they are what stops a host merging with
162
+ > its record still open. Every item naming a **Domain or bounded-context
163
+ > artifact** applies only to what this change **actually touched**: a **no-BC**
164
+ > host has no context to sync or document, a **T3** does no Domain work at all,
165
+ > and a **baseline capture** wrote Domain documents directly rather than syncing
166
+ > to them — so for those they read N/A. **Bounded-context-scoped only** —
167
+ > `glossary.md` and `migration/tech-debt.md` belong to no bounded context, stay
168
+ > in a no-BC host's sweep, and are a baseline capture's own capture
169
+ > destinations, so they are **not** N/A for either. **Code invariants are not
170
+ > artifacts** — the items here that state a rule about the **source** rather
171
+ > than name a document to update are **never N/A**: they hold for any change
172
+ > that touches code at all, and a host wrongly claiming to be no-BC is exactly
173
+ > what they catch. Record the N/A; do not create a context, a Domain document,
174
+ > or a BR row to tick a box.
175
+
139
176
  ---
140
177
 
141
178
  ## 4. Integration Commit Message Conventions
@@ -170,6 +207,31 @@ Related BR-IDs:
170
207
  Related SPEC-IDs: {SPEC-ID}{, follow-up SPEC-IDs if any}
171
208
  ```
172
209
 
210
+ **Zero-phase (minimal host) form.** A minimal host has no phases and may have
211
+ no bounded context, so its Change Scope block carries the values that are
212
+ actually true rather than padded ones:
213
+
214
+ ```
215
+ Change Scope:
216
+ - BC: none # or the real context, when the change has one
217
+ - Phase Count: 0
218
+ - Lightweight Changes: 1 T2 + 0 T3 # at least one row, always
219
+
220
+ Related BR-IDs: {empty, or the per-family no-BR marker this change carries}
221
+ ```
222
+
223
+ `none` and `0` are the honest values here, not placeholders waiting to be
224
+ filled. **`Related BR-IDs` is the exception — never force it to `none`.**
225
+ It reports what this change's own record carries, not what was synced, so it
226
+ takes the same values a BC-bearing host would: empty, or the per-family no-BR
227
+ marker when the T2 carries one. Writing `none` there erases the marker the
228
+ zero-phase shape requires (`references/finish-feature-flow.md` Step 5 states
229
+ the rule, and a baseline host leaves the field empty). A minimal host that genuinely touches a bounded context reports that
230
+ context and its real BR delta exactly as a phase-bearing feature would — the
231
+ zero is the **phase count**, not the significance. A **baseline capture** is
232
+ the one variant that always reports a real `BC:` — capturing it is the whole
233
+ point of the host.
234
+
173
235
  Example:
174
236
 
175
237
  ```
@@ -208,11 +270,17 @@ losing the feature-level summary.
208
270
 
209
271
  ### 4.3 Fast-forward (feature has exactly 1 commit)
210
272
 
211
- If the entire feature was a single commit (common for T2 / T3-only
212
- features or minimal features), fast-forward is fine. Use the commit
273
+ If the entire feature was a single commit (a hosted T2 / T3 whose work and
274
+ record landed together), fast-forward is fine. Use the commit
213
275
  message format from § 4.1 (squash) for that single commit — it already
214
276
  reads as the feature's single narrative.
215
277
 
278
+ **A minimal (zero-phase) host is never this case.** It records **exactly two**
279
+ commits — the implementation (or `spec-baseline`) checkpoint, then the closeout
280
+ commit that carries the archival `git mv` — so it does not arrive here with
281
+ one. A minimal host showing a single commit has not closed out: run
282
+ `/dflow:finish-feature` first rather than fast-forwarding it as it stands.
283
+
216
284
  ```bash
217
285
  git checkout main
218
286
  git pull --ff-only origin main
@@ -244,6 +312,8 @@ style.
244
312
 
245
313
  ---
246
314
 
315
+ <!-- dflow-generated: git-principles-canonical END -->
316
+
247
317
  ## 6. AI Collaboration Rules (Project Policy)
248
318
 
249
319
  Three categories:
@@ -292,6 +362,14 @@ can always decline. If your team also wants vendor attribution, appending the
292
362
  assistant's documented line (e.g. `Co-Authored-By: Claude
293
363
  <noreply@anthropic.com>`) is an independent, optional convention on top.
294
364
 
365
+ ### Commit and merge choices
366
+
367
+ Dflow does not choose these for you; §§ 2-3 give the trade-offs. Record what
368
+ this project settled on:
369
+
370
+ - **Conventional Commits**: {required / not required — fill in}
371
+ - **Merge strategy**: {squash / rebase / fast-forward — fill in}
372
+
295
373
  ---
296
374
 
297
375
  ## 7. CI / CD