create-anpunkit 2.1.0 → 2.3.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 (68) hide show
  1. package/bin/cli.js +2 -2
  2. package/package.json +2 -3
  3. package/template/.claude/agents/debugger.md +1 -1
  4. package/template/.claude/agents/e2e-runner.md +56 -29
  5. package/template/.claude/agents/implementer.md +14 -8
  6. package/template/.claude/agents/infra-provisioner.md +53 -59
  7. package/template/.claude/agents/planner.md +99 -30
  8. package/template/.claude/agents/researcher.md +16 -1
  9. package/template/.claude/agents/spec-author.md +126 -0
  10. package/template/.claude/agents/synthesizer.md +1 -1
  11. package/template/.claude/agents/test-author.md +81 -63
  12. package/template/.claude/anpunkit-manifest.json +66 -107
  13. package/template/.claude/commands/infra.md +7 -3
  14. package/template/.claude/commands/log-decision.md +1 -1
  15. package/template/.claude/commands/log-issue.md +1 -1
  16. package/template/.claude/commands/overview.md +55 -13
  17. package/template/.claude/commands/phase.md +153 -81
  18. package/template/.claude/commands/quick.md +1 -1
  19. package/template/.claude/commands/replan.md +1 -1
  20. package/template/.claude/commands/store-wisdom.md +1 -1
  21. package/template/.claude/commands/synthesize.md +1 -1
  22. package/template/.claude/commands/unstuck.md +1 -1
  23. package/template/.claude/hooks/session-start.sh +5 -11
  24. package/template/.claude/ref/compression.md +56 -0
  25. package/template/.claude/skills/karpathy-guidelines/SKILL.md +1 -1
  26. package/template/.gitattributes +1 -0
  27. package/template/AGENTS.md +264 -130
  28. package/template/CLAUDE.md +5 -9
  29. package/template/README.md +116 -136
  30. package/template/commands.src/infra.md +7 -3
  31. package/template/commands.src/log-decision.md +1 -1
  32. package/template/commands.src/log-issue.md +1 -1
  33. package/template/commands.src/overview.md +55 -13
  34. package/template/commands.src/phase.md +153 -81
  35. package/template/commands.src/quick.md +1 -1
  36. package/template/commands.src/replan.md +1 -1
  37. package/template/commands.src/store-wisdom.md +1 -1
  38. package/template/commands.src/synthesize.md +1 -1
  39. package/template/commands.src/unstuck.md +1 -1
  40. package/template/docs/DESIGN_LOG.md +414 -9
  41. package/template/knowledge/azure.md +161 -0
  42. package/template/knowledge/webapp.md +265 -0
  43. package/template/scripts/spec-conformance.sh +93 -0
  44. package/template/scripts/spec-staleness.sh +115 -0
  45. package/template/setup.sh +30 -111
  46. package/template/tests/helpers/spec-assert.py +162 -0
  47. package/template/tests/helpers/spec-assert.ts +158 -0
  48. package/template/.claude/hooks/cursor-session-start.sh +0 -17
  49. package/template/.claude/skills/caveman/SKILL.md +0 -39
  50. package/template/.cursor/commands/infra.md +0 -82
  51. package/template/.cursor/commands/log-decision.md +0 -29
  52. package/template/.cursor/commands/log-issue.md +0 -23
  53. package/template/.cursor/commands/overview.md +0 -145
  54. package/template/.cursor/commands/phase.md +0 -249
  55. package/template/.cursor/commands/quick.md +0 -25
  56. package/template/.cursor/commands/replan.md +0 -73
  57. package/template/.cursor/commands/store-wisdom.md +0 -191
  58. package/template/.cursor/commands/synthesize.md +0 -22
  59. package/template/.cursor/commands/unstuck.md +0 -36
  60. package/template/.cursor/hooks.json +0 -14
  61. package/template/.cursor/rules/anpunkit.md +0 -11
  62. package/template/anpunkit.png +0 -0
  63. package/template/docker-compose.test.yml +0 -34
  64. package/template/e2e/global-setup.ts +0 -57
  65. package/template/index.html +0 -340
  66. package/template/playwright.config.ts +0 -28
  67. package/template/scripts/auth-setup.sh +0 -51
  68. package/template/scripts/e2e-stack.sh +0 -65
@@ -1,14 +1,16 @@
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.3 -->
4
+ > **SENTINEL.** The HTML comment above (`ANPUNKIT-AGENTS-SENTINEL-v2.3`) 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.
10
- > This is the ONE place every rule lives. Claude Code, Cursor, and any tool that
11
- > reads the open `AGENTS.md` standard get the full methodology from here.
11
+ > This is the ONE place every rule lives. Claude Code reads the full methodology
12
+ > from here (as can any tool supporting the open `AGENTS.md` standard). v2.3 is
13
+ > Claude Code only.
12
14
 
13
15
  > **Anti-drift invariant (load-bearing).** Every rule lives in exactly ONE place:
14
16
  > this file. `CLAUDE.md` restates NO rule — it only maps roles to Claude-native
@@ -16,8 +18,10 @@
16
18
  > its automation may never contradict. Duplication between files is an
17
19
  > architectural defect, not a convenience.
18
20
 
