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.
Files changed (41) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/CONTRIBUTING.md +1 -0
  3. package/README.en.md +7 -4
  4. package/README.md +7 -4
  5. package/bin/dflow.js +75 -0
  6. package/docs/closeout-check.en.md +204 -0
  7. package/docs/closeout-check.md +204 -0
  8. package/docs/commands.en.md +4 -2
  9. package/docs/commands.md +4 -2
  10. package/docs/release-versioning-policy.md +1 -0
  11. package/lib/closeout-check.js +690 -0
  12. package/lib/doc-shapes.json +198 -0
  13. package/lib/init.js +17 -2
  14. package/package.json +2 -2
  15. package/templates/brownfield/references/finish-feature-flow.md +29 -26
  16. package/templates/brownfield/references/finish-feature-minimal-host.md +38 -17
  17. package/templates/brownfield/references/finish-feature-record-correction.md +45 -0
  18. package/templates/brownfield/references/git-integration.md +62 -28
  19. package/templates/brownfield/references/modify-existing-flow.md +55 -29
  20. package/templates/brownfield/references/modify-existing-follow-up.md +2 -1
  21. package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +121 -3
  22. package/templates/brownfield/references/new-feature-flow.md +49 -31
  23. package/templates/brownfield/references/new-phase-flow.md +2 -2
  24. package/templates/brownfield/references/pr-review-checklist.md +29 -4
  25. package/templates/brownfield/scaffolding/Git-principles-gitflow.md +13 -5
  26. package/templates/brownfield/scaffolding/Git-principles-trunk.md +8 -4
  27. package/templates/brownfield/templates/_index.md +17 -13
  28. package/templates/common/references/flow-rationale-registry.md +20 -4
  29. package/templates/greenfield/references/finish-feature-flow.md +29 -26
  30. package/templates/greenfield/references/finish-feature-minimal-host.md +36 -16
  31. package/templates/greenfield/references/finish-feature-record-correction.md +45 -0
  32. package/templates/greenfield/references/git-integration.md +63 -29
  33. package/templates/greenfield/references/modify-existing-flow.md +42 -27
  34. package/templates/greenfield/references/modify-existing-follow-up.md +2 -1
  35. package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +121 -3
  36. package/templates/greenfield/references/new-feature-flow.md +49 -31
  37. package/templates/greenfield/references/new-phase-flow.md +2 -2
  38. package/templates/greenfield/references/pr-review-checklist.md +28 -4
  39. package/templates/greenfield/scaffolding/Git-principles-gitflow.md +13 -5
  40. package/templates/greenfield/scaffolding/Git-principles-trunk.md +8 -4
  41. package/templates/greenfield/templates/_index.md +18 -13
@@ -53,6 +53,105 @@
53
53
  ["note","Resume Pointer","","6282e389a109b5f3"],
54
54
  ["comment","Resume Pointer","","5b3dcd00f70f0239"]
55
55
  ]
