dflow-sdd-ddd 0.15.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.
- package/CHANGELOG.md +156 -0
- package/CONTRIBUTING.md +1 -0
- package/README.en.md +7 -4
- package/README.md +7 -4
- package/bin/dflow.js +75 -0
- package/docs/closeout-check.en.md +204 -0
- package/docs/closeout-check.md +204 -0
- package/docs/commands.en.md +4 -2
- package/docs/commands.md +4 -2
- package/docs/release-versioning-policy.md +1 -0
- package/lib/closeout-check.js +690 -0
- package/lib/doc-shapes.json +198 -0
- package/lib/init.js +17 -2
- package/package.json +2 -2
- package/templates/brownfield/references/finish-feature-flow.md +29 -26
- package/templates/brownfield/references/finish-feature-minimal-host.md +38 -17
- package/templates/brownfield/references/finish-feature-record-correction.md +45 -0
- package/templates/brownfield/references/git-integration.md +62 -28
- package/templates/brownfield/references/modify-existing-flow.md +55 -29
- package/templates/brownfield/references/modify-existing-follow-up.md +2 -1
- package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +121 -3
- package/templates/brownfield/references/new-feature-flow.md +49 -31
- package/templates/brownfield/references/new-phase-flow.md +2 -2
- package/templates/brownfield/references/pr-review-checklist.md +29 -4
- package/templates/brownfield/scaffolding/Git-principles-gitflow.md +13 -5
- package/templates/brownfield/scaffolding/Git-principles-trunk.md +8 -4
- package/templates/brownfield/templates/_index.md +17 -13
- package/templates/common/references/flow-rationale-registry.md +20 -4
- package/templates/greenfield/references/finish-feature-flow.md +29 -26
- package/templates/greenfield/references/finish-feature-minimal-host.md +36 -16
- package/templates/greenfield/references/finish-feature-record-correction.md +45 -0
- package/templates/greenfield/references/git-integration.md +63 -29
- package/templates/greenfield/references/modify-existing-flow.md +42 -27
- package/templates/greenfield/references/modify-existing-follow-up.md +2 -1
- package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +121 -3
- package/templates/greenfield/references/new-feature-flow.md +49 -31
- package/templates/greenfield/references/new-phase-flow.md +2 -2
- package/templates/greenfield/references/pr-review-checklist.md +28 -4
- package/templates/greenfield/scaffolding/Git-principles-gitflow.md +13 -5
- package/templates/greenfield/scaffolding/Git-principles-trunk.md +8 -4
- package/templates/greenfield/templates/_index.md +18 -13
|
@@ -176,7 +176,8 @@ project's decision (GitFlow → `develop`, Trunk / GitHub Flow → `main`).
|
|
|
176
176
|
### Commit checkpoints
|
|
177
177
|
|
|
178
178
|
At lifecycle milestones the AI offers a commit checkpoint, folded into the
|
|
179
|
-
|
|
179
|
+
prompt the flow already shows there — a Step Gate, or the flow's closing
|
|
180
|
+
announcement (it does not add a separate question):
|
|
180
181
|
|
|
181
182
|
```
|
|
182
183
|
✓ {milestone} complete
|
|
@@ -187,26 +188,37 @@ existing Step Gate prompt (it does not add a separate question):
|
|
|
187
188
|
|
|
188
189
|
Tier sets how many checkpoints a change has: T1 three (spec / implementation /
|
|
189
190
|
closeout), T2 two (spec+implementation merged / closeout), T3 a single commit.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
**What a checkpoint carries follows from where its flow offers it.**
|
|
192
|
+
`references/modify-existing-flow.md` offers its checkpoint at the end of its
|
|
193
|
+
artifact step (Step 6), so a T2's merged commit — and a T3's single commit —
|
|
194
|
+
carries the change together with the documentation that step writes.
|
|
195
|
+
`/dflow:new-feature` and `/dflow:new-phase` offer the implementation checkpoint
|
|
196
|
+
at the gate into their completion step, so what that step writes rides the
|
|
197
|
+
host's next commit, whichever that is — for example the next phase's first
|
|
198
|
+
checkpoint, a hosted lightweight change's commit, or closeout.
|
|
199
|
+
"T3 = a single commit" means a single **implementation** commit. On a hosted T3
|
|
200
|
+
the entries that carry its hash ride the host's **next** commit (more work, or
|
|
201
|
+
closeout), as every checkpoint's do (below). If the host has no next commit
|
|
202
|
+
scheduled, one ledger-only tracking commit that references the T3 hash is
|
|
203
|
+
allowed. It is bookkeeping, not a lifecycle milestone: it adds no Checkpoint Log
|
|
204
|
+
row of its own (unlike closeout, which is a checkpoint and does get a row).
|
|
197
205
|
**Minimal host (zero-phase) exception — there, tier does not set the count.**
|
|
198
206
|
On a minimal host (`references/modify-existing-flow.md` Step 1.7 standalone, or
|
|
199
207
|
its Step 1.6 follow-up minimal variant) there is no later host commit for a row
|
|
200
208
|
to ride, so the count is **two for every tier** — implementation, or
|
|
201
|
-
`spec-baseline` for a baseline capture, then closeout — and a T3's
|
|
202
|
-
|
|
209
|
+
`spec-baseline` for a baseline capture, then closeout — and every row, a T3's
|
|
210
|
+
included, is written into checkpoint 1 itself; only the entries that carry
|
|
211
|
+
checkpoint 1's hash ride the closeout commit.
|
|
203
212
|
Everything above about "T3 = a single commit" describes a **hosted** T3, the
|
|
204
213
|
case where a later host commit exists.
|
|
205
214
|
Whether you choose Y or N, the AI records one row in the feature `_index.md`
|
|
206
215
|
Checkpoint Log — every checkpoint is accounted for (`committed` / `skipped` /
|
|
207
|
-
`failed`), even when no commit happens.
|
|
208
|
-
commit
|
|
209
|
-
|
|
216
|
+
`failed`), even when no commit happens.
|
|
217
|
+
**No checkpoint commit can contain its own hash.** The entries that carry a
|
|
218
|
+
checkpoint's hash — its Checkpoint Log Result `committed ({hash})`, and any
|
|
219
|
+
Lightweight Changes `Commit` cell holding that hash — are written after the
|
|
220
|
+
commit succeeds and ride the host's **next** commit. A hook rejection or failed
|
|
221
|
+
commit is recorded as `failed` (never a fake hash).
|
|
210
222
|
**One further Result value — `reconciled ({merged-hotfix-hash})`.** It records
|
|
211
223
|
that this checkpoint documents a change that was **already merged** before any
|
|
212
224
|
ceremony ran, and it is written only on a post-hoc hotfix host's implementation
|
|
@@ -215,8 +227,8 @@ belongs to the **merged hotfix**, not to this host's own documentation commit
|
|
|
215
227
|
that one goes in the Lightweight Changes row's `Commit` cell, and the two have
|
|
216
228
|
different provenance and must never be swapped. On every other host the three
|
|
217
229
|
values above are the whole vocabulary.
|
|
218
|
-
**Exception — the closeout row**:
|
|
219
|
-
|
|
230
|
+
**Exception — the closeout row**: no later commit of this host's lifecycle
|
|
231
|
+
carries it, so the closeout row is written before the commit
|
|
220
232
|
as `closeout | committed` with **no hash** (see
|
|
221
233
|
`references/finish-feature-flow.md` Step 4); trace that commit via
|
|
222
234
|
`git log -1 -- dflow/specs/features/completed/{SPEC-ID}-{slug}` or the optional
|
|
@@ -339,12 +351,25 @@ heavily enough that git's similarity index dropped below the rename
|
|
|
339
351
|
threshold; consider using `git mv` for the move, then making content
|
|
340
352
|
edits in a follow-up commit).
|
|
341
353
|
|
|
342
|
-
### CI / hook automation
|
|
354
|
+
### CI / hook automation
|
|
343
355
|
|
|
344
|
-
|
|
345
|
-
`dflow/specs/features/completed/`
|
|
346
|
-
|
|
347
|
-
|
|
356
|
+
Dflow ships `dflow check-closeout`, a gate for the closeout commit. For each
|
|
357
|
+
feature directory newly archived to `dflow/specs/features/completed/` it checks
|
|
358
|
+
that `_index.md` and every spec say `status: completed`, that nothing is left
|
|
359
|
+
under `active/`, that the Checkpoint Log has a real `closeout` row reading
|
|
360
|
+
`committed` or `skipped`, and — with `--staged` — that nothing under the
|
|
361
|
+
archived directory is left unstaged; it exits 1 when one fails. A project wires
|
|
362
|
+
it into a pre-commit hook (`--staged`) or a CI job (`--range <base>..<head>`)
|
|
363
|
+
itself — Dflow installs neither. `dflow check-closeout --help` names the page
|
|
364
|
+
with the hook and CI templates. When the hook refuses a closeout commit, handle
|
|
365
|
+
it as `references/finish-feature-flow.md` Step 4 instruction 3 says.
|
|
366
|
+
|
|
367
|
+
Passing it is not a clean closeout: the post-commit verification in
|
|
368
|
+
`references/finish-feature-flow.md` Step 4 still applies in full.
|
|
369
|
+
|
|
370
|
+
A hook that refuses paired `D` + `A` instead of `R` for the same feature
|
|
371
|
+
directory is compatible with the `git mv` rule, but it is not part of
|
|
372
|
+
`check-closeout`.
|
|
348
373
|
|
|
349
374
|
## Gate Checks by Branch Type
|
|
350
375
|
|
|
@@ -405,8 +430,12 @@ AI should verify:
|
|
|
405
430
|
- [ ] All `phase-spec-*.md` in the feature directory have `status: completed`
|
|
406
431
|
- [ ] `_index.md` Current BR Snapshot has been synced to BC layer
|
|
407
432
|
(`rules.md` / `behavior.md`) — typically by `/dflow:finish-feature`
|
|
408
|
-
- [ ]
|
|
409
|
-
|
|
433
|
+
- [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
|
|
434
|
+
complete for this host — its Local-closeout gate is satisfied (the
|
|
435
|
+
closeout commit landed and passed post-commit verification) and, if
|
|
436
|
+
the host carries `follow-up-of`, the Step 6 tracking commit has also
|
|
437
|
+
landed and been verified. `status: completed` or a directory already
|
|
438
|
+
under `completed/` does not show this on its own.
|
|
410
439
|
- [ ] All new business logic is in `src/Domain/` (not delivery/entrypoint code — presentation/UI layer, controllers, handlers, jobs, message consumers, data pipelines, or stored procedures)
|
|
411
440
|
- [ ] New terms added to `glossary.md`
|
|
412
441
|
- [ ] `rules.md` and `models.md` updated if applicable
|
|
@@ -414,8 +443,8 @@ AI should verify:
|
|
|
414
443
|
- [ ] Domain layer code has no delivery-framework references
|
|
415
444
|
|
|
416
445
|
> **On a minimal (zero-phase) host**, split this list by what each item reads.
|
|
417
|
-
> Items about **this host's own record** — `_index.md` status,
|
|
418
|
-
>
|
|
446
|
+
> Items about **this host's own record** — `_index.md` status, **Closeout
|
|
447
|
+
> complete**, and the phase-spec check, which passes vacuously on an empty
|
|
419
448
|
> table — apply **unchanged**: they are what stops a host merging with its
|
|
420
449
|
> record still open. Every item that names a **Domain or bounded-context
|
|
421
450
|
> artifact**, the BR-Snapshot sync included, applies only to what this change
|
|
@@ -464,10 +493,15 @@ AI should verify:
|
|
|
464
493
|
|
|
465
494
|
### bugfix/ branch — Before Merging (Pre-PR / Pre-Integration)
|
|
466
495
|
|
|
467
|
-
- [ ] `_index.md` status: `completed
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
496
|
+
- [ ] `_index.md` status: `completed`
|
|
497
|
+
- [ ] **Closeout complete**: `/dflow:finish-feature` has announced closeout
|
|
498
|
+
complete for this host — its Local-closeout gate is satisfied (the
|
|
499
|
+
closeout commit landed and passed post-commit verification) and, if
|
|
500
|
+
the host carries `follow-up-of`, the Step 6 tracking commit has also
|
|
501
|
+
landed and been verified. `status: completed` or a directory already
|
|
502
|
+
under `completed/` does not show this on its own.
|
|
503
|
+
A `bugfix/` host closes out exactly like a `feature/` one; an
|
|
504
|
+
un-closed-out host must not merge.
|
|
471
505
|
- [ ] **The tier's artifact** has the fix documented — a **T2**'s lightweight
|
|
472
506
|
spec, or for a **T3** the host `_index.md` Lightweight Changes row, which
|
|
473
507
|
is its whole record. Do not ask a T3 for a spec file here either: the
|
|
@@ -68,7 +68,9 @@ the guide states them rather than continuing through the steps below.
|
|
|
68
68
|
a follow-up (Step 1.6 minimal variant), otherwise it is standalone (Step 1.7) —
|
|
69
69
|
both are tier-exempt, cut `feature/{SPEC-ID}-{slug}`, and record a `Tier = baseline`
|
|
70
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.
|
|
71
|
+
cascade's "below workflow" as permission to skip the record. A baseline
|
|
72
|
+
minimal host does not stop at the capture: it goes on through Step 6 and
|
|
73
|
+
offers its first checkpoint (`spec-baseline`) at § 6.5 (Step 1.7 says how).
|
|
72
74
|
A capture about no bounded context at all — the role reach of functions that
|
|
73
75
|
belong to no context yet, say — is not a baseline capture and opens no host:
|
|
74
76
|
with no active feature to attach it to, record it and offer to commit that
|
|
@@ -298,6 +300,10 @@ observation-only and carries its own capture alone.
|
|
|
298
300
|
recorded, or a stale branch is still carrying it — and it is settled that
|
|
299
301
|
way with the developer, as duplicate / existing work or branch-history
|
|
300
302
|
cleanup. All identifiers are settled here, before the host exists.
|
|
303
|
+
|
|
304
|
+
For a **post-hoc hotfix** (Step 1.8), also run the branch-base check in
|
|
305
|
+
`references/modify-existing-post-hoc-hotfix.md` item 2 here, before step 3
|
|
306
|
+
creates anything: step 4 cuts from the base branch it settles.
|
|
301
307
|
3. **Create the minimal `_index.md`** from `templates/_index.md` at
|
|
302
308
|
`dflow/specs/features/active/{SPEC-ID}-{slug}/_index.md`, carrying all
|
|
303
309
|
**seven required sections** that template names — the Metadata front
|
|
@@ -344,10 +350,13 @@ above). A **baseline capture** is observation-only: it records the capture in
|
|
|
344
350
|
its BC-layer documents and/or `domain/analysis.md` and one `Tier = baseline`
|
|
345
351
|
row in `_index.md`, and its first checkpoint is named `spec-baseline` with
|
|
346
352
|
Result `committed` (never `implementation` — there is no implementation
|
|
347
|
-
work). Otherwise the **implementation commit is checkpoint 1
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
353
|
+
work). Otherwise the **implementation commit is checkpoint 1**. Either way,
|
|
354
|
+
checkpoint 1 is offered at the end of Step 6 (§ 6.5), after Step 6 has written
|
|
355
|
+
its record, and recorded in the Checkpoint Log. A baseline capture skips Step 5
|
|
356
|
+
— there is nothing to implement — so once the capture is recorded it goes
|
|
357
|
+
through the Step 5 → Step 6 gate into Step 6, not straight to a commit. (For a
|
|
358
|
+
**post-hoc** host, Step 5 is skipped as well and checkpoint 1 is the
|
|
359
|
+
**documentation** commit instead; see Step 1.8 and Step 5's guard.)
|
|
351
360
|
|
|
352
361
|
**Every artifact gets a Lightweight Changes row, and every row is written
|
|
353
362
|
*before* checkpoint 1.** A **T3**'s row *is* its whole record; a **T2**'s row is
|
|
@@ -359,7 +368,8 @@ implementation paths (for a baseline, the documents it captured into). The
|
|
|
359
368
|
exist until its commit does: closeout's allow-list admits that cell and no other
|
|
360
369
|
change **to the row**, so a row added after checkpoint 1 **blocks**. (The
|
|
361
370
|
allow-list separately admits the Checkpoint Log rows, the Resume Pointer and the
|
|
362
|
-
Current BR Snapshot
|
|
371
|
+
Current BR Snapshot; the first two are what "Finalize + close" writes after
|
|
372
|
+
checkpoint 1.)
|
|
363
373
|
|
|
364
374
|
**Name the implementation paths in the artifact.** Closeout's evidence checks
|
|
365
375
|
assert that a commit *touches the implementation paths this change describes* —
|
|
@@ -371,16 +381,17 @@ documents it wrote instead; that is its counterpart. An artifact that
|
|
|
371
381
|
declares none leaves that check nothing to compare, and finish-feature treats a
|
|
372
382
|
missing declaration as a **block**, not a pass.
|
|
373
383
|
|
|
374
|
-
**
|
|
375
|
-
|
|
376
|
-
lightweight-spec `status: completed
|
|
377
|
-
|
|
378
|
-
BC
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
Resume Pointer
|
|
384
|
+
**Before checkpoint 1 — Step 6 finalizes the record.** Step 6's completion
|
|
385
|
+
checklist runs before checkpoint 1, so everything it writes rides that commit.
|
|
386
|
+
For **every** T2, 6.3 sets the lightweight-spec `status: completed`. **Only when
|
|
387
|
+
that T2 is BC-bearing**, 6.3 also refreshes the host's Current BR Snapshot — a
|
|
388
|
+
no-BC T2 has no snapshot to refresh. A **T3** or a **baseline capture** has no
|
|
389
|
+
spec file and no snapshot to refresh; Step 6 only re-verifies its row.
|
|
390
|
+
|
|
391
|
+
**Finalize + close — after checkpoint 1.** Before `/dflow:finish-feature`,
|
|
392
|
+
write what cannot exist until checkpoint 1 does, for every tier: each row's
|
|
393
|
+
commit evidence (the two surfaces below) and the Resume Pointer advanced to the
|
|
394
|
+
closeout-ready state.
|
|
384
395
|
|
|
385
396
|
**Commit evidence goes to two surfaces, always — every row, every tier.** They
|
|
386
397
|
answer different questions, so filling one is never filling the other, and
|
|
@@ -397,20 +408,22 @@ The **mode** changes only *which hash* each surface carries:
|
|
|
397
408
|
|
|
398
409
|
- **Normal** (T2 or T3) — Checkpoint Log Result `committed ({hash})` and the
|
|
399
410
|
row's `Commit` cell both name **checkpoint 1**, the single commit that
|
|
400
|
-
carried the artifact
|
|
401
|
-
fill both.
|
|
411
|
+
carried the artifact, the implementation and Step 6's record together. Two
|
|
412
|
+
cells, one hash; fill both.
|
|
402
413
|
- **Post-hoc hotfix** (Step 1.8; T2 or T3) — the Checkpoint Log Result stays
|
|
403
|
-
`reconciled ({merged-hotfix-hash})`, **never overwrite it
|
|
404
|
-
|
|
405
|
-
|
|
414
|
+
`reconciled ({merged-hotfix-hash})`, **never overwrite it** — only closeout
|
|
415
|
+
corrects it, through `references/modify-existing-post-hoc-hotfix.md` item 6 —
|
|
416
|
+
while the row's `Commit` cell carries the **documentation** commit's hash.
|
|
417
|
+
This is the one mode where the two values genuinely differ (Step 1.8 item 4).
|
|
406
418
|
- **Baseline capture** — the `spec-baseline` checkpoint's Result
|
|
407
419
|
`committed ({hash})` and the `Tier = baseline` row's `Commit` cell both name
|
|
408
420
|
that capture commit, the one that carried what it captured. Two cells,
|
|
409
421
|
one hash; fill both.
|
|
410
422
|
|
|
411
423
|
**A declined checkpoint still owes its hash.** If the developer answered **N**
|
|
412
|
-
at the checkpoint-1 offer and made that commit themselves
|
|
413
|
-
|
|
424
|
+
at the checkpoint-1 offer and made that commit themselves — the change together
|
|
425
|
+
with Step 6's record — the Checkpoint Log row was written `skipped` honestly —
|
|
426
|
+
the AI did not commit — but it is now
|
|
414
427
|
**incomplete, not final**: complete it here to `committed ({hash})` with the
|
|
415
428
|
developer's actual hash. **That completion is for a normal checkpoint 1** (or a
|
|
416
429
|
`spec-baseline` one). On a **post-hoc** host the Result stays
|
|
@@ -420,7 +433,8 @@ developer's commit lands, never by overwriting the reconciliation hash, which
|
|
|
420
433
|
records a different commit entirely. A row left reading `skipped` blocks closeout, and
|
|
421
434
|
finish-feature cannot tell "declined then committed" from "never committed" on
|
|
422
435
|
your behalf. The **closeout** row is the deliberate exception — it carries no
|
|
423
|
-
hash at all, because
|
|
436
|
+
hash at all, because no later commit of this host carries it
|
|
437
|
+
(`references/git-integration.md` § Commit checkpoints). Its **Result is still
|
|
424
438
|
read** afterwards — finish-feature's post-commit gate rejects `failed` there. A
|
|
425
439
|
declined closeout stays `skipped` because that value records the declined offer
|
|
426
440
|
honestly, not because the row goes unread.
|
|
@@ -673,12 +687,18 @@ Wait for confirmation before entering Step 5.
|
|
|
673
687
|
> **Post-hoc hotfix (Step 1.8) — skip this step.** The implementation already
|
|
674
688
|
> landed on the mainline before any ceremony ran; that is the whole premise of
|
|
675
689
|
> 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
|
|
677
|
-
> **documentation only** — the T2 spec or T3
|
|
678
|
-
>
|
|
690
|
+
> implement here. Go straight to the Step 5 → Step 6 gate and on through Step 6;
|
|
691
|
+
> checkpoint 1 (§ 6.5) then commits **documentation only** — the T2 spec or T3
|
|
692
|
+
> row, this host's `_index.md` and what Step 6 wrote, and no source.
|
|
693
|
+
> Re-implementing the fix on this branch would satisfy the letter
|
|
679
694
|
> of the checkpoint while breaking §8's reconciliation contract, which is why
|
|
680
695
|
> closeout inspects that commit's changed paths.
|
|
681
696
|
|
|
697
|
+
> **Baseline capture (a baseline minimal host, Step 1.7) — skip this step.**
|
|
698
|
+
> There is nothing to implement. Once the capture is recorded, go through the
|
|
699
|
+
> Step 5 → Step 6 gate into Step 6; checkpoint 1 (§ 6.5) is the `spec-baseline`
|
|
700
|
+
> commit of what the capture wrote.
|
|
701
|
+
|
|
682
702
|
If extracting to Domain layer:
|
|
683
703
|
|
|
684
704
|
```csharp
|
|
@@ -717,9 +737,10 @@ protected void Calculate()
|
|
|
717
737
|
Announce to developer:
|
|
718
738
|
> "Implementation appears complete. Ready to update artifacts (spec, rules.md, models.md, glossary, tech-debt)? `/dflow:next` to proceed."
|
|
719
739
|
|
|
720
|
-
|
|
740
|
+
A **baseline capture** implemented nothing, so it announces instead:
|
|
741
|
+
> "Baseline capture recorded. Ready to update artifacts? `/dflow:next` to proceed."
|
|
721
742
|
|
|
722
|
-
Wait for confirmation before entering Step 6. This step gate is where the completion checklist is triggered — do not skip.
|
|
743
|
+
Wait for confirmation before entering Step 6. This step gate is where the completion checklist is triggered — do not skip. It offers **no** commit: checkpoint 1 is offered at the end of Step 6 (§ 6.5).
|
|
723
744
|
|
|
724
745
|
## Step 6: Update Artifacts
|
|
725
746
|
|
|
@@ -756,6 +777,7 @@ Ask these one-by-one.
|
|
|
756
777
|
> **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
778
|
|
|
758
779
|
- [ ] 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)
|
|
780
|
+
- [ ] **BC-bearing T2, on every host** — refresh the host `_index.md` Current BR Snapshot from this spec's final delta (`templates/_index.md` regenerates it when a T2 lightweight-spec is finalized; on a minimal host this is the refresh Step 1.7 places before checkpoint 1). A spec with no BR delta leaves the Snapshot as it is. N/A for a no-BC T2, a T3 and a baseline capture
|
|
759
781
|
- [ ] 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
|
|
760
782
|
- [ ] `dflow/specs/domain/{context}/rules.md` — business rules updated
|
|
761
783
|
- [ ] `dflow/specs/domain/{context}/models.md` — domain model updated
|
|
@@ -800,3 +822,7 @@ directory — the closeout `git mv` happens at `/dflow:finish-feature` time
|
|
|
800
822
|
|
|
801
823
|
Only announce "change complete" after the appropriate archival step
|
|
802
824
|
above (or the Step 6.3 docs sweep) is done.
|
|
825
|
+
|
|
826
|
+
### 6.5 Commit checkpoint (checkpoint 1)
|
|
827
|
+
|
|
828
|
+
> Commit checkpoint (per `references/git-integration.md` § Commit Checkpoints, Branch Gate & AI Commits): fold the offer into the "change complete" announcement, then record the result in the `_index.md` Checkpoint Log. This commit is **checkpoint 1**: it carries the change — the spec or row plus the implementation — **and** everything Steps 2–6 wrote. Tier sets the count — T2 commits the merged spec+implementation here (closeout is the second checkpoint); T3 is a single implementation commit. The entries that carry this commit's hash — the Checkpoint Log Result and each Lightweight Changes `Commit` cell naming it — are written after the commit and ride the host's next commit; on a phase-bearing host, `/dflow:finish-feature` Step 4 backfills any `Commit` cell still unfilled at closeout. **Minimal host exception (Step 1.7 standalone *and* the Step 1.6 follow-up variant)**: a minimal host takes no host commit between checkpoint 1 and closeout, so **every row rides checkpoint 1 itself** — a T3 row included, written into `_index.md` *before* this commit, because finish-feature Step 1 reads **checkpoint 1's committed `_index.md`** for it. Only the entries that carry the hash come later: Step 1.7's "Finalize + close" writes them, and they ride 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` and what Step 6 wrote, 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.
|
|
@@ -103,7 +103,8 @@ hardcoded `feature/` branch). Step 1.7's **step 1 does not apply**: it is the
|
|
|
103
103
|
standalone-classification gate, and this caller has already been classified as
|
|
104
104
|
a follow-up. Everything Step 1.7 states **after** step 4 *does* apply
|
|
105
105
|
unchanged — every artifact's row written before checkpoint 1, the
|
|
106
|
-
implementation-path declaration,
|
|
106
|
+
implementation-path declaration, the finalization before checkpoint 1 and
|
|
107
|
+
"Finalize + close" after it, and the two
|
|
107
108
|
commit-evidence surfaces — because finish-feature reads for all of it on a
|
|
108
109
|
follow-up host exactly as on a standalone one. Then record the change's
|
|
109
110
|
artifacts — a T2 lightweight-spec, one
|
|
@@ -32,6 +32,10 @@ If you arrived here with a T1, go back to Part A's routing.
|
|
|
32
32
|
includes *a related feature that is still in flight* — see above for why
|
|
33
33
|
it cannot be the host.
|
|
34
34
|
|
|
35
|
+
Make the choice here, and **act on it only after item 2's branch-base
|
|
36
|
+
check**: on either route, nothing is opened, linked or cut before that
|
|
37
|
+
check.
|
|
38
|
+
|
|
35
39
|
Do not skip this choice. If a feature that was in flight turns out to have
|
|
36
40
|
touched the same code, that is a **merge** question, settled when the
|
|
37
41
|
branches actually meet — see `finish-feature-flow.md` Step 5.
|
|
@@ -42,11 +46,69 @@ If you arrived here with a T1, go back to Part A's routing.
|
|
|
42
46
|
1.6's delegation to it) like any other minimal host — that branch *is* the
|
|
43
47
|
**post-hoc branch** the rest of this step names, and the value `_index.md`
|
|
44
48
|
`branch:` records.
|
|
49
|
+
|
|
50
|
+
**Branch-base check — run it before Step 1.7 step 3 creates anything**
|
|
51
|
+
(on the follow-up route: before Step 1.6 opens the host and writes the
|
|
52
|
+
reverse link). It settles which base branch this host's branch is cut
|
|
53
|
+
from. Closeout requires the commit item 3 records to be an ancestor of
|
|
54
|
+
this branch, so a branch cut from a base that does not contain that commit
|
|
55
|
+
yet passes every step until closeout and is blocked there. Settle that
|
|
56
|
+
commit with the developer first (item 3), then:
|
|
57
|
+
1. Settle the base branch and fetch it. The developer decides which
|
|
58
|
+
branch is the base — Dflow does not know it, though the project may
|
|
59
|
+
record it under `_conventions.md` § Git Policy — and it is the branch
|
|
60
|
+
Step 1.7 step 4 cuts from anyway. `{base-ref}` is that branch's latest
|
|
61
|
+
ref (for example `origin/develop`). Fetch the remote it belongs to
|
|
62
|
+
(`git fetch origin` for `origin/develop`; `git fetch --all` when
|
|
63
|
+
unsure): a bare `git fetch` updates only the default remote, so a base
|
|
64
|
+
on another remote stays stale and the steps below misjudge it. The fix
|
|
65
|
+
is merged and pushed by now, and it often reached the base on the
|
|
66
|
+
server — a PR merge or a squash — that this clone has not fetched yet.
|
|
67
|
+
2. Run `git cat-file -t {hash}`. It must print `commit`. If it prints
|
|
68
|
+
anything else or fails, and step 1's fetch failed, the commit may only
|
|
69
|
+
be missing from this clone: stop, say the check needs the fetch, and
|
|
70
|
+
run it again once the remote is reachable. Otherwise the hash is
|
|
71
|
+
mistyped, names an object that is not a commit, or names a commit that
|
|
72
|
+
remote does not have — stop and ask the developer. Do not guess.
|
|
73
|
+
3. Run `git show --stat {hash}`. At least one path it lists must be an
|
|
74
|
+
implementation path this record will declare. If none is, stop and
|
|
75
|
+
settle the commit with the developer — closeout's (c) would block it.
|
|
76
|
+
A last commit that touches only tests does this. Then run
|
|
77
|
+
`git rev-list --parents -n 1 {hash}`: more than two hashes means a
|
|
78
|
+
merge commit — for example the one a PR page shows as its merged
|
|
79
|
+
commit. Item 3 never records one, and a merge usually passes the path
|
|
80
|
+
check above, so stop here and settle the commit with the developer.
|
|
81
|
+
4. Run `git merge-base --is-ancestor {hash} {base-ref}`:
|
|
82
|
+
- **Exit `0`** — cut this host's branch from `{base-ref}` at Step 1.7
|
|
83
|
+
step 4. Do **not** let the new branch track the base: run
|
|
84
|
+
`git checkout -b {branch} --no-track {base-ref}`, or update the local
|
|
85
|
+
base branch the way the project normally does and cut from that. A
|
|
86
|
+
branch that tracks `origin/develop` can, under some push settings,
|
|
87
|
+
push its documentation commits straight to `develop`.
|
|
88
|
+
- **Exit `1`** — the fix is not in that base yet. Tell the developer
|
|
89
|
+
both causes. **The fix has not been merged back yet**: merge it back
|
|
90
|
+
first (under GitFlow, into `develop`). **The recorded commit is not
|
|
91
|
+
the one item 3 names**: under a squash or rebase merge, or a
|
|
92
|
+
cherry-pick into the base, the fix's own commits never reach it —
|
|
93
|
+
record the commit the fix landed as (item 3).
|
|
94
|
+
⚠ Do **not** cut from `main` instead to make the check pass: the
|
|
95
|
+
documentation branch would carry `main`'s merge commits into
|
|
96
|
+
`develop` when it merges, and its documents would start from
|
|
97
|
+
`main`'s older Domain documents and conflict there.
|
|
98
|
+
- **Any other exit code** — a mistyped ref or a failed command. Stop
|
|
99
|
+
and show the developer the output.
|
|
100
|
+
- **If step 1's fetch failed** (offline): exit `0` is still
|
|
101
|
+
trustworthy — the ref you cut from does contain the commit. Exit `1`
|
|
102
|
+
may only mean the local ref is behind; treat it as provisional and
|
|
103
|
+
say so.
|
|
45
104
|
3. **Implementation checkpoint Result = `reconciled ({merged-hotfix-hash})`.**
|
|
46
105
|
In the host's Checkpoint Log the implementation row's Result is
|
|
47
106
|
`reconciled (...)` — the value meaning "this checkpoint documents an
|
|
48
|
-
already-merged change" — carrying the
|
|
49
|
-
|
|
107
|
+
already-merged change" — carrying the hash of **one of the fix's own
|
|
108
|
+
commits**, or of **the commit the fix landed as** when it reached the base
|
|
109
|
+
branch by a squash, a rebase or a cherry-pick — a commit on the base
|
|
110
|
+
branch this host's branch is cut from (item 2).
|
|
111
|
+
It sits alongside the usual `committed` / `skipped` / `failed` Results (see
|
|
50
112
|
`references/git-integration.md` § Commit Checkpoints, Branch Gate & AI
|
|
51
113
|
Commits). That hash belongs to the **hotfix**, so it is **not** evidence
|
|
52
114
|
that this host's own first commit landed — the documentation work still owes
|
|
@@ -54,12 +116,27 @@ If you arrived here with a T1, go back to Part A's routing.
|
|
|
54
116
|
Committing the documentation together with closeout collapses the host to
|
|
55
117
|
one commit and fails finish-feature Step 1.
|
|
56
118
|
|
|
119
|
+
**Which commit that is depends on how the fix reached the base branch:**
|
|
120
|
+
|
|
121
|
+
| The fix reached the base branch by | Record |
|
|
122
|
+
|---|---|
|
|
123
|
+
| a merge (under GitFlow, merging the hotfix branch back into `develop`) or a fast-forward | the last of **the fix's own commits** that touches a declared implementation path — never a merge commit, and under GitFlow never the tagged merge commit on `main`, which the back-merge does not bring into `develop` |
|
|
124
|
+
| a squash merge | the squash commit on the base branch |
|
|
125
|
+
| a rebase merge or a cherry-pick | the last of the fix's commits **as they landed on the base branch** that touches a declared implementation path |
|
|
126
|
+
|
|
127
|
+
When the fix's own commits are on the base branch, record one of them even if
|
|
128
|
+
a copy of the fix got there first. Closeout accepts a commit that touches only
|
|
129
|
+
some of the declared paths: it asks for at least one. The hotfix branch's own
|
|
130
|
+
name still goes in `hotfix-branch:` (item 4).
|
|
131
|
+
|
|
57
132
|
**You are asserting this hash, not deriving it.** Nothing in the repository
|
|
58
133
|
records which commit was the hotfix, so no check in this flow can confirm
|
|
59
134
|
it — finish-feature's reconciliation gate is explicit that it tests
|
|
60
135
|
plausibility only. So state the identity
|
|
61
136
|
and **cite what it rests on**: the PR, incident, or tracker reference that
|
|
62
|
-
identifies this fix.
|
|
137
|
+
identifies this fix. **Cite the source, not the hash** — a corrected hash
|
|
138
|
+
(item 6) then never has to touch the citation. Record the citation
|
|
139
|
+
alongside the per-tier trace
|
|
63
140
|
(item 4). An **uncited** hash blocks closeout —
|
|
64
141
|
`references/pr-review-checklist.md` is what confirms the identity, and it
|
|
65
142
|
needs something to confirm against.
|
|
@@ -80,3 +157,44 @@ If you arrived here with a T1, go back to Part A's routing.
|
|
|
80
157
|
5. **Branch equality** for the host is asserted against the **post-hoc
|
|
81
158
|
documentation branch** (the `_index.md` `branch:` value), never the deleted
|
|
82
159
|
hotfix branch.
|
|
160
|
+
6. **Closeout: (b) fails on the `reconciled (...)` hash.**
|
|
161
|
+
`references/finish-feature-minimal-host.md`'s `Minimal host, hotfix
|
|
162
|
+
post-hoc only` check sends you here. Report which cause it is — never only
|
|
163
|
+
"not an ancestor" — and give the developer the repair for that cause. First
|
|
164
|
+
fetch the remote `{base-ref}` belongs to (item 2 step 1) and find the
|
|
165
|
+
commit item 3 says to record, then test where it is. If the fetch fails, a
|
|
166
|
+
result that depends on `{base-ref}`, or on a commit this clone does not
|
|
167
|
+
have, is provisional — say so, as item 2 does:
|
|
168
|
+
- **It is already on this branch** (`git merge-base --is-ancestor
|
|
169
|
+
{its-hash} HEAD` exits `0`) — the record names the right fix but the
|
|
170
|
+
wrong commit — for example the tagged merge commit on `main`. Correct
|
|
171
|
+
only the Checkpoint Log hash. The citation (item 3 cites the source, not
|
|
172
|
+
the hash), `hotfix-branch:` and the declared paths stay as they are, so
|
|
173
|
+
the correction rides the closeout commit — closeout's closed list admits
|
|
174
|
+
Checkpoint Log rows. Checkpoint 1 is not touched.
|
|
175
|
+
- **It is on the base branch but not on this branch** (`git merge-base
|
|
176
|
+
--is-ancestor {its-hash} {base-ref}` exits `0`) — this branch was cut
|
|
177
|
+
before the fix reached the base, so correcting the hash is not enough.
|
|
178
|
+
Merge `{base-ref}` into this branch — or, if nothing is pushed yet,
|
|
179
|
+
rebase this branch onto it and refill every Lightweight Changes row's
|
|
180
|
+
`Commit` cell — then record that commit. Set closeout's uncommitted
|
|
181
|
+
finalization edits aside first with `git stash push --include-untracked`
|
|
182
|
+
(a plain `git stash` leaves newly created files behind), check that
|
|
183
|
+
`git status --porcelain` prints nothing, and restore them afterwards
|
|
184
|
+
with `git stash pop`: `git rebase` refuses to run over uncommitted
|
|
185
|
+
edits, and `git merge` refuses when the base changed the same files. If
|
|
186
|
+
`git stash pop` reports a conflict — it can when the base changed the
|
|
187
|
+
same part of a file those edits touch — resolve it before closeout
|
|
188
|
+
continues.
|
|
189
|
+
- **It is not on the base branch either** — the fix was never merged back.
|
|
190
|
+
Merge it back first (under GitFlow, into `develop`), then take the case
|
|
191
|
+
above.
|
|
192
|
+
- ⚠ **Never merge `main` or the tag into this branch to make (b) pass.** It
|
|
193
|
+
lets the wrongly recorded commit pass unchanged, and it carries `main`'s
|
|
194
|
+
commits into `develop` when this branch merges.
|
|
195
|
+
- **The record names a different fix** (the citation, the hotfix branch and
|
|
196
|
+
the declared paths are all wrong) — checkpoint 1's own record is wrong,
|
|
197
|
+
and closeout cannot repair that. Follow
|
|
198
|
+
`references/finish-feature-record-correction.md`: it says when
|
|
199
|
+
checkpoint 1 can be amended and when to stop for the developer, and it
|
|
200
|
+
covers `reconciled (...)`, which names the wrong fix too.
|
|
@@ -416,7 +416,7 @@ During implementation, continuously check:
|
|
|
416
416
|
**→ Step Gate: Step 7 → Step 8**
|
|
417
417
|
|
|
418
418
|
Announce to developer:
|
|
419
|
-
> "Implementation appears complete. Ready to run the completion checklist (verify against spec, update domain docs,
|
|
419
|
+
> "Implementation appears complete. Ready to run the completion checklist (verify against spec, update domain docs, complete the phase)? `/dflow:next` to proceed."
|
|
420
420
|
|
|
421
421
|
> Commit checkpoint (T1 milestone 2 of 3): offer to commit the implementation, then record the result in the `_index.md` Checkpoint Log. Milestone 3 (closeout) is the `/dflow:finish-feature` checkpoint.
|
|
422
422
|
|
|
@@ -468,33 +468,51 @@ Ask these one-by-one; do not dump all five at once.
|
|
|
468
468
|
- [ ] `analysis.md`, at either of its two paths — re-check every entry this feature recorded before building: an entry for what the feature was to add or change against what was built (corrected where the build differs, removed where nothing was built for it), and an entry for something already in the system against the system as it now stands (corrected where this feature changed it, never removed because this feature built nothing for it). Read the entries in the file, not in a diff: a checkpoint may already have committed them.
|
|
469
469
|
- [ ] `dflow/specs/migration/tech-debt.md` — tech debt discovered during implementation recorded
|
|
470
470
|
|
|
471
|
-
### 8.4
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
- [ ]
|
|
484
|
-
|
|
485
|
-
- [ ]
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
471
|
+
### 8.4 Phase completion and handoff
|
|
472
|
+
|
|
473
|
+
This step completes the phase and hands the feature on. It does not close the
|
|
474
|
+
feature out: `/dflow:finish-feature` is the only closeout path — it flips the
|
|
475
|
+
`_index.md` `status`, moves the feature directory to `completed/`, and takes
|
|
476
|
+
the closeout commit checkpoint.
|
|
477
|
+
|
|
478
|
+
**Complete this phase** — all four items, whether or not another phase
|
|
479
|
+
follows:
|
|
480
|
+
|
|
481
|
+
- [ ] This phase-spec's frontmatter `status` changed from `in-progress` to
|
|
482
|
+
`completed`
|
|
483
|
+
- [ ] This phase's row in the `_index.md` Phase Specs table changed from
|
|
484
|
+
`in-progress` to `completed`
|
|
485
|
+
- [ ] `_index.md` Current BR Snapshot reconciled against this phase-spec's
|
|
486
|
+
**Business Rules** section — this is the feature's first phase, so it
|
|
487
|
+
has no Delta from prior phases. If implementation changed a rule, update
|
|
488
|
+
the phase-spec first, then reconcile. Touch only this phase's rows: a
|
|
489
|
+
row that another change in this host wrote — a lightweight change
|
|
490
|
+
hosted under this feature, for example — stays as it is. Where this
|
|
491
|
+
phase and such a change both changed the same rule, keep the later
|
|
492
|
+
change's text; if the host's record does not show which change came
|
|
493
|
+
later, ask the developer which text is current instead of choosing.
|
|
494
|
+
- [ ] `_index.md` Resume Pointer: rewrite **both** narrative lines — Current
|
|
495
|
+
Progress says this phase is completed, and Next Action names the
|
|
496
|
+
command the handoff below picks. Step 4 wrote "phase-1 in progress:
|
|
497
|
+
drafting phase-spec." and "finish phase-spec, then implement …" into
|
|
498
|
+
these two lines; either one left standing reads as open work.
|
|
499
|
+
|
|
500
|
+
`/dflow:finish-feature` relies on these four whenever the feature reaches it,
|
|
501
|
+
next or after later phases. Its Step 1 checks the phase-spec `status`, the
|
|
502
|
+
Phase Specs row and the Resume Pointer, and stops closeout on a stale one.
|
|
503
|
+
Its Step 3 syncs the Current BR Snapshot into the bounded context as it
|
|
504
|
+
stands, without re-deriving it from the phase-specs.
|
|
505
|
+
|
|
506
|
+
`Implementation Tasks` is not on this list: 8.1 verified it, and 8.2 may have
|
|
507
|
+
collapsed or removed it by team convention. BC document sync is not on it
|
|
508
|
+
either: 8.3 did it.
|
|
509
|
+
|
|
510
|
+
**Hand off:**
|
|
511
|
+
|
|
512
|
+
- Another phase is still ahead → run `/dflow:new-phase` next.
|
|
513
|
+
- No further phase — a single-phase feature, or this was the last phase →
|
|
514
|
+
run `/dflow:finish-feature` next. It is the only closeout path.
|
|
515
|
+
|
|
516
|
+
Announce that this phase is completed and name the next command. Do not
|
|
517
|
+
announce the feature as complete: `/dflow:finish-feature` announces that once
|
|
518
|
+
its closeout is complete.
|
|
@@ -338,5 +338,5 @@ feature from `/dflow:new-phase`.
|
|
|
338
338
|
|
|
339
339
|
After completion, summarize for the developer:
|
|
340
340
|
> "Phase {N+1} is implemented and marked completed. `_index.md` is refreshed.
|
|
341
|
-
> If another slice is needed, run `/dflow:new-phase`; if
|
|
342
|
-
> run `/dflow:finish-feature
|
|
341
|
+
> If another slice is needed, run `/dflow:new-phase`; if there is no further
|
|
342
|
+
> phase, run `/dflow:finish-feature` to close the feature out."
|