19
- Caveman ULTRA mode always on. Apply the `karpathy-guidelines` skill (engineering
20
- discipline) on every coding and debugging task.
21
+ Compression is always on: profile `user` from `.claude/ref/compression.md`
22
+ governs all human-facing output; every subagent prompt declares profile
23
+ `internal`. Apply the `karpathy-guidelines` skill (engineering discipline) on
24
+ every coding and debugging task.
21
25
 
22
26
  -----
23
27
 
@@ -25,13 +29,13 @@ discipline) on every coding and debugging task.
25
29
 
26
30
  `design-research -> grill (×2) -> plan -> implement -> test -> deploy`, one
27
31
  VERTICAL SLICE per phase. Implement AND test a phase before the next. The last
28
- phase always includes deployment.
32
+ phase always includes DEPLOY_KIND completion.
29
33
 
30
34
  A phase runs in one of two orders, chosen at RESEARCH time by the TDD
31
35
  APPLICABILITY check (see Procedures → `phase`):
32
36
 
33
37
  - **TDD phase** (`TDD_PHASE=true`):
34
- `RESEARCH -> SCAFFOLD -> RED -> TEST REVIEW -> GREEN -> E2E -> FIX -> CLOSE`
38
+ `RESEARCH -> SPEC fill -> spec-staleness -> SPEC REVIEW -> SCAFFOLD -> RED -> spec-conformance -> GREEN -> boundary/E2E -> FIX -> CLOSE`
35
39
  - **Non-TDD phase** (pure infra / config / doc — `TDD_PHASE=false`):
36
40
  `RESEARCH -> IMPLEMENT -> TEST -> FIX -> CLOSE`
37
41
 
@@ -39,34 +43,68 @@ APPLICABILITY check (see Procedures → `phase`):
39
43
  exported function/class, CLI command, or message contract) that is assertable
40
44
  from the acceptance spec." Size is NOT the criterion. On ambiguity, default
41
45
  `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
55
- (`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)
46
+ non-TDD before SPEC fill fires.
47
+
48
+ **Project flags (adaptive loop, hard rule 10).** DECLARED once at `/overview` and
49
+ recorded in `docs/OVERVIEW.md`: `project_type`, `has_frontend` (+ root),
50
+ `infra_needed`, `e2e_kind` (browser | cli | http | library-api), `deploy_kind`
51
+ (cloud-deploy | package-publish | install-run-verified | none), `knowledge_docs`.
52
+ Per-phase bindings happen at RESEARCH (same idiom as `TDD_PHASE`): the effective
53
+ `E2E_KIND` (browser iff the phase is a frontend phase, else the baseline) and,
54
+ on the final phase, `DEPLOY_KIND` confirmation. Derivation is deterministic
55
+ (tables live in `commands.src/overview.md`); nothing is inferred mid-phase.
56
+ These branch the loop: Phase 0 exists iff `infra_needed`; the boundary run is
57
+ selected by `E2E_KIND`; the final phase completes `DEPLOY_KIND`.
58
+
59
+ **SPEC REVIEW (v2.2)** is the mandatory human gate on every TDD phase, sitting
60
+ UPSTREAM between RESEARCH and SCAFFOLD, before any code. The reviewable,
61
+ authoritative artifact is the SPEC, not the test. After RESEARCH, `spec-author`
62
+ fills `docs/spec-phase-<n>.md` (skeleton case-names generated at `/overview`) with
63
+ concrete observable behavior — real input payloads, real expected outputs, matcher
64
+ tokens for volatile fields — grounded in fresh per-phase research and the confirmed
65
+ datasource baseline. `scripts/spec-staleness.sh` then loud-fails if the upstream
66
+ `acceptance:` line or `DATAFLOW.md` transition rows drifted since the skeleton was
67
+ generated. The orchestrator surfaces the filled cases as FALSIFIABLE CLAIMS
68
+ ("POST /orders/submit with an empty line-item list → 422 EMPTY_ORDER"); SCAFFOLD
69
+ cannot fire until the human confirms. Rejection is classified at the gate (§5.50):
70
+ wrong expected → fix the case row + fixture; wrong input shape → re-dispatch
71
+ `spec-author`; a new or contradicted case → hard re-entry to amend the up-front
72
+ case-name contract (§5.52). Tests are then GENERATED from the locked spec rows
73
+ (deep-equality + matcher tokens for `data`; Playwright from the descriptor for
74
+ `ui`) — humans never review test code. This is the fix for "both agents
75
+ independently fabricated the same wrong contract from a one-line acceptance and the
76
+ suite went green on a broken core." (§5.43–§5.50)
77
+
78
+ **Boundary test is the system-of-record per case (v2.2).** Every spec case has
79
+ exactly one OUTER-BOUNDARY test — `data` cases: a real HTTP call / CLI invocation /
80
+ real message against the running backend + real services (v2.1's "real API suite");
81
+ `ui` cases: a Playwright assertion against the deployed (or local-docker) target
82
+ (v2.1's "E2E"). The boundary test is the phase gate; green mock alone never closes a
83
+ phase. A mock mirror is optional and shares the SAME fixture + comparator via a
84
+ `TEST_MODE` flag, so it cannot assert different values than the boundary test. (§5.47)
85
+
86
+ **The boundary run is mandatory, not a judgment call (per E2E_KIND).** Every phase
87
+ that ships or changes its outer surface MUST run the boundary suite before CLOSE,
88
+ selected by the phase's bound `E2E_KIND`. **Browser** (`has_frontend: true` AND the
89
+ phase's `changes` touch the frontend root recorded in OVERVIEW.md — a deterministic
90
+ path match, not "does this feel frontend-y"): `ui` boundary cases MUST run; a
91
+ frontend file changed with no `ui` boundary run is a loud CLOSE failure. `e2e-runner`
92
+ EMITS the Playwright assertion from each case's `ui` descriptor (it no longer authors
93
+ blind) and retains screenshot-on-each-UI-existence-assertion as the visual backstop
94
+ (browser practice + stack ritual: `knowledge/webapp.md`). **cli / http /
95
+ library-api**: the phase's real-mode boundary suite is the outer run, executed
96
+ against the shipped artifact with its transcript captured as evidence. On a project
97
+ whose `e2e_kind` is not `browser` there is no browser: `ui` case rows are invalid.
98
+ (§5.34, §5.54, §5.65)
59
99
 