56
+ },
57
+ {
58
+ "number": 2,
59
+ "digest": "d0d9702bc58d71fb69e8faae01b209fdcca194ae83df02842e660dde035477fc",
60
+ "changes": [
61
+ {"kind":"reworded","from":["note","Checkpoint Log","","7ba7cd7e457fce40"],"to":["note","Checkpoint Log","","f0076376f5650ae1"]}
62
+ ],
63
+ "skeleton": [
64
+ ["field","spec-id"],
65
+ ["field","slug"],
66
+ ["field","status"],
67
+ ["field","created"],
68
+ ["field","branch"],
69
+ ["field","follow-up-of","optional"],
70
+ ["h2","Goals & Scope"],
71
+ ["h2","Phase Specs"],
72
+ ["column","Phase Specs","",1,1,"Phase"],
73
+ ["column","Phase Specs","",1,2,"Date"],
74
+ ["column","Phase Specs","",1,3,"Slug"],
75
+ ["column","Phase Specs","",1,4,"Status"],
76
+ ["column","Phase Specs","",1,5,"File Link"],
77
+ ["h2","Current BR Snapshot"],
78
+ ["column","Current BR Snapshot","",1,1,"BR-ID"],
79
+ ["column","Current BR Snapshot","",1,2,"Current Rule"],
80
+ ["column","Current BR Snapshot","",1,3,"First Seen (phase)"],
81
+ ["column","Current BR Snapshot","",1,4,"Last Updated (phase)"],
82
+ ["column","Current BR Snapshot","",1,5,"Status"],
83
+ ["h2","Lightweight Changes"],
84
+ ["column","Lightweight Changes","",1,1,"Date"],
85
+ ["column","Lightweight Changes","",1,2,"Tier"],
86
+ ["column","Lightweight Changes","",1,3,"Description"],
87
+ ["column","Lightweight Changes","",1,4,"Commit"],
88
+ ["h2","Checkpoint Log"],
89
+ ["column","Checkpoint Log","",1,1,"Timestamp"],
90
+ ["column","Checkpoint Log","",1,2,"Checkpoint"],
91
+ ["column","Checkpoint Log","",1,3,"Result"],
92
+ ["h2","Resume Pointer"],
93
+ ["comment","","","43746d19844776ca"],
94
+ ["note","Goals & Scope","","6bf4aa3e408ea8bc"],
95
+ ["note","Phase Specs","","5dff0b02b2fefdac"],
96
+ ["comment","Phase Specs","","60305a8c385cd40f"],
97
+ ["note","Current BR Snapshot","","6a432bf9bd86ac85"],
98
+ ["comment","Current BR Snapshot","","44a797a7db5f5224"],
99
+ ["note","Lightweight Changes","","673f6f4bda4182b3"],
100
+ ["comment","Lightweight Changes","","013165e8c56f2b73"],
101
+ ["note","Checkpoint Log","","f0076376f5650ae1"],
102
+ ["note","Resume Pointer","","6282e389a109b5f3"],
103
+ ["comment","Resume Pointer","","5b3dcd00f70f0239"]
104
+ ]
105
+ },
106
+ {
107
+ "number": 3,
108
+ "digest": "b8531afb23e1244c53e31d41a8566adfa53e68057165426b8252285aab4a1833",
109
+ "changes": [
110
+ {"kind":"reworded","from":["note","Lightweight Changes","","673f6f4bda4182b3"],"to":["note","Lightweight Changes","","3f9caac2c8fb4600"]},
111
+ {"kind":"reworded","from":["note","Checkpoint Log","","f0076376f5650ae1"],"to":["note","Checkpoint Log","","006cc4257a5c13f2"]}
112
+ ],
113
+ "skeleton": [
114
+ ["field","spec-id"],
115
+ ["field","slug"],
116
+ ["field","status"],
117
+ ["field","created"],
118
+ ["field","branch"],
119
+ ["field","follow-up-of","optional"],
120
+ ["h2","Goals & Scope"],
121
+ ["h2","Phase Specs"],
122
+ ["column","Phase Specs","",1,1,"Phase"],
123
+ ["column","Phase Specs","",1,2,"Date"],
124
+ ["column","Phase Specs","",1,3,"Slug"],
125
+ ["column","Phase Specs","",1,4,"Status"],
126
+ ["column","Phase Specs","",1,5,"File Link"],
127
+ ["h2","Current BR Snapshot"],
128
+ ["column","Current BR Snapshot","",1,1,"BR-ID"],
129
+ ["column","Current BR Snapshot","",1,2,"Current Rule"],
130
+ ["column","Current BR Snapshot","",1,3,"First Seen (phase)"],
131
+ ["column","Current BR Snapshot","",1,4,"Last Updated (phase)"],
132
+ ["column","Current BR Snapshot","",1,5,"Status"],
133
+ ["h2","Lightweight Changes"],
134
+ ["column","Lightweight Changes","",1,1,"Date"],
135
+ ["column","Lightweight Changes","",1,2,"Tier"],
136
+ ["column","Lightweight Changes","",1,3,"Description"],
137
+ ["column","Lightweight Changes","",1,4,"Commit"],
138
+ ["h2","Checkpoint Log"],
139
+ ["column","Checkpoint Log","",1,1,"Timestamp"],
140
+ ["column","Checkpoint Log","",1,2,"Checkpoint"],
141
+ ["column","Checkpoint Log","",1,3,"Result"],
142
+ ["h2","Resume Pointer"],
143
+ ["comment","","","43746d19844776ca"],
144
+ ["note","Goals & Scope","","6bf4aa3e408ea8bc"],
145
+ ["note","Phase Specs","","5dff0b02b2fefdac"],
146
+ ["comment","Phase Specs","","60305a8c385cd40f"],
147
+ ["note","Current BR Snapshot","","6a432bf9bd86ac85"],
148
+ ["comment","Current BR Snapshot","","44a797a7db5f5224"],
149
+ ["note","Lightweight Changes","","3f9caac2c8fb4600"],
150
+ ["comment","Lightweight Changes","","013165e8c56f2b73"],
151
+ ["note","Checkpoint Log","","006cc4257a5c13f2"],
152
+ ["note","Resume Pointer","","6282e389a109b5f3"],
153
+ ["comment","Resume Pointer","","5b3dcd00f70f0239"]
154
+ ]
56
155
  }
