create-anpunkit 2.1.0 → 2.2.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/package.json +1 -1
- package/template/.claude/agents/e2e-runner.md +42 -25
- package/template/.claude/agents/implementer.md +13 -7
- package/template/.claude/agents/planner.md +66 -3
- package/template/.claude/agents/spec-author.md +118 -0
- package/template/.claude/agents/test-author.md +74 -64
- package/template/.claude/anpunkit-manifest.json +38 -18
- package/template/.claude/commands/overview.md +17 -0
- package/template/.claude/commands/phase.md +110 -63
- package/template/.cursor/commands/overview.md +17 -0
- package/template/.cursor/commands/phase.md +109 -62
- package/template/.gitattributes +1 -0
- package/template/AGENTS.md +163 -60
- package/template/CLAUDE.md +1 -0
- package/template/README.md +26 -15
- package/template/commands.src/overview.md +17 -0
- package/template/commands.src/phase.md +110 -63
- package/template/docs/DESIGN_LOG.md +192 -1
- package/template/index.html +1 -2
- package/template/scripts/spec-conformance.sh +93 -0
- package/template/scripts/spec-staleness.sh +115 -0
- package/template/tests/helpers/spec-assert.py +162 -0
- package/template/tests/helpers/spec-assert.ts +158 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Caveman ULTRA mode. You are the ORCHESTRATOR. Route work to subagents —
|
|
2
|
-
you do NOT implement or debug yourself.
|
|
2
|
+
you do NOT implement, fill specs, or debug yourself.
|
|
3
3
|
|
|
4
4
|
Note: subagents cannot talk to the user. Only YOU can.
|
|
5
5
|
|
|
@@ -24,20 +24,21 @@ b. PHASE STATE CHECK: Read docs/STATE.md and docs/PLAN.md.
|
|
|
24
24
|
c. FINAL PHASE CHECK: Read docs/PLAN.md. Is this the last phase (no further
|
|
25
25
|
pending phases after this one)? Record this as IS_FINAL_PHASE=true/false.
|
|
26
26
|
|
|
27
|
-
d. AUTH LIVENESS GATE (hard rule 16
|
|
28
|
-
|
|
27
|
+
d. AUTH LIVENESS GATE (hard rule 16): if this phase will run a boundary/E2E suite,
|
|
28
|
+
confirm every credential it needs is live NOW.
|
|
29
29
|
- If INFRA.md has no `AUTH PROOF: PASS` marker -> STOP: "Auth never proven
|
|
30
30
|
reusable. Run `/infra` first."
|
|
31
31
|
- Run `scripts/auth-setup.sh --check` (Entra token obtainable + not expired)
|
|
32
32
|
and, for each external system this phase touches (docs/DATAFLOW.md external
|
|
33
33
|
rows + docs/ENDPOINTS.md auth column), confirm its credential is obtainable
|
|
34
|
-
headlessly. Any failure ->
|
|
34
|
+
headlessly. Any failure -> boundary/E2E is BLOCKED; tell me what to run; the
|
|
35
35
|
MOCK suite may still proceed.
|
|
36
36
|
|
|
37
37
|
e. FRONTEND TRIGGER (hard rule 13): read docs/OVERVIEW.md `has_frontend` + the
|
|
38
38
|
frontend root. Set FRONTEND_PHASE=true iff `has_frontend: true` AND this
|
|
39
39
|
phase's `changes` (docs/PLAN.md) include any path under the frontend root.
|
|
40
|
-
This is a PATH MATCH, not a judgment call. Record FRONTEND_PHASE
|
|
40
|
+
This is a PATH MATCH, not a judgment call. Record FRONTEND_PHASE — it gates the
|
|
41
|
+
`ui` boundary run + evidence at CLOSE.
|
|
41
42
|
|
|
42
43
|
---
|
|
43
44
|
|
|
@@ -52,8 +53,9 @@ datasource, compare what it touches to the confirmed BASELINE in
|
|
|
52
53
|
docs/research/datasource-<name>.md. If it touches a NEW table/column beyond the
|
|
53
54
|
baseline -> surface my understanding of just that delta as a falsifiable claim;
|
|
54
55
|
WAIT for confirm; append it to datasource-<name>.md. If it touches only confirmed
|
|
55
|
-
data -> proceed with a one-line note, no stop.
|
|
56
|
-
datasource is HARD-BLOCKED (mock still runs).
|
|
56
|
+
data -> proceed with a one-line note, no stop. Boundary/E2E against an UNCONFIRMED
|
|
57
|
+
datasource is HARD-BLOCKED (mock still runs). The confirmed baseline is what
|
|
58
|
+
`spec-author` grounds fixtures in.
|
|
57
59
|
|
|
58
60
|
Then classify the phase:
|
|
59
61
|
|
|
@@ -61,63 +63,105 @@ Then classify the phase:
|
|
|
61
63
|
exported function/class, CLI command, message contract) assertable from the
|
|
62
64
|
acceptance spec. Size is NOT the criterion.
|
|
63
65
|
|
|
64
|
-
- Clear public surface -> `TDD_PHASE=true` -> run the TDD path (§2 → §
|
|
66
|
+
- Clear public surface -> `TDD_PHASE=true` -> run the TDD path (§2 → §3 → §4 → §5 → §6 → §7).
|
|
65
67
|
- Pure infra/config/doc, no public surface -> `TDD_PHASE=false` -> run the
|
|
66
68
|
non-TDD path (§2N → §3N).
|
|
67
69
|
- AMBIGUOUS -> default `TDD_PHASE=true`, but STATE the classification + the reason
|
|
68
|
-
to me, so I can override to non-TDD BEFORE
|
|
69
|
-
downgrade a TDD phase just to dodge the
|
|
70
|
+
to me, so I can override to non-TDD BEFORE SPEC fill fires. (Hard rule 11: never
|
|
71
|
+
downgrade a TDD phase just to dodge the gates.)
|
|
70
72
|
|
|
71
73
|
=====================================================================
|
|
72
74
|
## TDD PATH (TDD_PHASE=true)
|
|
73
75
|
=====================================================================
|
|
74
76
|
|
|
75
|
-
## 2.
|
|
77
|
+
## 2. SPEC FILL + STALENESS
|
|
78
|
+
|
|
79
|
+
a. SKELETON CHECK: confirm docs/spec-phase-<n>.md exists (planner generated it at
|
|
80
|
+
/overview). If MISSING (planner classified it non-TDD, or it's a new phase from
|
|
81
|
+
/replan): generate the skeleton NOW from this phase's PLAN.md `acceptance` +
|
|
82
|
+
`dataflow:` transitions in the planner skeleton format (generated header + named
|
|
83
|
+
`TBD` rows), then `bash scripts/spec-staleness.sh stamp <n>` to stamp its hash.
|
|
84
|
+
|
|
85
|
+
b. Dispatch `spec-author`. It fills each case row with a real input payload
|
|
86
|
+
(`fixtures/<case-id>-input.json`), concrete expected output
|
|
87
|
+
(`fixtures/<case-id>-expected.json`), matcher tokens for volatile fields,
|
|
88
|
+
`error-code` for failures, and `selector/assert/value` `ui` descriptors —
|
|
89
|
+
grounded in the RESEARCH findings + the confirmed datasource baseline.
|
|
90
|
+
|
|
91
|
+
c. CASE-SET-DIVERGENCE (hard re-entry, hard rule 12 / §5.52): if `spec-author`
|
|
92
|
+
returns `CASE-SET-DIVERGENCE` (a required case can't be filled from real facts,
|
|
93
|
+
or research revealed an unlisted/contradicted case) -> STOP. Surface the finding.
|
|
94
|
+
I amend the up-front case-name contract in the skeleton; you re-stamp
|
|
95
|
+
(`bash scripts/spec-staleness.sh stamp <n>`); then re-dispatch `spec-author` to
|
|
96
|
+
re-fill from scratch. AI never amends the case-name set — I own the contract.
|
|
97
|
+
|
|
98
|
+
d. STALENESS (hard rule 17): run `bash scripts/spec-staleness.sh <n>`. Nonzero
|
|
99
|
+
(upstream PLAN acceptance line / DATAFLOW rows drifted since the skeleton was
|
|
100
|
+
stamped, e.g. via /replan) -> regenerate the skeleton header from current
|
|
101
|
+
PLAN/DATAFLOW, re-stamp, re-dispatch `spec-author`. Do NOT hand-edit the hash.
|
|
102
|
+
|
|
103
|
+
## 3. SPEC REVIEW — human gate (hard rule 12)
|
|
104
|
+
|
|
105
|
+
STOP. Surface the FILLED cases to me as FALSIFIABLE CLAIMS in plain language, e.g.:
|
|
106
|
+
- "POST /orders/submit with an empty line-item list → 422 EMPTY_ORDER."
|
|
107
|
+
- "Successful submit of a 3-line order → 201; order.id is a UUID; order.status is
|
|
108
|
+
'submitted'."
|
|
109
|
+
Re-run `bash scripts/spec-staleness.sh <n>` at entry (nonzero -> back to §2d).
|
|
110
|
+
SCAFFOLD cannot begin until I confirm. Classify any rejection WITH me (§5.50):
|
|
111
|
+
- WRONG EXPECTED -> fix the case row + `fixtures/<case-id>-expected.json`; no
|
|
112
|
+
re-research. (You may patch the fixture directly per my correction.)
|
|
113
|
+
- WRONG INPUT SHAPE -> re-dispatch `spec-author` with the correction.
|
|
114
|
+
- NEW CASE or CONTRADICTED CASE -> hard re-entry (§2c): I amend the skeleton, you
|
|
115
|
+
re-stamp, re-confirm the amended case(s) + any case sharing their `covers` id
|
|
116
|
+
(the staleness hash certifies the unchanged remainder — not re-read), re-fill.
|
|
117
|
+
Loop until I approve. Unskippable on TDD phases.
|
|
118
|
+
|
|
119
|
+
## 4. SCAFFOLD
|
|
76
120
|
|
|
77
121
|
Dispatch `implementer` in SCAFFOLD mode: interface stubs only (signatures +
|
|
78
|
-
types; bodies raise NotImplementedError / return 501); NO logic, NO tests
|
|
79
|
-
Returns the stub files + the interface surface.
|
|
122
|
+
types; bodies raise NotImplementedError / return 501); NO logic, NO tests, NO
|
|
123
|
+
edits to the spec or fixtures. Returns the stub files + the interface surface.
|
|
80
124
|
|
|
81
|
-
##
|
|
125
|
+
## 5. RED
|
|
82
126
|
|
|
83
|
-
Dispatch `test-author` to
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
tests in `tests/
|
|
127
|
+
Dispatch `test-author` to EMIT the boundary harness from the locked spec `data`
|
|
128
|
+
rows: one deep-equality assertion per case against `fixtures/<case-id>-expected.json`
|
|
129
|
+
via the kit comparator `tests/helpers/spec-assert.*`, each citing its case with a
|
|
130
|
+
`# spec: <case-id>` comment. It does NOT author assertions — it generates them from
|
|
131
|
+
the spec. Place contract/ENDPOINTS/transition tests in `tests/regression/`,
|
|
132
|
+
phase-local in `tests/phase-<n>/`.
|
|
88
133
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
134
|
+
If FRONTEND_PHASE (and the phase has `ui` cases): also dispatch `e2e-runner` to EMIT
|
|
135
|
+
Playwright assertions from each `ui` case's `fixtures/<case-id>-ui.json` descriptor,
|
|
136
|
+
each citing `// spec: <case-id>`. Run the suites.
|
|
137
|
+
|
|
138
|
+
RED GATE = every case test COLLECTS cleanly AND FAILS (assertion / NotImplemented).
|
|
139
|
+
- Any test PASSES on stubs -> STOP (spec trivial or emitter wrong); show me.
|
|
92
140
|
- Collection / import / syntax error -> stub mismatch; re-dispatch SCAFFOLD to
|
|
93
141
|
fix SIGNATURES (not logic); re-run.
|
|
94
|
-
- UNDERSPEC -> STOP; ask me to sharpen the acceptance spec.
|
|
95
142
|
|
|
96
|
-
##
|
|
143
|
+
## 6. CONFORMANCE GATE (hard rule 18) — replaces the v2.1 human TEST REVIEW
|
|
97
144
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- UNDERSPEC (the acceptance spec itself is too vague) -> sharpen the acceptance
|
|
104
|
-
spec in docs/PLAN.md, then re-dispatch `test-author` fresh.
|
|
105
|
-
Loop until I approve. This gate is unskippable on TDD phases.
|
|
145
|
+
Run `bash scripts/spec-conformance.sh <n>`. It loud-fails (and BLOCKS GREEN) if:
|
|
146
|
+
- any `TBD` marker remains in docs/spec-phase-<n>.md or a referenced fixture, OR
|
|
147
|
+
- any case-id in the spec table has no boundary test citing it (`# spec: <case-id>`).
|
|
148
|
+
Nonzero -> fix the gap (re-dispatch `spec-author` for a stray TBD, or `test-author`/
|
|
149
|
+
`e2e-runner` for a missing citation) and re-run. GREEN cannot start until it passes.
|
|
106
150
|
|
|
107
|
-
##
|
|
151
|
+
## 7. GREEN + BOUNDARY/E2E
|
|
108
152
|
|
|
109
|
-
Dispatch `implementer` in FILL mode with the
|
|
110
|
-
file paths (it MAY read the tests — frozen
|
|
111
|
-
|
|
153
|
+
Dispatch `implementer` in FILL mode with the FILLED docs/spec-phase-<n>.md + its
|
|
154
|
+
fixtures + research + the generated test file paths (it MAY read the tests — frozen
|
|
155
|
+
before logic, no overfit — but must NOT edit tests, spec, or fixtures). Fill to
|
|
156
|
+
green against the spec. Budget 3, WARN@2, STUCK@3.
|
|
112
157
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/ Playwright / `down`, and captures a
|
|
116
|
-
regardless of pass/fail to
|
|
117
|
-
docs/research/e2e-<slug>.md.
|
|
118
|
-
e2e-runner returns UNDERSPEC -> STOP, sharpen the spec.
|
|
158
|
+
Run the BOUNDARY suite (real HTTP/CLI/message; `TEST_MODE=real`). If FRONTEND_PHASE,
|
|
159
|
+
`e2e-runner` runs its emitted `ui` specs — MANDATORY (hard rule 13) — reads INFRA.md
|
|
160
|
+
target, runs `scripts/e2e-stack.sh up` / Playwright / `down`, and captures a
|
|
161
|
+
screenshot at EACH UI-existence assertion regardless of pass/fail to
|
|
162
|
+
docs/evidence/e2e-phase-<n>/, with a summary in docs/research/e2e-<slug>.md.
|
|
119
163
|
|
|
120
|
-
PHASE GATE (rule 5) -> go to §
|
|
164
|
+
PHASE GATE (rule 5) -> go to §8/§9/§10 (see GATE below).
|
|
121
165
|
|
|
122
166
|
=====================================================================
|
|
123
167
|
## NON-TDD PATH (TDD_PHASE=false)
|
|
@@ -132,18 +176,19 @@ includes "deployed URL" before proceeding.
|
|
|
132
176
|
|
|
133
177
|
## 3N. TEST (blind)
|
|
134
178
|
|
|
135
|
-
Dispatch `test-author`. It writes MOCK +
|
|
136
|
-
spec — never reads the logic. (No
|
|
137
|
-
public surface to
|
|
179
|
+
Dispatch `test-author`. It writes MOCK + boundary suites from the acceptance
|
|
180
|
+
spec — never reads the logic. (No spec file, SPEC REVIEW, or conformance gate on
|
|
181
|
+
the non-TDD path — no public surface to contract. e2e-runner only if FRONTEND_PHASE.)
|
|
138
182
|
|
|
139
183
|
=====================================================================
|
|
140
184
|
|
|
141
185
|
## GATE (both paths)
|
|
142
186
|
|
|
143
|
-
PHASE GATE = current-phase
|
|
144
|
-
WITH evidence captured AND the accumulated mock regression corpus
|
|
145
|
-
every docs/ENDPOINTS.md entry has a regression test AND
|
|
146
|
-
docs/DATAFLOW.md transition has a
|
|
187
|
+
PHASE GATE = current-phase BOUNDARY suite passes AND (FRONTEND_PHASE) the `ui`
|
|
188
|
+
boundary passes WITH evidence captured AND the accumulated mock regression corpus
|
|
189
|
+
stays green AND every docs/ENDPOINTS.md entry has a regression test AND (TDD)
|
|
190
|
+
`spec-conformance.sh` passed AND every REACHABLE docs/DATAFLOW.md transition has a
|
|
191
|
+
filled case in the phase spec (all checked at CLOSE).
|
|
147
192
|
- GATE PASS -> go to CLOSE.
|
|
148
193
|
- GATE BLOCKED (SERVICE UNAVAILABLE, STACK NOT READY, AZURE UNAVAILABLE, FLAKE)
|
|
149
194
|
-> tell me, wait. Not a code bug. For AZURE UNAVAILABLE: suggest `/infra verify`.
|
|
@@ -151,17 +196,17 @@ docs/DATAFLOW.md transition has a regression test (all checked at CLOSE).
|
|
|
151
196
|
|
|
152
197
|
---
|
|
153
198
|
|
|
154
|
-
##
|
|
199
|
+
## 8. FIX
|
|
155
200
|
|
|
156
201
|
Dispatch `debugger` (isolated context) on the specific failure.
|
|
157
|
-
- FIXED -> re-run
|
|
202
|
+
- FIXED -> re-run the boundary suite (and the regression corpus).
|
|
158
203
|
- SERVICE UNAVAILABLE -> tell me, wait. Suggest `/infra verify` if Azure.
|
|
159
204
|
- WARN (2 attempts failed) -> relay immediately, then let debugger finish attempt 3.
|
|
160
205
|
- STUCK -> go to ESCALATE.
|
|
161
206
|
|
|
162
207
|
---
|
|
163
208
|
|
|
164
|
-
##
|
|
209
|
+
## 9. ESCALATE — circuit breaker. Mode B.
|
|
165
210
|
|
|
166
211
|
FIRST STUCK: STOP. Present to me: the problem, 3 failed hypotheses, the
|
|
167
212
|
debugger's recommendation, the debug file path. Ask what to do. Wait. Options:
|
|
@@ -174,20 +219,22 @@ what to try next. Hand control to me.
|
|
|
174
219
|
|
|
175
220
|
---
|
|
176
221
|
|
|
177
|
-
##
|
|
222
|
+
## 10. CLOSE
|
|
178
223
|
|
|
179
224
|
REGRESSION + COVERAGE GATES (before closing — all FAIL HARD, do not close):
|
|
180
|
-
- Run `scripts/regression.sh` (mock corpus). A failure BLOCKS close -> route to FIX.
|
|
225
|
+
- Run `bash scripts/regression.sh` (mock corpus). A failure BLOCKS close -> route to FIX.
|
|
181
226
|
- ENDPOINTS COVERAGE: every `docs/ENDPOINTS.md` entry MUST have >=1 test in
|
|
182
227
|
`tests/regression/`. Zero coverage -> FAIL HARD.
|
|
183
|
-
- DATAFLOW COVERAGE (hard rule 14): every `docs/DATAFLOW.md`
|
|
184
|
-
trigger is REACHABLE in the code shipped so far MUST have >=1
|
|
185
|
-
|
|
186
|
-
Unreachable transitions list as PENDING (not failed). IF
|
|
187
|
-
transition still PENDING -> FAIL HARD (
|
|
228
|
+
- DATAFLOW COVERAGE (hard rule 14, re-seamed v2.2): every `docs/DATAFLOW.md`
|
|
229
|
+
transition whose trigger is REACHABLE in the code shipped so far MUST have >=1
|
|
230
|
+
FILLED CASE in docs/spec-phase-<n>.md. Zero coverage on a reachable transition ->
|
|
231
|
+
FAIL HARD. Unreachable transitions list as PENDING (not failed). IF
|
|
232
|
+
IS_FINAL_PHASE: any transition still PENDING -> FAIL HARD. (The case→test half is
|
|
233
|
+
already enforced by `spec-conformance.sh` at §6 — every case-id is cited by a
|
|
234
|
+
boundary test, which by placement lands in tests/regression/.)
|
|
188
235
|
- EVIDENCE (FRONTEND_PHASE only, hard rule 13): docs/evidence/e2e-phase-<n>/ must
|
|
189
236
|
contain at least the per-UI-existence-assertion screenshots. Empty -> FAIL HARD.
|
|
190
|
-
- IF IS_FINAL_PHASE: additionally run `scripts/regression.sh --real` (full real
|
|
237
|
+
- IF IS_FINAL_PHASE: additionally run `bash scripts/regression.sh --real` (full real
|
|
191
238
|
corpus). A failure blocks close.
|
|
192
239
|
|
|
193
240
|
Mark phase `done` in docs/PLAN.md.
|
|
@@ -197,7 +244,7 @@ ARCHITECTURE / DATAFLOW SELF-CHECK:
|
|
|
197
244
|
workflow rule? YES -> run `/log-decision`. NO -> state why not.
|
|
198
245
|
- Did this phase add/change an object's STATE LIFECYCLE? YES -> update
|
|
199
246
|
docs/DATAFLOW.md (hard rule 9) in this CLOSE, and confirm new reachable
|
|
200
|
-
transitions are covered. NO -> state why not.
|
|
247
|
+
transitions are covered by a filled case. NO -> state why not.
|
|
201
248
|
|
|
202
249
|
IF IS_FINAL_PHASE — FINAL CLOSE sequence:
|
|
203
250
|
|
package/template/.gitattributes
CHANGED
package/template/AGENTS.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# anpunkit — portable agent methodology (single source of truth)
|
|
2
2
|
|
|
3
|
-
<!-- ANPUNKIT-AGENTS-SENTINEL-v2.
|
|
4
|
-
> **SENTINEL.** The HTML comment above (`ANPUNKIT-AGENTS-SENTINEL-v2.
|
|
5
|
-
> load-bearing marker. `setup.sh` greps for
|
|
6
|
-
> disk and was not clobbered. Do not remove or
|
|
3
|
+
<!-- ANPUNKIT-AGENTS-SENTINEL-v2.2 -->
|
|
4
|
+
> **SENTINEL.** The HTML comment above (`ANPUNKIT-AGENTS-SENTINEL-v2.2`) is a
|
|
5
|
+
> load-bearing marker. `setup.sh` greps for the bare prefix `ANPUNKIT-AGENTS-SENTINEL`
|
|
6
|
+
> to confirm this file resolved on disk and was not clobbered. Do not remove or
|
|
7
|
+
> rename it.
|
|
7
8
|
|
|
8
9
|
> **What this file is.** The complete, tool-agnostic methodology for the anpunkit
|
|
9
10
|
> workflow: the loop, the roles, the procedures, the rituals, and the hard rules.
|
|
@@ -31,7 +32,7 @@ A phase runs in one of two orders, chosen at RESEARCH time by the TDD
|
|
|
31
32
|
APPLICABILITY check (see Procedures → `phase`):
|
|
32
33
|
|
|
33
34
|
- **TDD phase** (`TDD_PHASE=true`):
|
|
34
|
-
`RESEARCH ->
|
|
35
|
+
`RESEARCH -> SPEC fill -> spec-staleness -> SPEC REVIEW -> SCAFFOLD -> RED -> spec-conformance -> GREEN -> boundary/E2E -> FIX -> CLOSE`
|
|
35
36
|
- **Non-TDD phase** (pure infra / config / doc — `TDD_PHASE=false`):
|
|
36
37
|
`RESEARCH -> IMPLEMENT -> TEST -> FIX -> CLOSE`
|
|
37
38
|
|
|
@@ -39,23 +40,44 @@ APPLICABILITY check (see Procedures → `phase`):
|
|
|
39
40
|
exported function/class, CLI command, or message contract) that is assertable
|
|
40
41
|
from the acceptance spec." Size is NOT the criterion. On ambiguity, default
|
|
41
42
|
`TDD_PHASE=true` AND state the classification + reason so a human can override to
|
|
42
|
-
non-TDD before
|
|
43
|
-
|
|
44
|
-
**
|
|
45
|
-
between
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
non-TDD before SPEC fill fires.
|
|
44
|
+
|
|
45
|
+
**SPEC REVIEW (v2.2)** is the mandatory human gate on every TDD phase, sitting
|
|
46
|
+
UPSTREAM — between RESEARCH and SCAFFOLD, before any code. The reviewable,
|
|
47
|
+
authoritative artifact is the SPEC, not the test. After RESEARCH, `spec-author`
|
|
48
|
+
fills `docs/spec-phase-<n>.md` (skeleton case-names generated at `/overview`) with
|
|
49
|
+
concrete observable behavior — real input payloads, real expected outputs, matcher
|
|
50
|
+
tokens for volatile fields — grounded in fresh per-phase research and the confirmed
|
|
51
|
+
datasource baseline. `scripts/spec-staleness.sh` then loud-fails if the upstream
|
|
52
|
+
`acceptance:` line or `DATAFLOW.md` transition rows drifted since the skeleton was
|
|
53
|
+
generated. The orchestrator surfaces the filled cases as FALSIFIABLE CLAIMS
|
|
54
|
+
("POST /orders/submit with an empty line-item list → 422 EMPTY_ORDER"); SCAFFOLD
|
|
55
|
+
cannot fire until the human confirms. Rejection is classified at the gate (§5.50):
|
|
56
|
+
wrong expected → fix the case row + fixture; wrong input shape → re-dispatch
|
|
57
|
+
`spec-author`; a new or contradicted case → hard re-entry to amend the up-front
|
|
58
|
+
case-name contract (§5.52). Tests are then GENERATED from the locked spec rows
|
|
59
|
+
(deep-equality + matcher tokens for `data`; Playwright from the descriptor for
|
|
60
|
+
`ui`) — humans never review test code. This is the fix for "both agents
|
|
61
|
+
independently fabricated the same wrong contract from a one-line acceptance and the
|
|
62
|
+
suite went green on a broken core." (§5.43–§5.50)
|
|
63
|
+
|
|
64
|
+
**Boundary test is the system-of-record per case (v2.2).** Every spec case has
|
|
65
|
+
exactly one OUTER-BOUNDARY test — `data` cases: a real HTTP call / CLI invocation /
|
|
66
|
+
real message against the running backend + real services (v2.1's "real API suite");
|
|
67
|
+
`ui` cases: a Playwright assertion against the deployed (or local-docker) target
|
|
68
|
+
(v2.1's "E2E"). The boundary test is the phase gate; green mock alone never closes a
|
|
69
|
+
phase. A mock mirror is optional and shares the SAME fixture + comparator via a
|
|
70
|
+
`TEST_MODE` flag, so it cannot assert different values than the boundary test. (§5.47)
|
|
71
|
+
|
|
72
|
+
**E2E is mandatory, not a judgment call.** If the project is frontend-bearing
|
|
55
73
|
(`has_frontend: true` in `docs/OVERVIEW.md`) AND the phase's `changes` touch the
|
|
56
|
-
frontend root recorded in OVERVIEW.md, `
|
|
57
|
-
trigger is a deterministic path match, not "does this phase feel frontend-y." A
|
|
58
|
-
frontend file changed with no
|
|
74
|
+
frontend root recorded in OVERVIEW.md, `ui` boundary cases MUST run before CLOSE.
|
|
75
|
+
The trigger is a deterministic path match, not "does this phase feel frontend-y." A
|
|
76
|
+
frontend file changed with no `ui` boundary run is a loud CLOSE failure. `e2e-runner`
|
|
77
|
+
EMITS the Playwright assertion from each case's `ui` descriptor (it no longer authors
|
|
78
|
+
blind) and retains screenshot-on-each-UI-existence-assertion as the visual backstop.
|
|
79
|
+
On `has_frontend: false` projects there is no browser: `ui` case rows are invalid and
|
|
80
|
+
all cases are `data` boundary. (§5.34, §5.54)
|
|
59
81
|
|
|
60
82
|
-----
|
|
61
83
|
|
|
@@ -81,24 +103,46 @@ can. Escalation is at most two hops.
|
|
|
81
103
|
`changes` touch the frontend root, the `acceptance` MUST include ≥1 UI-existence
|
|
82
104
|
criterion naming the specific user-visible interactive element introduced (not
|
|
83
105
|
"page renders 200"). Populates each phase's expected `DATAFLOW.md` transitions.
|
|
106
|
+
At `/overview` it ALSO enumerates the up-front CASE-NAME contract (§5.44): for
|
|
107
|
+
every `DATAFLOW.md` transition and every `acceptance:` criterion in a TDD phase,
|
|
108
|
+
the case *names* that must exist (happy path, each named edge, each named failure
|
|
109
|
+
+ error code) — no fixture values yet — written as skeleton `docs/spec-phase-<n>.md`
|
|
110
|
+
files (generated header + named rows, values `TBD`).
|
|
111
|
+
- **spec-author** — fills the per-phase spec. Runs AFTER RESEARCH, BEFORE SPEC
|
|
112
|
+
REVIEW. Reads the skeleton `spec-phase-<n>.md`, the confirmed
|
|
113
|
+
`datasource-<name>.md` baseline, and per-phase RESEARCH for the real API shape;
|
|
114
|
+
fills each case row with a real input payload (`fixtures/<case-id>-input.json`),
|
|
115
|
+
concrete expected output (`fixtures/<case-id>-expected.json`), matcher tokens for
|
|
116
|
+
volatile fields, `error-code` for failures, and `selector/assert/value` for `ui`
|
|
117
|
+
cases. Returns `CASE-SET-DIVERGENCE` if a required case cannot be filled from real
|
|
118
|
+
facts, or research reveals an unlisted branch/failure-mode. `spec-author` is NOT
|
|
119
|
+
`implementer` (author ≠ implementer invariant, §5.53) and never reads
|
|
120
|
+
implementation logic.
|
|
84
121
|
- **infra-provisioner** — generates Bicep, runs `az deployment what-if`, applies
|
|
85
122
|
only on human approval, writes `docs/INFRA.md` + `.env.test`. Runs the one-time
|
|
86
123
|
AUTH PROOF (§5.37): proves every credential the project's real tests will use is
|
|
87
124
|
obtainable headlessly twice in a row (prime + reuse) with zero prompts.
|
|
88
125
|
- **implementer** — builds ONE phase. Two MODES for TDD phases (SCAFFOLD: stubs
|
|
89
126
|
only; FILL: logic to green) plus a legacy full-build mode for non-TDD phases.
|
|
90
|
-
Writes code, never tests.
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
`
|
|
127
|
+
Writes code, never tests. On TDD phases it reads the human-approved filled
|
|
128
|
+
`docs/spec-phase-<n>.md` as its behavioral contract (normal spec-driven
|
|
129
|
+
development) — it never authors spec fixtures (author ≠ implementer, §5.53).
|
|
130
|
+
Maintains `docs/ENDPOINTS.md` each phase.
|
|
131
|
+
- **test-author** — now a HARNESS EMITTER, not a blind assertion author (§5.53). On
|
|
132
|
+
TDD phases it reads the locked spec rows and GENERATES the assertion harness: one
|
|
133
|
+
deep-equality assertion against `fixtures/<case-id>-expected.json` per `data` case,
|
|
134
|
+
citing the case with a `# spec: <case-id>` comment, using the kit-versioned
|
|
135
|
+
comparator `tests/helpers/spec-assert.*` (which honors matcher tokens). It does
|
|
136
|
+
not invent assertions — there is nothing for a human to review at the test layer.
|
|
137
|
+
Places contract/transition tests in `tests/regression/`, phase-local in
|
|
138
|
+
`tests/phase-<n>/`; mock-vs-boundary is a `TEST_MODE` flag on the SAME test.
|
|
139
|
+
- **e2e-runner** — now a Playwright EMITTER for `ui` boundary cases, not a blind
|
|
140
|
+
author (§5.54). Reads `docs/INFRA.md` for the target and each `ui` case's
|
|
141
|
+
`fixtures/<case-id>-ui.json` descriptor (`selector / assert / value`, closed
|
|
142
|
+
vocabulary: `visible | text-equals | enabled | count`), and emits the assertion.
|
|
143
|
+
Captures a screenshot at EACH UI-existence assertion regardless of pass/fail
|
|
144
|
+
(capture-on-success) to `docs/evidence/e2e-phase-<n>/`, plus a summary in
|
|
145
|
+
`docs/research/e2e-<slug>.md`.
|
|
102
146
|
- **debugger** — debugs in an ISOLATED context. Writes a trace to
|
|
103
147
|
`docs/research/debug-<slug>.md`; returns a summary.
|
|
104
148
|
- **synthesizer** — compresses `docs/STATE.md` / `docs/ISSUES.md`, prunes
|
|
@@ -116,14 +160,19 @@ generated copy per tool (`.claude/commands/`, `.cursor/commands/`).
|
|
|
116
160
|
- **overview** — bootstrap a project: design-research → grill r1 → design-research
|
|
117
161
|
→ RESEARCH REVIEW → re-grill r2 (covers data structures, dataflow, and object
|
|
118
162
|
state flow) → `OVERVIEW.md` (+ `has_frontend`/frontend-root, `DATAFLOW.md`,
|
|
119
|
-
confirmed datasource understanding) → planner → `PLAN.md` (Phase 0 always first)
|
|
163
|
+
confirmed datasource understanding) → planner → `PLAN.md` (Phase 0 always first)
|
|
164
|
+
+ skeleton `docs/spec-phase-<n>.md` case-name files. The end-of-`/overview` human
|
|
165
|
+
approval is EXTENDED to confirm the cross-phase skeleton case-name set in the same
|
|
166
|
+
surface (no new gate, §5.51).
|
|
120
167
|
- **infra** — provision/verify Azure infra: Bicep → what-if → human review → apply
|
|
121
168
|
→ `INFRA.md` + `.env.test`. Runs the one-time AUTH PROOF.
|
|
122
169
|
- **phase [n]** — run one phase end-to-end with the circuit breaker. Chooses the
|
|
123
170
|
TDD or non-TDD order at RESEARCH. PRE-FLIGHT runs the auth liveness check. TDD
|
|
124
|
-
phases
|
|
125
|
-
|
|
126
|
-
|
|
171
|
+
phases: `spec-author` fills the spec → `spec-staleness.sh` → SPEC REVIEW (human,
|
|
172
|
+
before SCAFFOLD) → SCAFFOLD → RED (generated harness) → `spec-conformance.sh` →
|
|
173
|
+
GREEN → boundary/E2E. Frontend phases run mandatory `ui` boundary with screenshot
|
|
174
|
+
evidence. CLOSE runs the regression guard + ENDPOINTS coverage gate + DATAFLOW
|
|
175
|
+
transition→case coverage gate + evidence-present check.
|
|
127
176
|
- **quick [change]** — small, obvious, non-phase change; no agent chain. Stays
|
|
128
177
|
non-TDD. Runs the mock regression corpus after the change.
|
|
129
178
|
- **unstuck** — deep re-research after a circuit breaker (human-triggered).
|
|
@@ -161,7 +210,7 @@ recover: current phase, next action, open blocker.
|
|
|
161
210
|
|
|
162
211
|
-----
|
|
163
212
|
|
|
164
|
-
## Hard rules (1–
|
|
213
|
+
## Hard rules (1–19)
|
|
165
214
|
|
|
166
215
|
1. Before debugging ANY error: grep `docs/ISSUES.md` AND `docs/research/INDEX.md`.
|
|
167
216
|
The SESSION-OPEN ritual surfaces ISSUES.md — there is no excuse to miss it.
|
|
@@ -170,15 +219,21 @@ recover: current phase, next action, open blocker.
|
|
|
170
219
|
3. Every resolved error -> logged to `docs/ISSUES.md` with root cause + failed
|
|
171
220
|
attempts.
|
|
172
221
|
4. End of phase -> synthesize -> context reset -> next phase.
|
|
173
|
-
5. **PHASE GATE** =
|
|
174
|
-
|
|
175
|
-
regression corpus stays green AND every `docs/ENDPOINTS.md`
|
|
176
|
-
one test in `tests/regression/` AND
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
222
|
+
5. **PHASE GATE** = every current-phase spec case's BOUNDARY test passes (`data`:
|
|
223
|
+
real HTTP/CLI/message; `ui`: Playwright with screenshot evidence) AND the
|
|
224
|
+
accumulated mock regression corpus stays green AND every `docs/ENDPOINTS.md`
|
|
225
|
+
entry has at least one test in `tests/regression/` AND `spec-conformance.sh`
|
|
226
|
+
passed (no TBD, every case-id cited by a boundary test) AND every REACHABLE
|
|
227
|
+
`docs/DATAFLOW.md` transition has at least one filled case in the phase spec
|
|
228
|
+
(rule 14). The final phase additionally runs the full REAL regression corpus and
|
|
229
|
+
requires zero PENDING transitions. A green mock suite alone can never close a phase.
|
|
230
|
+
6. On TDD phases the behavioral contract is the human-approved
|
|
231
|
+
`docs/spec-phase-<n>.md`; tests are GENERATED from its case rows (not authored):
|
|
232
|
+
`test-author` emits a deep-equality harness against the shared fixtures for
|
|
233
|
+
`data` cases, `e2e-runner` emits Playwright from the `ui` descriptor. Because the
|
|
234
|
+
spec row and the test load the SAME fixture, a test physically cannot assert
|
|
235
|
+
different values than the locked spec. Humans review the spec (SPEC REVIEW), never
|
|
236
|
+
the tests.
|
|
182
237
|
7. Service outage is not a bug — `SERVICE UNAVAILABLE` / `AZURE UNAVAILABLE` /
|
|
183
238
|
`STACK NOT READY` / `FLAKE` do not spend the debug budget. Only `LOGIC FAIL`
|
|
184
239
|
reaches the debugger.
|
|
@@ -192,24 +247,36 @@ recover: current phase, next action, open blocker.
|
|
|
192
247
|
11. **No-rationalization (scoped).** Do not, in order to dodge a gate:
|
|
193
248
|
downgrade a TDD phase to non-TDD or route phase-worthy work through `quick`
|
|
194
249
|
(RED gate); set `has_frontend: false` or keep a touched element out of the
|
|
195
|
-
acceptance spec (E2E / UI-existence gate);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
250
|
+
acceptance spec (E2E / UI-existence gate); fabricate a fixture value or leave a
|
|
251
|
+
`TBD` to slip past SPEC REVIEW / conformance instead of escalating UNDERSPEC or
|
|
252
|
+
`CASE-SET-DIVERGENCE`; mark a reachable transition PENDING (DATAFLOW gate); or
|
|
253
|
+
skip evidence capture. (Scoped deliberately to these named seams; this is not a
|
|
254
|
+
broad "never make excuses" rule.)
|
|
255
|
+
12. **SPEC REVIEW (TDD phases).** SCAFFOLD cannot begin until the human confirms the
|
|
256
|
+
filled `docs/spec-phase-<n>.md` cases, surfaced as falsifiable claims. Rejection
|
|
257
|
+
is classified at the gate (§5.50): wrong expected → fix case row + fixture; wrong
|
|
258
|
+
input shape → re-dispatch `spec-author`; new or contradicted case → hard re-entry
|
|
259
|
+
to amend the up-front case-name contract, re-confirm the amended + same-`covers`
|
|
260
|
+
neighbor cases (staleness-hash certifies the unchanged remainder), then re-fill
|
|
261
|
+
(§5.52). Unskippable on TDD phases; absent on the non-TDD path (no behavioral
|
|
262
|
+
contract to review). Replaces the v2.1 human TEST REVIEW gate (removed — humans
|
|
263
|
+
no longer review tests).
|
|
202
264
|
13. **Mandatory frontend E2E + evidence.** When `has_frontend: true` and the
|
|
203
265
|
phase's `changes` touch the frontend root recorded in OVERVIEW.md, E2E MUST
|
|
204
266
|
run. Each UI-existence assertion captures a screenshot (on success too) to
|
|
205
267
|
`docs/evidence/e2e-phase-<n>/`. Frontend files changed with no E2E run, or a
|
|
206
268
|
closed frontend phase with no evidence on disk, fails CLOSE hard. (Evidence is
|
|
207
269
|
gitignored — present-on-disk at CLOSE is the check, not committed history.)
|
|
208
|
-
14. **DATAFLOW transition coverage.** Every transition in
|
|
209
|
-
trigger is reachable in the code shipped so far MUST
|
|
210
|
-
|
|
270
|
+
14. **DATAFLOW transition coverage (re-seamed v2.2, §5.56).** Every transition in
|
|
271
|
+
`docs/DATAFLOW.md` whose trigger is reachable in the code shipped so far MUST
|
|
272
|
+
have ≥1 FILLED CASE in `docs/spec-phase-<n>.md` (was: ≥1 test in
|
|
273
|
+
`tests/regression/`); zero coverage on a reachable transition fails CLOSE hard.
|
|
211
274
|
Unreachable transitions list as PENDING. Any transition still PENDING at the
|
|
212
|
-
final phase fails hard.
|
|
275
|
+
final phase fails hard. The case→test half of the old guarantee now lives in
|
|
276
|
+
`spec-conformance.sh` (rule 18: every case-id is cited by a boundary test, which
|
|
277
|
+
by placement convention lands in `tests/regression/`). Peer to the ENDPOINTS
|
|
278
|
+
coverage gate, which is unchanged and orthogonal (endpoint-keyed, not
|
|
279
|
+
behavior-keyed).
|
|
213
280
|
15. **Datasource data understanding.** Real-suite / E2E tests against an external
|
|
214
281
|
datasource are HARD-BLOCKED until that datasource's DATA UNDERSTANDING is
|
|
215
282
|
confirmed (baseline at `/overview`; per-phase delta-confirm for any
|
|
@@ -221,6 +288,25 @@ recover: current phase, next action, open blocker.
|
|
|
221
288
|
zero prompts; "reusable without interaction" means exactly this. Each `/phase`
|
|
222
289
|
PRE-FLIGHT runs a cheap liveness check (token obtainable, not expired) before
|
|
223
290
|
dispatching real/E2E. Both fail loud; the mock suite proceeds regardless.
|
|
291
|
+
17. **Spec staleness (§5.55).** `scripts/spec-staleness.sh <n>` runs immediately
|
|
292
|
+
after `spec-author` fills the spec AND again at SPEC REVIEW entry. It re-hashes
|
|
293
|
+
the current `PLAN.md` `acceptance:` line + the in-scope `DATAFLOW.md` transition
|
|
294
|
+
rows and compares to the hash embedded in the spec's generated header. A
|
|
295
|
+
mismatch (upstream drifted since the skeleton was generated) exits nonzero and
|
|
296
|
+
blocks SPEC REVIEW — the spec must be regenerated/re-filled. The generated
|
|
297
|
+
header is never hand-edited.
|
|
298
|
+
18. **Spec conformance (§5.55).** `scripts/spec-conformance.sh <n>` runs between RED
|
|
299
|
+
and GREEN, replacing the removed human TEST REVIEW gate. It loud-fails (blocks
|
|
300
|
+
GREEN) if any `TBD` marker remains in the spec or its fixtures, or if any case-id
|
|
301
|
+
in the spec table has no boundary test citing it via the `# spec: <case-id>`
|
|
302
|
+
convention.
|
|
303
|
+
19. **Author ≠ implementer (§5.53).** `spec-author` and `implementer` are distinct
|
|
304
|
+
roles. `spec-author` fills the spec + fixtures and NEVER reads implementation
|
|
305
|
+
logic; `implementer` reads the filled spec as its contract and NEVER authors spec
|
|
306
|
+
fixtures. `test-author` / `e2e-runner` are harness EMITTERS, not assertion
|
|
307
|
+
authors. This replaces the v2.1 test-author RED-first blindness invariant: spec
|
|
308
|
+
fixtures are written before code, so the contract cannot be shaped toward an
|
|
309
|
+
implementation.
|
|
224
310
|
|
|
225
311
|
-----
|
|
226
312
|
|
|
@@ -247,8 +333,21 @@ the KB. The kit works normally without a KB.
|
|
|
247
333
|
transition (from→to) | trigger | who writes | external system`). Living doc,
|
|
248
334
|
grill-driven; drives the CLOSE transition-coverage gate. The data-side analogue
|
|
249
335
|
of `ENDPOINTS.md`. (v2.1)
|
|
250
|
-
- `docs/
|
|
251
|
-
+
|
|
336
|
+
- `docs/spec-phase-<n>.md` — the per-phase behavioral contract (v2.2). Skeleton
|
|
337
|
+
(case names + `TBD` values) generated at `/overview`; filled by `spec-author` per
|
|
338
|
+
phase. Generated self-correlating header transcludes the phase's `PLAN.md`
|
|
339
|
+
`acceptance:` line + in-scope `DATAFLOW.md` transition rows and embeds a staleness
|
|
340
|
+
hash (never hand-edited). The only human-authored region is the example-case table.
|
|
341
|
+
Human-approved at SPEC REVIEW before SCAFFOLD. (Committed.)
|
|
342
|
+
- `fixtures/<case-id>-input.json` / `-expected.json` / `-ui.json` — the shared
|
|
343
|
+
fixtures a spec row references AND the generated test harness loads (transcription
|
|
344
|
+
is structural, not honor-system). `-expected.json` carries matcher tokens for
|
|
345
|
+
volatile fields; `-ui.json` is the `[{selector,assert,value}]` UI descriptor.
|
|
346
|
+
(Committed — part of the contract.) (v2.2)
|
|
347
|
+
- `tests/helpers/spec-assert.*` — the kit-versioned per-language comparator that
|
|
348
|
+
honors matcher tokens (`<UUID>`, `<ISO8601>`, `<ANY_STRING>`, `<ANY_NUMBER>`,
|
|
349
|
+
`<UNORDERED>`, `<MATCHES:regex>`). One implementation per supported test language;
|
|
350
|
+
NO per-project comparator code. (v2.2)
|
|
252
351
|
- `docs/evidence/e2e-phase-<n>/` — screenshot evidence captured at each UI-existence
|
|
253
352
|
assertion (gitignored; present-on-disk at CLOSE is the gate). (v2.1)
|
|
254
353
|
- `docs/INFRA.md` — Azure infra manifest: resource IDs, endpoints, cost estimates,
|
|
@@ -267,6 +366,10 @@ the KB. The kit works normally without a KB.
|
|
|
267
366
|
- `tests/phase-<n>/` — phase-local test suites.
|
|
268
367
|
- `tests/regression/` — cross-phase contract tests (the regression corpus). Run by
|
|
269
368
|
`scripts/regression.sh` (default mock; `--real` runs the real corpus).
|
|
369
|
+
- `scripts/spec-staleness.sh <n>` — loud-fails if the spec's generated header drifted
|
|
370
|
+
from the current `PLAN.md` acceptance line + `DATAFLOW.md` rows (rule 17). (v2.2)
|
|
371
|
+
- `scripts/spec-conformance.sh <n>` — loud-fails on any remaining `TBD` or any
|
|
372
|
+
case-id with no citing boundary test (rule 18). Runs between RED and GREEN. (v2.2)
|
|
270
373
|
- `scripts/auth-setup.sh` — session Azure credential check. Run once per session.
|
|
271
374
|
- `.claude/kb-config.json` — shared KB path + remote (optional, written by setup.sh).
|
|
272
375
|
- `docs/.kb-snapshot.md` — KB INDEX loaded this session (auto-generated, gitignored).
|
package/template/CLAUDE.md
CHANGED
|
@@ -17,6 +17,7 @@ The roles defined in AGENTS.md map to these Claude Code subagent files:
|
|
|
17
17
|
|researcher |`.claude/agents/researcher.md` |haiku |
|
|
18
18
|
|planner |`.claude/agents/planner.md` |opus |
|
|
19
19
|
|infra-provisioner |`.claude/agents/infra-provisioner.md` |opus |
|
|
20
|
+
|spec-author |`.claude/agents/spec-author.md` |opus |
|
|
20
21
|
|implementer |`.claude/agents/implementer.md` |opus |
|
|
21
22
|
|test-author |`.claude/agents/test-author.md` |opus |
|
|
22
23
|
|e2e-runner |`.claude/agents/e2e-runner.md` |opus |
|