60
100
  -----
61
101
 
62
102
  ## Roles (fresh-context workers)
63
103
 
64
- Each role is a fresh-context worker. Where the host tool supports named subagents
65
- (Claude Code natively; Cursor reads the same `.claude/agents/` files via its
66
- Claude-compatibility path), each maps to a definition file. Where it does not, the role
67
- degrades to a bounded sub-task that dumps its noise to a file and returns only a
68
- terse summary + path. Workers cannot address the user — only the orchestrator
69
- can. Escalation is at most two hops.
104
+ Each role is a fresh-context worker. On Claude Code each maps to a named subagent
105
+ definition file (`.claude/agents/*.md`). Each worker dumps its noise to a file and
106
+ returns only a terse summary + path. Workers cannot address the user — only the
107
+ orchestrator can. Escalation is at most two hops.
70
108
 
71
109
  - **researcher** — two modes. DESIGN: domain/constraint research before planning
72
110
  (service limits, API contracts, architectural constraints, cost surprises);
@@ -76,29 +114,57 @@ can. Escalation is at most two hops.
76
114
  datasource-<name>.md`. IMPL: per-phase codebase + service investigation. Checks
77
115
  the shared KB snapshot first (step 0). Writes findings to `docs/research/`;
78
116
  returns terse summary + path.
79
- - **planner** — research → vertical-slice `docs/PLAN.md`. Phase 0 (infra) always
80
- first; the last phase always contains the deploy task. For any phase whose
81
- `changes` touch the frontend root, the `acceptance` MUST include ≥1 UI-existence
117
+ - **planner** — research → vertical-slice `docs/PLAN.md`. Phase 0 (infra) first
118
+ iff `infra_needed: true`; the last phase always completes `deploy_kind`. For any
119
+ phase whose `changes` touch the frontend root, the `acceptance` MUST include ≥1
120
+ UI-existence
82
121
  criterion naming the specific user-visible interactive element introduced (not
83
122
  "page renders 200"). Populates each phase's expected `DATAFLOW.md` transitions.
84
- - **infra-provisioner** generates Bicep, runs `az deployment what-if`, applies
85
- only on human approval, writes `docs/INFRA.md` + `.env.test`. Runs the one-time
86
- AUTH PROOF (§5.37): proves every credential the project's real tests will use is
87
- obtainable headlessly twice in a row (prime + reuse) with zero prompts.
123
+ At `/overview` it ALSO enumerates the up-front CASE-NAME contract (§5.44): for
124
+ every `DATAFLOW.md` transition and every `acceptance:` criterion in a TDD phase,
125
+ the case *names* that must exist (happy path, each named edge, each named failure
126
+ + error code) no fixture values yet written as skeleton `docs/spec-phase-<n>.md`
127
+ files (generated header + named rows, values `TBD`).
128
+ - **spec-author** — fills the per-phase spec. Runs AFTER RESEARCH, BEFORE SPEC
129
+ REVIEW. Reads the skeleton `spec-phase-<n>.md`, the confirmed
130
+ `datasource-<name>.md` baseline, and per-phase RESEARCH for the real API shape;
131
+ fills each case row with a real input payload (`fixtures/<case-id>-input.json`),
132
+ concrete expected output (`fixtures/<case-id>-expected.json`), matcher tokens for
133
+ volatile fields, `error-code` for failures, and `selector/assert/value` for `ui`
134
+ cases. Returns `CASE-SET-DIVERGENCE` if a required case cannot be filled from real
135
+ facts, or research reveals an unlisted branch/failure-mode. `spec-author` is NOT
136
+ `implementer` (author ≠ implementer invariant, §5.53) and never reads
137
+ implementation logic.
138
+ - **infra-provisioner** — dispatched only when `infra_needed: true` (Phase 0).
139
+ Generates IaC, runs the provider's what-if/plan diff, applies only on human
140
+ approval, writes `docs/INFRA.md` + `.env.test`. Runs the one-time AUTH PROOF
141
+ (§5.37): proves every credential the project's real tests will use is obtainable
142
+ headlessly twice in a row (prime + reuse) with zero prompts. Cloud-specific
143
+ practice (Azure Bicep/`az`, Entra/MSAL) lives in `knowledge/azure.md`.
88
144
  - **implementer** — builds ONE phase. Two MODES for TDD phases (SCAFFOLD: stubs
89
145
  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`.
