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.
@@ -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 replaces the old soft nudge): if this phase
28
- will run a real/E2E suite, confirm every credential it needs is live NOW.
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 -> real/E2E is BLOCKED; tell me what to run; the
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 for the GATE.
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. Real/E2E against an UNCONFIRMED
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 → §3a → §3r → §3b).
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 SCAFFOLD fires. (Hard rule 11: never
69
- downgrade a TDD phase just to dodge the RED gate.)
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. SCAFFOLD
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
- ## 3a. RED
125
+ ## 5. RED
82
126
 
83
- Dispatch `test-author` to write the REAL API suite (+ mock) BLIND against the
84
- stubs + acceptance, AND emit docs/test-plan-phase-<n>.md (acceptance criteria →
85
- test names, plus a mandatory "NOT covered / assumptions" section). Place
86
- contract/ENDPOINTS/DATAFLOW-transition tests in `tests/regression/`, phase-local
87
- tests in `tests/phase-<n>/`. Run the suite.
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
- RED GATE = every acceptance test COLLECTS cleanly AND FAILS (assertion /
90
- NotImplemented).
91
- - Any test PASSES on stubs -> STOP (spec trivial or test wrong); show me.
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
- ## 3r. TEST REVIEWhuman gate (hard rule 12)
143
+ ## 6. CONFORMANCE GATE (hard rule 18) replaces the v2.1 human TEST REVIEW
97
144
 
98
- STOP. Surface docs/test-plan-phase-<n>.md to me: what each acceptance criterion
99
- maps to, and the "NOT covered / assumptions" section. GREEN cannot begin until I
100
- approve. On rejection, classify with me:
101
- - MISREAD of an adequate spec -> re-dispatch `test-author` with my feedback as
102
- added constraint; re-run RED; re-present the test plan.
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
- ## 3b. GREEN
151
+ ## 7. GREEN + BOUNDARY/E2E
108
152
 
