dflow-sdd-ddd 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +824 -1
- package/CONTRIBUTING.md +16 -10
- package/README.en.md +156 -200
- package/README.md +89 -144
- package/TEMPLATE-COVERAGE.md +15 -8
- package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
- package/bin/dflow.js +36 -4
- package/docs/commands.en.md +110 -0
- package/docs/commands.md +101 -0
- package/docs/doctor-uncertainty.en.md +212 -0
- package/docs/doctor-uncertainty.md +212 -0
- package/docs/evaluating-dflow.en.md +29 -11
- package/docs/evaluating-dflow.md +8 -6
- package/docs/npm-publish-checklist.md +3 -1
- package/docs/release-versioning-policy.md +8 -2
- package/docs/upgrading.en.md +196 -0
- package/docs/upgrading.md +197 -0
- package/docs/using-with-claude-code.en.md +25 -10
- package/docs/using-with-claude-code.md +20 -7
- package/docs/using-with-codex.en.md +18 -6
- package/docs/using-with-codex.md +16 -5
- package/docs/using-with-github-copilot.en.md +25 -10
- package/docs/using-with-github-copilot.md +21 -8
- package/lib/doc-shapes.json +997 -0
- package/lib/doctor-checks.js +2654 -0
- package/lib/init.js +3583 -107
- package/lib/render-diagrams.js +1474 -0
- package/lib/render.js +865 -49
- package/package.json +2 -2
- package/templates/brownfield/references/drift-verification.md +4 -0
- package/templates/brownfield/references/finish-feature-flow.md +635 -88
- package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
- package/templates/brownfield/references/finish-feature-minimal-host.md +406 -0
- package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/brownfield/references/git-integration.md +160 -15
- package/templates/brownfield/references/init-project-flow.md +26 -4
- package/templates/brownfield/references/modify-existing-flow.md +412 -87
- package/templates/brownfield/references/modify-existing-follow-up.md +121 -0
- package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +82 -0
- package/templates/brownfield/references/new-feature-flow.md +61 -6
- package/templates/brownfield/references/new-phase-flow.md +57 -7
- package/templates/brownfield/references/pr-review-checklist.md +303 -10
- package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +158 -34
- package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
- package/templates/brownfield/scaffolding/Git-principles-gitflow.md +75 -6
- package/templates/brownfield/scaffolding/Git-principles-trunk.md +82 -8
- package/templates/brownfield/scaffolding/_conventions.md +50 -28
- package/templates/brownfield/scaffolding/_overview.md +1 -0
- package/templates/brownfield/templates/_index.md +151 -7
- package/templates/brownfield/templates/analysis.md +79 -0
- package/templates/brownfield/templates/behavior.md +1 -0
- package/templates/brownfield/templates/context-definition.md +1 -0
- package/templates/brownfield/templates/context-map.md +2 -1
- package/templates/brownfield/templates/glossary.md +1 -0
- package/templates/brownfield/templates/lightweight-spec.md +154 -11
- package/templates/brownfield/templates/models.md +1 -0
- package/templates/brownfield/templates/phase-spec.md +9 -1
- package/templates/brownfield/templates/rules.md +1 -0
- package/templates/brownfield/templates/tech-debt.md +1 -0
- package/templates/common/references/ddd-modeling-guide.md +33 -16
- package/templates/{greenfield → common}/references/dflow-feedback-flow.md +2 -1
- package/templates/common/references/flow-rationale-registry.md +130 -0
- package/templates/common/skill/SKILL.md +13 -11
- package/templates/greenfield/references/drift-verification.md +4 -0
- package/templates/greenfield/references/finish-feature-flow.md +625 -89
- package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
- package/templates/greenfield/references/finish-feature-minimal-host.md +363 -0
- package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/greenfield/references/git-integration.md +148 -15
- package/templates/greenfield/references/init-project-flow.md +28 -8
- package/templates/greenfield/references/modify-existing-flow.md +378 -85
- package/templates/greenfield/references/modify-existing-follow-up.md +103 -0
- package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +82 -0
- package/templates/greenfield/references/new-feature-flow.md +67 -4
- package/templates/greenfield/references/new-phase-flow.md +56 -7
- package/templates/greenfield/references/pr-review-checklist.md +287 -8
- package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +153 -32
- package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
- package/templates/greenfield/scaffolding/Git-principles-gitflow.md +74 -6
- package/templates/greenfield/scaffolding/Git-principles-trunk.md +88 -12
- package/templates/greenfield/scaffolding/_conventions.md +50 -28
- package/templates/greenfield/scaffolding/_overview.md +6 -2
- package/templates/greenfield/templates/_index.md +137 -7
- package/templates/greenfield/templates/aggregate-design.md +1 -0
- package/templates/greenfield/templates/analysis.md +79 -0
- package/templates/greenfield/templates/behavior.md +1 -0
- package/templates/greenfield/templates/context-definition.md +1 -0
- package/templates/greenfield/templates/context-map.md +2 -1
- package/templates/greenfield/templates/events.md +4 -1
- package/templates/greenfield/templates/glossary.md +1 -0
- package/templates/greenfield/templates/lightweight-spec.md +154 -11
- package/templates/greenfield/templates/models.md +1 -0
- package/templates/greenfield/templates/phase-spec.md +9 -1
- package/templates/greenfield/templates/rules.md +1 -0
- package/templates/greenfield/templates/tech-debt.md +1 -0
- package/templates/brownfield/references/dflow-feedback-flow.md +0 -251
|
@@ -11,7 +11,7 @@ Crossing any step gate above also updates the host feature's `_index.md` Resume
|
|
|
11
11
|
|
|
12
12
|
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.
|
|
13
13
|
|
|
14
|
-
**Ceremony
|
|
14
|
+
**Ceremony when triggered by `/dflow:bug-fix`**: the command does **not** set a tier — run the same ordered cascade as any other modification (Part A below). Most functional defects land **T2**, so the Lightweight Spec Template (`templates/lightweight-spec.md`) is the usual outcome, and Step 4 (extraction) may default to "defer and record in tech-debt.md" unless the bug itself is in extractable logic; T2 still generates a concise `Implementation Tasks` checklist (see Step 4). That is the usual landing, not a fixed set: the cascade also puts defects below T2 and above it, through any of its steps — not only via a Domain structural redesign. Let the cascade decide.
|
|
15
15
|
|
|
16
16
|
## Mindset
|
|
17
17
|
|
|
@@ -31,40 +31,112 @@ through `/dflow:bug-fix`.
|
|
|
31
31
|
|
|
32
32
|
This step has two parallel concerns:
|
|
33
33
|
|
|
34
|
-
**Part A — Determine the Ceremony Tier (T1 / T2 / T3)**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
**
|
|
50
|
-
|
|
34
|
+
**Part A — Determine the Ceremony Tier (T1 / T2 / T3 / below workflow)**
|
|
35
|
+
|
|
36
|
+
The tier has **one source**: `AI-AGENT-GUIDE.md` § Ceremony Scaling — the
|
|
37
|
+
ordered cascade, steps 0–4, where **the first step that matches wins**. **Open
|
|
38
|
+
that section and classify from it before going further.** Do not classify from
|
|
39
|
+
memory, from this flow's step headings, or from a summary: the cases that
|
|
40
|
+
actually decide a tier — new work versus a modification, what stays below
|
|
41
|
+
workflow, how far a T3 may reach, inbound contracts, compound requests — are
|
|
42
|
+
settled there, and a second copy of those criteria here would be a second answer
|
|
43
|
+
to the same question.
|
|
44
|
+
|
|
45
|
+
Two of the cascade's outcomes leave this flow entirely: genuinely new work
|
|
46
|
+
(`/dflow:new-feature`) and a change Dflow does not track. Take those two exits as
|
|
47
|
+
the guide states them rather than continuing through the steps below.
|
|
48
|
+
|
|
49
|
+
**Tier-aware routing (don't run heavier ceremony than the tier needs):**
|
|
50
|
+
|
|
51
|
+
- **T3** → locate the host, then **skip the Domain / extraction work**: go to the
|
|
52
|
+
branch gate, implement, and record the inline `_index.md` row. Do **not** create
|
|
53
|
+
or update any spec file, and do **not** run the Step 2 Document-Current-Behavior
|
|
54
|
+
baseline capture, the Step 3 delivery-layer analysis, or the Step 4
|
|
55
|
+
Evaluate-Extraction-Opportunity step (a T3 produces no baseline / extraction /
|
|
56
|
+
tech-debt entries unless the request is itself about them).
|
|
57
|
+
- **T2** → a lightweight-spec at the depth the change needs; run the
|
|
58
|
+
behavior-capture / layer steps only where the change actually touches them.
|
|
59
|
+
- **Observation-only (tier-exempt, step 0)** → record the capture where it belongs
|
|
60
|
+
(BC-layer `behavior.md` and `analysis.md`, `domain/analysis.md` for a
|
|
61
|
+
cross-context flow, for role reach and for whatever else no one context owns,
|
|
62
|
+
a hotspot in the copy that holds the knowledge it is stuck on,
|
|
63
|
+
`tech-debt.md`, the host's Resume Pointer) and stop there; create either
|
|
64
|
+
`analysis.md` from `templates/analysis.md` the first time there is something to
|
|
65
|
+
record.
|
|
66
|
+
When the baseline capture needs its own host (no active feature to attach
|
|
67
|
+
it to), open a **baseline minimal host**: a related **completed** feature makes it
|
|
68
|
+
a follow-up (Step 1.6 minimal variant), otherwise it is standalone (Step 1.7) —
|
|
69
|
+
both are tier-exempt, cut `feature/{SPEC-ID}-{slug}`, and record a `Tier = baseline`
|
|
70
|
+
row rather than a change. Do not invent a spec for it, and do not read the
|
|
71
|
+
cascade's "below workflow" as permission to skip the record.
|
|
72
|
+
A capture about no bounded context at all — the role reach of functions that
|
|
73
|
+
belong to no context yet, say — is not a baseline capture and opens no host:
|
|
74
|
+
with no active feature to attach it to, record it and offer to commit that
|
|
75
|
+
record on its own.
|
|
76
|
+
- **T1** → escalate to `/dflow:new-phase` (extending an active feature) or
|
|
77
|
+
`/dflow:new-feature` (a truly new concern); full ceremony via that flow.
|
|
51
78
|
|
|
52
79
|
**Part B — Locate the Feature this Change Belongs To**
|
|
53
80
|
|
|
54
|
-
Walk through these in order
|
|
81
|
+
Walk through these in order to **classify** the change. Do **not** jump to
|
|
82
|
+
Step 1.5 / 1.7 mid-list: the in-flight overlap scan (item 4) and the hotfix
|
|
83
|
+
check below both run first, and the actual routing to Step 1.5 / 1.6 / 1.7 /
|
|
84
|
+
1.8 / Step 2 happens at this step's closing transition.
|
|
55
85
|
|
|
56
86
|
1. **Active features**: scan `dflow/specs/features/active/*/_index.md`. Does
|
|
57
87
|
the change belong inside an existing active feature directory? If
|
|
58
88
|
yes, use that as the host (T1 → `/dflow:new-phase`; T2 → place
|
|
59
89
|
lightweight-spec inside; T3 → inline row in that `_index.md`).
|
|
90
|
+
**Exception — a minimal (zero-phase) host that has already taken its
|
|
91
|
+
implementation (or `spec-baseline`) checkpoint is not an eligible host.** A
|
|
92
|
+
minimal host is fixed at two commits and **every** Lightweight Changes row
|
|
93
|
+
must belong to the first one (Step 1.7), so once that checkpoint has landed
|
|
94
|
+
it can accept nothing further, however well it fits. It does **not** become
|
|
95
|
+
this change's host, and for the rest of this walk it does not count as one —
|
|
96
|
+
keep scanning, and let the routing at this step's closing transition proceed
|
|
97
|
+
as if it were not there. (Item 4 still surfaces it as an overlap; that is
|
|
98
|
+
information for the developer, not a host.) **Before** that checkpoint lands
|
|
99
|
+
the host is still open, and a compound request legitimately records more than
|
|
100
|
+
one **T2 / T3** artifact under it ("minimal means zero-phase, not
|
|
101
|
+
one-artifact", Step 1.7) — but **never a phase**: a minimal host is
|
|
102
|
+
*defined* by carrying no `phase-spec-*`, so it is not an eligible host for a
|
|
103
|
+
**T1** at any point, before or after that checkpoint. Keep scanning, exactly
|
|
104
|
+
as above.
|
|
105
|
+
**Exception — an already-merged T2 / T3 emergency fix** (the callout
|
|
106
|
+
below): it is already on the mainline, so an in-flight host cannot hold
|
|
107
|
+
it. It takes **Step 1.8** and gets a host of its own there, however well
|
|
108
|
+
a related active feature seems to fit — Step 1.8 says why. A **T1**
|
|
109
|
+
post-hoc is unaffected and uses this route normally.
|
|
60
110
|
2. **Completed features**: scan `dflow/specs/features/completed/*/_index.md`
|
|
61
111
|
Goals & Scope sections. If the change description is semantically
|
|
62
|
-
related to a completed feature, this
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
112
|
+
related to a completed feature, this is the **completed-feature-reopen**
|
|
113
|
+
case (Step 1.5, routed to at the closing transition) — with **two
|
|
114
|
+
exceptions that never reach the Step 1.5 A/B/C prompt**: a **T2 / T3**
|
|
115
|
+
already-merged emergency fix documented after the fact takes **Step 1.8**
|
|
116
|
+
(the callout below), and an **observation-only baseline capture** takes
|
|
117
|
+
**Step 1.6** directly (Part A already routed it). This scan still runs for
|
|
118
|
+
both — each needs to know whether a related completed feature exists in
|
|
119
|
+
order to pick its own host (follow-up when one relates, standalone
|
|
120
|
+
otherwise). (A **T1** post-hoc is not a Step 1.8 case at all and does reach
|
|
121
|
+
Step 1.5 normally.)
|
|
122
|
+
3. **Standalone**: if no related feature exists (active or completed) that can
|
|
123
|
+
host this change — a host item 1 ruled **ineligible** does not count as one —
|
|
124
|
+
this is a new concern. For T1, use `/dflow:new-feature`. A standalone
|
|
125
|
+
T2 / T3 needs a **minimal host feature directory** to hold the change —
|
|
126
|
+
its open → record → close lifecycle is the **standalone** case (Step 1.7,
|
|
127
|
+
routed to at the closing transition). Do not improvise a host and do not
|
|
128
|
+
leave an empty one behind. (If a related active feature genuinely fits
|
|
129
|
+
after all, use it as the host instead.)
|
|
130
|
+
**Exception — an already-merged T2 / T3 emergency fix** (the callout
|
|
131
|
+
below): finding nothing related does **not** make it an ordinary standalone.
|
|
132
|
+
It still routes through **Step 1.8**, which picks standalone itself and
|
|
133
|
+
supplies what this item cannot — the `reconciled (...)` checkpoint, the
|
|
134
|
+
per-tier hotfix trace, and reconcile-instead-of-re-implement. Coming to
|
|
135
|
+
Step 1.7 straight from here drops all of that. A **T1** post-hoc is
|
|
136
|
+
unaffected and uses this route normally. An observation-only **baseline
|
|
137
|
+
capture** with nothing related also reaches Step 1.7, but by **Part A's**
|
|
138
|
+
observation-only routing, not by this item — it is tier-exempt, so this
|
|
139
|
+
item's "standalone T2 / T3" wording does not describe it.
|
|
68
140
|
4. **In-flight overlap scan (cross-branch)**: this branch's `active/` is not
|
|
69
141
|
everything in flight. Run the in-flight scan (classification and dedup
|
|
70
142
|
rules in `AI-AGENT-GUIDE.md` § Status / Control Commands) — `git fetch`
|
|
@@ -75,19 +147,51 @@ Walk through these in order:
|
|
|
75
147
|
awaiting integration, or unknown — or an unfinished feature — semantically
|
|
76
148
|
overlaps this change, surface it and wait for the developer to decide
|
|
77
149
|
before creating anything new (stale branches are non-blocking).
|
|
150
|
+
**Exception — an already-merged T2 / T3 emergency fix** (the callout
|
|
151
|
+
below): run the scan, but a surfaced overlap is **information, not a
|
|
152
|
+
blocker**. The fix is already on the mainline, so no unmerged feature branch
|
|
153
|
+
can host it (Step 1.8 says why) — there is no routing choice left to wait
|
|
154
|
+
for. Report the overlap as notice that a merge reconciliation is coming
|
|
155
|
+
(`finish-feature-flow.md` Step 5), then let Step 1.8 proceed: do not offer
|
|
156
|
+
the in-flight feature as a host and do not hold host creation on it.
|
|
157
|
+
Step 1.7's overlap scan states the same rule at the point of use. A **T1**
|
|
158
|
+
post-hoc is unaffected and waits normally, and so does a **baseline
|
|
159
|
+
capture** — an overlapping in-flight feature may well be the right place to
|
|
160
|
+
attach the capture, which is precisely the decision this item asks for.
|
|
78
161
|
|
|
79
162
|
> **Why scan completed too?** Completed features are frozen history
|
|
80
163
|
> and **cannot accept** any T2 / T3 directly
|
|
81
164
|
> (would break the "completed = frozen" semantic). Reopen routes through
|
|
82
|
-
> a new follow-up feature instead — see Step 1.5.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
165
|
+
> a new follow-up feature instead — see Step 1.5, or Step 1.8 (**T2 / T3**
|
|
166
|
+
> post-hoc hotfix) / Step 1.6 (baseline capture), which reach the same
|
|
167
|
+
> follow-up host without the A/B/C prompt.
|
|
168
|
+
|
|
169
|
+
> **Already-merged emergency fix?** If this change was hotfixed to production
|
|
170
|
+
> **before** any Dflow ceremony ran and you are now documenting it after the
|
|
171
|
+
> fact, **the tier Part A decided routes it**:
|
|
172
|
+
> - **T2 / T3 post-hoc** → **Step 1.8** (post-hoc mode) rather than opening a
|
|
173
|
+
> fresh host here — it picks the host linkage and reconciles instead of
|
|
174
|
+
> re-implementing.
|
|
175
|
+
> - **T1 post-hoc** → **not** a minimal-host case. It keeps the normal
|
|
176
|
+
> phase-bearing route (`/dflow:new-phase` or `/dflow:new-feature`, as Part A
|
|
177
|
+
> says), documenting the merged work there. Step 1.8 does not admit it, and
|
|
178
|
+
> a T1 must never be given a zero-phase host.
|
|
179
|
+
>
|
|
180
|
+
> Every pointer to Step 1.8 below carries this same T2 / T3 restriction.
|
|
181
|
+
|
|
182
|
+
**→ Transition (step-internal)**: Step 1 complete. Announce "Step 1 complete (classification {T1/T2/T3 / baseline (tier-exempt)} decided, host feature {SPEC-ID-slug / new / follow-up} identified). Entering Step 1.5 / 1.6 / 1.7 / 1.8 / Step 2 as appropriate." and continue. An observation-only **baseline** capture carries **no tier** — announce it as `baseline (tier-exempt)`, never as T1 / T2 / T3.
|
|
183
|
+
|
|
184
|
+
## Step 1.5: Completed-Feature Reopen Detection (only if Step 1 found a related completed feature — and this is a normal modification, not a T2 / T3 post-hoc hotfix or a baseline capture)
|
|
87
185
|
|
|
88
186
|
If Step 1 Part B identified a semantically related completed feature, AI
|
|
89
187
|
must explicitly disambiguate the user's intent **before** writing any
|
|
90
|
-
files
|
|
188
|
+
files. **Skip this step entirely for a T2 / T3 post-hoc hotfix (Step 1.8) or an
|
|
189
|
+
observation-only baseline capture (Part A routes it straight to Step 1.6)** —
|
|
190
|
+
each picks its own host without this prompt (follow-up when a completed
|
|
191
|
+
feature relates, standalone otherwise), and asking it anyway lets Option B
|
|
192
|
+
file a related hotfix or capture as an independent standalone, losing the
|
|
193
|
+
`follow-up-of` lineage and both reverse-link transitions. (A **T1** post-hoc
|
|
194
|
+
is a normal reopen and belongs in this prompt.)
|
|
91
195
|
|
|
92
196
|
```
|
|
93
197
|
"I notice this change overlaps with completed feature
|
|
@@ -98,10 +202,14 @@ Is this a follow-up to that feature, or an independent new concern?
|
|
|
98
202
|
|
|
99
203
|
Option A — follow-up of `{SPEC-ID}-{slug}`
|
|
100
204
|
→ Build a new feature with a fresh SPEC-ID and `follow-up-of:
|
|
101
|
-
{SPEC-ID}` link back to the original.
|
|
102
|
-
from the BC's rules.md
|
|
205
|
+
{SPEC-ID}` link back to the original. A BC-bearing follow-up inherits
|
|
206
|
+
its BR Snapshot baseline from the BC's rules.md; a no-BC follow-up
|
|
207
|
+
inherits nothing (see Step 1.6).
|
|
103
208
|
Option B — independent new requirement
|
|
104
|
-
→
|
|
209
|
+
→ Route by the tier Part A already decided: T1 → run /dflow:new-feature
|
|
210
|
+
normally; T2 / T3 → this is an independent standalone change, go to
|
|
211
|
+
Step 1.7 (do NOT send a T2/T3 to new-feature — its intake would bounce
|
|
212
|
+
it right back here). No link to the completed feature either way.
|
|
105
213
|
Option C — actually I think it's just a tiny lightweight tweak, no
|
|
106
214
|
new feature needed
|
|
107
215
|
→ Refused. Completed features are frozen — even T3 inline rows must
|
|
@@ -113,54 +221,229 @@ Option C — actually I think it's just a tiny lightweight tweak, no
|
|
|
113
221
|
**Wait for the developer's explicit choice (A / B / C).**
|
|
114
222
|
|
|
115
223
|
If A (follow-up): proceed to **Step 1.6: Create Follow-up Feature**.
|
|
116
|
-
If B (independent):
|
|
117
|
-
|
|
224
|
+
If B (independent): route by tier — **T1** → `/dflow:new-feature` (this flow
|
|
225
|
+
ends); **T2 / T3** → Step 1.7 (standalone minimal host).
|
|
118
226
|
If C: gently re-explain (per decision 17) that completed features
|
|
119
227
|
cannot accept direct T2 / T3 writes; offer Option A (follow-up with
|
|
120
228
|
just a T3 inline row) as the lightweight equivalent.
|
|
121
229
|
|
|
122
|
-
## Step 1.6: Create Follow-up Feature (only
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
feature
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
230
|
+
## Step 1.6: Create Follow-up Feature (Step 1.5 Option A, a completed-only baseline capture, or the follow-up linkage chosen at Step 1.8)
|
|
231
|
+
|
|
232
|
+
**Open `references/modify-existing-follow-up.md` and follow it there.** This
|
|
233
|
+
step's rules live in that file and are not repeated here.
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
## Step 1.7: Open a Standalone Minimal Host (no active feature hosts this change, and no completed feature is being taken as its follow-up)
|
|
237
|
+
|
|
238
|
+
A standalone T2 / T3 — one with no active host and no completed feature
|
|
239
|
+
taken as its follow-up — or a **baseline capture** with no related feature
|
|
240
|
+
(brownfield) — has no feature that will host it, yet the host-ledger
|
|
241
|
+
invariants (SPEC-ID, branch, Checkpoint Log, and the `_index.md` as the
|
|
242
|
+
authoritative record) still apply. Open a **minimal host**: a feature
|
|
243
|
+
directory that carries the change's lightweight artifacts — or one baseline
|
|
244
|
+
capture — and **never a phase-spec**. The lifecycle is
|
|
245
|
+
**open → record → close, two commits** (implementation — or baseline capture
|
|
246
|
+
— then closeout).
|
|
247
|
+
|
|
248
|
+
**"Minimal" means zero-phase, not one-artifact.** A compound standalone
|
|
249
|
+
request is split into its atomic changes, each run through the cascade, with
|
|
250
|
+
the **highest tier governing the host** and **each lower-tier part still
|
|
251
|
+
recording its own artifact under that same host** (`AI-AGENT-GUIDE.md`
|
|
252
|
+
§ Ceremony Scaling, Unit of classification). So one minimal host may carry a
|
|
253
|
+
T2 lightweight-spec **and** one or more T3 inline rows — that is the correct
|
|
254
|
+
shape, not a reason to open a second standalone host, and never a reason to
|
|
255
|
+
drop the T3 evidence. A **baseline capture** is the exception: it is
|
|
256
|
+
observation-only and carries its own capture alone.
|
|
257
|
+
|
|
258
|
+
**Open — do this here, before writing the change:**
|
|
259
|
+
|
|
260
|
+
1. **Confirm it is standalone.** The test is a **condition**, not a list of
|
|
261
|
+
routes: *no active feature hosts this change, and no completed feature is
|
|
262
|
+
being taken as its follow-up.* Whatever brought you here — Part B item 3
|
|
263
|
+
(nothing related found), Step 1.5 **Option B** (a related completed feature
|
|
264
|
+
the developer settled as an independent concern), Step 1.8's standalone
|
|
265
|
+
linkage, Part A's observation-only routing for a baseline with no related
|
|
266
|
+
feature, or a route added later — it belongs here exactly when that
|
|
267
|
+
condition holds. If an **active** feature genuinely hosts this change, stop
|
|
268
|
+
and record it there instead — do not open a redundant host. If a
|
|
269
|
+
**completed** feature is the right home, that is a follow-up (Step 1.6),
|
|
270
|
+
not a standalone. Do **not** re-run Step 1.5 to decide: an Option B arrival
|
|
271
|
+
already answered there, and Part A (baseline) / Step 1.8 (post-hoc hotfix)
|
|
272
|
+
each made the choice themselves.
|
|
273
|
+
|
|
274
|
+
**Overlap scan.** For every arrival except a T2 / T3 post-hoc hotfix, an
|
|
275
|
+
overlap the in-flight scan (Part B item 4) surfaced must be settled before
|
|
276
|
+
you create anything. For a **post-hoc hotfix** the condition above holds even when a
|
|
277
|
+
related feature is in flight — the fix is already merged on the mainline, so
|
|
278
|
+
no unmerged feature branch can host it (Step 1.8 says why) — and a surfaced
|
|
279
|
+
overlap is **information, not a blocker**: it tells the developer a merge
|
|
280
|
+
reconciliation is coming (`finish-feature-flow.md` Step 5).
|
|
281
|
+
2. **Assign the identifiers** per `_conventions.md` § SPEC-ID Format
|
|
282
|
+
(`SPEC-YYYYMMDD-NNN`). For a **functional bug**, also assign its
|
|
283
|
+
**BUG-NUMBER** here (issue-tracker number, else `max+1` over the existing
|
|
284
|
+
`BUG-*` across `dflow/specs/**`, active + completed). Collision-check
|
|
285
|
+
**before creating anything** in step 3: no `active/` or `completed/`
|
|
286
|
+
directory and no local or remote branch already carries this SPEC-ID (or
|
|
287
|
+
BUG-NUMBER) or the branch name you will cut (stale branches are non-blocking
|
|
288
|
+
but are never reused).
|
|
289
|
+
|
|
290
|
+
**What a collision means depends on who owns the number.** A SPEC-ID, and a
|
|
291
|
+
**locally allocated** `max+1` BUG-NUMBER, are this flow's to hand out — a
|
|
292
|
+
collision is an allocation clash and nothing more, so re-assign the day
|
|
293
|
+
counter (or take the next BUG-NUMBER) and re-check. A **tracker-owned**
|
|
294
|
+
BUG-NUMBER is not: the issue tracker owns that identity, and renaming
|
|
295
|
+
tracker issue 42 to `BUG-43` to dodge a collision silently severs the record
|
|
296
|
+
from the issue it is about. **Never renumber a tracker-owned BUG-NUMBER.**
|
|
297
|
+
A collision there is reporting something real — this work is already
|
|
298
|
+
recorded, or a stale branch is still carrying it — and it is settled that
|
|
299
|
+
way with the developer, as duplicate / existing work or branch-history
|
|
300
|
+
cleanup. All identifiers are settled here, before the host exists.
|
|
301
|
+
3. **Create the minimal `_index.md`** from `templates/_index.md` at
|
|
302
|
+
`dflow/specs/features/active/{SPEC-ID}-{slug}/_index.md`, carrying all
|
|
303
|
+
**seven required sections** that template names — the Metadata front
|
|
304
|
+
matter, Goals & Scope, Phase Specs, Current BR Snapshot, Lightweight
|
|
305
|
+
Changes, Checkpoint Log, Resume Pointer. (`Follow-up Tracking` is the
|
|
306
|
+
template's **optional** eighth section; a standalone host gets one only if
|
|
307
|
+
it later grows follow-ups of its own.) "Minimal" means the sections are
|
|
308
|
+
thin, not missing:
|
|
309
|
+
- Metadata `status: in-progress`; `branch:` = the branch you cut in
|
|
310
|
+
step 4. This field is **authoritative** — the branch gate and any
|
|
311
|
+
lightweight-spec frontmatter read their branch from it.
|
|
312
|
+
- Goals & Scope: one or two sentences. A standalone change need not touch
|
|
313
|
+
a bounded context; if it does not, say so plainly in Goals & Scope
|
|
314
|
+
rather than inventing one. (A baseline capture names the context it
|
|
315
|
+
captures — that is a real BC, not `none`.)
|
|
316
|
+
- Phase Specs: **leave the table empty** — a minimal host has no
|
|
317
|
+
phase-spec.
|
|
318
|
+
- Current BR Snapshot: fill it only if the change carries a BR delta; a
|
|
319
|
+
no-BR / T3 host leaves it empty (finish-feature Step 1 reads an
|
|
320
|
+
intentionally empty snapshot as a no-BR feature, not a validation
|
|
321
|
+
failure).
|
|
322
|
+
- Lightweight Changes, Checkpoint Log, Resume Pointer: start them; the
|
|
323
|
+
record and the two checkpoints land here as you go.
|
|
324
|
+
4. **Branch gate — by change class.** A **functional bug** cuts
|
|
325
|
+
`bugfix/BUG-{NUMBER}-{slug}`, using the BUG-NUMBER assigned and
|
|
326
|
+
collision-checked in step 2. **Otherwise** — a standalone non-bug **T2 / T3**, or a **baseline
|
|
327
|
+
capture** — cut `feature/{SPEC-ID}-{slug}`. The `_index.md` `branch:` field must equal the
|
|
328
|
+
branch cut here. (See `references/git-integration.md` § Commit Checkpoints,
|
|
329
|
+
Branch Gate & AI Commits.)
|
|
330
|
+
|
|
331
|
+
**Record + commit — rejoin the normal flow.** Follow this flow's tier-aware
|
|
332
|
+
routing (Part A): a **T2** writes its lightweight-spec (classic BR form or
|
|
333
|
+
the matching no-BR family variant — shapes are defined in
|
|
334
|
+
`templates/lightweight-spec.md`) and runs the Step 2–6 record **to the depth
|
|
335
|
+
Part A set** — that range names the route, not an instruction to run every item
|
|
336
|
+
in it. In particular a **no-BC** T2 — one whose host Goals & Scope says it
|
|
337
|
+
touches no bounded context — does not acquire one by walking Step 2: it does no
|
|
338
|
+
Domain-file work there (Step 2 carries the same guard at its own site), so
|
|
339
|
+
closeout's no-BC branch has nothing fictitious to skip past. A **T3** skips
|
|
340
|
+
the Domain / extraction work and records an inline row in `_index.md`
|
|
341
|
+
Lightweight Changes — **one row per atomic T3 change**, so a compound request
|
|
342
|
+
records each of them here (see "minimal means zero-phase, not one-artifact"
|
|
343
|
+
above). A **baseline capture** is observation-only: it records the capture in
|
|
344
|
+
its BC-layer documents and/or `domain/analysis.md` and one `Tier = baseline`
|
|
345
|
+
row in `_index.md`, and its first checkpoint is named `spec-baseline` with
|
|
346
|
+
Result `committed` (never `implementation` — there is no implementation
|
|
347
|
+
work). Otherwise the **implementation commit is checkpoint 1** — the Step 5 →
|
|
348
|
+
Step 6 commit checkpoint records it in the Checkpoint Log. (For a **post-hoc**
|
|
349
|
+
host, Step 5 is skipped and checkpoint 1 is the **documentation** commit
|
|
350
|
+
instead; see Step 1.8 and Step 5's guard.)
|
|
351
|
+
|
|
352
|
+
**Every artifact gets a Lightweight Changes row, and every row is written
|
|
353
|
+
*before* checkpoint 1.** A **T3**'s row *is* its whole record; a **T2**'s row is
|
|
354
|
+
the outbound link to its lightweight-spec; a **baseline** capture's is its
|
|
355
|
+
`Tier = baseline` row — all three are rows, and closeout requires one per
|
|
356
|
+
artifact. Write them now, carrying the tier, the description and the
|
|
357
|
+
implementation paths (for a baseline, the documents it captured into). The
|
|
358
|
+
**only** part that may appear afterwards is the `Commit` cell, which cannot
|
|
359
|
+
exist until its commit does: closeout's allow-list admits that cell and no other
|
|
360
|
+
change **to the row**, so a row added after checkpoint 1 **blocks**. (The
|
|
361
|
+
allow-list separately admits the Checkpoint Log rows, the Resume Pointer and the
|
|
362
|
+
Current BR Snapshot — the finalization edits this step makes next.)
|
|
363
|
+
|
|
364
|
+
**Name the implementation paths in the artifact.** Closeout's evidence checks
|
|
365
|
+
assert that a commit *touches the implementation paths this change describes* —
|
|
366
|
+
which is only mechanical if the artifact actually declares them. So a **T2**'s
|
|
367
|
+
lightweight-spec names the source paths it changes, and a **T3**'s row
|
|
368
|
+
Description names them alongside its one-line description and tag. Paths, not a
|
|
369
|
+
diff — enough to compare a commit against. A **baseline capture** declares the
|
|
370
|
+
documents it wrote instead; that is its counterpart. An artifact that
|
|
371
|
+
declares none leaves that check nothing to compare, and finish-feature treats a
|
|
372
|
+
missing declaration as a **block**, not a pass.
|
|
373
|
+
|
|
374
|
+
**Finalize + close.** Before `/dflow:finish-feature`, run the Step 6
|
|
375
|
+
completion checklist's minimal-host finalization. For **every** T2: set the
|
|
376
|
+
lightweight-spec `status: completed`, record its commit evidence, and advance
|
|
377
|
+
the Resume Pointer to the closeout-ready state. **Only when that T2 is
|
|
378
|
+
BC-bearing**, additionally refresh the host's Current BR Snapshot — a no-BC T2
|
|
379
|
+
has no snapshot to refresh, but still owes the commit evidence and the Resume
|
|
380
|
+
Pointer. A **T3** has no spec file — record its inline row's commit evidence
|
|
381
|
+
and advance the Resume Pointer. A **baseline capture** likewise has no spec
|
|
382
|
+
file — record its `Tier = baseline` row's commit evidence and advance the
|
|
383
|
+
Resume Pointer.
|
|
384
|
+
|
|
385
|
+
**Commit evidence goes to two surfaces, always — every row, every tier.** They
|
|
386
|
+
answer different questions, so filling one is never filling the other, and
|
|
387
|
+
finish-feature Step 1 reads both:
|
|
388
|
+
|
|
389
|
+
- **Checkpoint Log Result** — what happened at the *lifecycle checkpoint*.
|
|
390
|
+
- **Lightweight Changes row `Commit`** — the commit carrying *that row's own
|
|
391
|
+
artifact*. Every row needs one; a blank cell fails closeout — **and so does a
|
|
392
|
+
placeholder**. `{hash}`, `{pending}`, `(待 commit)`, anything
|
|
393
|
+
`git cat-file -t` cannot resolve to a commit: it counts as **unfilled**, not
|
|
394
|
+
as filled. Leave the cell empty until the hash exists.
|
|
395
|
+
|
|
396
|
+
The **mode** changes only *which hash* each surface carries:
|
|
397
|
+
|
|
398
|
+
- **Normal** (T2 or T3) — Checkpoint Log Result `committed ({hash})` and the
|
|
399
|
+
row's `Commit` cell both name **checkpoint 1**, the single commit that
|
|
400
|
+
carried the artifact and the implementation together. Two cells, one hash;
|
|
401
|
+
fill both.
|
|
402
|
+
- **Post-hoc hotfix** (Step 1.8; T2 or T3) — the Checkpoint Log Result stays
|
|
403
|
+
`reconciled ({merged-hotfix-hash})`, **never overwrite it**, while the row's
|
|
404
|
+
`Commit` cell carries the **documentation** commit's hash. This is the one
|
|
405
|
+
mode where the two values genuinely differ (Step 1.8 item 4).
|
|
406
|
+
- **Baseline capture** — the `spec-baseline` checkpoint's Result
|
|
407
|
+
`committed ({hash})` and the `Tier = baseline` row's `Commit` cell both name
|
|
408
|
+
that capture commit, the one that carried what it captured. Two cells,
|
|
409
|
+
one hash; fill both.
|
|
410
|
+
|
|
411
|
+
**A declined checkpoint still owes its hash.** If the developer answered **N**
|
|
412
|
+
at the checkpoint-1 offer and made that commit themselves, the Checkpoint Log
|
|
413
|
+
row was written `skipped` honestly — the AI did not commit — but it is now
|
|
414
|
+
**incomplete, not final**: complete it here to `committed ({hash})` with the
|
|
415
|
+
developer's actual hash. **That completion is for a normal checkpoint 1** (or a
|
|
416
|
+
`spec-baseline` one). On a **post-hoc** host the Result stays
|
|
417
|
+
`reconciled ({merged-hotfix-hash})` — a declined documentation commit is
|
|
418
|
+
completed by filling each Lightweight Changes row's `Commit` cell once the
|
|
419
|
+
developer's commit lands, never by overwriting the reconciliation hash, which
|
|
420
|
+
records a different commit entirely. A row left reading `skipped` blocks closeout, and
|
|
421
|
+
finish-feature cannot tell "declined then committed" from "never committed" on
|
|
422
|
+
your behalf. The **closeout** row is the deliberate exception — it carries no
|
|
423
|
+
hash at all, because a commit cannot contain its own. Its **Result is still
|
|
424
|
+
read** afterwards — finish-feature's post-commit gate rejects `failed` there. A
|
|
425
|
+
declined closeout stays `skipped` because that value records the declined offer
|
|
426
|
+
honestly, not because the row goes unread.
|
|
427
|
+
|
|
428
|
+
In every case leave the host `status: in-progress` until closeout — do not flip
|
|
429
|
+
the host to `completed` early and do not invent a spec file for a T3. Then
|
|
430
|
+
`/dflow:finish-feature` performs the zero-phase closeout, and its **closeout
|
|
431
|
+
commit is checkpoint 2** — it includes the `git mv` archival. The two
|
|
432
|
+
checkpoints each record their own Checkpoint Log
|
|
433
|
+
row (implementation or baseline capture, then closeout); they are asserted
|
|
434
|
+
separately, never merged into one.
|
|
435
|
+
|
|
436
|
+
## Step 1.8: Hotfix T2 / T3 Post-Hoc (documenting an already-merged emergency change that Part A classified T2 or T3)
|
|
437
|
+
|
|
438
|
+
**Open `references/modify-existing-post-hoc-hotfix.md` and follow it there.**
|
|
439
|
+
This step's rules live in that file and are not repeated here.
|
|
440
|
+
|
|
441
|
+
⚠ Do not record a post-hoc hotfix from this heading alone. That file carries the
|
|
442
|
+
host-linkage choice, the `reconciled ({merged-hotfix-hash})` checkpoint Result,
|
|
443
|
+
the identity citation an **uncited** hash blocks closeout for, and the per-tier
|
|
444
|
+
hotfix trace. Reconstructed from this heading, post-hoc mode collapses into
|
|
445
|
+
re-implementing a fix that is already on the mainline — which Step 5's guard
|
|
446
|
+
forbids and closeout inspects that checkpoint's changed paths for.
|
|
164
447
|
|
|
165
448
|
## Step 2: Document Current Behavior (if no spec exists)
|
|
166
449
|
|
|
@@ -176,7 +459,17 @@ Create a spec with status `in-progress` that includes:
|
|
|
176
459
|
- Current business rules (extracted from delivery/entrypoint code)
|
|
177
460
|
- The proposed change clearly marked — use the **Delta** format below
|
|
178
461
|
|
|
179
|
-
|
|
462
|
+
> **No-BC guard — never manufacture a bounded context to satisfy this step.**
|
|
463
|
+
> The creations below apply only when the change actually touches one. A
|
|
464
|
+
> **no-BC** change — a standalone appearance sweep, say, whose host Goals &
|
|
465
|
+
> Scope states it touches no bounded context — records **N/A** here and moves
|
|
466
|
+
> on. Inventing a `{context}` it does not have plants fictitious Domain files
|
|
467
|
+
> that finish-feature's no-BC closeout branch **skips past rather than
|
|
468
|
+
> removes**, so they survive into the archive as permanent fiction. Same rule
|
|
469
|
+
> as Step 6.3's tier-conditional note: state the verdict, do not manufacture
|
|
470
|
+
> the artifact an item names.
|
|
471
|
+
|
|
472
|
+
If baseline domain docs are missing **for a change that does touch a bounded context**, create them from templates before filling content:
|
|
180
473
|
- `dflow/specs/domain/glossary.md` → `templates/glossary.md`
|
|
181
474
|
- `dflow/specs/domain/{context}/models.md` → `templates/models.md`
|
|
182
475
|
- `dflow/specs/domain/{context}/rules.md` → `templates/rules.md`
|
|
@@ -230,7 +523,8 @@ When the feature being modified has no existing spec, take the opportunity to do
|
|
|
230
523
|
2. Extract all business rules found (if/else conditions, calculations, validations)
|
|
231
524
|
3. Identify domain concepts (potential Entities, Value Objects, Services)
|
|
232
525
|
4. Check for duplicated logic across pages
|
|
233
|
-
5.
|
|
526
|
+
5. Identify the system-level knowledge no single context document holds — an ordered flow that crosses contexts (always the domain-root copy), the lifecycle a status field moves through, a figure computed rather than stored, a mechanism no single rule explains, which roles reach the function (always the domain-root copy), and any spot in those this system keeps working around pending a domain decision (in the copy that holds the knowledge it is stuck on)
|
|
527
|
+
6. Record findings in the appropriate domain docs (`models.md`, `rules.md`, and `analysis.md` — the owning context's copy, or `dflow/specs/domain/analysis.md` when no one context owns what you found, created from `templates/analysis.md` the first time there is something to record) and `tech-debt.md`
|
|
234
528
|
|
|
235
529
|
This is an **opportunistic** strategy — "capture while we're already here." Do not force a full codebase scan; scope it to the modified feature and its immediate neighbors. Share what you find:
|
|
236
530
|
|
|
@@ -240,6 +534,7 @@ the related delivery/entrypoint code. I found:
|
|
|
240
534
|
- 3 business rules in {entrypoint file} (documented in rules.md)
|
|
241
535
|
- Duplicated validation logic shared with {other entrypoint} (recorded in tech-debt.md)
|
|
242
536
|
- A potential Money value object hiding in the calculation at line {N}
|
|
537
|
+
- The approval status moves through four states, two of them set by the batch job (recorded in analysis.md)
|
|
243
538
|
This gives us a better baseline before we make our change."
|
|
244
539
|
```
|
|
245
540
|
|
|
@@ -275,6 +570,17 @@ Record each finding in `dflow/specs/migration/tech-debt.md` with:
|
|
|
275
570
|
- [ ] {File}:{Line} — {Description} — Severity: {High|Medium|Low}
|
|
276
571
|
```
|
|
277
572
|
|
|
573
|
+
### System-Level Knowledge to Record
|
|
574
|
+
Look for what this change depends on and no single context document holds:
|
|
575
|
+
- **Cross-context flows** — ordered steps owned by more than one context (always the domain-root copy)
|
|
576
|
+
- **Lifecycles** — a status field and the transitions it moves through
|
|
577
|
+
- **Read models and derived figures** — a number computed rather than stored
|
|
578
|
+
- **Mechanisms** — behavior no single rule explains
|
|
579
|
+
- **Function / role index** — which roles reach this function, and what data each one sees (always the domain-root copy)
|
|
580
|
+
- **Hotspots** in any of the above — what this change worked around, pending a domain decision (in the copy that holds the knowledge it is stuck on)
|
|
581
|
+
|
|
582
|
+
Record each finding 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.
|
|
583
|
+
|
|
278
584
|
**→ Transition (step-internal)**: Step 3 complete. Announce "Step 3 complete (delivery/entrypoint layer analyzed, tech debt recorded). Entering Step 4: Evaluate Extraction Opportunity." and continue.
|
|
279
585
|
|
|
280
586
|
## Step 4: Evaluate Extraction Opportunity
|
|
@@ -358,12 +664,21 @@ If the lightweight checklist looks larger than a short-fix checklist, AI must pa
|
|
|
358
664
|
Announce to developer:
|
|
359
665
|
> "Extraction decision made — {extract now / defer and record}. Ready to start implementation? `/dflow:next` to proceed, or adjust the extraction scope first."
|
|
360
666
|
|
|
361
|
-
> Branch gate (policy-aware): a feature branch is mandatory for every tier (T1 / T2 / T3) under both Git policies (`_conventions.md` § Git Policy). If you are already on this work's `feature/{SPEC-ID}-{slug}` (or `bugfix/{BUG-ID}-{slug}`) branch — e.g. the change belongs to the active feature you are already in — the gate is satisfied and nothing new is created. Otherwise (on the base branch the project cuts from, or an unrelated branch) the AI offers to create/switch to the correct branch, switch to an existing matching one, or override and record it in the `_index.md` Checkpoint Log. Dflow does not need to know which branch is your base. See `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI Commits.
|
|
667
|
+
> Branch gate (policy-aware): a feature branch is mandatory for every tier (T1 / T2 / T3) under both Git policies (`_conventions.md` § Git Policy). If you are already on this work's `feature/{SPEC-ID}-{slug}` (or `bugfix/{BUG-ID}-{slug}`) branch — e.g. the change belongs to the active feature you are already in — the gate is satisfied and nothing new is created. Otherwise (on the base branch the project cuts from, or an unrelated branch) the AI offers to create/switch to the correct branch, switch to an existing matching one, or override and record it in the `_index.md` Checkpoint Log. Dflow does not need to know which branch is your base. **Minimal-host exception (Step 1.6 follow-up variant / Step 1.7 standalone / Step 1.8 post-hoc): the override is not available.** Those hosts assert branch equality against the `_index.md` `branch:` value they cut by change class, so working them on an unrelated branch would falsify the host's own authoritative field — switch to the host's branch instead. See `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI Commits.
|
|
362
668
|
|
|
363
669
|
Wait for confirmation before entering Step 5.
|
|
364
670
|
|
|
365
671
|
## Step 5: Implement the Change
|
|
366
672
|
|
|
673
|
+
> **Post-hoc hotfix (Step 1.8) — skip this step.** The implementation already
|
|
674
|
+
> landed on the mainline before any ceremony ran; that is the whole premise of
|
|
675
|
+
> post-hoc mode, and Step 1.8 item 2 forbids redoing it. There is nothing to
|
|
676
|
+
> implement here. Go straight to the Step 5 → Step 6 gate and commit
|
|
677
|
+
> **documentation only** — the T2 spec or T3 row plus this host's `_index.md`,
|
|
678
|
+
> and no source. Re-implementing the fix on this branch would satisfy the letter
|
|
679
|
+
> of the checkpoint while breaking §8's reconciliation contract, which is why
|
|
680
|
+
> closeout inspects that commit's changed paths.
|
|
681
|
+
|
|
367
682
|
If extracting to Domain layer:
|
|
368
683
|
|
|
369
684
|
```csharp
|
|
@@ -402,7 +717,7 @@ protected void Calculate()
|
|
|
402
717
|
Announce to developer:
|
|
403
718
|
> "Implementation appears complete. Ready to update artifacts (spec, rules.md, models.md, glossary, tech-debt)? `/dflow:next` to proceed."
|
|
404
719
|
|
|
405
|
-
> Commit checkpoint (per `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI Commits): offer to commit, then record the result in the `_index.md` Checkpoint Log. Tier sets the count — T2 commits the merged spec+implementation here (closeout is the second checkpoint); T3 is a single commit.
|
|
720
|
+
> Commit checkpoint (per `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI Commits): offer to commit, then record the result in the `_index.md` Checkpoint Log. Tier sets the count — T2 commits the merged spec+implementation here (closeout is the second checkpoint); T3 is a single implementation commit, and its `_index.md` rows ride along on the host's next commit (see `references/git-integration.md` § Commit checkpoints). **Minimal host exception (Step 1.7 standalone *and* the Step 1.6 follow-up variant)**: a minimal host has no later host commit for a T3 row to ride along on, so **the row rides checkpoint 1 itself** — write it into `_index.md` *before* this commit, alongside the implementation, because finish-feature Step 1 reads **checkpoint 1's committed `_index.md`** for it. Only what cannot exist until the commit does — the row's `Commit` cell and the Checkpoint Log Result — is backfilled later and rides the closeout commit. And a minimal host takes a second **closeout** checkpoint too: **every** minimal host records **two** checkpoints (implementation — or `spec-baseline` for a baseline — then closeout), for T3, T2, and baseline alike. **Post-hoc hotfix (Step 1.8) — the same two checkpoints, but the first carries no implementation**: the fix is already on the mainline, so checkpoint 1 is the **documentation** commit (spec / row + `_index.md`, no source), and its Checkpoint Log Result is `reconciled ({merged-hotfix-hash})` rather than `committed`. "Commits the merged spec+implementation" above describes a normal host and does **not** apply here.
|
|
406
721
|
|
|
407
722
|
Wait for confirmation before entering Step 6. This step gate is where the completion checklist is triggered — do not skip.
|
|
408
723
|
|
|
@@ -410,16 +725,19 @@ Wait for confirmation before entering Step 6. This step gate is where the comple
|
|
|
410
725
|
|
|
411
726
|
Triggered by the Step 5 → Step 6 Step Gate. AI runs the completion checklist in the order below; do **not** skip a section. `Implementation Tasks` checks apply to both `phase-spec.md` and `lightweight-spec.md` (T3 inline-only has no task section).
|
|
412
727
|
|
|
728
|
+
> **Tier-conditional (matches the Part A routing — the checklist must not undo it).** A **T3** produces no spec file and no Domain-document updates: for a T3, 6.1's spec and Domain items and all of 6.3 are **N/A** except the `_index.md` row — which is **already written** (Step 1.7 for a minimal host, at record time otherwise), so this checklist **re-verifies** it and never creates it — record them as N/A, and do not create a spec or a Domain file to make an item pass. A **baseline capture** is tier-exempt and likewise produces **no spec file**: 6.1's spec items and 6.3's spec item are **N/A** — do not create one to make an item pass. Its **Domain documents are not N/A**, but this checklist does not create them either: the capture wrote them before checkpoint 1, so here they are **re-verified**, exactly as a T3's row is. A **no-BR family T2** has a spec but no BR delta: its **BR-derived** items are N/A (6.1 says the same). "No BR delta" is **not** "no Domain delta" — decide each Domain document from the actual change, not from the BR line. A family (b) contract change that touches a documented behavior still updates `behavior.md`; a family (e) defect in an extracted model still updates `models.md` if the shape moved. "Do not skip a section" means work through every section and state each verdict — including N/A — not manufacture the artifact an item names.
|
|
729
|
+
|
|
413
730
|
### 6.1 Verification — AI runs independently
|
|
414
731
|
|
|
415
732
|
Items marked *(post-6.3)* are re-verified after the documentation merge in 6.3 lands:
|
|
416
733
|
|
|
417
734
|
- [ ] Every ADDED / MODIFIED / REMOVED / RENAMED entry in the Delta section is covered by implementation or tests
|
|
735
|
+
- [ ] **No-BR family evidence** — when the spec's Behavior Delta is a `BR:` / `BR Delta:` none line instead of delta entries, verify *that family's* evidence is present and substantive: (a) `Output Footprint`; (b) `Contract Delta` + `**Downstream consumers**`; (c) `Operational Rationale` + `**Trace**`; (d) `Performance Delta` + `**SLA / resource context**`; (e) `Governing BR-IDs` + root cause + a regression check; (f) `Change Rationale` with `**Before**` / `**After**` + `**Regression**`. For such a spec the **BR-derived** items in this checklist are **N/A** — say so explicitly rather than passing them on an empty delta set, and never add a BR or a `behavior.md` anchor just to make an item pass. Domain documents are **not** automatically N/A: judge each from the actual change (a family (b) contract change that touches a documented behavior still updates `behavior.md`). When a change matches more than one family (an operational refactor that also shifts SLA), **every** matching family's evidence must be present — one BR line, all matching evidence sections. A spec written in the classic BR-delta form, or a bug spec written with the older single `BR:` line, is accepted as-is
|
|
418
736
|
- [ ] Domain layer has **no** delivery-framework references (grep `src/Domain/`)
|
|
419
737
|
- [ ] Extracted logic (if Step 4 decided "extract now") lives under `src/Domain/` as framework-pure code
|
|
420
738
|
- [ ] `Implementation Tasks` section (`phase-spec.md` or `lightweight-spec.md`): all tasks checked, or unchecked items explicitly labelled as follow-up
|
|
421
739
|
- [ ] *(post-6.3)* `dflow/specs/domain/{context}/behavior.md` has a section anchor for every `BR-*` in ADDED / MODIFIED entries; REMOVED entries' anchors have been deleted (mechanical input for `/dflow:verify`)
|
|
422
|
-
- [ ] *(post-6.3)* every ADDED / MODIFIED / RENAMED BR's `Last updated` in `dflow/specs/domain/{context}/rules.md` is
|
|
740
|
+
- [ ] *(post-6.3)* every ADDED / MODIFIED / RENAMED BR's `Last updated` in `dflow/specs/domain/{context}/rules.md` is **not earlier than** this spec's `created` date (mechanical drift guard). ⚠ **Not earlier**, not *later*: `Last updated` is set to **today**, so a spec created and swept on the same day — the modal case for this tier — gives `Last updated == created`. Requiring *later* blocks it with no legitimate escape (post-dating the row fabricates a record). Same operator as `new-feature-flow.md` § 8.1; the two must not diverge.
|
|
423
741
|
|
|
424
742
|
If any item fails, report the gap and pause — don't proceed to 6.2.
|
|
425
743
|
|
|
@@ -435,10 +753,15 @@ Ask these one-by-one.
|
|
|
435
753
|
|
|
436
754
|
### 6.3 Documentation updates
|
|
437
755
|
|
|
438
|
-
-
|
|
756
|
+
> **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).
|
|
757
|
+
|
|
758
|
+
- [ ] Update or create the feature / bug spec; set `status: completed` — **T3 and baseline: N/A** (no spec file exists; the `_index.md` inline row — a T3 row, or a `Tier = baseline` row — is the record, and the host's own status is not touched)
|
|
759
|
+
- [ ] The items below are the Domain sweep — **N/A for a T3**. For a **no-BC change** (one whose host Goals & Scope says it touches no bounded context) the **BC-scoped** items are N/A — everything under `dflow/specs/domain/{context}/`: there is no `{context}` to sweep, and inventing one plants the fiction Step 2's no-BC guard refuses. The **global** documents are *not* covered by that: `glossary.md`, `domain/analysis.md` and `migration/tech-debt.md` belong to no bounded context, and a no-BC operational T2 can genuinely rename a term, change which roles reach a function, or discover migration debt — judge those three from the actual change, as always. For a no-BR family T2 only the *BR-derived* items are N/A; run each remaining item where this change actually touches that document
|
|
439
760
|
- [ ] `dflow/specs/domain/{context}/rules.md` — business rules updated
|
|
440
761
|
- [ ] `dflow/specs/domain/{context}/models.md` — domain model updated
|
|
762
|
+
- [ ] `dflow/specs/domain/{context}/analysis.md` — lifecycles, derived figures or mechanisms no single rule explains this change found or altered, in the owning context's copy, which may not be this host's; any spot this change worked around pending a domain decision, in those or in a rule or unrecorded knowledge that belongs there; and any open row there this change settled (created from `templates/analysis.md` the first time there is something to record; N/A when there is none)
|
|
441
763
|
- [ ] `dflow/specs/domain/glossary.md` — new / renamed terms (mirror any RENAMED delta entries here)
|
|
764
|
+
- [ ] `dflow/specs/domain/analysis.md` — ordered cross-context flows, role reach, or anything else no one context owns, that this change found or altered; any spot this change worked around pending a domain decision, in those or in unrecorded knowledge that belongs here; and any open row there this change settled (created from `templates/analysis.md` the first time there is something to record; N/A when there is none)
|
|
442
765
|
- [ ] `dflow/specs/domain/{context}/behavior.md` — update scenarios to reflect Delta result (merge final state, not Delta markup). Sub-steps:
|
|
443
766
|
- Promote any Activity 3 (Spec Writing) draft sections (from B3 mid-sync) to formal sections
|
|
444
767
|
- Update the corresponding `rules.md` anchor's `last-updated` date (B4)
|
|
@@ -469,9 +792,11 @@ file move at this point. The whole feature directory moves to
|
|
|
469
792
|
If this modification was a **T3 inline-only** change, no spec file
|
|
470
793
|
exists — archival is just leaving the row in `_index.md` Lightweight Changes.
|
|
471
794
|
|
|
472
|
-
If the modification
|
|
473
|
-
via Step 1.6
|
|
474
|
-
|
|
795
|
+
If the modification opened a **standalone minimal host** (Step 1.7) or a
|
|
796
|
+
**follow-up feature** (created via Step 1.6, including its minimal
|
|
797
|
+
variant), the same rule applies: this flow does not archive the host
|
|
798
|
+
directory — the closeout `git mv` happens at `/dflow:finish-feature` time
|
|
799
|
+
(checkpoint 2 of the two-checkpoint minimal-host lifecycle).
|
|
475
800
|
|
|
476
801
|
Only announce "change complete" after the appropriate archival step
|
|
477
802
|
above (or the Step 6.3 docs sweep) is done.
|