57
156
  ]
58
157
  },
@@ -599,6 +698,105 @@
599
698
  ["note","Resume Pointer","","6282e389a109b5f3"],
600
699
  ["comment","Resume Pointer","","5b3dcd00f70f0239"]
601
700
  ]
701
+ },
702
+ {
703
+ "number": 2,
704
+ "digest": "7d4a5014ba47bb069f170d5a1db2b96c9f4292bf2d87e00b104b7f6e47ad0970",
705
+ "changes": [
706
+ {"kind":"reworded","from":["note","Checkpoint Log","","359aef25b21362ca"],"to":["note","Checkpoint Log","","87725d2856e7692d"]}
707
+ ],
708
+ "skeleton": [
709
+ ["field","spec-id"],
710
+ ["field","slug"],
711
+ ["field","status"],
712
+ ["field","created"],
713
+ ["field","branch"],
714
+ ["field","follow-up-of","optional"],
715
+ ["h2","Goals & Scope"],
716
+ ["h2","Phase Specs"],
717
+ ["column","Phase Specs","",1,1,"Phase"],
718
+ ["column","Phase Specs","",1,2,"Date"],
719
+ ["column","Phase Specs","",1,3,"Slug"],
720
+ ["column","Phase Specs","",1,4,"Status"],
721
+ ["column","Phase Specs","",1,5,"File Link"],
722
+ ["h2","Current BR Snapshot"],
723
+ ["column","Current BR Snapshot","",1,1,"BR-ID"],
724
+ ["column","Current BR Snapshot","",1,2,"Current Rule"],
725
+ ["column","Current BR Snapshot","",1,3,"First Seen (phase)"],
726
+ ["column","Current BR Snapshot","",1,4,"Last Updated (phase)"],
727
+ ["column","Current BR Snapshot","",1,5,"Status"],
728
+ ["h2","Lightweight Changes"],
729
+ ["column","Lightweight Changes","",1,1,"Date"],
730
+ ["column","Lightweight Changes","",1,2,"Tier"],
731
+ ["column","Lightweight Changes","",1,3,"Description"],
732
+ ["column","Lightweight Changes","",1,4,"Commit"],
733
+ ["h2","Checkpoint Log"],
734
+ ["column","Checkpoint Log","",1,1,"Timestamp"],
735
+ ["column","Checkpoint Log","",1,2,"Checkpoint"],
736
+ ["column","Checkpoint Log","",1,3,"Result"],
737
+ ["h2","Resume Pointer"],
738
+ ["comment","","","ebf6a0dffec4e89d"],
739
+ ["note","Goals & Scope","","47f7d220a44ffc70"],
740
+ ["note","Phase Specs","","5dff0b02b2fefdac"],
741
+ ["comment","Phase Specs","","60305a8c385cd40f"],
742
+ ["note","Current BR Snapshot","","bb237977c8b6a9c8"],
743
+ ["comment","Current BR Snapshot","","44a797a7db5f5224"],
744
+ ["note","Lightweight Changes","","5194f717a8955b59"],
745
+ ["comment","Lightweight Changes","","013165e8c56f2b73"],
746
+ ["note","Checkpoint Log","","87725d2856e7692d"],
747
+ ["note","Resume Pointer","","6282e389a109b5f3"],
748
+ ["comment","Resume Pointer","","5b3dcd00f70f0239"]
749
+ ]
750
+ },
751
+ {
752
+ "number": 3,
753
+ "digest": "6a45d40b5f5cdefa1afcdca62cb8f5b320dc6da9aacd6ff42e34d059c5683319",
754
+ "changes": [
755
+ {"kind":"reworded","from":["note","Lightweight Changes","","5194f717a8955b59"],"to":["note","Lightweight Changes","","5d6225b2a04687b3"]},
756
+ {"kind":"reworded","from":["note","Checkpoint Log","","87725d2856e7692d"],"to":["note","Checkpoint Log","","f3336d6c95603aa2"]}
757
+ ],
758
+ "skeleton": [
759
+ ["field","spec-id"],
760
+ ["field","slug"],
761
+ ["field","status"],
762
+ ["field","created"],
763
+ ["field","branch"],
764
+ ["field","follow-up-of","optional"],
765
+ ["h2","Goals & Scope"],
766
+ ["h2","Phase Specs"],
767
+ ["column","Phase Specs","",1,1,"Phase"],
768
+ ["column","Phase Specs","",1,2,"Date"],
769
+ ["column","Phase Specs","",1,3,"Slug"],
770
+ ["column","Phase Specs","",1,4,"Status"],
771
+ ["column","Phase Specs","",1,5,"File Link"],
772
+ ["h2","Current BR Snapshot"],
773
+ ["column","Current BR Snapshot","",1,1,"BR-ID"],
774
+ ["column","Current BR Snapshot","",1,2,"Current Rule"],
775
+ ["column","Current BR Snapshot","",1,3,"First Seen (phase)"],
776
+ ["column","Current BR Snapshot","",1,4,"Last Updated (phase)"],
777
+ ["column","Current BR Snapshot","",1,5,"Status"],
778
+ ["h2","Lightweight Changes"],
779
+ ["column","Lightweight Changes","",1,1,"Date"],
780
+ ["column","Lightweight Changes","",1,2,"Tier"],
781
+ ["column","Lightweight Changes","",1,3,"Description"],
782
+ ["column","Lightweight Changes","",1,4,"Commit"],
783
+ ["h2","Checkpoint Log"],
784
+ ["column","Checkpoint Log","",1,1,"Timestamp"],
785
+ ["column","Checkpoint Log","",1,2,"Checkpoint"],
786
+ ["column","Checkpoint Log","",1,3,"Result"],
787
+ ["h2","Resume Pointer"],
788
+ ["comment","","","ebf6a0dffec4e89d"],
789
+ ["note","Goals & Scope","","47f7d220a44ffc70"],
790
+ ["note","Phase Specs","","5dff0b02b2fefdac"],
791
+ ["comment","Phase Specs","","60305a8c385cd40f"],
792
+ ["note","Current BR Snapshot","","bb237977c8b6a9c8"],
793
+ ["comment","Current BR Snapshot","","44a797a7db5f5224"],
794
+ ["note","Lightweight Changes","","5d6225b2a04687b3"],
795
+ ["comment","Lightweight Changes","","013165e8c56f2b73"],
796
+ ["note","Checkpoint Log","","f3336d6c95603aa2"],
797
+ ["note","Resume Pointer","","6282e389a109b5f3"],
798
+ ["comment","Resume Pointer","","5b3dcd00f70f0239"]
799
+ ]
602
800
  }
