create-anpunkit 2.0.3 → 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.
Files changed (34) hide show
  1. package/bin/cli.js +3 -2
  2. package/package.json +1 -1
  3. package/template/.claude/agents/e2e-runner.md +44 -13
  4. package/template/.claude/agents/implementer.md +13 -7
  5. package/template/.claude/agents/infra-provisioner.md +33 -2
  6. package/template/.claude/agents/planner.md +79 -6
  7. package/template/.claude/agents/researcher.md +19 -8
  8. package/template/.claude/agents/spec-author.md +118 -0
  9. package/template/.claude/agents/test-author.md +76 -43
  10. package/template/.claude/anpunkit-manifest.json +47 -27
  11. package/template/.claude/commands/infra.md +28 -3
  12. package/template/.claude/commands/overview.md +84 -24
  13. package/template/.claude/commands/phase.md +139 -40
  14. package/template/.claude/commands/replan.md +23 -9
  15. package/template/.cursor/commands/infra.md +26 -1
  16. package/template/.cursor/commands/overview.md +83 -23
  17. package/template/.cursor/commands/phase.md +138 -39
  18. package/template/.cursor/commands/replan.md +22 -8
  19. package/template/.gitattributes +1 -0
  20. package/template/AGENTS.md +215 -36
  21. package/template/CLAUDE.md +1 -0
  22. package/template/README.md +59 -23
  23. package/template/anpunkit.png +0 -0
  24. package/template/commands.src/infra.md +28 -3
  25. package/template/commands.src/overview.md +84 -24
  26. package/template/commands.src/phase.md +139 -40
  27. package/template/commands.src/replan.md +23 -9
  28. package/template/docs/DESIGN_LOG.md +192 -1
  29. package/template/index.html +339 -0
  30. package/template/scripts/spec-conformance.sh +93 -0
  31. package/template/scripts/spec-staleness.sh +115 -0
  32. package/template/setup.sh +110 -47
  33. package/template/tests/helpers/spec-assert.py +162 -0
  34. package/template/tests/helpers/spec-assert.ts +158 -0
@@ -1,9 +1,10 @@
1
1
  # anpunkit — portable agent methodology (single source of truth)
2
2
 
3
- <!-- ANPUNKIT-AGENTS-SENTINEL-v2.0 -->
4
- > **SENTINEL.** The HTML comment above (`ANPUNKIT-AGENTS-SENTINEL-v2.0`) 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 -> GREEN -> TEST(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,7 +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
+ 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
73
+ (`has_frontend: true` in `docs/OVERVIEW.md`) AND the phase's `changes` touch the
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)
43
81
 
44
82
  -----
45
83
 
@@ -53,21 +91,58 @@ terse summary + path. Workers cannot address the user — only the orchestrator
53
91
  can. Escalation is at most two hops.
54
92
 
55
93
  - **researcher** — two modes. DESIGN: domain/constraint research before planning
56
- (service limits, API contracts, architectural constraints, cost surprises).
57
- IMPL: per-phase codebase + service investigation. Checks the shared KB snapshot
58
- first (step 0). Writes findings to `docs/research/`; returns terse summary + path.
94
+ (service limits, API contracts, architectural constraints, cost surprises);
95
+ for any external datasource, drafts a falsifiable DATA UNDERSTANDING (grain,
96
+ fields-under-test with meaning + real nullability/range, sample-fixture shape,
97
+ the assumption that if wrong makes a test meaningless) to `docs/research/
98
+ datasource-<name>.md`. IMPL: per-phase codebase + service investigation. Checks
99
+ the shared KB snapshot first (step 0). Writes findings to `docs/research/`;
100
+ returns terse summary + path.
59
101
  - **planner** — research → vertical-slice `docs/PLAN.md`. Phase 0 (infra) always