146
+ Writes code, never tests. On TDD phases it reads the human-approved filled
147
+ `docs/spec-phase-<n>.md` as its behavioral contract (normal spec-driven
148
+ development) it never authors spec fixtures (author implementer, §5.53).
149
+ Maintains `docs/ENDPOINTS.md` each phase.
150
+ - **test-author** now a HARNESS EMITTER, not a blind assertion author (§5.53). On
151
+ TDD phases it reads the locked spec rows and GENERATES the assertion harness: one
152
+ deep-equality assertion against `fixtures/<case-id>-expected.json` per `data` case,
153
+ citing the case with a `# spec: <case-id>` comment, using the kit-versioned
154
+ comparator `tests/helpers/spec-assert.*` (which honors matcher tokens). It does
155
+ not invent assertions there is nothing for a human to review at the test layer.
156
+ Places contract/transition tests in `tests/regression/`, phase-local in
157
+ `tests/phase-<n>/`; mock-vs-boundary is a `TEST_MODE` flag on the SAME test.
158
+ - **e2e-runner** — the browser boundary emitter (E2E_KIND `browser`), dispatched
159
+ only for frontend phases; a Playwright EMITTER for `ui` boundary cases, not a
160
+ blind author (§5.54). Reads `docs/INFRA.md` for the target and each `ui` case's
161
+ `fixtures/<case-id>-ui.json` descriptor (`selector / assert / value`, closed
162
+ vocabulary: `visible | text-equals | enabled | count`), and emits the assertion.
163
+ Captures a screenshot at EACH UI-existence assertion regardless of pass/fail
164
+ (capture-on-success) to `docs/evidence/e2e-phase-<n>/`, plus a summary in
165
+ `docs/research/e2e-<slug>.md`. Stack ritual + config templates: `knowledge/webapp.md`.
166
+ (Non-browser E2E_KINDs — cli/http/library-api — have no separate emitter; the
167
+ real-mode boundary suite is the outer run.)
102
168
  - **debugger** — debugs in an ISOLATED context. Writes a trace to
103
169
  `docs/research/debug-<slug>.md`; returns a summary.
104
170
  - **synthesizer** — compresses `docs/STATE.md` / `docs/ISSUES.md`, prunes
@@ -110,20 +176,27 @@ The orchestrator ROUTES. It does not implement or debug.
110
176
 
111
177
  ## Procedures (the slash-command set)
112
178
 
113
- Named procedures, each with a canonical body in `commands.src/<name>.md` and a
114
- generated copy per tool (`.claude/commands/`, `.cursor/commands/`).
179
+ Named procedures, each with a canonical body in `commands.src/<name>.md`, copied
180
+ to `.claude/commands/` at install.
115
181
 
116
182
  - **overview** — bootstrap a project: design-research → grill r1 → design-research
117
183
  → RESEARCH REVIEW → re-grill r2 (covers data structures, dataflow, and object
118
184
  state flow) → `OVERVIEW.md` (+ `has_frontend`/frontend-root, `DATAFLOW.md`,
119
- confirmed datasource understanding) → planner → `PLAN.md` (Phase 0 always first).
120
- - **infra** — provision/verify Azure infra: Bicep → what-if human review → apply
121
- `INFRA.md` + `.env.test`. Runs the one-time AUTH PROOF.
185
+ confirmed datasource understanding) → planner → `PLAN.md` (Phase 0 always first)
186
+ + skeleton `docs/spec-phase-<n>.md` case-name files. The end-of-`/overview` human
187
+ approval is EXTENDED to confirm the cross-phase skeleton case-name set in the same
188
+ surface (no new gate, §5.51). Also declares the project flags (`project_type`,
189
+ `infra_needed`, `e2e_kind`, `deploy_kind`, `knowledge_docs`).
190
+ - **infra** — provision/verify infra (only when `infra_needed: true`): IaC →
191
+ what-if/plan → human review → apply → `INFRA.md` + `.env.test`. Runs the one-time
192
+ AUTH PROOF. Cloud specifics in `knowledge/azure.md`.
122
193
  - **phase [n]** — run one phase end-to-end with the circuit breaker. Chooses the
123
194
  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.
195
+ phases: `spec-author` fills the spec `spec-staleness.sh` SPEC REVIEW (human,
196
+ before SCAFFOLD) SCAFFOLD RED (generated harness) `spec-conformance.sh`
197
+ GREEN boundary/E2E. Frontend phases run mandatory `ui` boundary with screenshot
198
+ evidence. CLOSE runs the regression guard + ENDPOINTS coverage gate + DATAFLOW
199
+ transition→case coverage gate + evidence-present check.
127
200
  - **quick [change]** — small, obvious, non-phase change; no agent chain. Stays
128
201
  non-TDD. Runs the mock regression corpus after the change.
129
202
  - **unstuck** — deep re-research after a circuit breaker (human-triggered).
@@ -139,9 +212,8 @@ generated copy per tool (`.claude/commands/`, `.cursor/commands/`).
139
212
 
140
213
  ## Rituals (model-run fallback for hooks)
141
214
 