603
801
  ]
604
802
  },
package/lib/init.js CHANGED
@@ -5765,7 +5765,12 @@ async function listShapeScopeDocuments(specsRoot) {
5765
5765
  return { docs: docs.sort(), unreadable };
5766
5766
  }
5767
5767
 
5768
- async function checkDocumentShapes(cwd, findings) {
5768
+ // The registry, and whether this package can trust it: the entries' own shape,
5769
+ // and coverage of every template the shape check covers. Shared with
5770
+ // `dflow check-closeout` (PROPOSAL-105), which derives its spec set from the same
5771
+ // registry and has to stop, not skip, when the package is damaged — a registry
5772
+ // missing one template's entry still reads as valid JSON.
5773
+ async function readDocShapesRegistry() {
5769
5774
  const packageDamage = [];
5770
5775
  let registry = null;
5771
5776
  try {
@@ -5818,6 +5823,11 @@ async function checkDocumentShapes(cwd, findings) {
5818
5823
  registry = null;
5819
5824
  }
5820
5825
  }
5826
+ return { registry, packageDamage };
5827
+ }
5828
+
5829
+ async function checkDocumentShapes(cwd, findings) {
5830
+ const { registry, packageDamage } = await readDocShapesRegistry();
5821
5831
 
5822
5832
  // The current number of every template: its own marker, in THIS package.
5823
5833
  const current = new Map();
@@ -6809,5 +6819,10 @@ module.exports = {
6809
6819
  // fixture removed one of the three structural signals and stayed on the
6810
6820
  // single-candidate path while claiming to test the other, so the test asserts
6811
6821
  // the precondition directly instead of assuming it.
6812
- inferProjectBundleEdition
6822
+ inferProjectBundleEdition,
6823
+ // Shared with `dflow check-closeout` (PROPOSAL-105): the registry it derives its
6824
+ // spec set from, read and trusted by the same rules doctor uses, and the line a
6825
+ // document copied whole from a projected template starts with.
6826
+ readDocShapesRegistry,
6827
+ WORKFLOW_BUNDLE_GENERATED_MARKER
6813
6828
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dflow-sdd-ddd",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Spec-first SDD/DDD workflow kit for AI-assisted development",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "homepage": "https://github.com/weilung/dflow-sdd-ddd#readme",
41
41
  "scripts": {
42
- "test": "node test/smoke.mjs && node test/skill-default.mjs && node test/registry-parity.mjs && node test/agent-inject.mjs && node test/upgrade-drift.mjs && node test/doc-shapes.mjs && node test/bundle-guards.mjs && node test/lightweight-families.mjs && node test/render.mjs"
42
+ "test": "node test/smoke.mjs && node test/skill-default.mjs && node test/registry-parity.mjs && node test/agent-inject.mjs && node test/upgrade-drift.mjs && node test/doc-shapes.mjs && node test/bundle-guards.mjs && node test/lightweight-families.mjs && node test/render.mjs && node test/closeout-check.mjs"
43
43
  },
44
44
  "license": "AGPL-3.0-or-later",
45
45
  "publishConfig": {
@@ -26,9 +26,10 @@ state, archives the feature directory, and emits a Git-strategy-neutral
26
26
  stance — the AI helps at natural checkpoints, you keep the final say.
27
27
  - The BC-layer sync in Step 3 **reuses the existing documentation-sync
28
28
  mechanism** from `new-feature-flow` (§ 8.3) and `modify-existing-flow`
29
- (Step 6.3) — it does not introduce a new sync flow. Treat it as "lift
30
- that step out of the per-phase checklist and run it once at feature
31
- closeout, with the `_index.md` Current BR Snapshot as input."
29
+ (Step 6.3) — it does not introduce a new sync flow. § 8.3 and Step 6.3
30
+ sync when the work they record completes; Step 3 runs the same mechanism
31
+ once more at feature closeout, with the `_index.md` Current BR Snapshot as
32
+ input.
32
33
 
33
34
  **Step Gates** in this flow (stop-and-confirm before proceeding):
34
35
  - Step 1 → Step 2 (validation passed → flip status)
@@ -160,8 +161,9 @@ Step 4's post-commit verification, and to Step 5's Integration Summary fields.
160
161
  carries none. Decide from the artifact, not from a
161
162
  declaration: "the feature is intentionally no-BR" is a claim, and the
162
163
  record is what settles it. A classic BR-delta spec carrying ADDED /
163
- MODIFIED / RENAMED entries **and** an empty Snapshot means finalization
164
- never refreshed it (`modify-existing-flow.md` Step 1.7) and **blocks**.
164
+ MODIFIED / RENAMED entries **and** an empty Snapshot means the
165
+ completion checklist never refreshed it (`modify-existing-flow.md`
166
+ Step 6.3, before checkpoint 1) and **blocks**.
165
167
 
166
168
  If any check fails:
167
169
  > "Cannot finish feature `{SPEC-ID}-{slug}` yet — {N} validation issues
@@ -376,10 +378,10 @@ Deltas are the audit trail. **Cross-reference each hosted lightweight-spec's
376
378
  recorded delta the same way** — on any host shape, for the reason above.
377
379
 
378
380
  > Note: this step does NOT read individual phase-specs to re-derive the BR
379
- > set — that work was already reconciled by `/dflow:new-phase` Step 7 each
380
- > time a phase completed. We trust `_index.md` Current BR Snapshot as the
381
- > feature-level truth here. If the developer finds drift between Snapshot
382
- > and the phase-specs, fix `_index.md` first, then re-run
381
+ > set. `/dflow:new-feature` § 8.4 and `/dflow:new-phase` Step 7 reconcile the
382
+ > Snapshot when they complete a phase, and we trust `_index.md` Current BR
383
+ > Snapshot as the feature-level truth here. If the developer finds drift
384
+ > between Snapshot and the phase-specs, fix `_index.md` first, then re-run
383
385
  > `/dflow:finish-feature`.
384
386
 
385
387
  Also update `migration/tech-debt.md` / `models.md` / `glossary.md` /
@@ -486,13 +488,13 @@ Then, in this order:
486
488
 
487
489
  1. **Record the checkpoint row first.** Write one row in the moved
488
490
  `_index.md` Checkpoint Log — `closeout | committed` for Y, `closeout |
489
- skipped` for N. The closeout row carries **no commit hash**: the closeout
490
- commit cannot contain its own hash. Trace it later via
491
+ skipped` for N. The closeout row carries **no commit hash**: no later
492
+ commit of this host carries it. Trace it later via
491
493
  `git log -1 -- dflow/specs/features/completed/{SPEC-ID}-{slug}` (or the
492
- optional `Dflow-Checkpoint` trailer). The "hash only after success" rule
493
- still applies to spec / implementation rows — closeout is the documented
494
- exception (see `references/git-integration.md` § Commit Checkpoints,
495
- Branch Gate & AI Commits).
494
+ optional `Dflow-Checkpoint` trailer). On any other checkpoint row, a
495
+ `committed ({hash})` Result is written after its commit and carried by the
496
+ host's next commit (see `references/git-integration.md` § Commit
497
+ Checkpoints, Branch Gate & AI Commits).
496
498
  **Backfill any unfilled hosted `Commit` cell in the same edit** — a hosted row
497
499
  waits for the host's *next* commit and this is it. **Unfilled means empty *or*
498
500
  holding a placeholder** — `{hash}`, `{pending}`, `(待 commit)`, anything that
@@ -526,10 +528,11 @@ Then, in this order:
526
528
  `migration/tech-debt.md`) — Step 3 is **skipped entirely for a no-BC host**
527
529
  (and for a baseline host), so this half is empty there; **and**
528
530
  **(b)** the **documentation-sweep step of the flow that produced *this
529
- change*** — take the paths from that step, not from a list kept here. It runs
530
- *after* that flow's implementation checkpoint and *before* closeout, so **that
531
- flow** leaves its deltas uncommitted; a later phase's own checkpoints may have
532
- committed them since, and staging an already-committed path is a no-op.
531
+ change*** — take the paths from that step, not from a list kept here. A
532
+ commit may already have carried them — `modify-existing-flow.md`'s
533
+ checkpoint 1 carries its own sweep, and a later phase's checkpoint may have
534
+ carried a `new-feature-flow.md` sweep — and staging an already-committed path
535
+ is a no-op, so stage them either way.
533
536
  Those sweeps reach
534
537
  Domain-layer documents under `dflow/specs/domain/`, plus the **global**
535
538
  documents `glossary.md`, `domain/analysis.md` and `migration/tech-debt.md`,
@@ -571,7 +574,8 @@ Then, in this order:
571
574
  admitted. On a **phase-bearing** host there is **no allow-list at all** —
572
575
  that check is minimal-host-only and lives in that branch file — so read the
573
576
  sweep directly and **do not go looking for a list that host never produced.**
574
- Read each delta (`git diff -- {path}`) and scope every one to *this change*;
577
+ Read each delta (`git diff HEAD -- {path}`, which includes what is already
578
+ staged) and scope every one to *this change*;
575
579
  staging only "what Step 3 wrote" leaves a no-BC host's global delta dirty and
576
580
  the post-commit clean-tree check fails.
577
581
  3. **Commit (Y) or stop (N).** For Y the AI commits. If a pre-commit hook
@@ -621,10 +625,9 @@ every item:
621
625
  only when the baseline became unreadable *during* closeout.
622
626
  Step 1 blocks unless every
623
627
  spec in the host already reads `status: completed`, so those flips are
624
- already **in** the baseline whichever step made them: a **minimal** host's
625
- come from `modify-existing-flow.md` Step 1.7's finalization, a
626
- **phase-bearing** host's from its phases completing — no phase-bearing
627
- host runs Step 1.7, whichever flow opened it. Either way the
628
+ already **in** the baseline whichever step made them: a lightweight-spec's
629
+ comes from `modify-existing-flow.md` Step 6.3, a phase-spec's from its
630
+ phase completing. Either way the
628
631
  flips are not differences this check admits; they are part of what it
629
632
  compares against. (They are differences only from the *pre-flip* record,
630
633
  which is not the baseline.)
@@ -756,8 +759,8 @@ itself, state in the conversation *how* Step 4's post-commit verification
756
759
  reached its result — not that it passed, but how it was computed:
757
760
 
758
761
  1. **The baseline** — the tree Step 1 read, and which step put each spec's
759
- `status: completed` flip into it (Step 1.7's finalization on a minimal host;
760
- the phases completing on a phase-bearing one, which never runs Step 1.7).
762
+ `status: completed` flip into it (`modify-existing-flow.md` Step 6.3 for a
763
+ lightweight-spec; the phase completing for a phase-spec).
761
764
  2. **The differences you derived, each with the step that ordered it** —
762
765
  Step 2, Step 4's terminal Resume Pointer write, or Step 4 instruction 1. This
763
766
  is the set the check *derives* instead of listing, so printing it is what
@@ -185,15 +185,17 @@ A `✗` here stops closeout there, on the same terms.
185
185
  `Commit` must still name the **same single documentation commit**.
186
186
  - [ ] **Minimal host (zero-phase) only** — **nothing that constitutes the change
187
187
  itself is still uncommitted.** This is deliberately not "the host
188
- directory is clean": **checkpoint 1 carries the change, the closeout
189
- commit carries the record the flow writes afterwards.** Checkpoint 1 sits
190
- at `modify-existing-flow.md`'s Step 5 → Step 6 gate and holds the change
191
- itself — for a **T2** its lightweight-spec plus the implementation source,
192
- for a **T3** its `_index.md` row plus the implementation source, and for a
193
- **baseline** host the capture itself, which *is* that host's
194
- change. What the flow writes *after* that gate — Step 6's completion
195
- checklist and Step 1.7's "Finalize + close" — is derived record and rides
196
- into the closeout commit.
188
+ directory is clean": **checkpoint 1 carries the change and the record
189
+ Step 6 writes; the closeout commit carries what the flow writes after
190
+ checkpoint 1.** Checkpoint 1 is offered at the end of
191
+ `modify-existing-flow.md`'s Step 6 (§ 6.5) and holds the change itself —
192
+ for a **T2** its lightweight-spec plus the implementation source, for a
193
+ **T3** its `_index.md` row plus the implementation source, and for a
194
+ **baseline** host the capture itself, which *is* that host's change —
195
+ together with Step 6's completion checklist. What the flow writes *after*
196
+ checkpoint 1 — Step 1.7's "Finalize + close" — is derived record and
197
+ rides into the closeout commit, and so may a correction to Step 6's
198
+ record made after checkpoint 1.
197
199
  **A post-hoc host (Step 1.8) inverts the source half, and this is where
198
200
  the reconciliation contract is enforced.** Its change is the *already
199
201
  merged* hotfix; checkpoint 1 is the **documentation** commit. So that
@@ -236,8 +238,9 @@ A `✗` here stops closeout there, on the same terms.
236
238
  to both phase-spec and lightweight-spec"): ticking the tasks this change
237
239
  completed and labelling each unchecked one as follow-up (6.1), and — when
238
240
  the developer accepted the offer — collapsing or removing the section
239
- (6.2). On a minimal host that checklist necessarily runs *after*
240
- checkpoint 1, so these edits are uncommitted here by construction;
241
+ (6.2). That checklist runs before checkpoint 1, so these edits are
242
+ normally committed already; this admits a correction to them made after
243
+ checkpoint 1;
241
244
  (iii) the Domain-layer documents **this change's Step 6.3 sweep** updates
242
245
  — under `dflow/specs/domain/`, plus
243
246
  `dflow/specs/migration/tech-debt.md` — scoped to *this change's* delta.
@@ -251,11 +254,24 @@ A `✗` here stops closeout there, on the same terms.
251
254
  and therefore still qualify under (iii). **(iii) never covers a baseline
252
255
  host** either — its capture *is* the change, and is blocked
253
256
  above.
254
- Read each delta (`git diff -- {path}`) — do not infer it from the
255
- filename. **The list is closed** — if a later change adds another
257
+ Read each delta with `git diff HEAD -- {path}` — plain `git diff` hides
258
+ what is already staged — and do not infer it from the filename.
259
+ **The list is closed** — if a later change adds another
256
260
  finalization field, add it here explicitly; "a host file is dirty" is never
257
261
  on its own a reason to pass. (Unrelated work in progress elsewhere is
258
262
  fine; say which files you judged unrelated.)
263
+ **Checkpoint 1's own record, corrected after checkpoint 1, is outside the
264
+ list** — the spec's content beyond (ii)'s edits, a row's own text, a
265
+ document a baseline capture wrote, or the reverse-link row a follow-up
266
+ wrote into its original's `_index.md`. It blocks: the closeout commit
267
+ does not carry checkpoint 1's content. The dispatch right after this
268
+ item gives the repair.
269
+
270
+ **Open `references/finish-feature-record-correction.md` and follow it there.**
271
+ Do this only when the check above blocked on a correction to checkpoint 1's own
272
+ record: the repair depends on where checkpoint 1 stands now, and that file gives
273
+ it for each case. Otherwise go on to the next check.
274
+
259
275
  - [ ] **Minimal host (zero-phase), no-BC only** — **the host did not commit a
260
276
  bounded context it does not have.** This file's `nothing that constitutes
261
277
  the change itself is still uncommitted` check reads the *working
@@ -330,10 +346,11 @@ A `✗` here stops closeout there, on the same terms.
330
346
  assertion.
331
347
  The plausibility conditions, all required: the
332
348
  `reconciled ({merged-hotfix-hash})` value passes hash evidence — (a) and
333
- (b) as usual, and for **(c)** its diff touches the implementation paths
334
- the T2 lightweight-spec or the T3 row **declares** (Step 1.7 requires that
335
- declaration; an artifact naming none leaves (c) nothing to compare and
336
- **blocks** rather than passing vacuously). It must also **differ**
349
+ (b) as usual, and for **(c)** its diff touches **at least one** of the
350
+ implementation paths the T2 lightweight-spec or the T3 row **declares**
351
+ (Step 1.7 requires that declaration; an artifact naming none leaves (c)
352
+ nothing to compare and **blocks** rather than passing vacuously). It
353
+ must also **differ**
337
354
  from the Lightweight Changes row's documentation-commit hash (different
338
355
  provenance; see Step 1.8). The per-tier trace must exist too: a **T2**
339
356
  carries `hotfix-branch:` in its lightweight-spec frontmatter, a **T3** has
@@ -345,6 +362,10 @@ A `✗` here stops closeout there, on the same terms.
345
362
  for a **T3**. An uncited hash **blocks** closeout: it leaves pr-review
346
363
  nothing to confirm against, and this gate is not a substitute for that
347
364
  confirmation.
365
+ **When (b) fails for the `reconciled (...)` hash, do not report only
366
+ "not an ancestor".** Open `references/modify-existing-post-hoc-hotfix.md`
367
+ item 6: it names the causes and the repair for each; report the one that
368
+ is true.
348
369
 
349
370
  > **Zero-phase minimal host (`modify-existing-flow.md` Step 1.7 / the Step 1.6
350
371
  > minimal variant / Step 1.8's post-hoc hotfix, whose linkage resolves to one of
@@ -0,0 +1,45 @@
1
+ # Correcting Checkpoint 1's Own Record — Brownfield Progressive Extraction
2
+
3
+ Branch file of `references/finish-feature-minimal-host.md`. It **adds** the
4
+ repair for one case that file's working-tree check blocks; it does not restate
5
+ or override anything in that file.
6
+
7
+ **You are here because** that file's `nothing that constitutes the change
8
+ itself is still uncommitted` check blocked on a correction to checkpoint 1's
9
+ own record — it owns that judgement — or because
10
+ `references/modify-existing-post-hoc-hotfix.md` item 6 found that a post-hoc
11
+ record names a different fix.
12
+
13
+ The correction belongs in checkpoint 1 itself, and whether it can go there
14
+ depends on where checkpoint 1 stands now. Report the case that is true and give
15
+ the developer its repair:
16
+
17
+ - **Not pushed, and checkpoint 1 is `HEAD`** (`git rev-parse HEAD` prints
18
+ checkpoint 1's hash) — first set every entry that holds checkpoint 1's hash
19
+ back to what checkpoint 1 has (`git show HEAD:{path}`); the refill below
20
+ writes them again. Then stage the correction alone (in `_index.md`, `git add
21
+ -p` only its hunk: the Resume Pointer rides the closeout commit), check that
22
+ `git diff --cached` shows nothing else, and `git commit --amend`. Then write
23
+ the new hash into every entry that names checkpoint 1 — the Checkpoint Log
24
+ `committed (...)` and each row's `Commit` cell. An entry left on the old hash
25
+ fails hash evidence (b).
26
+ - **Not pushed, but a later commit sits on top of checkpoint 1** — stop:
27
+ rewriting an earlier commit is the developer's to do.
28
+ - **Already pushed** — stop and leave it to the developer. Rewriting a pushed
29
+ commit is the team's call (refill the entries as above if they do). The other
30
+ way is to commit the correction on its own: add no Checkpoint Log row for it
31
+ (a second row blocks), and ask for it to be named in the PR description — it
32
+ departs from the two-commit lifecycle, and
33
+ `references/pr-review-checklist.md`'s whole-history item sees it only when it
34
+ touches this host's directory.
35
+
36
+ **A post-hoc host's `reconciled (...)`** names the hotfix, not checkpoint 1, so
37
+ refilling after an amend leaves it as it is — **unless the correction changes
38
+ which fix the record names** (`references/modify-existing-post-hoc-hotfix.md`
39
+ item 6, "The record names a different fix"). Then `reconciled (...)` names the
40
+ wrong fix too. Item 3 wrote it before checkpoint 1, so checkpoint 1 carries it:
41
+ correct it to the right fix's commit — the one item 3 says to record — as part
42
+ of the same correction, whichever way that lands (the amend, the developer's
43
+ rewrite, or the correction's own commit). Put that commit through item 6's test
44
+ before closeout continues; that item gives the repair if (b) fails for it as
45
+ well.