60
- first; the last phase always contains the deploy task.
102
+ first; the last phase always contains the deploy task. For any phase whose
103
+ `changes` touch the frontend root, the `acceptance` MUST include ≥1 UI-existence
104
+ criterion naming the specific user-visible interactive element introduced (not
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.
61
121
  - **infra-provisioner** — generates Bicep, runs `az deployment what-if`, applies
62
- only on human approval, writes `docs/INFRA.md` + `.env.test`.
122
+ only on human approval, writes `docs/INFRA.md` + `.env.test`. Runs the one-time
123
+ AUTH PROOF (§5.37): proves every credential the project's real tests will use is
124
+ obtainable headlessly twice in a row (prime + reuse) with zero prompts.
63
125
  - **implementer** — builds ONE phase. Two MODES for TDD phases (SCAFFOLD: stubs
64
126
  only; FILL: logic to green) plus a legacy full-build mode for non-TDD phases.
65
- Writes code, never tests. Maintains `docs/ENDPOINTS.md` each phase.
66
- - **test-author** writes tests BLIND (never reads implementation logic). On TDD
67
- phases it is dispatched BEFORE logic exists (RED-first), so blindness is
68
- structural, not honor-system. Writes a MOCK suite + a REAL API suite.
69
- - **e2e-runner** — writes/runs functional browser E2E (Playwright) BLIND. Reads
70
- `docs/INFRA.md` for the target.
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`.
71
146
  - **debugger** — debugs in an ISOLATED context. Writes a trace to
72
147
  `docs/research/debug-<slug>.md`; returns a summary.
73
148
  - **synthesizer** — compresses `docs/STATE.md` / `docs/ISSUES.md`, prunes
@@ -83,12 +158,21 @@ Named procedures, each with a canonical body in `commands.src/<name>.md` and a
83
158
  generated copy per tool (`.claude/commands/`, `.cursor/commands/`).
84
159
 
85
160
  - **overview** — bootstrap a project: design-research → grill r1 → design-research
86
- → re-grill r2 `OVERVIEW.md` planner `PLAN.md` (Phase 0 always first).
161
+ RESEARCH REVIEW → re-grill r2 (covers data structures, dataflow, and object
162
+ state flow) → `OVERVIEW.md` (+ `has_frontend`/frontend-root, `DATAFLOW.md`,
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).
87
167
  - **infra** — provision/verify Azure infra: Bicep → what-if → human review → apply
88
- → `INFRA.md` + `.env.test`.
168
+ → `INFRA.md` + `.env.test`. Runs the one-time AUTH PROOF.
89
169
  - **phase [n]** — run one phase end-to-end with the circuit breaker. Chooses the
90
- TDD or non-TDD order at RESEARCH. CLOSE runs the regression guard + ENDPOINTS
91
- coverage gate.
170
+ TDD or non-TDD order at RESEARCH. PRE-FLIGHT runs the auth liveness check. TDD
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.
92
176
  - **quick [change]** — small, obvious, non-phase change; no agent chain. Stays
93
177
  non-TDD. Runs the mock regression corpus after the change.
94
178
  - **unstuck** — deep re-research after a circuit breaker (human-triggered).
@@ -126,7 +210,7 @@ recover: current phase, next action, open blocker.
126
210
 
127
211
  -----
128
212
 
129
- ## Hard rules (1–11)
213
+ ## Hard rules (1–19)
130
214
 
131
215
  1. Before debugging ANY error: grep `docs/ISSUES.md` AND `docs/research/INDEX.md`.
132
216
  The SESSION-OPEN ritual surfaces ISSUES.md — there is no excuse to miss it.
@@ -135,26 +219,94 @@ recover: current phase, next action, open blocker.
135
219
  3. Every resolved error -> logged to `docs/ISSUES.md` with root cause + failed
136
220
  attempts.
137
221
  4. End of phase -> synthesize -> context reset -> next phase.
138
- 5. **PHASE GATE** = the current-phase REAL API suite passes AND (frontend phase)
139
- the E2E suite passes AND the accumulated mock regression corpus stays green AND
140
- every `docs/ENDPOINTS.md` entry has at least one test in `tests/regression/`.
141
- The final phase additionally runs the full REAL regression corpus. A green
142
- mock suite alone can never close a phase.
143
- 6. Tests are written by `test-author`, which never sees the implementation logic
144
- (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.
145
237
  7. Service outage is not a bug — `SERVICE UNAVAILABLE` / `AZURE UNAVAILABLE` /
146
238
  `STACK NOT READY` / `FLAKE` do not spend the debug budget. Only `LOGIC FAIL`
147
239
  reaches the debugger.
148
240
  8. E2E auth = ROPC with a dedicated MFA-excluded test account. NEVER script the
149
241
  Microsoft login UI.
150
242
  9. Architectural change (new/removed agent, hook, command, or a changed workflow
151
- rule)? -> run `log-decision` before closing.
243
+ rule)? -> run `log-decision` before closing. A phase that changes an object's
244
+ state lifecycle MUST update `docs/DATAFLOW.md` in the same CLOSE.
152
245
  10. Azure project? Run `scripts/auth-setup.sh` ONCE per session before any Azure
153
246
  work. Never debug an auth error without checking this first.
154
- 11. **No-rationalization (scoped).** Do not downgrade a TDD phase to non-TDD to
155
- dodge the RED gate, and do not route phase-worthy work through `quick` to
156
- dodge it. (Scoped deliberately to these two seams; this is not a broad
157
- "never make excuses" rule.)
247
+ 11. **No-rationalization (scoped).** Do not, in order to dodge a gate:
248
+ downgrade a TDD phase to non-TDD or route phase-worthy work through `quick`
249
+ (RED gate); set `has_frontend: false` or keep a touched element out of the
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).
264
+ 13. **Mandatory frontend E2E + evidence.** When `has_frontend: true` and the
265
+ phase's `changes` touch the frontend root recorded in OVERVIEW.md, E2E MUST
266
+ run. Each UI-existence assertion captures a screenshot (on success too) to
267
+ `docs/evidence/e2e-phase-<n>/`. Frontend files changed with no E2E run, or a
268
+ closed frontend phase with no evidence on disk, fails CLOSE hard. (Evidence is
269
+ gitignored — present-on-disk at CLOSE is the check, not committed history.)
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.
274
+ Unreachable transitions list as PENDING. Any transition still PENDING at the
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).
280
+ 15. **Datasource data understanding.** Real-suite / E2E tests against an external
281
+ datasource are HARD-BLOCKED until that datasource's DATA UNDERSTANDING is
282
+ confirmed (baseline at `/overview`; per-phase delta-confirm for any
283
+ new table/column). The mock suite still runs. No testing against data you
284
+ never confirmed understanding of.
285
+ 16. **Auth proof + liveness.** A one-time AUTH PROOF at `/infra` proves every
286
+ credential the real tests use — Entra/MSAL app login AND external datasource
287
+ credentials — is obtainable headlessly twice in a row (prime + reuse) with
288
+ zero prompts; "reusable without interaction" means exactly this. Each `/phase`
289
+ PRE-FLIGHT runs a cheap liveness check (token obtainable, not expired) before
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.
158
310
 
159
311
  -----
160
312
 
@@ -176,13 +328,36 @@ the KB. The kit works normally without a KB.
176
328
  - `docs/HISTORY.md` — one line per finished phase.
177
329
  - `docs/DESIGN_LOG.md` — kit architectural rationale (§5.x decision log).
178
330
  - `docs/OVERVIEW.md` — project scope. Written after the double-grill in `overview`.
331
+ Carries `has_frontend` + the frontend root path, and the data/state-flow summary.
332
+ - `docs/DATAFLOW.md` — state-transition table per key object (`object | states |
333
+ transition (from→to) | trigger | who writes | external system`). Living doc,
334
+ grill-driven; drives the CLOSE transition-coverage gate. The data-side analogue
335
+ of `ENDPOINTS.md`. (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)
351
+ - `docs/evidence/e2e-phase-<n>/` — screenshot evidence captured at each UI-existence
352
+ assertion (gitignored; present-on-disk at CLOSE is the gate). (v2.1)
179
353
  - `docs/INFRA.md` — Azure infra manifest: resource IDs, endpoints, cost estimates,
180
- E2E target.
354
+ E2E target, AUTH PROOF result.
181
355
  - `docs/ENDPOINTS.md` — API/service endpoint catalogue. Maintained by implementer
182
356
  each phase. Drives the CLOSE coverage gate.
183
357
  - `docs/research/` — full research + debug files. `INDEX.md` is the searchable map.
184
358
  `design-<slug>.md` (design research), `<slug>.md` (impl research),
185
- `debug-<slug>.md` (debugger traces).
359
+ `debug-<slug>.md` (debugger traces), `datasource-<name>.md` (confirmed data
360
+ understanding, referenced from DATAFLOW.md external rows).
186
361
  - `docs/.snapshots/` — pre-compact recovery markers (auto-pruned, gitignored).
187
362
  - `infra/` — Bicep templates. Committed (IaC audit trail). `infra/params.json`
188
363
  holds no secrets.
@@ -191,6 +366,10 @@ the KB. The kit works normally without a KB.
191
366
  - `tests/phase-<n>/` — phase-local test suites.
192
367
  - `tests/regression/` — cross-phase contract tests (the regression corpus). Run by
193
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)
194
373
  - `scripts/auth-setup.sh` — session Azure credential check. Run once per session.
195
374
  - `.claude/kb-config.json` — shared KB path + remote (optional, written by setup.sh).
196
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 |
@@ -25,8 +25,12 @@ npx create-anpunkit # non-destructive: never clobbers your files
25
25
  # then open Claude Code or Cursor — the session-start hook fires automatically
26
26
  /overview # bootstrap the project (includes Phase 0 infra)
27
27
  ```
28
- Useful flags: `--dry-run` (print the plan, write nothing), `--force` (overwrite
29
- user-modified kit files), `--kb-path <dir>` (your pre-cloned KB repo; remote auto-recorded from its origin) / `--no-kb`.
28
+ Useful flags: `--dry-run` (print the per-tool plan, write nothing), `--force`
29
+ (overwrite user-modified kit files), `--tools <claude,cursor>` (install only the
30
+ selected tools' files; interactive menu if omitted on a fresh TTY install),
31
+ `--add-tool <name>` (lay down an additional tool's files into an existing
32
+ project), `--kb-path <dir>` (your pre-cloned KB repo; remote auto-recorded from
33
+ its origin) / `--no-kb`.
30
34
 
31
35
  Upgrading an existing anpunkit project? Re-run `npx create-anpunkit`. It refreshes
32
36
  kit-owned files, preserves anything you modified as `<file>.anpunkit-new`, merges
@@ -46,38 +50,63 @@ cd my-project && bash setup.sh
46
50
 
47
51
  |Command |Does |
48
52
  |-----------------|------------------------------------------------------------------------------|
49
- |`/overview` |design-research → grill (×2) → OVERVIEW → PLAN (Phase 0 always first) → STATE |
50
- |`/infra` |provision Azure infra: Bicep → what-if → review → apply → INFRA.md + .env.test|
51
- |`/phase [n]` |run one phase: research → implementblind test, with circuit breaker |
53
+ |`/overview` |design-research → RESEARCH REVIEW → grill (×2, incl. data/state flow) → OVERVIEW + DATAFLOW → PLAN (Phase 0 first) → STATE|
54
+ |`/infra` |provision Azure infra: Bicep → what-if → review → apply → INFRA.md + .env.test → AUTH PROOF|
55
+ |`/phase [n]` |run one phase: research → SPEC fill SPEC REVIEW → SCAFFOLD → RED → conformance → GREEN → boundary/E2E, with circuit breaker|
52
56
  |`/quick [change]`|small obvious change, direct, no agent chain |
53
57
  |`/unstuck` |deep re-research after a circuit breaker (you trigger it) |
54
58
  |`/synthesize` |compress STATE.md, dedup ISSUES.md, prune snapshots |
55
- |`/replan` |revise PLAN.md when it drifts |
59
+ |`/replan` |revise PLAN.md when it drifts (reconciles regression corpus + DATAFLOW) |
56
60
  |`/log-issue` |append an error with root cause + failed attempts |
57
61
  |`/log-decision` |record an architectural change in DESIGN_LOG.md |
58
62
  |`/store-wisdom` |promote resolved issues + research findings to shared KB |
59
63
 
60
64
  ## Subagents
61
65
 
62
- `researcher` (Haiku, two modes: design + impl) · `planner` (Opus) · `infra-provisioner` (Opus) ·
63
- `implementer` (Opus, SCAFFOLD/FILL modes) · `test-author` (Opus, blind, RED-first) · `debugger` (Opus, isolated) ·
64
- `e2e-runner` (Opus, blind, Playwright) · `synthesizer` (Haiku)
66
+ `researcher` (Haiku, two modes: design + impl) · `planner` (Opus, also writes skeleton specs) ·
67
+ `infra-provisioner` (Opus) · `spec-author` (Opus, fills per-phase spec + fixtures) ·
68
+ `implementer` (Opus, SCAFFOLD/FILL modes) · `test-author` (Opus, harness emitter) · `debugger` (Opus, isolated) ·
69
+ `e2e-runner` (Opus, Playwright emitter) · `synthesizer` (Haiku)
65
70
 
66
71
  The main session is the orchestrator — it routes, it does not implement.
67
72
 
68
- ## The loop (v2.0: TDD-first + regression guard)
69
-
70
- Phases that add a public callable surface run test-first:
71
- `RESEARCH -> SCAFFOLD -> RED -> GREEN -> TEST -> FIX -> CLOSE`. The implementer
72
- writes interface stubs only; the `test-author` writes the suite blind against
73
- those stubs (it must collect cleanly and FAIL the RED gate); the implementer
74
- then fills to green. Pure infra/config/doc phases keep the direct
75
- `RESEARCH -> IMPLEMENT -> TEST` order.
73
+ ## The loop (v2.2: spec-driven contract + upstream human gate + generated tests)
74
+
75
+ Phases that add a public callable surface run spec-first:
76
+ `RESEARCH -> SPEC fill -> spec-staleness -> SPEC REVIEW -> SCAFFOLD -> RED -> spec-conformance -> GREEN -> boundary/E2E -> FIX -> CLOSE`.
77
+ The reviewable, authoritative artifact is the **spec**, not the test. At `/overview`
78
+ the planner enumerates the case *names* per phase (skeleton `docs/spec-phase-<n>.md`).
79
+ At phase start the new `spec-author` fills them with concrete cases real inputs,
80
+ real expected outputs, matcher tokens for volatile fields — written to shared
81
+ `fixtures/` files. **SPEC REVIEW** is a human gate that sits *upstream* (before any
82
+ code): you confirm falsifiable claims in plain language ("empty order → 422
83
+ EMPTY_ORDER"). Tests are then GENERATED from the locked spec rows (deep-equality +
84
+ matcher tokens for `data`; Playwright from the descriptor for `ui`) loading the
85
+ *same* fixtures — so a test physically cannot assert different values than the spec.
86
+ `spec-conformance.sh` blocks GREEN until no `TBD` remains and every case-id is cited
87
+ by a boundary test. This is the v2.2 fix for "both agents independently fabricated
88
+ the same wrong contract from a one-line acceptance and the suite went green on a
89
+ broken core." Pure infra/config/doc phases keep the direct
90
+ `RESEARCH -> IMPLEMENT -> TEST` order (no spec, no SPEC REVIEW — no public surface).
91
+
92
+ Frontend phases are detected by a **deterministic path match** (`has_frontend` +
93
+ the frontend root, both set in `docs/OVERVIEW.md`): if a phase changes a file
94
+ under the frontend root, **E2E is mandatory**, the acceptance spec must name the
95
+ specific user-visible element it introduces (not "page renders 200"), and the
96
+ `e2e-runner` captures a screenshot at each such assertion — on success too — to a
97
+ gitignored `docs/evidence/` dir. That's the fix for shipping a missing sign-in button.
76
98
 
77
99
  Every phase CLOSE runs the accumulated **mock regression corpus**
78
- (`tests/regression/`, via `scripts/regression.sh`) and a hard ENDPOINTS coverage
79
- gate so a contract built in an early phase cannot be silently broken later. The
80
- final phase additionally runs the full real corpus.
100
+ (`tests/regression/`, via `scripts/regression.sh`) plus a hard ENDPOINTS coverage
101
+ gate AND a **DATAFLOW transition-coverage gate** every reachable state
102
+ transition in `docs/DATAFLOW.md` (the data-side analogue of `ENDPOINTS.md`,
103
+ grilled out at `/overview`) must have a regression test. The final phase
104
+ additionally runs the full real corpus and allows zero PENDING transitions.
105
+
106
+ External datasources get a confirmed, falsifiable **DATA UNDERSTANDING** (grain,
107
+ fields, sample shape, meaning-breaking assumption) before real tests run, and auth
108
+ is proven reusable once at `/infra` (obtainable headlessly twice in a row) with a
109
+ cheap liveness check each phase.
81
110
 
82
111
  Methodology lives in one place: the portable **`AGENTS.md`** at the repo root.
83
112
  `CLAUDE.md` is a thin `@AGENTS.md` shim with Claude-native wiring only.
@@ -142,6 +171,10 @@ home-dir custom-prompts with a divergent UX).
142
171
  - `docs/PLAN.md` — vertical-slice phase plan (Phase 0 always first)
143
172
  - `docs/HISTORY.md` — one line per finished phase
144
173
  - `docs/OVERVIEW.md` — project scope, written after double-grill
174
+ - `docs/DATAFLOW.md` — state-transition table per key object (grilled at /overview; drives CLOSE coverage gate)
175
+ - `docs/spec-phase-<n>.md` — per-phase behavioral contract (skeleton at /overview, filled by spec-author; human-reviewed at SPEC REVIEW)
176
+ - `fixtures/<case-id>-{input,expected,ui}.json` — shared by the spec row and the generated test harness (committed; part of the contract)
177
+ - `tests/helpers/spec-assert.{py,ts}` — kit-versioned matcher-aware comparator (honors `<UUID>`, `<ISO8601>`, … tokens)
145
178
  - `docs/INFRA.md` — Azure resource manifest + cost estimates (written by infra-provisioner)
146
179
  - `docs/ENDPOINTS.md` — API/service endpoint catalogue (maintained by implementer)
147
180
  - `docs/.snapshots/` — pre-compact recovery markers (auto-pruned, gitignored)
@@ -206,6 +239,7 @@ phase starts, owned by the `infra-provisioner` subagent.
206
239
  /infra # generates Bicep -> what-if diff -> you review -> "go" -> apply
207
240
  # writes docs/INFRA.md (resource manifest + cost estimates)
208
241
  # writes .env.test (generated, never fill manually)
242
+ # runs AUTH PROOF (every credential proven reusable headlessly)
209
243
  /phase 1 # PRE-FLIGHT checks Phase 0 is done before starting
210
244
  ```
211
245
 
@@ -225,13 +259,15 @@ Prompts `az login` only if stale. No credential storage — your account only.
225
259
  1. `infra-provisioner` reads `docs/OVERVIEW.md` for the system design
226
260
  1. Generates `infra/main.bicep` + per-service modules under `infra/modules/`
227
261
  1. Runs `az deployment what-if` — shows exactly what will be created
228
- 1. **Stops and waits for your go”** — nothing applied without your review
262
+ 1. **Stops and waits for your "go"** — nothing applied without your review
229
263
  1. Applies the deployment
230
264
  1. Writes `docs/INFRA.md` — resource IDs, endpoints, cost estimates (THB, SEA region)
231
265
  1. Generates `.env.test` from the manifest
266
+ 1. Runs the **AUTH PROOF** — proves every credential (Entra/MSAL + datasources) is obtainable headlessly twice in a row
232
267
 
233
268
  Re-run `/infra` any time infra drifts or a new resource is needed.
234
269
  Re-run `/infra regenerate-env` to refresh `.env.test` only.
270
+ Re-run `/infra auth-proof` to re-prove credentials on demand.
235
271
 
236
272
  ### Cost awareness
237
273
 
@@ -257,7 +293,7 @@ Three layers: unit/integration (mock suite), real API (`test-author`), and
257
293
  functional browser E2E (`e2e-runner`, Playwright).
258
294
 
259
295
  **Phase gate:** a frontend-touching phase closes only when the real API suite
260
- AND the browser E2E suite pass. Mock-green alone never closes a phase.
296
+ AND the browser E2E suite pass with screenshot evidence. Mock-green alone never closes a phase.
261
297
 
262
298
  **MSAL / Entra ID auth.** Browser E2E never drives the Microsoft login UI.
263
299
  `e2e/global-setup.ts` uses ROPC flow with a dedicated test account (MFA excluded
@@ -265,7 +301,7 @@ via Conditional Access) to fetch a real token and inject it into the MSAL cache.
265
301
 
266
302
  **E2E setup (one-time per project):**
267
303
 
268
- 1. Run `/infra` — it generates `.env.test` automatically.
304
+ 1. Run `/infra` — it generates `.env.test` automatically and runs the AUTH PROOF.
269
305
  1. Provision the Entra test user + Conditional Access MFA exclusion.
270
306
  1. `npm i -D @playwright/test && npx playwright install chromium`
271
307
 
Binary file
@@ -1,6 +1,6 @@
1
1
  ---
2
- description: Provision or verify Azure infrastructure. Generates Bicep, shows what-if diff for your review, applies only after your approval, writes docs/INFRA.md and .env.test.
3
- argument-hint: [provision | verify | update <what changed> | regenerate-env]
2
+ description: Provision or verify Azure infrastructure. Generates Bicep, shows what-if diff for your review, applies only after your approval, writes docs/INFRA.md and .env.test. Runs the one-time AUTH PROOF.
3
+ argument-hint: [provision | verify | update <what changed> | regenerate-env | auth-proof]
4
4
  ---
5
5
 
6
6
  Caveman ULTRA mode. You are the ORCHESTRATOR.
@@ -36,6 +36,31 @@ Action: $ARGUMENTS (default: "provision" if INFRA.md missing, "verify" if presen
36
36
  4. On "make changes": dispatch UPDATE with feedback. Loop to step 2.
37
37
 
38
38
  5. On APPLIED: tell me INFRA.md ✓, .env.test ✓, and any manual steps remaining.
39
+ Then run AUTH PROOF (below) before declaring Phase 0 complete.
40
+
41
+ ---
42
+
43
+ ## AUTH PROOF (one-time, hard rule 16)
44
+
45
+ Runs after a successful PROVISION (and on demand via `/infra auth-proof`). Proves
46
+ every credential the project's real tests will use is reusable WITHOUT interaction.
47
+ "Reusable" is defined falsifiably: obtainable headlessly TWICE IN A ROW.
48
+
49
+ 1. Enumerate the credentials in scope: the Entra/MSAL app login, plus every
50
+ external datasource credential referenced in docs/DATAFLOW.md (external rows)
51
+ and docs/ENDPOINTS.md (auth column) — Azure SQL, Tableau, etc.
52
+
53
+ 2. Dispatch `infra-provisioner` to run, for EACH credential, a headless obtain
54
+ twice in a row: first call primes (token fetch / connect), second call must
55
+ succeed from cache/refresh with ZERO prompts. The Microsoft login UI is never
56
+ driven (ROPC + dedicated MFA-excluded test account; hard rule 8).
57
+
58
+ 3. Result:
59
+ - All credentials pass twice headlessly -> write `AUTH PROOF: PASS <timestamp>`
60
+ to docs/INFRA.md with the per-credential list. Phase 0 may complete.
61
+ - Any credential prompts or fails the second obtain -> NOT reusable. Write
62
+ `AUTH PROOF: FAIL` + which credential, STOP, tell me what to fix. Phase 0 is
63
+ not complete until the proof passes.
39
64
 
40
65
  ---
41
66
 
@@ -43,7 +68,7 @@ Action: $ARGUMENTS (default: "provision" if INFRA.md missing, "verify" if presen
43
68
 
44
69
  1. Check INFRA.md exists. If missing: tell me to run `/infra provision` first.
45
70
  2. Dispatch `infra-provisioner` VERIFY mode.
46
- 3. Return drift report.
71
+ 3. Return drift report. If the AUTH PROOF marker is missing or stale, re-run AUTH PROOF.
47
72
 
48
73
  ---
49
74