142
- Where the host tool can run lifecycle hooks (Claude Code, Cursor), these rituals
143
- are AUTOMATED by hook scripts and must NOT be run by hand. Where the tool cannot
144
- inject context, the model performs them itself.
215
+ On Claude Code these rituals are AUTOMATED by hook scripts and must NOT be run by
216
+ hand. Where a host tool cannot inject context, the model performs them itself.
145
217
 
146
218
  ### SESSION-OPEN (start / clear / compact-resume)
147
219
 
@@ -149,7 +221,7 @@ At the start of every session, before any other work, surface:
149
221
  1. git state (branch, uncommitted count, last 3 commits).
150
222
  2. `docs/STATE.md` — the current position. READ THIS FIRST.
151
223
  3. open items in `docs/ISSUES.md`.
152
- 4. `docs/research/INDEX.md` (research map) + infra status + auth nudge.
224
+ 4. `docs/research/INDEX.md` (research map) + infra status (when `infra_needed`).
153
225
  5. shared KB: pull latest + load `docs/.kb-snapshot.md` if `.claude/kb-config.json`
154
226
  exists.
155
227
  6. a one-line reminder of the hard rules below.
@@ -161,7 +233,7 @@ recover: current phase, next action, open blocker.
161
233
 
162
234
  -----
163
235
 
164
- ## Hard rules (1–16)
236
+ ## Hard rules (1–19)
165
237
 
166
238
  1. Before debugging ANY error: grep `docs/ISSUES.md` AND `docs/research/INDEX.md`.
167
239
  The SESSION-OPEN ritual surfaces ISSUES.md — there is no excuse to miss it.
@@ -170,57 +242,103 @@ recover: current phase, next action, open blocker.
170
242
  3. Every resolved error -> logged to `docs/ISSUES.md` with root cause + failed
171
243
  attempts.
172
244
  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).
182
- 7. Service outage is not a bug `SERVICE UNAVAILABLE` / `AZURE UNAVAILABLE` /
183
- `STACK NOT READY` / `FLAKE` do not spend the debug budget. Only `LOGIC FAIL`
184
- reaches the debugger.
185
- 8. E2E auth = ROPC with a dedicated MFA-excluded test account. NEVER script the
186
- Microsoft login UI.
245
+ 5. **PHASE GATE** = every current-phase spec case's BOUNDARY test passes (`data`:
246
+ real HTTP/CLI/message; `ui` (browser E2E_KIND): Playwright with screenshot evidence) AND the
247
+ accumulated mock regression corpus stays green AND every `docs/ENDPOINTS.md`
248
+ entry has at least one test in `tests/regression/` AND `spec-conformance.sh`
249
+ passed (no TBD, every case-id cited by a boundary test) AND every REACHABLE
250
+ `docs/DATAFLOW.md` transition has at least one filled case in the phase spec
251
+ (rule 14). The final phase additionally runs the full REAL regression corpus and
252
+ requires zero PENDING transitions. A green mock suite alone can never close a phase.
253
+ 6. On TDD phases the behavioral contract is the human-approved
254
+ `docs/spec-phase-<n>.md`; tests are GENERATED from its case rows (not authored):
255
+ `test-author` emits a deep-equality harness against the shared fixtures for
256
+ `data` cases, `e2e-runner` emits Playwright from the `ui` descriptor (browser
257
+ E2E_KIND). Because the
258
+ spec row and the test load the SAME fixture, a test physically cannot assert
259
+ different values than the locked spec. Humans review the spec (SPEC REVIEW), never
260
+ the tests.
261
+ 7. Service outage is not a bug — `SERVICE UNAVAILABLE` / `STACK NOT READY` /
262
+ `FLAKE` (plus cloud-specific aliases like `AZURE UNAVAILABLE` per the knowledge
263
+ doc) do not spend the debug budget. Only `LOGIC FAIL` reaches the debugger.
264
+ 8. E2E auth = a dedicated headless-capable test credential. NEVER script an
265
+ interactive login UI. (Provider specifics — Azure ROPC + MFA-excluded account —
266
+ in `knowledge/azure.md`.)
187
267
  9. Architectural change (new/removed agent, hook, command, or a changed workflow
188
268
  rule)? -> run `log-decision` before closing. A phase that changes an object's
189
269
  state lifecycle MUST update `docs/DATAFLOW.md` in the same CLOSE.
190
- 10. Azure project? Run `scripts/auth-setup.sh` ONCE per session before any Azure
191
- work. Never debug an auth error without checking this first.
270
+ 10. **Deterministic flags.** `project_type` / `has_frontend` / `infra_needed` /
271
+ `e2e_kind` / `deploy_kind` / `knowledge_docs` are DECLARED at `/overview` and
272
+ recorded in `docs/OVERVIEW.md`; per-phase `TDD_PHASE` + effective `E2E_KIND`
273
+ are bound at RESEARCH and stated. No flag is ever inferred silently mid-phase;
274
+ changing one is a `/replan`-level event.
192
275
  11. **No-rationalization (scoped).** Do not, in order to dodge a gate:
193
276
  downgrade a TDD phase to non-TDD or route phase-worthy work through `quick`
