dflow-sdd-ddd 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +915 -0
- package/CONTRIBUTING.md +11 -1
- package/README.en.md +160 -212
- package/README.md +93 -147
- package/TEMPLATE-COVERAGE.md +13 -6
- package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
- package/bin/dflow.js +90 -4
- package/docs/closeout-check.en.md +204 -0
- package/docs/closeout-check.md +204 -0
- package/docs/commands.en.md +112 -0
- package/docs/commands.md +103 -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/release-versioning-policy.md +6 -0
- package/docs/upgrading.en.md +196 -0
- package/docs/upgrading.md +197 -0
- package/docs/using-with-claude-code.en.md +13 -4
- package/docs/using-with-claude-code.md +13 -4
- package/docs/using-with-codex.en.md +13 -4
- package/docs/using-with-codex.md +13 -4
- package/docs/using-with-github-copilot.en.md +13 -4
- package/docs/using-with-github-copilot.md +13 -4
- package/lib/closeout-check.js +690 -0
- package/lib/doc-shapes.json +1195 -0
- package/lib/doctor-checks.js +2500 -24
- package/lib/init.js +2861 -143
- 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 +648 -98
- package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
- package/templates/brownfield/references/finish-feature-minimal-host.md +427 -0
- package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/brownfield/references/finish-feature-record-correction.md +45 -0
- package/templates/brownfield/references/git-integration.md +205 -26
- package/templates/brownfield/references/init-project-flow.md +23 -3
- package/templates/brownfield/references/modify-existing-flow.md +439 -88
- package/templates/brownfield/references/modify-existing-follow-up.md +122 -0
- package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +200 -0
- package/templates/brownfield/references/new-feature-flow.md +110 -37
- package/templates/brownfield/references/new-phase-flow.md +59 -9
- package/templates/brownfield/references/pr-review-checklist.md +328 -10
- package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +151 -34
- package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
- package/templates/brownfield/scaffolding/Git-principles-gitflow.md +85 -8
- package/templates/brownfield/scaffolding/Git-principles-trunk.md +88 -10
- package/templates/brownfield/scaffolding/_conventions.md +50 -28
- package/templates/brownfield/scaffolding/_overview.md +1 -0
- package/templates/brownfield/templates/_index.md +158 -10
- 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 +146 -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 +639 -100
- package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
- package/templates/greenfield/references/finish-feature-minimal-host.md +383 -0
- package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
- package/templates/greenfield/references/finish-feature-record-correction.md +45 -0
- package/templates/greenfield/references/git-integration.md +193 -26
- package/templates/greenfield/references/init-project-flow.md +23 -3
- package/templates/greenfield/references/modify-existing-flow.md +395 -87
- package/templates/greenfield/references/modify-existing-follow-up.md +104 -0
- package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +200 -0
- package/templates/greenfield/references/new-feature-flow.md +116 -35
- package/templates/greenfield/references/new-phase-flow.md +58 -9
- package/templates/greenfield/references/pr-review-checklist.md +311 -8
- package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +146 -32
- package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
- package/templates/greenfield/scaffolding/Git-principles-gitflow.md +84 -8
- package/templates/greenfield/scaffolding/Git-principles-trunk.md +94 -14
- package/templates/greenfield/scaffolding/_conventions.md +50 -28
- package/templates/greenfield/scaffolding/_overview.md +6 -2
- package/templates/greenfield/templates/_index.md +145 -10
- 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,104 @@
|
|
|
1
|
+
# Step 1.6: Create Follow-up Feature — Greenfield Clean Architecture
|
|
2
|
+
|
|
3
|
+
Branch file of `references/modify-existing-flow.md`. It **adds** the
|
|
4
|
+
follow-up-specific rules; it does not restate or override anything in that flow.
|
|
5
|
+
|
|
6
|
+
**You are here because** that flow's Step 1.6 dispatched you — it owns whether
|
|
7
|
+
this route applies, and what has already been decided by the time you arrive.
|
|
8
|
+
|
|
9
|
+
Build the follow-up feature using the same machinery as
|
|
10
|
+
`/dflow:new-feature` (see `new-feature-flow.md` Steps 3.5 and 4), with
|
|
11
|
+
these follow-up-specific differences. **Use the tier Part A already decided.**
|
|
12
|
+
This is the same change Part A classified, and re-running the cascade on it can
|
|
13
|
+
return a second answer to one question. Re-enter Part A **only** when the
|
|
14
|
+
Step 1.5 A/B/C discussion materially changed the scope (work added or dropped);
|
|
15
|
+
say so explicitly when you do, and let that re-run **replace** the earlier tier
|
|
16
|
+
rather than stand beside it. On that tier: a **T1** follow-up takes the full
|
|
17
|
+
new-feature machinery below; a **T2 / T3** follow-up takes
|
|
18
|
+
the **minimal (zero-phase) variant** described after the reverse-link step —
|
|
19
|
+
it does **not** delegate new-feature Step 4's unconditional first phase-spec.
|
|
20
|
+
A **post-hoc hotfix** whose host linkage Step 1.8 resolved to *follow-up*
|
|
21
|
+
also arrives here (never through the Step 1.5 prompt, and always T2 / T3, so
|
|
22
|
+
always the minimal variant); its first checkpoint keeps the `implementation`
|
|
23
|
+
name but carries Result `reconciled (...)` per Step 1.8.
|
|
24
|
+
|
|
25
|
+
- **New SPEC-ID** (today's date sequence — do NOT reuse the original
|
|
26
|
+
SPEC-ID): e.g. original `SPEC-20260201-003-訂單折扣` → follow-up
|
|
27
|
+
`SPEC-20260424-002-訂單折扣-匯率擴充` (or any new slug)
|
|
28
|
+
- **New slug**: not required to equal the original slug; pick whatever
|
|
29
|
+
best describes the follow-up scope
|
|
30
|
+
- **`_index.md` Metadata**: `follow-up-of: {原 SPEC-ID}` is REQUIRED
|
|
31
|
+
(uncomment the optional line in the template; can be a YAML array if
|
|
32
|
+
the follow-up spans multiple originals)
|
|
33
|
+
- **`_index.md` Goals & Scope** auto-prepended note:
|
|
34
|
+
```
|
|
35
|
+
> 本 feature 為 `{原 SPEC-ID}-{原 slug}` 的 follow-up,原 feature
|
|
36
|
+
> 完成於 `{date}`,詳見 `completed/{原 SPEC-ID}-{原 slug}/_index.md`。
|
|
37
|
+
```
|
|
38
|
+
- **`_index.md` Current BR Snapshot baseline** (**BC-bearing follow-up only**):
|
|
39
|
+
if the follow-up touches a bounded context, AI reads the BC's
|
|
40
|
+
`dflow/specs/domain/{context}/rules.md` and inherits the BRs that are
|
|
41
|
+
in-scope for this follow-up. Mark each inherited row with First Seen
|
|
42
|
+
= `inherited from rules.md` and Last Updated = (empty until the new
|
|
43
|
+
feature's first phase Delta — or, for a minimal follow-up, its
|
|
44
|
+
lightweight-spec's delta — touches it). For a **no-BC follow-up** (the
|
|
45
|
+
minimal variant on a completed no-BC host), leave the Current BR Snapshot
|
|
46
|
+
**empty** — do not read or fabricate a BC's `rules.md`.
|
|
47
|
+
|
|
48
|
+
**Reverse-link into the old `_index.md`**: AI also updates
|
|
49
|
+
`dflow/specs/features/completed/{原 SPEC-ID}-{原 slug}/_index.md` —
|
|
50
|
+
uncomment the Follow-up Tracking section (if not already present) and
|
|
51
|
+
add a row. When `follow-up-of` names **more than one** original (it may be a
|
|
52
|
+
YAML array), do this in **every** one of them; a parent left without its row
|
|
53
|
+
never gets the `absent → in-progress → completed` transition the contract
|
|
54
|
+
requires, and on a **minimal** follow-up host finish-feature Step 1 blocks
|
|
55
|
+
closeout on it (that check is scoped "Minimal host (zero-phase), follow-up
|
|
56
|
+
only" and proves the *opening* half; on a phase-bearing follow-up Step 6 still
|
|
57
|
+
flips and verifies the closing half, but nothing checks that the row was ever
|
|
58
|
+
opened as `in-progress`):
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
| {新 SPEC-ID} | {新 slug} | {today} | in-progress |
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This update is **part of the same change set** as opening the host. For a
|
|
65
|
+
**T1** follow-up the AI may offer to commit the new host and this initial
|
|
66
|
+
`absent → in-progress` reverse-link together (commit message should mention
|
|
67
|
+
"Add follow-up reference to `{新 SPEC-ID}`"). For the **minimal (T2 / T3)
|
|
68
|
+
variant** the AI does **not** offer a separate host-open commit — the
|
|
69
|
+
initial reverse-link edit rides along in the implementation checkpoint (see
|
|
70
|
+
the variant paragraph below), keeping the follow-up at exactly two host
|
|
71
|
+
checkpoints. The reverse link is a derived index — the new feature's
|
|
72
|
+
`follow-up-of` field is the authoritative source.
|
|
73
|
+
|
|
74
|
+
After a **T1** follow-up feature is set up, this flow hands off to the
|
|
75
|
+
`/dflow:new-phase` flow (or stays in this flow at Step 2 for the first
|
|
76
|
+
phase's content).
|
|
77
|
+
|
|
78
|
+
**Minimal (zero-phase) follow-up variant (T2 / T3).** When the follow-up
|
|
79
|
+
change is itself lightweight, do **not** delegate new-feature Step 4 (which
|
|
80
|
+
would create an unconditional first phase-spec). Instead treat the follow-up
|
|
81
|
+
host exactly like a standalone minimal host — open it via **Step 1.7's
|
|
82
|
+
mechanics, steps 2–4 only** (assign identifiers + collision check, create the
|
|
83
|
+
minimal `_index.md` with an empty Phase Specs table, branch gate **by change
|
|
84
|
+
class**: `bugfix/BUG-{NUMBER}-{slug}` for a functional bug,
|
|
85
|
+
`feature/{SPEC-ID}-{slug}` otherwise — this **overrides** new-feature's
|
|
86
|
+
hardcoded `feature/` branch). Step 1.7's **step 1 does not apply**: it is the
|
|
87
|
+
standalone-classification gate, and this caller has already been classified as
|
|
88
|
+
a follow-up. Everything Step 1.7 states **after** step 4 *does* apply
|
|
89
|
+
unchanged — every artifact's row written before checkpoint 1, the
|
|
90
|
+
implementation-path declaration, the finalization before checkpoint 1 and
|
|
91
|
+
"Finalize + close" after it, and the two
|
|
92
|
+
commit-evidence surfaces — because finish-feature reads for all of it on a
|
|
93
|
+
follow-up host exactly as on a standalone one. Then record the change's
|
|
94
|
+
artifacts — a T2 lightweight-spec, one
|
|
95
|
+
or more T3 inline rows, or both for a compound follow-up (Step 1.7's
|
|
96
|
+
"minimal means zero-phase, not one-artifact") — and close with
|
|
97
|
+
`/dflow:finish-feature`. The lifecycle is **two host checkpoints**
|
|
98
|
+
(implementation, then closeout) **plus one post-closeout reverse-link flip
|
|
99
|
+
tracking commit** — the flip (the original feature's Follow-up Tracking row
|
|
100
|
+
`in-progress → completed`, done by `/dflow:finish-feature` Step 6) is a
|
|
101
|
+
**sanctioned post-completion mutation, not a host checkpoint**, and is
|
|
102
|
+
recorded in **neither** the follow-up host's Checkpoint Log **nor** the
|
|
103
|
+
original feature's. Option C of Step 1.5 ("a follow-up containing only one
|
|
104
|
+
T3 row") lands here.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Step 1.8: Hotfix T2 / T3 Post-Hoc — Greenfield Clean Architecture
|
|
2
|
+
|
|
3
|
+
Branch file of `references/modify-existing-flow.md`. It **adds** the
|
|
4
|
+
post-hoc-specific rules; it does not restate or override anything in that flow.
|
|
5
|
+
|
|
6
|
+
**You are here because** that flow's Step 1.8 dispatched you — it owns whether
|
|
7
|
+
this route applies, and what has already been decided by the time you arrive.
|
|
8
|
+
|
|
9
|
+
Sometimes an urgent fix is merged, pushed, and its branch cleaned up
|
|
10
|
+
**before** any Dflow ceremony runs. When you come back to record it,
|
|
11
|
+
declare **post-hoc mode** and reconcile rather than re-implement.
|
|
12
|
+
|
|
13
|
+
**Admission condition — T2 / T3 only.** This step builds a *minimal
|
|
14
|
+
(zero-phase)* host, so it admits only a post-hoc change Part A classified
|
|
15
|
+
**T2 or T3**. A **T1** post-hoc keeps the normal phase-bearing route
|
|
16
|
+
(`/dflow:new-phase` / `/dflow:new-feature`) and documents the merged work
|
|
17
|
+
there — it is not routed here, and giving it a zero-phase host would be wrong.
|
|
18
|
+
If you arrived here with a T1, go back to Part A's routing.
|
|
19
|
+
|
|
20
|
+
1. **Host-linkage choice first.** A post-hoc hotfix is **already merged on the
|
|
21
|
+
mainline**, so no in-flight feature branch can host it: documenting it into
|
|
22
|
+
an unmerged `feature/...` host would strand the production fix's record on a
|
|
23
|
+
branch the mainline cannot see — possibly for weeks — and would let that
|
|
24
|
+
feature's Integration Summary claim work it never did. The hotfix therefore
|
|
25
|
+
always gets a host of its own, and the only question is whether that host is
|
|
26
|
+
linked:
|
|
27
|
+
- **A related completed feature** → run it as a **follow-up** (Step 1.6
|
|
28
|
+
minimal variant — keep `follow-up-of` and its two reverse-link
|
|
29
|
+
transitions). A hotfix on a completed feature filed as an unlinked
|
|
30
|
+
standalone loses its lineage.
|
|
31
|
+
- **Otherwise** → open a **standalone** minimal host (Step 1.7). "Otherwise"
|
|
32
|
+
includes *a related feature that is still in flight* — see above for why
|
|
33
|
+
it cannot be the host.
|
|
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
|
+
|
|
39
|
+
Do not skip this choice. If a feature that was in flight turns out to have
|
|
40
|
+
touched the same code, that is a **merge** question, settled when the
|
|
41
|
+
branches actually meet — see `finish-feature-flow.md` Step 5.
|
|
42
|
+
2. **Reconcile, do not re-run.** The implementation already happened on the
|
|
43
|
+
(now often deleted) hotfix branch. Do **not** reopen an implementation
|
|
44
|
+
branch for it or redo the work. The documentation is recorded on **this
|
|
45
|
+
host's own branch**, cut by change class at Step 1.7 step 4 (or at Step
|
|
46
|
+
1.6's delegation to it) like any other minimal host — that branch *is* the
|
|
47
|
+
**post-hoc branch** the rest of this step names, and the value `_index.md`
|
|
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.
|
|
104
|
+
3. **Implementation checkpoint Result = `reconciled ({merged-hotfix-hash})`.**
|
|
105
|
+
In the host's Checkpoint Log the implementation row's Result is
|
|
106
|
+
`reconciled (...)` — the value meaning "this checkpoint documents an
|
|
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
|
|
112
|
+
`references/git-integration.md` § Commit Checkpoints, Branch Gate & AI
|
|
113
|
+
Commits). That hash belongs to the **hotfix**, so it is **not** evidence
|
|
114
|
+
that this host's own first commit landed — the documentation work still owes
|
|
115
|
+
checkpoint 1 a real commit of its own (item 4), made **before** closeout.
|
|
116
|
+
Committing the documentation together with closeout collapses the host to
|
|
117
|
+
one commit and fails finish-feature Step 1.
|
|
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
|
+
|
|
132
|
+
**You are asserting this hash, not deriving it.** Nothing in the repository
|
|
133
|
+
records which commit was the hotfix, so no check in this flow can confirm
|
|
134
|
+
it — finish-feature's reconciliation gate is explicit that it tests
|
|
135
|
+
plausibility only. So state the identity
|
|
136
|
+
and **cite what it rests on**: the PR, incident, or tracker reference that
|
|
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
|
|
140
|
+
(item 4). An **uncited** hash blocks closeout —
|
|
141
|
+
`references/pr-review-checklist.md` is what confirms the identity, and it
|
|
142
|
+
needs something to confirm against.
|
|
143
|
+
4. **Per-tier trace.** A **T2** records the merged-hotfix branch in its
|
|
144
|
+
lightweight-spec `hotfix-branch:` field; a **T3** marks its `_index.md`
|
|
145
|
+
Lightweight Changes row Description as a hotfix (no new field, no T3 spec
|
|
146
|
+
file). Item 3's identity citation goes in the same place — beside
|
|
147
|
+
`hotfix-branch:` for a T2, in the row Description for a T3 — so the trace
|
|
148
|
+
and the thing it rests on stay together. In **both** tiers the host's
|
|
149
|
+
Lightweight Changes row carries a `Commit` value, and that value is the
|
|
150
|
+
**post-hoc documentation commit**
|
|
151
|
+
hash (the row is produced by the documentation work) — **not** the
|
|
152
|
+
merged hotfix hash, which already lives in the `reconciled (...)` checkpoint
|
|
153
|
+
above; the two have different provenance and must not be conflated. This
|
|
154
|
+
row hash is what finish-feature Step 1 reads to prove the documentation
|
|
155
|
+
commit exists separately from closeout, so fill it in as soon as that
|
|
156
|
+
commit lands.
|
|
157
|
+
5. **Branch equality** for the host is asserted against the **post-hoc
|
|
158
|
+
documentation branch** (the `_index.md` `branch:` value), never the deleted
|
|
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.
|
|
@@ -14,7 +14,7 @@ Crossing any step gate above also updates the host feature's `_index.md` Resume
|
|
|
14
14
|
|
|
15
15
|
All other step transitions are **step-internal**: announce "Step N complete, entering Step N+1" and proceed without waiting. See AI-AGENT-GUIDE.md § Workflow Transparency for the full transparency protocol and confirmation signals.
|
|
16
16
|
|
|
17
|
-
**Ceremony**: this flow always defaults to **T1 Heavy** — the first phase of a brand-new feature is by definition a full SDD cycle. Tier judgement (T1 / T2 / T3)
|
|
17
|
+
**Ceremony**: this flow always defaults to **T1 Heavy** — the first phase of a brand-new feature is by definition a full SDD cycle. Tier judgement (the ordered cascade — T1 / T2 / T3 / below workflow) applies to `/dflow:modify-existing` and `/dflow:bug-fix`; the criteria live in AI-AGENT-GUIDE.md § Ceremony Scaling, and `references/modify-existing-flow.md` is where they are applied.
|
|
18
18
|
|
|
19
19
|
## Step 1: Intake — Understand the Request
|
|
20
20
|
|
|
@@ -28,6 +28,25 @@ Ask naturally:
|
|
|
28
28
|
2. **Who needs it?** Stakeholder or user role.
|
|
29
29
|
3. **Why now?** Priority and urgency.
|
|
30
30
|
|
|
31
|
+
> **`/dflow:new-feature` is always T1 — it does not re-run the cascade.**
|
|
32
|
+
> Entering here declares "genuinely new work" (a new capability, page, or
|
|
33
|
+
> navigable surface). If the request is really a **modification** of existing
|
|
34
|
+
> behaviour — a tweak, a bug fix, an appearance change, or anything that would
|
|
35
|
+
> land at T2 / T3 / below-workflow — it belongs in `/dflow:modify-existing`,
|
|
36
|
+
> whose Step 1 cascade (step 0) is the only place a misroute is caught. So
|
|
37
|
+
> sanity-check at intake: if this looks like a small change to something that
|
|
38
|
+
> already exists, redirect to `/dflow:modify-existing` rather than minting a T1
|
|
39
|
+
> feature. ⚠ **Do not redirect a request that already came from there.** A
|
|
40
|
+
> `/dflow:modify-existing` or `/dflow:bug-fix` request the cascade landed at T1
|
|
41
|
+
> — including one a project convention escalated to T1, which the overlay may
|
|
42
|
+
> only ever raise — is routed here **by** step 0 and has already been caught;
|
|
43
|
+
> sending it back is a loop, because step 0 provably returns the same answer.
|
|
44
|
+
> `AI-AGENT-GUIDE.md` § Ceremony Scaling's T1 row says so directly. The guard
|
|
45
|
+
> is for a request that arrived at `/dflow:new-feature` **without** passing the
|
|
46
|
+
> cascade. (A follow-up to a *completed* feature is the one new-feature-shaped
|
|
47
|
+
> case that may still be lightweight — it arrives through `modify-existing`
|
|
48
|
+
> Step 1.6's minimal variant, not here.)
|
|
49
|
+
|
|
31
50
|
Check existing assets:
|
|
32
51
|
- Search `dflow/specs/domain/` for related concepts
|
|
33
52
|
- Search `dflow/specs/features/` for related features
|
|
@@ -148,6 +167,20 @@ valid outcome; extending silently is not.
|
|
|
148
167
|
- Service interfaces for external systems
|
|
149
168
|
- Define in Domain layer, implement in Infrastructure
|
|
150
169
|
|
|
170
|
+
### System-Level Knowledge
|
|
171
|
+
```
|
|
172
|
+
"Which parts of this feature will no single context document hold?"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- What crosses a bounded context, and what does each step hand to the next? (always the domain-root copy)
|
|
176
|
+
- Which status fields does this feature introduce, and what transitions do they move through?
|
|
177
|
+
- Which figures are derived rather than stored?
|
|
178
|
+
- Who reaches this feature, and what data scope does each role see? (always the domain-root copy)
|
|
179
|
+
|
|
180
|
+
Record each answer in `dflow/specs/domain/{context}/analysis.md` when one context owns what it describes and in `dflow/specs/domain/analysis.md` when no one context does, creating the file from `templates/analysis.md` the first time there is something to record. That template's sections carry the notation.
|
|
181
|
+
|
|
182
|
+
Domain events keep their definitions and payloads in `events.md`; name them in the flow here instead of restating them.
|
|
183
|
+
|
|
151
184
|
If foundational domain docs are missing, create them from templates before writing content:
|
|
152
185
|
- `dflow/specs/domain/glossary.md` → `templates/glossary.md`
|
|
153
186
|
- `dflow/specs/domain/{context}/models.md` → `templates/models.md`
|
|
@@ -159,7 +192,7 @@ If foundational domain docs are missing, create them from templates before writi
|
|
|
159
192
|
**→ Step Gate: Step 3 → Step 3.5**
|
|
160
193
|
|
|
161
194
|
Announce to developer:
|
|
162
|
-
> "Aggregate / VO / Events identified. Before I create
|
|
195
|
+
> "Aggregate / VO / Events identified. Before I create the feature directory or branch, let me confirm the SPEC-ID, slug, directory name, and branch name with you (Step 3.5). `/dflow:next` to proceed."
|
|
163
196
|
|
|
164
197
|
Wait for confirmation before entering Step 3.5.
|
|
165
198
|
|
|
@@ -208,7 +241,30 @@ If the developer asks to change the slug, re-propose and re-confirm.
|
|
|
208
241
|
|
|
209
242
|
## Step 4: Write the Spec
|
|
210
243
|
|
|
211
|
-
|
|
244
|
+
> **Minimal hosts do not come here (defensive guard).** Step 4 creates a first
|
|
245
|
+
> phase-spec, which only a genuinely **T1** new feature has. A **minimal host**
|
|
246
|
+
> is zero-phase and is recorded through its own path in `modify-existing-flow.md`,
|
|
247
|
+
> **not here**: Step 1.6 explicitly does **not** delegate to this step. If you
|
|
248
|
+
> reached Step 4 while handling a minimal / zero-phase host, **stop and re-enter
|
|
249
|
+
> `modify-existing-flow.md` at Step 1** — *not* at Step 1.6, 1.7 or 1.8.
|
|
250
|
+
>
|
|
251
|
+
> Those steps each assume work Step 1 has already done: Part A has decided the
|
|
252
|
+
> tier, and Part B has done the host linkage. An entry that arrived *here* ran
|
|
253
|
+
> neither, so recovering into one of them skips the authoritative cascade and
|
|
254
|
+
> the completed-feature scan — which is how a change that should have been a
|
|
255
|
+
> follow-up gets archived as an unlinked standalone. Step 1 routes it from
|
|
256
|
+
> there, and its Part B hotfix callout is what sends a **T2 / T3 post-hoc**
|
|
257
|
+
> to Step 1.8 — the only route that attaches `reconciled
|
|
258
|
+
> ({merged-hotfix-hash})`, the identity citation, and the per-tier hotfix
|
|
259
|
+
> trace, all of which a host recovered straight into 1.6 / 1.7 would silently
|
|
260
|
+
> lack. (A **T1** post-hoc is not a minimal host and is not this guard's
|
|
261
|
+
> business.)
|
|
262
|
+
>
|
|
263
|
+
> Either way, do not create a phase-spec, and do not treat this step as a
|
|
264
|
+
> zero-phase execution path.
|
|
265
|
+
|
|
266
|
+
Create the **feature directory** + **`_index.md`** + **first phase-spec** (T1
|
|
267
|
+
new feature):
|
|
212
268
|
|
|
213
269
|
```
|
|
214
270
|
dflow/specs/features/active/{SPEC-ID}-{slug}/
|
|
@@ -216,6 +272,8 @@ dflow/specs/features/active/{SPEC-ID}-{slug}/
|
|
|
216
272
|
└── phase-spec-{YYYY-MM-DD}-{slug}.md
|
|
217
273
|
```
|
|
218
274
|
|
|
275
|
+
> **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).
|
|
276
|
+
|
|
219
277
|
1. **Create the directory**: `dflow/specs/features/active/{SPEC-ID}-{slug}/`
|
|
220
278
|
2. **Create `_index.md`** using `templates/_index.md`:
|
|
221
279
|
- Metadata: fill `spec-id`, `slug`, `status: in-progress`, `created`, `branch`
|
|
@@ -391,7 +449,7 @@ During implementation, continuously verify:
|
|
|
391
449
|
**→ Step Gate: Step 7 → Step 8**
|
|
392
450
|
|
|
393
451
|
Announce to developer:
|
|
394
|
-
> "Implementation appears complete across all four layers. Ready to run the completion checklist (verify against spec, update domain docs + context-map, ensure test coverage,
|
|
452
|
+
> "Implementation appears complete across all four layers. Ready to run the completion checklist (verify against spec, update domain docs + context-map, ensure test coverage, complete the phase)? `/dflow:next` to proceed."
|
|
395
453
|
|
|
396
454
|
> 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.
|
|
397
455
|
|
|
@@ -414,7 +472,7 @@ AI reports `✓` / `✗` for every item before touching docs. Items marked *(pos
|
|
|
414
472
|
- [ ] Aggregate invariants still hold after the change (all state changes go through methods, no public setters)
|
|
415
473
|
- [ ] ORM / persistence mapping is kept outside Domain entities (no persistence attributes/annotations on Domain entities)
|
|
416
474
|
- [ ] *(post-8.3)* `dflow/specs/domain/{context}/behavior.md` contains a section anchor for every `BR-*` introduced by this spec (mechanical input for `/dflow:verify`)
|
|
417
|
-
- [ ] *(post-8.3)* `dflow/specs/domain/{context}/rules.md` `
|
|
475
|
+
- [ ] *(post-8.3)* for **every `BR-*` this spec introduced or changed**, that rule's row in `dflow/specs/domain/{context}/rules.md` carries a `Last updated` not earlier than this spec's `created` date (mechanical drift guard). ⚠ Quantified per-BR on purpose, like the item above: a T1 may legitimately introduce **no** BR (§ Ceremony Scaling step 0 admits it), and this then passes vacuously rather than blocking. `rules.md` has no document-level `last-updated` — it is a column in the Rule Index, which is what 8.3 sub-step B4 updates.
|
|
418
476
|
|
|
419
477
|
If any item fails, report the gap and pause — don't proceed to 8.2.
|
|
420
478
|
|
|
@@ -433,44 +491,67 @@ Ask these one-by-one; do not dump all six at once.
|
|
|
433
491
|
|
|
434
492
|
### 8.3 Documentation updates
|
|
435
493
|
|
|
494
|
+
> **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).
|
|
495
|
+
|
|
436
496
|
- [ ] `dflow/specs/domain/glossary.md` — new terms added
|
|
497
|
+
- [ ] `dflow/specs/domain/analysis.md` — ordered cross-context flows, role reach, or anything else no one context owns, that this feature introduced, found or altered; any spot this feature worked around pending a domain decision, in those or in unrecorded knowledge that belongs here; and any open row there this feature settled (created from `templates/analysis.md` the first time there is something to record)
|
|
437
498
|
- [ ] `dflow/specs/domain/{context}/models.md` — model definitions updated
|
|
499
|
+
- [ ] `dflow/specs/domain/{context}/analysis.md` — lifecycles, derived figures or mechanisms no single rule explains this feature introduced, found or altered, in the owning context's copy, which may not be this host's; any spot this feature worked around pending a domain decision, in those or in a rule or unrecorded knowledge that belongs there; and any open row there this feature settled (created from `templates/analysis.md` the first time there is something to record) — including the lifecycle any `aggregate-design.md` worksheet recorded as State Transition Methods: that worksheet freezes with the feature directory, this file does not
|
|
438
500
|
- [ ] `dflow/specs/domain/{context}/rules.md` — business rules updated
|
|
439
501
|
- [ ] `dflow/specs/domain/{context}/behavior.md` — merge completed spec's Given/When/Then scenarios (incl. Aggregate transitions + Events) into consolidated behavior. Sub-steps:
|
|
440
502
|
- Promote any Activity 3 (Spec Writing) draft sections (from B3 mid-sync) to formal sections
|
|
441
503
|
- Update the corresponding `rules.md` anchor's `last-updated` date (B4)
|
|
442
504
|
- [ ] `behavior.md` draft cleanup — if the spec was abandoned mid-way, keep the `## 提案中變更` section's history or explicitly REMOVE it
|
|
505
|
+
- [ ] `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.
|
|
443
506
|
- [ ] `dflow/specs/domain/{context}/events.md` — Domain Events updated
|
|
444
507
|
- [ ] `dflow/specs/domain/context-map.md` — updated if cross-context interaction was added or changed
|
|
445
508
|
- [ ] `dflow/specs/architecture/tech-debt.md` — tech debt discovered during implementation recorded
|
|
446
509
|
|
|
447
|
-
### 8.4
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
- [ ]
|
|
460
|
-
|
|
461
|
-
- [ ]
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
510
|
+
### 8.4 Phase completion and handoff
|
|
511
|
+
|
|
512
|
+
This step completes the phase and hands the feature on. It does not close the
|
|
513
|
+
feature out: `/dflow:finish-feature` is the only closeout path — it flips the
|
|
514
|
+
`_index.md` `status`, moves the feature directory to `completed/`, and takes
|
|
515
|
+
the closeout commit checkpoint.
|
|
516
|
+
|
|
517
|
+
**Complete this phase** — all four items, whether or not another phase
|
|
518
|
+
follows:
|
|
519
|
+
|
|
520
|
+
- [ ] This phase-spec's frontmatter `status` changed from `in-progress` to
|
|
521
|
+
`completed`
|
|
522
|
+
- [ ] This phase's row in the `_index.md` Phase Specs table changed from
|
|
523
|
+
`in-progress` to `completed`
|
|
524
|
+
- [ ] `_index.md` Current BR Snapshot reconciled against this phase-spec's
|
|
525
|
+
**Business Rules** section — this is the feature's first phase, so it
|
|
526
|
+
has no Delta from prior phases. If implementation changed a rule, update
|
|
527
|
+
the phase-spec first, then reconcile. Touch only this phase's rows: a
|
|
528
|
+
row that another change in this host wrote — a lightweight change
|
|
529
|
+
hosted under this feature, for example — stays as it is. Where this
|
|
530
|
+
phase and such a change both changed the same rule, keep the later
|
|
531
|
+
change's text; if the host's record does not show which change came
|
|
532
|
+
later, ask the developer which text is current instead of choosing.
|
|
533
|
+
- [ ] `_index.md` Resume Pointer: rewrite **both** narrative lines — Current
|
|
534
|
+
Progress says this phase is completed, and Next Action names the
|
|
535
|
+
command the handoff below picks. Step 4 wrote "phase-1 in progress:
|
|
536
|
+
drafting phase-spec." and "finish phase-spec, then implement …" into
|
|
537
|
+
these two lines; either one left standing reads as open work.
|
|
538
|
+
|
|
539
|
+
`/dflow:finish-feature` relies on these four whenever the feature reaches it,
|
|
540
|
+
next or after later phases. Its Step 1 checks the phase-spec `status`, the
|
|
541
|
+
Phase Specs row and the Resume Pointer, and stops closeout on a stale one.
|
|
542
|
+
Its Step 3 syncs the Current BR Snapshot into the bounded context as it
|
|
543
|
+
stands, without re-deriving it from the phase-specs.
|
|
544
|
+
|
|
545
|
+
`Implementation Tasks` is not on this list: 8.1 verified it, and 8.2 may have
|
|
546
|
+
collapsed or removed it by team convention. BC document sync is not on it
|
|
547
|
+
either: 8.3 did it.
|
|
548
|
+
|
|
549
|
+
**Hand off:**
|
|
550
|
+
|
|
551
|
+
- Another phase is still ahead → run `/dflow:new-phase` next.
|
|
552
|
+
- No further phase — a single-phase feature, or this was the last phase →
|
|
553
|
+
run `/dflow:finish-feature` next. It is the only closeout path.
|
|
554
|
+
|
|
555
|
+
Announce that this phase is completed and name the next command. Do not
|
|
556
|
+
announce the feature as complete: `/dflow:finish-feature` announces that once
|
|
557
|
+
its closeout is complete.
|