109
- Dispatch `implementer` in FILL mode with the phase spec + research + the test
110
- file paths (it MAY read the tests — frozen before logic, no overfit — but must
111
- NOT edit them). Fill to green. Budget 3, WARN@2, STUCK@3.
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
- If FRONTEND_PHASE (from PRE-FLIGHT e): dispatch `e2e-runner` MANDATORY, not
114
- optional (hard rule 13). It reads INFRA.md target, runs `scripts/e2e-stack.sh up`
115
- / Playwright / `down`, and captures a screenshot at EACH UI-existence assertion
116
- regardless of pass/fail to docs/evidence/e2e-phase-<n>/, with a summary in
117
- docs/research/e2e-<slug>.md. Acceptance spec has no UI-existence criterion ->
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 §456 (see GATE below).
164
+ PHASE GATE (rule 5) -> go to §8910 (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 + REAL API suites from the acceptance
136
- spec — never reads the logic. (No TEST REVIEW gate on the non-TDD path — no
137
- public surface to mis-test. e2e-runner only if FRONTEND_PHASE.)
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 REAL API suite passes AND (FRONTEND_PHASE) E2E passes
144
- WITH evidence captured AND the accumulated mock regression corpus stays green AND
145
- every docs/ENDPOINTS.md entry has a regression test AND every REACHABLE
146
- docs/DATAFLOW.md transition has a regression test (all checked at CLOSE).
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
- ## 4. FIX
199
+ ## 8. FIX
155
200
 
156
201
  Dispatch `debugger` (isolated context) on the specific failure.
157
- - FIXED -> re-run TEST (and the regression corpus).
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
- ## 5. ESCALATE — circuit breaker. Mode B.
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
- ## 6. CLOSE
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` transition whose
184
- trigger is REACHABLE in the code shipped so far MUST have >=1 test in
185
- `tests/regression/`. Zero coverage on a reachable transition -> FAIL HARD.
186
- Unreachable transitions list as PENDING (not failed). IF IS_FINAL_PHASE: any
187
- transition still PENDING -> FAIL HARD (everything must be live by the last phase).
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
 
@@ -5,6 +5,7 @@
5
5
  *.js text eol=lf
6
6
  *.mjs text eol=lf
7
7
  *.ts text eol=lf
8
+ *.py text eol=lf
8
9
  *.json text eol=lf
9
10
  *.md text eol=lf
10
11
  *.ps1 text eol=crlf
@@ -1,9 +1,10 @@
1
1
  # anpunkit — portable agent methodology (single source of truth)
2
2
 
3
- <!-- ANPUNKIT-AGENTS-SENTINEL-v2.1 -->
4
- > **SENTINEL.** The HTML comment above (`ANPUNKIT-AGENTS-SENTINEL-v2.1`) is a
5
- > load-bearing marker. `setup.sh` greps for it to confirm this file resolved on
6
- > disk and was not clobbered. Do not remove or rename it.
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 -> SCAFFOLD -> RED -> TEST REVIEW -> GREEN -> E2E -> FIX -> CLOSE`
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 SCAFFOLD fires.
43
-
44
- **TEST REVIEW (v2.1)** is a mandatory human gate on every TDD phase, sitting
45
- between RED and GREEN. After `test-author` writes the suite it emits a
46
- `docs/test-plan-phase-<n>.md` (acceptance criteria test names, plus a mandatory
47
- "NOT covered / assumptions" section). The orchestrator surfaces it; FILL cannot
48
- fire until the human approves. A rejected coverage map is classified at the gate:
49
- a misread of an adequate spec re-dispatch `test-author` with feedback; an
50
- underspecified acceptance spec → sharpen `PLAN.md` and re-dispatch fresh. The gate
51
- is unskippable on TDD phases and absent on the non-TDD path (no public surface to
52
- mis-test). This is the fix for "all tests green, core still broken." (§5.33)
53
-
54
- **E2E is mandatory, not a judgment call (v2.1).** If the project is frontend-bearing
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, `e2e-runner` MUST run before CLOSE. The
57
- trigger is a deterministic path match, not "does this phase feel frontend-y." A
58
- frontend file changed with no E2E run is a loud CLOSE failure. (§5.34)
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. Maintains `docs/ENDPOINTS.md` each phase.
91
- - **test-author** writes tests BLIND (never reads implementation logic). On TDD
92
- phases it is dispatched BEFORE logic exists (RED-first), so blindness is
93
- structural, not honor-system. Writes a MOCK suite + a REAL API suite, and emits
94
- `docs/test-plan-phase-<n>.md` (the TEST REVIEW artifact) with a mandatory "NOT
95
- covered / assumptions" section. For phases touching an external datasource,
96
- surfaces any DATA UNDERSTANDING delta (new table/column beyond the confirmed
97
- baseline) for confirmation before the real suite runs.
98
- - **e2e-runner** writes/runs functional browser E2E (Playwright) BLIND. Reads
99
- `docs/INFRA.md` for the target. Captures a screenshot at EACH UI-existence
100
- assertion regardless of pass/fail (capture-on-success, not just on-failure) to
101
- `docs/evidence/e2e-phase-<n>/`, plus a summary in `docs/research/e2e-<slug>.md`.
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 stop at TEST REVIEW before GREEN. Frontend phases run mandatory E2E with
125
- screenshot evidence. CLOSE runs the regression guard + ENDPOINTS coverage gate +
126
- DATAFLOW transition-coverage gate + evidence-present check.
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–16)
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** = the current-phase REAL API suite passes AND (frontend phase)
174
- the E2E suite passes with screenshot evidence captured AND the accumulated mock
175
- regression corpus stays green AND every `docs/ENDPOINTS.md` entry has at least
176
- one test in `tests/regression/` AND every REACHABLE `docs/DATAFLOW.md` transition
177
- has at least one test in `tests/regression/`. The final phase additionally runs
178
- the full REAL regression corpus and requires zero PENDING transitions. A green
179
- mock suite alone can never close a phase.
180
- 6. Tests are written by `test-author`, which never sees the implementation logic
181
- (unbiased). On TDD phases the suite is written before the logic (RED-first).
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); mark a reachable transition PENDING
196
- (DATAFLOW gate); or skip evidence capture. (Scoped deliberately to these named
197
- seams; this is not a broad "never make excuses" rule.)
198
- 12. **TEST REVIEW (TDD phases).** GREEN cannot begin until the human approves
199
- `docs/test-plan-phase-<n>.md`. Rejection is classified at the gate (misread
200
- spec re-dispatch test-author with feedback; underspec sharpen PLAN.md and
201
- re-dispatch fresh). Unskippable on TDD phases; absent on the non-TDD path.
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 `docs/DATAFLOW.md` whose
209
- trigger is reachable in the code shipped so far MUST have ≥1 test in
210
- `tests/regression/`; zero coverage on a reachable transition fails CLOSE hard.
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. Peer to the ENDPOINTS coverage gate.
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/test-plan-phase-<n>.md` — the TEST REVIEW artifact: acceptance → test names
251
- + mandatory "NOT covered / assumptions" section. Human-approved before GREEN. (v2.1)
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).
@@ -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 |