194
277
  (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.
202
- 13. **Mandatory frontend E2E + evidence.** When `has_frontend: true` and the
203
- phase's `changes` touch the frontend root recorded in OVERVIEW.md, E2E MUST
204
- run. Each UI-existence assertion captures a screenshot (on success too) to
205
- `docs/evidence/e2e-phase-<n>/`. Frontend files changed with no E2E run, or a
206
- closed frontend phase with no evidence on disk, fails CLOSE hard. (Evidence is
207
- 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.
278
+ acceptance spec (E2E / UI-existence gate); fabricate a fixture value or leave a
279
+ `TBD` to slip past SPEC REVIEW / conformance instead of escalating UNDERSPEC or
280
+ `CASE-SET-DIVERGENCE`; mark a reachable transition PENDING (DATAFLOW gate); or
281
+ skip evidence capture. (Scoped deliberately to these named seams; this is not a
282
+ broad "never make excuses" rule.)
283
+ 12. **SPEC REVIEW (TDD phases).** SCAFFOLD cannot begin until the human confirms the
284
+ filled `docs/spec-phase-<n>.md` cases, surfaced as falsifiable claims. Rejection
285
+ is classified at the gate (§5.50): wrong expected fix case row + fixture; wrong
286
+ input shape re-dispatch `spec-author`; new or contradicted case hard re-entry
287
+ to amend the up-front case-name contract, re-confirm the amended + same-`covers`
288
+ neighbor cases (staleness-hash certifies the unchanged remainder), then re-fill
289
+ (§5.52). Unskippable on TDD phases; absent on the non-TDD path (no behavioral
290
+ contract to review). Replaces the v2.1 human TEST REVIEW gate (removed — humans
291
+ no longer review tests).
292
+ 13. **Mandatory boundary run + evidence (per E2E_KIND).** Browser: when
293
+ `has_frontend: true` and the phase's `changes` touch the frontend root recorded
294
+ in OVERVIEW.md, E2E MUST run; each UI-existence assertion captures a screenshot
295
+ (on success too) to `docs/evidence/e2e-phase-<n>/`. Other kinds
296
+ (cli/http/library-api): the phase's boundary tests MUST run in real mode against
297
+ the outer surface with output captured to the same evidence dir. Boundary-relevant
298
+ files changed with no boundary run, or a closed phase with no evidence on disk,
299
+ fails CLOSE hard. (Evidence is gitignored — present-on-disk at CLOSE is the check,
300
+ not committed history.)
301
+ 14. **DATAFLOW transition coverage (re-seamed v2.2, §5.56).** Every transition in
302
+ `docs/DATAFLOW.md` whose trigger is reachable in the code shipped so far MUST
303
+ have ≥1 FILLED CASE in `docs/spec-phase-<n>.md` (was: ≥1 test in
304
+ `tests/regression/`); zero coverage on a reachable transition fails CLOSE hard.
211
305
  Unreachable transitions list as PENDING. Any transition still PENDING at the
212
- final phase fails hard. Peer to the ENDPOINTS coverage gate.
306
+ final phase fails hard. The case→test half of the old guarantee now lives in
307
+ `spec-conformance.sh` (rule 18: every case-id is cited by a boundary test, which
308
+ by placement convention lands in `tests/regression/`). Peer to the ENDPOINTS
309
+ coverage gate, which is unchanged and orthogonal (endpoint-keyed, not
310
+ behavior-keyed).
213
311
  15. **Datasource data understanding.** Real-suite / E2E tests against an external
214
312
  datasource are HARD-BLOCKED until that datasource's DATA UNDERSTANDING is
215
313
  confirmed (baseline at `/overview`; per-phase delta-confirm for any
216
314
  new table/column). The mock suite still runs. No testing against data you
217
315
  never confirmed understanding of.
218
- 16. **Auth proof + liveness.** A one-time AUTH PROOF at `/infra` proves every
219
- credential the real tests use — Entra/MSAL app login AND external datasource
220
- credentials — is obtainable headlessly twice in a row (prime + reuse) with
221
- zero prompts; "reusable without interaction" means exactly this. Each `/phase`
222
- PRE-FLIGHT runs a cheap liveness check (token obtainable, not expired) before
223
- dispatching real/E2E. Both fail loud; the mock suite proceeds regardless.
316
+ 16. **Auth proof + liveness.** A one-time AUTH PROOF at `/infra` (when
317
+ `infra_needed`) proves every credential the real tests use — the app login AND
318
+ every external datasource credential — is obtainable headlessly twice in a row
319
+ (prime + reuse) with zero prompts; "reusable without interaction" means exactly
320
+ this. Each `/phase` PRE-FLIGHT runs a cheap liveness check (the command recorded
321
+ in `docs/INFRA.md ## AUTH`) before dispatching real/E2E. Both fail loud; the
322
+ mock suite proceeds regardless.
323
+ 17. **Spec staleness (§5.55).** `scripts/spec-staleness.sh <n>` runs immediately
324
+ after `spec-author` fills the spec AND again at SPEC REVIEW entry. It re-hashes
325
+ the current `PLAN.md` `acceptance:` line + the in-scope `DATAFLOW.md` transition
326
+ rows and compares to the hash embedded in the spec's generated header. A
327
+ mismatch (upstream drifted since the skeleton was generated) exits nonzero and
328
+ blocks SPEC REVIEW — the spec must be regenerated/re-filled. The generated
329
+ header is never hand-edited.
330
+ 18. **Spec conformance (§5.55).** `scripts/spec-conformance.sh <n>` runs between RED
331
+ and GREEN, replacing the removed human TEST REVIEW gate. It loud-fails (blocks
332
+ GREEN) if any `TBD` marker remains in the spec or its fixtures, or if any case-id
333
+ in the spec table has no boundary test citing it via the `# spec: <case-id>`
334
+ convention.
335
+ 19. **Author ≠ implementer (§5.53).** `spec-author` and `implementer` are distinct
336
+ roles. `spec-author` fills the spec + fixtures and NEVER reads implementation
337
+ logic; `implementer` reads the filled spec as its contract and NEVER authors spec
338
+ fixtures. `test-author` / `e2e-runner` are harness EMITTERS, not assertion
339
+ authors. This replaces the v2.1 test-author RED-first blindness invariant: spec
340
+ fixtures are written before code, so the contract cannot be shaped toward an
341
+ implementation.
224
342
 
225
343
  -----
226
344
 
@@ -237,22 +355,42 @@ the KB. The kit works normally without a KB.
237
355
 
238
356
  - `docs/STATE.md` — current position. Small. Rewritten, not appended.
239
357
  - `docs/ISSUES.md` — error log. Deduped by synthesizer.
240
- - `docs/PLAN.md` — the phase plan. Phase 0 (infra) always first; last phase has
241
- the deploy task.
358
+ - `docs/PLAN.md` — the phase plan. Phase 0 (infra) first iff `infra_needed`; last
359
+ phase completes `deploy_kind`.
242
360
  - `docs/HISTORY.md` — one line per finished phase.
243
361
  - `docs/DESIGN_LOG.md` — kit architectural rationale (§5.x decision log).
244
362
  - `docs/OVERVIEW.md` — project scope. Written after the double-grill in `overview`.
245
- Carries `has_frontend` + the frontend root path, and the data/state-flow summary.
363
+ Carries the project flags (`project_type`, `has_frontend` + frontend root,
364
+ `infra_needed`, `e2e_kind`, `deploy_kind`, `knowledge_docs`) and the
365
+ data/state-flow summary.
366
+ - `knowledge/<usecase>.md` — preinstalled matured practice (`webapp.md`,
367
+ `azure.md`), consulted by `researcher` when listed in OVERVIEW `knowledge_docs`.
368
+ Ships use-case templates materialized per project on demand.
369
+ - `.claude/ref/compression.md` — kit-native compression profiles (`user`,
370
+ `internal`), single source, always-on. Not a skill.
246
371
  - `docs/DATAFLOW.md` — state-transition table per key object (`object | states |
247
372
  transition (from→to) | trigger | who writes | external system`). Living doc,
248
373
  grill-driven; drives the CLOSE transition-coverage gate. The data-side analogue
249
374
  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)
375
+ - `docs/spec-phase-<n>.md` — the per-phase behavioral contract (v2.2). Skeleton
376
+ (case names + `TBD` values) generated at `/overview`; filled by `spec-author` per
377
+ phase. Generated self-correlating header transcludes the phase's `PLAN.md`
378
+ `acceptance:` line + in-scope `DATAFLOW.md` transition rows and embeds a staleness
379
+ hash (never hand-edited). The only human-authored region is the example-case table.
380
+ Human-approved at SPEC REVIEW before SCAFFOLD. (Committed.)
381
+ - `fixtures/<case-id>-input.json` / `-expected.json` / `-ui.json` — the shared
382
+ fixtures a spec row references AND the generated test harness loads (transcription
383
+ is structural, not honor-system). `-expected.json` carries matcher tokens for
384
+ volatile fields; `-ui.json` is the `[{selector,assert,value}]` UI descriptor.
385
+ (Committed — part of the contract.) (v2.2)
386
+ - `tests/helpers/spec-assert.*` — the kit-versioned per-language comparator that
387
+ honors matcher tokens (`<UUID>`, `<ISO8601>`, `<ANY_STRING>`, `<ANY_NUMBER>`,
388
+ `<UNORDERED>`, `<MATCHES:regex>`). One implementation per supported test language;
389
+ NO per-project comparator code. (v2.2)
252
390
  - `docs/evidence/e2e-phase-<n>/` — screenshot evidence captured at each UI-existence
253
391
  assertion (gitignored; present-on-disk at CLOSE is the gate). (v2.1)
254
- - `docs/INFRA.md` — Azure infra manifest: resource IDs, endpoints, cost estimates,
255
- E2E target, AUTH PROOF result.
392
+ - `docs/INFRA.md` — infra manifest (when `infra_needed`): resource IDs, endpoints,
393
+ cost estimates, E2E target, `## AUTH` liveness command, AUTH PROOF result.
256
394
  - `docs/ENDPOINTS.md` — API/service endpoint catalogue. Maintained by implementer
257
395
  each phase. Drives the CLOSE coverage gate.
258
396
  - `docs/research/` — full research + debug files. `INDEX.md` is the searchable map.
@@ -260,14 +398,19 @@ the KB. The kit works normally without a KB.
260
398
  `debug-<slug>.md` (debugger traces), `datasource-<name>.md` (confirmed data
261
399
  understanding, referenced from DATAFLOW.md external rows).
262
400
  - `docs/.snapshots/` — pre-compact recovery markers (auto-pruned, gitignored).
263
- - `infra/` — Bicep templates. Committed (IaC audit trail). `infra/params.json`
264
- holds no secrets.
265
- - `e2e/`, `scripts/e2e-stack.sh`, `docker-compose.test.yml`, `playwright.config.ts`
266
- the E2E stack.
401
+ - `infra/` — IaC templates, generated per project by `infra-provisioner`. Committed
402
+ (audit trail). `infra/params.json` holds no secrets. (Azure Bicep specifics:
403
+ `knowledge/azure.md`.)
404
+ - `knowledge/webapp.md` owns the browser E2E stack templates (`playwright.config.ts`,
405
+ `e2e/global-setup.ts`, `docker-compose.test.yml`, `scripts/e2e-stack.sh`) —
406
+ materialized into the project only when a browser phase needs them, then user-owned.
267
407
  - `tests/phase-<n>/` — phase-local test suites.
268
408
  - `tests/regression/` — cross-phase contract tests (the regression corpus). Run by
269
409
  `scripts/regression.sh` (default mock; `--real` runs the real corpus).
270
- - `scripts/auth-setup.sh`session Azure credential check. Run once per session.
410
+ - `scripts/spec-staleness.sh <n>` loud-fails if the spec's generated header drifted
411
+ from the current `PLAN.md` acceptance line + `DATAFLOW.md` rows (rule 17). (v2.2)
412
+ - `scripts/spec-conformance.sh <n>` — loud-fails on any remaining `TBD` or any
413
+ case-id with no citing boundary test (rule 18). Runs between RED and GREEN. (v2.2)
271
414
  - `.claude/kb-config.json` — shared KB path + remote (optional, written by setup.sh).
272
415
  - `docs/.kb-snapshot.md` — KB INDEX loaded this session (auto-generated, gitignored).
273
416
 
@@ -275,18 +418,9 @@ the KB. The kit works normally without a KB.
275
418
 
276
419
  ## Capability matrix (which tools get what)
277
420
 
278
- - **Claude Code — full (reference implementation).** Generated commands; all three
279
- lifecycle hooks WITH context injection (SessionStart / PreCompact / SubagentStop);
280
- named subagents (`.claude/agents/*.md`); `@AGENTS.md` import; shared KB.
281
- - **Cursor full (verified against cursor.com/docs, 2026-06).** Generated
282
- commands (`.cursor/commands/`); the three lifecycle hooks via `.cursor/hooks.json`
283
- (sessionStart / preCompact / subagentStop) wired to the SAME shared hook scripts —
284
- sessionStart injects context via a JSON-envelope wrapper
285
- (`cursor-session-start.sh`); named subagents work natively because Cursor reads
286
- `.claude/agents/*.md` directly (no duplication); methodology via a
287
- `.cursor/rules/` pointer at this file. Known degradations: `model: haiku/opus`
288
- tiers are Claude-specific (Cursor falls back to inherit/compatible), and Cursor's
289
- preCompact is observational (the snapshot side-effect still runs; no context
290
- modification).
421
+ - **Claude Code — full (the only supported target, v2.3).** Generated commands
422
+ (`.claude/commands/`); all three lifecycle hooks WITH context injection
423
+ (SessionStart / PreCompact / SubagentStop); named subagents (`.claude/agents/*.md`);
424
+ `@AGENTS.md` import; shared KB.
291
425
  - **Everything else.** Reads this `AGENTS.md` if it supports the open standard.
292
- No generated adapters. Not claimed as supported in v2.0.
426
+ No generated adapters, no support claim (Cursor parity was dropped in v2.3, §5.69).
@@ -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 |
@@ -34,12 +35,6 @@ hooks (wired in `.claude/settings.json`) perform them:
34
35
  live position before compaction.
35
36
  - **SubagentStop** (`.claude/hooks/subagent-stop.sh`) writes a subagent trace.
36
37
 
37
- The same script bodies are wired for Cursor in `.cursor/hooks.json`; only the
38
- wiring differs (Cursor's sessionStart expects JSON output, so it runs the shared
39
- body through the `cursor-session-start.sh` envelope wrapper). Cursor also reads
40
- `.claude/agents/*.md` natively for subagents — one set of role files serves both
41
- tools.
42
-
43
38
  ## /clear keeps hooks
44
39
 
45
40
  `/clear` does not drop hooks — the wiring lives in `settings.json`, not in
@@ -47,9 +42,10 @@ context. After `/clear`, SessionStart fires again and re-injects state.
47
42
 
48
43
  ## Skills resolution
49
44
 
50
- - `karpathy-guidelines` — kit-owned (`.claude/skills/karpathy-guidelines/`).
51
- - `caveman`, `grill-me` — global-authoritative if installed; the vendored copies
52
- under `.claude/skills/` are a fallback only.
45
+ - `karpathy-guidelines`, `grill-me` — kit-owned (`.claude/skills/…`), the sole
46
+ source. No "global-authoritative if installed" resolution.
47
+ - Compression is kit-native (`.claude/ref/compression.md`), NOT a skill — always
48
+ on, single source, never model-invoked.
53
49
 
54
50
  ## Platform notes
55
51