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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Step 6: Reverse-Update Follow-up Tracking — Greenfield Clean Architecture
|
|
2
|
+
|
|
3
|
+
Branch file of `references/finish-feature-flow.md`. It **adds** the follow-up
|
|
4
|
+
closing rules; it does not restate or override anything in that flow.
|
|
5
|
+
|
|
6
|
+
**You are here because** that flow's Step 6 dispatched you — it owns whether
|
|
7
|
+
this route applies.
|
|
8
|
+
|
|
9
|
+
For features that were created as follow-ups of an earlier completed
|
|
10
|
+
feature, update the Follow-up Tracking table of **every** original this host's
|
|
11
|
+
`follow-up-of` names — one parent, or several when the field is a YAML array.
|
|
12
|
+
For each of them:
|
|
13
|
+
|
|
14
|
+
1. Locate `dflow/specs/features/completed/{原 SPEC-ID}-{原 slug}/_index.md`
|
|
15
|
+
2. Find the Follow-up Tracking section's row for this feature's SPEC-ID
|
|
16
|
+
3. Flip Status → `completed`
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# The AI makes the edit and may offer to commit it (Y / N), per the AI commit policy
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This flip is a **sanctioned post-completion mutation, not a checkpoint** —
|
|
23
|
+
the follow-up host is already closed out and archived, so it is recorded in
|
|
24
|
+
**no** Checkpoint Log (neither this original feature's nor the follow-up
|
|
25
|
+
host's). It **must still be committed**, though: the flip is a real edit to
|
|
26
|
+
the original feature's `_index.md`. Require the tracking commit — the AI offers
|
|
27
|
+
it (Y / N); if the developer declines or the commit fails, **stop and do not
|
|
28
|
+
declare closeout complete** until the flip is committed. After it commits,
|
|
29
|
+
verify **per original** with
|
|
30
|
+
`git show HEAD:dflow/specs/features/completed/{原 SPEC-ID}-{原 slug}/_index.md`
|
|
31
|
+
that the Follow-up Tracking row now reads `completed` in the **committed** blob,
|
|
32
|
+
and that `git status --short` is clean. **Then check the commit itself, two ways
|
|
33
|
+
— neither replaces the other.**
|
|
34
|
+
**(1) Its full path set** (`git show --stat HEAD`) contains **only** the
|
|
35
|
+
`_index.md` of the originals this host's `follow-up-of` names: nothing under the
|
|
36
|
+
archived follow-up host — that would be a third host-mutating commit, which the
|
|
37
|
+
two-checkpoint lifecycle does not allow — and nothing else at all.
|
|
38
|
+
**(2) Its patch per original** (`git show HEAD -- {that path}`) carries **that
|
|
39
|
+
row's own transition** — the `in-progress` line removed, the `completed` line
|
|
40
|
+
added — and **no Checkpoint Log change**: this flip enters *neither* ledger, so
|
|
41
|
+
a Checkpoint Log row appearing in a parent is a violation even when the flip
|
|
42
|
+
itself is correct.
|
|
43
|
+
Why both: the blob proves the final state, not who wrote it — a commit that
|
|
44
|
+
merely edits other text in parent A while flipping parent B leaves both blobs
|
|
45
|
+
reading `completed` with the flips split across two commits — and the patch in
|
|
46
|
+
(2) is **path-filtered**, so it cannot see what else the commit touched. Only
|
|
47
|
+
(1) can. The commit message references the
|
|
48
|
+
follow-up host's SPEC-ID. Where there are several originals, flip them **in one
|
|
49
|
+
commit** — for a minimal follow-up host that keeps this the single post-closeout
|
|
50
|
+
tracking commit named in `modify-existing-flow.md` Step 1.6's minimal variant.
|
|
51
|
+
|
|
52
|
+
After the update:
|
|
53
|
+
> "Follow-up Tracking row updated to Status = `completed` in
|
|
54
|
+
> `{原 SPEC-ID}-{原 slug}/_index.md` (and every other original listed).
|
|
55
|
+
> Closeout complete."
|
|
56
|
+
|
|
57
|
+
The connection is bidirectional and weakly redundant: the new feature's
|
|
58
|
+
`follow-up-of` field is the authoritative source; the old feature's
|
|
59
|
+
Follow-up Tracking row is a derived index. If they ever disagree, trust
|
|
60
|
+
`follow-up-of`.
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Minimal Host (Zero-Phase) Closeout — Greenfield Clean Architecture
|
|
2
|
+
|
|
3
|
+
Branch file of `references/finish-feature-flow.md`. It **adds** the checks and
|
|
4
|
+
field rules a minimal (zero-phase) host takes; it does not restate or override
|
|
5
|
+
anything in that flow.
|
|
6
|
+
|
|
7
|
+
**You are here when** `references/finish-feature-flow.md` Step 1's minimal-host
|
|
8
|
+
selector sent you — it states the condition; this file does not restate it.
|
|
9
|
+
|
|
10
|
+
**Keep this file for the whole closeout.** It adds to four of that flow's
|
|
11
|
+
steps — Step 1, Step 3, Step 4's post-commit verification, and Step 5 — and each
|
|
12
|
+
of those places points back here.
|
|
13
|
+
|
|
14
|
+
## Hash evidence
|
|
15
|
+
|
|
16
|
+
**Hash evidence** (several checks in this file use this test). A hash recorded in
|
|
17
|
+
`_index.md` passes *hash evidence* when all three hold:
|
|
18
|
+
- **(a) it is a commit** — `git cat-file -t {hash}` reports `commit`;
|
|
19
|
+
- **(b) it is on this branch** — `git merge-base --is-ancestor {hash} HEAD`
|
|
20
|
+
succeeds;
|
|
21
|
+
- **(c) its diff carries what the record claims** — the commit's **changed
|
|
22
|
+
paths** include the artifact that row or checkpoint points at; each check
|
|
23
|
+
in this file names which. **Tree presence is not enough**: every commit
|
|
24
|
+
inherits the files an earlier one added, so a commit that only touched the
|
|
25
|
+
implementation would otherwise satisfy (c) for an artifact it never wrote. (a)
|
|
26
|
+
and (b) alone prove only that *some* earlier commit exists on this branch; (c)
|
|
27
|
+
is what ties it to the record.
|
|
28
|
+
|
|
29
|
+
## Step 1 — additional validation checks
|
|
30
|
+
|
|
31
|
+
Run these as part of `references/finish-feature-flow.md` Step 1's checklist, in
|
|
32
|
+
the order given here, and report `✓` / `✗` for each exactly as that flow says.
|
|
33
|
+
A `✗` here stops closeout there, on the same terms.
|
|
34
|
+
|
|
35
|
+
- [ ] **Minimal host (zero-phase) only** — every row in `_index.md` Lightweight
|
|
36
|
+
Changes has a **non-empty `Commit` cell that passes hash evidence**; for
|
|
37
|
+
(c), the commit carries that row's own work: a **T2**'s
|
|
38
|
+
`lightweight-*.md` / `BUG-*.md` file, or for a **T3** an `_index.md` that
|
|
39
|
+
already carries this row at that hash — Step 1.7 writes every row *before*
|
|
40
|
+
checkpoint 1, which is what makes that provable here. This applies to
|
|
41
|
+
**T2 and T3 rows alike**. Three failures, all blocking — **report the one
|
|
42
|
+
that is true**, because the message is the developer's only clue about what
|
|
43
|
+
to do next: an **empty** cell means that change is not committed yet; a
|
|
44
|
+
cell holding a **placeholder** (`{hash}`, `{pending}`, `(待 commit)` —
|
|
45
|
+
anything `git cat-file -t` cannot resolve) means the cell was **never
|
|
46
|
+
filled in**, which is a different repair and may well have a commit sitting
|
|
47
|
+
there unrecorded; a **resolvable** value that fails (a)–(c) means the hash
|
|
48
|
+
is the wrong one. ⚠ Do not collapse the middle case into the first.
|
|
49
|
+
(`modify-existing-flow.md` Step 1.7 "Finalize + close" is where the
|
|
50
|
+
**cell** gets backfilled once its commit exists.)
|
|
51
|
+
**Deliberately not run on a phase-bearing host.** Those hosts keep
|
|
52
|
+
`references/finish-feature-flow.md` Step 1's two `Tier = T2` checks, which
|
|
53
|
+
never covered a T3 row anyway — a T3 has
|
|
54
|
+
no spec file in Dflow (`references/git-integration.md` § Gate Checks by
|
|
55
|
+
Branch Type).
|
|
56
|
+
- [ ] **Minimal host (zero-phase) only** — the Lightweight Changes table has
|
|
57
|
+
**at least one row** (a T2 or T3 row). An empty Phase Specs table **and**
|
|
58
|
+
an empty Lightweight Changes table is an **empty host** → reject closeout.
|
|
59
|
+
- [ ] **Minimal host (zero-phase) only** — **every spec file in the host
|
|
60
|
+
directory is named by a row.** The row-driven checks — this file's
|
|
61
|
+
`Commit` cell check and `references/finish-feature-flow.md` Step 1's two
|
|
62
|
+
`Tier = T2` items — walk rows → files, so a spec file that no row names is
|
|
63
|
+
never examined by them; this item closes
|
|
64
|
+
the other direction. A `phase-spec-*` always fails (the Phase Specs table
|
|
65
|
+
is empty by definition); a `lightweight-*.md` / `BUG-*.md` with no
|
|
66
|
+
Tier = T2 row fails the same way. A **T3-only** host carries no spec file
|
|
67
|
+
at all, so any spec file there fails this check.
|
|
68
|
+
- [ ] **Minimal host (zero-phase) only** — the Checkpoint Log shows a
|
|
69
|
+
**committed** first checkpoint before this closeout: Checkpoint
|
|
70
|
+
`implementation` with Result `committed ({hash})` (normal) or `reconciled
|
|
71
|
+
({merged-hotfix-hash})` (hotfix post-hoc). A first checkpoint still
|
|
72
|
+
reading `skipped` or `failed` **blocks** closeout — but they are not the
|
|
73
|
+
same problem. `failed` means the commit was attempted and did not land:
|
|
74
|
+
the work is genuinely uncommitted and has to land. `skipped` means only
|
|
75
|
+
that **the AI's offer was declined** (`references/git-integration.md`
|
|
76
|
+
§ Commit Checkpoints), *not* that no commit exists — the developer may
|
|
77
|
+
have made it themselves, which leaves the ledger **incomplete rather than
|
|
78
|
+
final**. Complete it: `modify-existing-flow.md` Step 1.7's "Finalize +
|
|
79
|
+
close" backfills the row to `committed ({hash})` with the developer's real
|
|
80
|
+
hash. Do **not** waive this check for a `skipped` row, and do **not** write
|
|
81
|
+
a hash you have not verified.
|
|
82
|
+
- [ ] **Minimal host (zero-phase) only** — **the Checkpoint Log carries exactly
|
|
83
|
+
one row at this point.** A minimal host takes exactly two checkpoints and
|
|
84
|
+
the second is the closeout row `references/finish-feature-flow.md` Step 4
|
|
85
|
+
instruction 1 adds, so before closeout there is exactly one: the first
|
|
86
|
+
checkpoint the preceding item validated. Any second pre-closeout row
|
|
87
|
+
**blocks** — **report the one that is true**, because the repairs differ.
|
|
88
|
+
What separates them is **whether the row records a checkpoint this host
|
|
89
|
+
actually reached**, not what its cells hold. A row that records none is
|
|
90
|
+
repaired **by deleting it**, however it is filled in: a `closeout` row is
|
|
91
|
+
one, because no closeout has run yet — Step 4 instruction 1 writes it at
|
|
92
|
+
closeout — and so is any row carried over from `templates/_index.md`'s
|
|
93
|
+
example table. A row that does record a reached checkpoint — a second
|
|
94
|
+
`implementation`, a leftover from an abandoned attempt, or one this list
|
|
95
|
+
does not name — says the host did not take the two-commit lifecycle, and
|
|
96
|
+
that is settled with the developer, not by deleting a line. A failed or
|
|
97
|
+
declined attempt does **not** add a row: both are recorded by editing the
|
|
98
|
+
existing one in place.
|
|
99
|
+
This counts the rows in **this host's own table** — it is not
|
|
100
|
+
the whole-history assertion, which stays with
|
|
101
|
+
`references/pr-review-checklist.md`.
|
|
102
|
+
- [ ] **Minimal host (zero-phase) only** — **that first commit is real, and it
|
|
103
|
+
is this host's.** The Checkpoint Log is prose; verify the hash behind it
|
|
104
|
+
against **hash evidence**. Take the hash that stands for checkpoint 1 —
|
|
105
|
+
for a **normal** host the `committed ({hash})` value; for a **hotfix
|
|
106
|
+
post-hoc** host the Lightweight Changes row's `Commit` cell (**not** the
|
|
107
|
+
`reconciled (...)` hash, which names the already-merged hotfix). For (c),
|
|
108
|
+
touching *some* path under
|
|
109
|
+
`dflow/specs/features/active/{SPEC-ID}-{slug}/` is **not enough** — a
|
|
110
|
+
stray host-open commit does that much while the work is still
|
|
111
|
+
uncommitted. Require the tier's artifact **among the commit's changed
|
|
112
|
+
paths** — (c) is what this commit wrote, not what its tree contains: a
|
|
113
|
+
**T2**'s `lightweight-*.md` / `BUG-*.md` spec file, or for a **T3** an
|
|
114
|
+
`_index.md` the commit **changed** *and* which, as committed at that hash,
|
|
115
|
+
already carries this change's Lightweight Changes row — `git show --stat
|
|
116
|
+
{hash}` **and** `git show
|
|
117
|
+
{hash}:dflow/specs/features/active/{SPEC-ID}-{slug}/_index.md`, both, not
|
|
118
|
+
either. Any of (a)–(c) failing **blocks** closeout.
|
|
119
|
+
- [ ] **Minimal host (zero-phase) only** — **checkpoint 1 is *one* commit, and
|
|
120
|
+
every row names it.** For a **normal** host the Checkpoint Log's
|
|
121
|
+
`committed ({hash})` and **every** Lightweight Changes row's `Commit` must
|
|
122
|
+
be the **same** hash, and that commit's diff must **touch the
|
|
123
|
+
implementation paths** its lightweight-spec or rows describe. Step 1.7
|
|
124
|
+
requires the artifact to **declare** those paths; an artifact naming none
|
|
125
|
+
leaves nothing to compare against, so a missing declaration **blocks** —
|
|
126
|
+
it never passes vacuously.
|
|
127
|
+
Assert the **equality itself**, not merely that each value passes hash
|
|
128
|
+
evidence on its own: two hashes that each resolve, are each reachable, and
|
|
129
|
+
each contain some named artifact describe a **three**-commit host —
|
|
130
|
+
host+spec at A, implementation at B, closeout at C — which clears every
|
|
131
|
+
other check on this list while breaking the two-commit lifecycle.
|
|
132
|
+
**Exempt — post-hoc hotfix only, and only this much:** the
|
|
133
|
+
`reconciled (...)` checkpoint hash and the row `Commit` cells name
|
|
134
|
+
different commits **by design** (Step 1.8), so do not assert equality
|
|
135
|
+
*between those two*, and do not apply the implementation-path condition to
|
|
136
|
+
this host's own commit — this file's `Minimal host, hotfix post-hoc only`
|
|
137
|
+
check tests the merged hotfix instead.
|
|
138
|
+
**Everything else still holds:** a post-hoc host can be compound too
|
|
139
|
+
(Step 1.7, "minimal means zero-phase, not one-artifact"), so **every** row
|
|
140
|
+
`Commit` must still name the **same single documentation commit**.
|
|
141
|
+
- [ ] **Minimal host (zero-phase) only** — **nothing that constitutes the change
|
|
142
|
+
itself is still uncommitted.** This is deliberately not "the host
|
|
143
|
+
directory is clean": **checkpoint 1 carries the change, the closeout
|
|
144
|
+
commit carries the record the flow writes afterwards.** Checkpoint 1 sits
|
|
145
|
+
at `modify-existing-flow.md`'s Step 4 → Step 5 gate and holds the change
|
|
146
|
+
itself — for a **T2** its lightweight-spec plus the implementation source,
|
|
147
|
+
for a **T3** its `_index.md` row plus the implementation source. What the
|
|
148
|
+
flow writes *after* that gate — Step 5's completion checklist and Step
|
|
149
|
+
1.7's "Finalize + close" — is derived record and rides into the closeout
|
|
150
|
+
commit.
|
|
151
|
+
**A post-hoc host (Step 1.8) inverts the source half, and this is where
|
|
152
|
+
the reconciliation contract is enforced.** Its change is the *already
|
|
153
|
+
merged* hotfix; checkpoint 1 is the **documentation** commit. So that
|
|
154
|
+
commit must carry the spec / row and this host's `_index.md` and must
|
|
155
|
+
**not** touch any implementation path the artifact declares — read
|
|
156
|
+
`git show --stat {checkpoint-1-hash}` and block if one appears. A
|
|
157
|
+
re-implementation committed there passes every other gate on this list
|
|
158
|
+
(rows agree, the `reconciled` hash differs from it and touches the
|
|
159
|
+
declared paths, the tree is clean) while breaking §8's "reconcile, do not
|
|
160
|
+
re-run" outright, so nothing else catches it.
|
|
161
|
+
**What this proves and what it does not — do not widen it here.** It
|
|
162
|
+
proves checkpoint 1 is documentation-only. It does **not** prove the
|
|
163
|
+
branch carries no re-implementation elsewhere: a second commit beside
|
|
164
|
+
checkpoint 1, or a re-implementation in a path the artifact does not
|
|
165
|
+
declare, both survive it. Widening it to the branch was tried and does not
|
|
166
|
+
work from inside closeout — the range needs a base branch, and Dflow
|
|
167
|
+
deliberately does not know yours. ⚠ **No check covers it today.** The
|
|
168
|
+
whole-history item `references/finish-feature-flow.md` Step 1 assigns to
|
|
169
|
+
`references/pr-review-checklist.md` is **not** it: that one counts commits
|
|
170
|
+
under this host's spec directory, so a re-implementation commit touching
|
|
171
|
+
only source never appears in its output. Review is where the missing
|
|
172
|
+
assertion belongs — a reviewer has the base branch in front of them — but
|
|
173
|
+
do not read the existing item as discharging it.
|
|
174
|
+
**Blocks closeout:** any of the **implementation source** files this
|
|
175
|
+
host's lightweight-spec or rows describe, staged or unstaged in
|
|
176
|
+
`git status --porcelain`; any **untracked** file under
|
|
177
|
+
`dflow/specs/features/active/{SPEC-ID}-{slug}/`; and any tracked file
|
|
178
|
+
dirty beyond the closed list below.
|
|
179
|
+
**May ride into the closeout commit — this list and nothing else:**
|
|
180
|
+
(i) `_index.md`, with its uncommitted delta confined to Lightweight
|
|
181
|
+
Changes `Commit` cells, Checkpoint Log rows, Resume Pointer, and Current
|
|
182
|
+
BR Snapshot;
|
|
183
|
+
(ii) an **already-committed** `lightweight-*.md` / `BUG-*.md`, with its
|
|
184
|
+
uncommitted delta confined to the frontmatter `status:` flip to
|
|
185
|
+
`completed` and the `Implementation Tasks` edits
|
|
186
|
+
`modify-existing-flow.md` Step 5's completion checklist makes ("applies
|
|
187
|
+
to both phase-spec and lightweight-spec"): ticking the tasks this change
|
|
188
|
+
completed and labelling each unchecked one as follow-up (5.1), and — when
|
|
189
|
+
the developer accepted the offer — collapsing or removing the section
|
|
190
|
+
(5.2). On a minimal host that checklist necessarily runs *after*
|
|
191
|
+
checkpoint 1, so these edits are uncommitted here by construction;
|
|
192
|
+
(iii) the Domain-layer documents **this change's Step 5.3 sweep** updates
|
|
193
|
+
— under `dflow/specs/domain/`, plus
|
|
194
|
+
`dflow/specs/architecture/tech-debt.md` — scoped to *this change's*
|
|
195
|
+
delta. A **T3** has no Domain sweep at all (`modify-existing-flow.md`
|
|
196
|
+
Step 5's tier-conditional
|
|
197
|
+
note), so nothing qualifies under (iii) for a T3. A **no-BC** host has no
|
|
198
|
+
*BC-scoped* sweep — a dirty `dflow/specs/domain/{context}/…` or
|
|
199
|
+
`context-map.md` under one is fiction and **blocks** — but the **global**
|
|
200
|
+
documents (`glossary.md`, `domain/analysis.md`,
|
|
201
|
+
`architecture/tech-debt.md`) belong to no bounded context, stay in its
|
|
202
|
+
sweep, and therefore still qualify under (iii).
|
|
203
|
+
Read each delta (`git diff -- {path}`) — do not infer it from the
|
|
204
|
+
filename. **The list is closed** — if a later change adds another
|
|
205
|
+
finalization field, add it here explicitly; "a host file is dirty" is never
|
|
206
|
+
on its own a reason to pass. (Unrelated work in progress elsewhere is
|
|
207
|
+
fine; say which files you judged unrelated.)
|
|
208
|
+
- [ ] **Minimal host (zero-phase), no-BC only** — **the host did not commit a
|
|
209
|
+
bounded context it does not have.** This file's `nothing that constitutes
|
|
210
|
+
the change itself is still uncommitted` check reads the *working
|
|
211
|
+
tree*; this one reads the **committed** side, because a fictitious
|
|
212
|
+
`{context}` invented at Step 2 and committed into checkpoint 1 leaves a
|
|
213
|
+
perfectly clean tree. Inspect checkpoint 1's diff
|
|
214
|
+
(`git show --stat {hash}`, with status — **not path names alone**): for a
|
|
215
|
+
host that declared itself no-BC that commit must **not touch, in any way**
|
|
216
|
+
— add, modify, delete or rename — any `dflow/specs/domain/{context}/…`
|
|
217
|
+
document. A deletion is a BC-layer change like any other, and reading only
|
|
218
|
+
the path list would accept one as if nothing had happened. The documents:
|
|
219
|
+
`rules.md`, `behavior.md`, `events.md`, `models.md`, `analysis.md` — and
|
|
220
|
+
no `context-map.md`. Any of them **blocks**
|
|
221
|
+
(`modify-existing-flow.md` Step 2's no-BC guard is where this should have
|
|
222
|
+
been caught first).
|
|
223
|
+
**Do not over-reach:** this rejects only Domain documents that commit
|
|
224
|
+
*added or changed* — pre-existing Domain files it never touched are
|
|
225
|
+
irrelevant, and the **global** documents (`glossary.md`,
|
|
226
|
+
`domain/analysis.md`, `architecture/tech-debt.md`) belong to no bounded
|
|
227
|
+
context and stay legitimate for a no-BC host, exactly as that check's
|
|
228
|
+
allow-list says.
|
|
229
|
+
**What this check cannot decide — stated, not asserted:** ⚠ **the rule it
|
|
230
|
+
enforces is not minimal-host-only; only this proof is.** *No no-BC host of
|
|
231
|
+
any shape may commit BC-scoped Domain material* — and what this reads is
|
|
232
|
+
**checkpoint 1**, one commit. It is not a branch-range proof: a second
|
|
233
|
+
commit beside checkpoint 1 carrying a `domain/{context}/…` document
|
|
234
|
+
survives it, and a **phase-bearing** no-BC host has no single checkpoint to
|
|
235
|
+
inspect at all, so it never runs this check in the first place. Closeout
|
|
236
|
+
cannot widen it — the range needs a base branch and Dflow deliberately does
|
|
237
|
+
not know yours (the same limit that working-tree check states).
|
|
238
|
+
**The branch-range assertion is confirmed by
|
|
239
|
+
`references/pr-review-checklist.md`'s "A no-BC host committed no BC-scoped
|
|
240
|
+
Domain material" item**, in that file's *Delegated to review by
|
|
241
|
+
`finish-feature-flow.md`* block, which applies to **every** no-BC host.
|
|
242
|
+
Keep this check anyway: it blocks earlier and more cheaply than review.
|
|
243
|
+
- [ ] **Minimal host (zero-phase), follow-up only** — **the reverse link was
|
|
244
|
+
opened, not only closed.** Step 1.6 requires the original feature's
|
|
245
|
+
Follow-up Tracking row for this host to be created as `in-progress` and to
|
|
246
|
+
ride checkpoint 1; `references/finish-feature-flow.md` Step 6 flips it to
|
|
247
|
+
`completed` afterwards. Verify the
|
|
248
|
+
opening half here, from committed state: for **every** SPEC-ID this host's
|
|
249
|
+
`follow-up-of` names — it may be a YAML array, so check each one —
|
|
250
|
+
`git show {checkpoint-1-hash}:dflow/specs/features/completed/{原 SPEC-ID}-{原 slug}/_index.md`
|
|
251
|
+
must already carry this host's row with Status `in-progress`. A row absent
|
|
252
|
+
there **blocks** closeout: the Step 6 flip would then create it directly as
|
|
253
|
+
`completed`, and the `absent → in-progress → completed` history the
|
|
254
|
+
follow-up contract requires never happened.
|
|
255
|
+
**What this check cannot decide — stated, not asserted:** ⚠ **only this
|
|
256
|
+
*proof* is minimal-host-only.** `references/finish-feature-flow.md`'s
|
|
257
|
+
Step 5 → Step 6 post-Local-closeout confirmation carries the requirement
|
|
258
|
+
itself and names who confirms it for a phase-bearing follow-up host; do
|
|
259
|
+
not read this check's scope as the requirement's scope. The evidence is what stops here: that host has no
|
|
260
|
+
single commit required to carry the row, so there is no committed blob for
|
|
261
|
+
this check to read and it never runs there.
|
|
262
|
+
- [ ] **Minimal host, hotfix post-hoc only** — the reconciliation record is
|
|
263
|
+
complete, **within a stated boundary**. This check proves **plausibility,
|
|
264
|
+
not identity**: that `{merged-hotfix-hash}` is a credible candidate, and
|
|
265
|
+
that the developer has said on the record which fix it is and how they
|
|
266
|
+
know. Whether it is *the* merged hotfix is **not decidable from inside
|
|
267
|
+
this flow** — the repository holds no independent record of which commit
|
|
268
|
+
that was; only the developer and the issue tracker do. Do not read a pass
|
|
269
|
+
here as identity confirmed. Identity is
|
|
270
|
+
**asserted** at `modify-existing-flow.md` Step 1.8 and **confirmed** by
|
|
271
|
+
`references/pr-review-checklist.md` — the same assignment
|
|
272
|
+
`references/finish-feature-flow.md` Step 1 gives the whole-history
|
|
273
|
+
assertion.
|
|
274
|
+
The plausibility conditions, all required: the
|
|
275
|
+
`reconciled ({merged-hotfix-hash})` value passes hash evidence — (a) and
|
|
276
|
+
(b) as usual, and for **(c)** its diff touches the implementation paths
|
|
277
|
+
the T2 lightweight-spec or the T3 row **declares** (Step 1.7 requires that
|
|
278
|
+
declaration; an artifact naming none leaves (c) nothing to compare and
|
|
279
|
+
**blocks** rather than passing vacuously). It must also **differ**
|
|
280
|
+
from the Lightweight Changes row's documentation-commit hash (different
|
|
281
|
+
provenance; see Step 1.8). The per-tier trace must exist too: a **T2**
|
|
282
|
+
carries `hotfix-branch:` in its lightweight-spec frontmatter, a **T3** has
|
|
283
|
+
its Lightweight Changes row Description marked as a hotfix. Finally the
|
|
284
|
+
developer's identity assertion must be **present and cited** — Step 1.8
|
|
285
|
+
requires the source it rests on (PR / incident / tracker reference), and
|
|
286
|
+
it lives with the per-tier trace, so look for it there: beside
|
|
287
|
+
`hotfix-branch:` in a **T2**'s lightweight-spec, in the row Description
|
|
288
|
+
for a **T3**. An uncited hash **blocks** closeout: it leaves pr-review
|
|
289
|
+
nothing to confirm against, and this gate is not a substitute for that
|
|
290
|
+
confirmation.
|
|
291
|
+
|
|
292
|
+
> **Zero-phase minimal host (`modify-existing-flow.md` Step 1.7 / the Step 1.6
|
|
293
|
+
> minimal variant / Step 1.8's post-hoc hotfix, whose linkage resolves to one of
|
|
294
|
+
> those two).** A standalone or follow-up minimal host closes out with
|
|
295
|
+
> an **empty Phase Specs table** — that is valid, not a failure: the "every
|
|
296
|
+
> Phase Specs row is completed" check passes vacuously and there is no
|
|
297
|
+
> `phase-spec-*` file to look for. A no-BR / T3 host also has an intentionally
|
|
298
|
+
> empty Current BR Snapshot — `references/finish-feature-flow.md` Step 1's
|
|
299
|
+
> **Current BR Snapshot** check decides that from the host's own record, not
|
|
300
|
+
> from a declaration. Do **not**
|
|
301
|
+
> manufacture a phase-spec or a BR row to make a check "pass".
|
|
302
|
+
|
|
303
|
+
## Step 3 — sync input
|
|
304
|
+
|
|
305
|
+
**Minimal host — sync input.** A minimal host has no phase-spec: read the
|
|
306
|
+
"phase-spec" references in `references/finish-feature-flow.md` Step 3's sync
|
|
307
|
+
instructions (events "introduced by phase-specs", "each phase-spec's Delta") as
|
|
308
|
+
the host's **lightweight-spec** recorded delta
|
|
309
|
+
plus its Current BR Snapshot. A no-BR family that changed an event field or a
|
|
310
|
+
documented behaviour still syncs `events.md` / `behavior.md` from that
|
|
311
|
+
lightweight-spec's delta.
|
|
312
|
+
⚠ What is minimal-host-only here is the **input binding** — the instruction to
|
|
313
|
+
read "phase-spec" as "lightweight-spec", which a host with no phase-spec needs
|
|
314
|
+
and a phase-bearing one must not apply. It is **not** that step's
|
|
315
|
+
**Every host — lightweight-spec deltas are a sync input too** paragraph, which
|
|
316
|
+
every host shape needs.
|
|
317
|
+
|
|
318
|
+
## Step 4 — post-commit verification, additionally
|
|
319
|
+
|
|
320
|
+
Add this to `references/finish-feature-flow.md` Step 4's post-commit
|
|
321
|
+
verification, inside its archived-host-directory item:
|
|
322
|
+
|
|
323
|
+
**Minimal host (zero-phase) additionally**: the **first** checkpoint row
|
|
324
|
+
still carries the hash this file's Step 1 checks validated —
|
|
325
|
+
`implementation` with `committed ({hash})` or
|
|
326
|
+
`reconciled ({merged-hotfix-hash})`.
|
|
327
|
+
|
|
328
|
+
## Step 5 — Integration Summary, exact fields
|
|
329
|
+
|
|
330
|
+
**Zero-phase minimal host — exact fields** (these must match the
|
|
331
|
+
`references/finish-feature-flow.md` Step 3 branch — do not require a field that
|
|
332
|
+
step left empty). A standalone or follow-up
|
|
333
|
+
minimal host has `Phase Count: 0`, an empty Phase List, and at least one row in
|
|
334
|
+
Lightweight Changes.
|
|
335
|
+
|
|
336
|
+
- a **no-BC host** (that step's case ii) sets the fields that report a **sync** to
|
|
337
|
+
none — `BC: none`, `Aggregates affected: none`, `Domain Events Changes:
|
|
338
|
+
none` (nothing was synced). **`Related BR-IDs` is not one of them**: it
|
|
339
|
+
reports what this change's own record carries, not what was synced, so it
|
|
340
|
+
takes the same values a BC-bearing host would — **empty**, or the
|
|
341
|
+
**per-family no-BR marker** when the T2 carries one. A T3-only no-BC host has
|
|
342
|
+
neither and leaves it empty.
|
|
343
|
+
- a **BC-bearing host** (that step's case i) sets `BC:` to the context and fills
|
|
344
|
+
each Domain field with **what it actually touched**: `Related BR-IDs:` a real
|
|
345
|
+
set, the per-family no-BR marker, or empty for a no-BR host; `Aggregates
|
|
346
|
+
affected:` and `Domain Events Changes:` the ones it changed, or `none` for
|
|
347
|
+
those it did not.
|
|
348
|
+
|
|
349
|
+
**What is scoped here and what is not.** This block fixes the *whole* field set
|
|
350
|
+
for a zero-phase host — `Phase Count: 0`, the empty Phase List, and which fields
|
|
351
|
+
each Step 3 branch leaves empty — and that part is genuinely zero-phase-only.
|
|
352
|
+
The `none`-for-unchanged rule on the last bullet is **not**: every BC-bearing
|
|
353
|
+
host needs it, and it is now stated where every one of them reads it, in
|
|
354
|
+
**`references/finish-feature-flow.md` Step 3 case (i)**. The two say the same
|
|
355
|
+
thing on purpose; if you change one, change the other.
|
|
356
|
+
|
|
357
|
+
⚠ **No proof obligation is delegated from this block, and that is not an
|
|
358
|
+
omission.** These are field-filling instructions — they order values, they do
|
|
359
|
+
not test anything — so there is no evidence duty here for another host shape to
|
|
360
|
+
discharge or for review to take over. **N/A, stated rather than left blank**:
|
|
361
|
+
elsewhere in this file a scoped check that cannot reach another host shape hands
|
|
362
|
+
that shape to `references/pr-review-checklist.md` by name, and a reader who
|
|
363
|
+
finds no such hand-off here should not conclude one went missing.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Post-Hoc Hotfix Reconciliation — Greenfield Clean Architecture
|
|
2
|
+
|
|
3
|
+
Branch file of `references/finish-feature-flow.md`. It **adds** the
|
|
4
|
+
reconciliation rules; it does not restate or override anything in that flow.
|
|
5
|
+
|
|
6
|
+
**Two different places in `references/finish-feature-flow.md` send you here, at
|
|
7
|
+
two different times. Read only the section that matches the one that sent you.**
|
|
8
|
+
|
|
9
|
+
- **Step 1's pre-checklist callout** — the branches met while this host was
|
|
10
|
+
still open → § Before closeout.
|
|
11
|
+
- **Step 5** — Step 4 has already archived and committed this host → § After
|
|
12
|
+
closeout.
|
|
13
|
+
|
|
14
|
+
## Before closeout
|
|
15
|
+
|
|
16
|
+
**You are here when** `references/finish-feature-flow.md` Step 1's hotfix
|
|
17
|
+
callout sent you — it states the condition; this file does not restate it.
|
|
18
|
+
|
|
19
|
+
**What you classify here is the merge-resolution delta, not the hotfix.** The
|
|
20
|
+
hotfix records itself in its **own** minimal host through Step 1.8 — follow-up
|
|
21
|
+
or standalone, never an in-flight feature — and that host is where
|
|
22
|
+
`reconciled ({merged-hotfix-hash})`, the identity citation and the per-tier
|
|
23
|
+
trace live. If the hotfix has not been documented yet, run Step 1.8 for it
|
|
24
|
+
first and come back; do **not** absorb it into this feature, whose ordinary
|
|
25
|
+
checkpoints would record none of that. What is left for this host is only what
|
|
26
|
+
*choosing between the two versions* changed. **Classify that by the cascade,
|
|
27
|
+
then record what the classification calls for:**
|
|
28
|
+
|
|
29
|
+
- **No tracked delta** — the cascade's **below workflow** level. It stays in
|
|
30
|
+
the integration commit message; do **not** manufacture a row or a document.
|
|
31
|
+
Nothing to validate, so nothing changes below. This is the common case.
|
|
32
|
+
- **A tracked delta (T3 or above), phase-bearing host** — record it in this
|
|
33
|
+
host and let it ride the normal checkpoints, then run
|
|
34
|
+
`references/finish-feature-flow.md` Step 1's checklist against the result. A
|
|
35
|
+
phase-bearing host has no fixed commit count, so an extra checkpoint is
|
|
36
|
+
ordinary.
|
|
37
|
+
- **A tracked delta (T3 or above), minimal (zero-phase) host** — it does
|
|
38
|
+
**not** go into this host: the two-commit lifecycle has one implementation
|
|
39
|
+
checkpoint and one closeout, and every Lightweight Changes row must belong
|
|
40
|
+
to that first commit. This host closes on what it already carries, and the
|
|
41
|
+
delta is routed **after** Step 4 archives it — by the **A tracked delta (T3
|
|
42
|
+
or above)** bullet of § After closeout, the same route every post-closeout
|
|
43
|
+
leftover takes. Do **not** route it now:
|
|
44
|
+
you are mid-closeout, and routing would open a second host before this one
|
|
45
|
+
is sealed. Note it, finish the closeout, then take § After closeout's route —
|
|
46
|
+
back through `/dflow:modify-existing`, which picks the host the way it
|
|
47
|
+
always does. Do not decide that here: by then this feature is *completed*,
|
|
48
|
+
so the normal completed-feature disambiguation applies and the answer may be
|
|
49
|
+
a follow-up or a standalone host.
|
|
50
|
+
|
|
51
|
+
Classification decides, never "is it worth writing down". After closeout the
|
|
52
|
+
host is frozen — § After closeout says what is left over, and applies the same
|
|
53
|
+
cascade.
|
|
54
|
+
|
|
55
|
+
## After closeout
|
|
56
|
+
|
|
57
|
+
**You are here when** `references/finish-feature-flow.md` Step 5 sent you.
|
|
58
|
+
|
|
59
|
+
**A mainline hotfix that overlapped this feature.** A T2 / T3 post-hoc hotfix
|
|
60
|
+
(`modify-existing-flow.md` Step 1.8) records itself in its own host, so when
|
|
61
|
+
this feature's branch finally meets the mainline both may have touched the same
|
|
62
|
+
code, and whoever merges picks between two existing versions. By the time you
|
|
63
|
+
read this, **Step 4 has already archived and committed this feature — its host
|
|
64
|
+
is frozen.** Classify whatever is left by the cascade (`AI-AGENT-GUIDE.md`
|
|
65
|
+
§ Ceremony Scaling), never by "is it worth writing down":
|
|
66
|
+
|
|
67
|
+
- **No conflict, or a resolution with no tracked delta** — it stays in the
|
|
68
|
+
integration commit message. That is the cascade's **below workflow** level:
|
|
69
|
+
do not manufacture a document, and do not reopen this feature.
|
|
70
|
+
- **A tracked delta (T3 or above)** — completed features are frozen, so it goes
|
|
71
|
+
where every post-completion change goes: back through
|
|
72
|
+
`/dflow:modify-existing`, which opens a follow-up or standalone host for it.
|
|
73
|
+
Do **not** edit the archived `_index.md`.
|
|
74
|
+
- **The resolution moves system state** — if choosing between the two versions
|
|
75
|
+
changes a business rule, a documented behaviour, an event, or the domain
|
|
76
|
+
model, the owning document (`rules.md` / `behavior.md` / `events.md` /
|
|
77
|
+
`models.md`) **must** be updated. That update is itself a tracked change and
|
|
78
|
+
takes the route above; system-state truth is never below workflow.
|
|
79
|
+
- **It is bigger than a merge** — if resolving it means *new or changed*
|
|
80
|
+
behaviour rather than choosing between two that already exist, it is not a
|
|
81
|
+
merge question at all: run it through the cascade and open the flow its tier
|
|
82
|
+
calls for.
|
|
83
|
+
|
|
84
|
+
**Reconciling before closeout is simpler.** If the branches meet while this
|
|
85
|
+
feature is still in flight — a rebase onto the mainline, say — handle it then
|
|
86
|
+
as ordinary in-flow work — but **which host takes it depends on this host's
|
|
87
|
+
shape**. A **phase-bearing** host absorbs a tracked delta (T3 or above) and
|
|
88
|
+
rides the normal checkpoints; a **minimal (zero-phase)** host **cannot** once
|
|
89
|
+
checkpoint 1 has landed, because every Lightweight Changes row must belong to
|
|
90
|
+
that commit — it closes on what it carries and the delta is routed afterwards.
|
|
91
|
+
No tracked delta stays below workflow, in the integration commit message.
|
|
92
|
+
§ Before closeout states that whole side in full, minimal-host branch
|
|
93
|
+
included. The four bullets above decide it whichever side of closeout you are on —
|
|
94
|
+
they are principles, not a checklist; the situation is rare and varied, so use
|
|
95
|
+
judgement.
|