Verify
Overview
/verify is the final gate before a change ships. Unit tests prove the code compiles and the methods return what their authors expected. They do not prove the running service accepts real payloads, returns the documented envelope, preserves cross-service contracts, or survives the weird shapes production traffic actually produces. /verify does that.
Core principle: No completion claim is trustworthy until a curl against a running service produces the right response body, status code, and side effects — with fresh, recorded output. Everything else is paraphrase.
Design goals every run must optimize for:
- Evidence, not assertion — every "pass" is backed by recorded
curl -ioutput stored under the ticket folder - Payload realism — fixtures come from real row shapes (DB sample) or user-provided cases, not invented JSON
- Variant coverage — happy path + at least one boundary + at least one negative per endpoint
- Iteration discipline — on failure, pass a specific delta to
/work, not "it broke, fix it" - Escalation bounds — unproductive
/workloops are detected and escalated, not retried forever - Environment-bounded blast radius — local/dev is default; audit/stg payload runs are allowed only when the user explicitly names that target; prod is never allowed
The Iron Law
NO "PRODUCTION READY" CLAIM UNTIL EVERY ASSERTION PASSES AGAINST A LIVE TARGET SERVICE
NO LIVE VERIFICATION OUTSIDE THE USER-AUTHORIZED TARGET AND DATA SCOPE
NO API VERIFICATION WITHOUT A GENERATED CURL HARNESS, RECORDED `curl -i` OUTPUT, AND SAVED REQUEST FIXTURES
NO REACHABLE HTTP ENDPOINT MAY BE VERIFIED BY UNIT TESTS, BYTECODE, MAPPER SQL, OR CODE READING INSTEAD OF CURL
NO PAYLOAD RUN AGAINST prod FROM THIS SKILL
AUDIT/STG PAYLOAD RUNS REQUIRE EXPLICIT USER INSTRUCTION AND RECORDED TARGET ENVIRONMENT
NO SKILL EXIT UNTIL verify.md IS WRITTEN AND ITS STATUS IS pass | fail-escalated | fail-user-required
When to Use
Normal mode — the pipeline position:
/explore → explore.md
/work → work.md (code + unit/integration tests + lint/build)
/verify → verify.md (HTTP-level E2E proof; re-triggers /work on failure)
Invoke /verify when any holds:
/workhas just completed for<YYYYMM>/<slug>and the user wants proof before merging.- A paired
work.mdexists but the current session has no fresh HTTP-level evidence. - The user supplies an API path + at least one payload and asks for ad-hoc verification (standalone mode — see below).
- A bug report arrived against an existing endpoint and you want to reproduce + gate the fix before touching code. (In this case
/verifyruns first, captures the failing curl, then hands off to/explore→/work→/verify.)
Skip only for:
- Pure frontend-only diffs with no backend surface touched (run
npm run devand use the browser; a separate skill owns frontend QA). - Config-only changes that do not alter any HTTP contract.
- Doc/comment-only commits.
Standalone Mode (no ticket folder)
If there is no <artifact-root>/.backend/<YYYYMM>/<slug>/ folder and the user wants ad-hoc API verification:
- Identify endpoint (method + path), target service, and sample payload from the request or existing fixtures; ask only for missing inputs or data-access authorization.
- Derive a slug from the endpoint (e.g.
verify-post-users-login) and today's<YYYYMM>. - Choose the artifact root:
- If the endpoint belongs to a single microservice/module, use that service directory. Example:
example-viewer-api/.backend/<YYYYMM>/<slug>/. - If the endpoint spans multiple services or is explicitly repo-wide, use the repo root.
- If unclear, infer from controller/service paths; ask only when multiple service roots are equally plausible.
- If the endpoint belongs to a single microservice/module, use that service directory. Example:
- Create
<artifact-root>/.backend/<YYYYMM>/<slug>/and proceed from Phase 2 onward.explore.mdandwork.mdwill not exist — record that in Phase 0 instead of loading them. - On Phase 6 write only
verify.md(no docs entry — that is/work's job).
Inputs & Outputs
Inputs
| Source | What to extract |
|---|---|
<artifact-root>/.backend/<YYYYMM>/<slug>/explore.md |
§5B.contract (req/resp shape), §7 (which endpoints changed), §8 (cross-service contracts that must still hold) |
<artifact-root>/.backend/<YYYYMM>/<slug>/work.md |
§4 (files edited → derive touched endpoints), §7 (cross-service impact to re-check), §8 (follow-ups that might be relevant to probe) |
The service's own CLAUDE.md |
Run command, local port, profile, auth scheme |
project root CLAUDE.md |
"local service ports, profile overrides, SSO callback rules"; Feign/Redis/SSE patterns |
| User messages | Extra payloads, environment overrides, explicit accept/reject on re-work |
| Saved fixtures | <artifact-root>/.backend/<YYYYMM>/<slug>/fixtures/*.json from earlier /verify runs on this ticket |
| Live read-only MySQL | Payload shapes sampled from real rows — PII redacted (see payload-sourcing.md) |
Outputs (all three are required for completion)
| Artifact | Path | Purpose |
|---|---|---|
| Curl harness | <artifact-root>/.backend/<YYYYMM>/<slug>/harness/*.sh |
Reusable shell scripts — one file per endpoint, BASE_URL/TOKEN configurable |
| Fixture payloads | <artifact-root>/.backend/<YYYYMM>/<slug>/fixtures/*.json |
Per-variant payload bodies, redacted of PII |
| Run log + report | <artifact-root>/.backend/<YYYYMM>/<slug>/verify.md + <artifact-root>/.backend/<YYYYMM>/<slug>/runs/run-<N>.log |
Dense symbolic report + raw curl output per iteration |
Folder layout (per ticket, post-verify):
<artifact-root>/.backend/
<YYYYMM>/
<slug>/
explore.md ← from /explore
work.md ← from /work
verify.md ← this skill
harness/
<endpoint>.sh ← one curl harness per endpoint (executable)
_env.sh ← BASE_URL / TOKEN / COMMON_HEADERS
fixtures/
<endpoint>.<variant>.json
...
runs/
run-1.log ← full curl -i output for iteration 1
run-2.log ← (only exists if /work was re-invoked)
run-3.log
See verify-template.md for the exact verify.md format and curl-harness.md for the shell script template.
Execution Rules
Language: Match the user's language for user-facing responses, verification plans, final summaries, and docs notes. Keep code symbols, file paths, SQL, endpoints, commands, and exact error strings unchanged.
Required:
- In Phase 0, state the target and verification plan. Reuse existing authorization; ask only for missing target/data permissions.
- Prepare harnesses and inspect code within scope. Before live calls or data sampling, verify the target and side effects are authorized; do not run unapproved shared-environment mutations.
- Perform verification directly; delegate bounded independent cases only when useful, available, and authorized.
- Verifier subagents write only under the ticket folder:
harness/*.sh,fixtures/*.json,runs/run-<N>.log. - The main agent writes the approved plan, verifier work log, and result matrix to
<artifact-root>/.backend/<YYYYMM>/<slug>/verify.md. - If a
/workdocs entry exists, append only aVerification (/verify)section to that file. In standalone mode, do not create a new docs entry.
Plan must include:
targets, env/base URL, payload sources, variants, assertions, artifact paths, safety bounds, subagent assignments.
Forbidden:
- prod payload run.
- audit/stg run without explicit user instruction.
- Substituting unit tests or code reading for a reachable endpoint.
- Delegating without a bounded task, available tools, and authorization.
Verifier handoff:
scope, artifacts, commands, result matrix rows, failures/blockers, redaction notes.
Quality gates:
- Done = approved plan recorded, fixtures/harness/run logs exist,
verify.md §6matrix matches latestruns/run-<N>.log, status is valid. - Scope = writes only under ticket
.backend/<YYYYMM>/<slug>/{harness,fixtures,runs,verify.md}plus optional docs-note append. - Evidence = HTTP claim cites
runs/run-<N>.log:line; payload claim cites fixture/source; DB claim records read-only query shape + redaction note. - Failure =
FAIL-APPservice behavior wrong,FAIL-CONTRACTexplore/work contract wrong,FAIL-ENVtarget/auth/downstream unavailable,FAIL-DATApayload source invalid,PASS-WITH-NOTESnon-blocking gap. - Escalate =
FAIL-APPcreates bounded/workdelta with user approval;FAIL-CONTRACTreturns to/explore;FAIL-ENV/FAIL-DATAasks user for env/data.
Final response:
Report the absolute verify.md path, status, endpoint/variant pass-fail, work performed and, if delegated, verifier ownership, and blockers, then STOP.
The Seven Phases
Complete each phase before the next. Do not interleave. The loop between Phase 4 and Phase 5 is the only legal loop; no ad-hoc retries.
Phase 0 — Load & Validate the Contract
- Determine artifact root and ticket folder — ask or infer
<YYYYMM>/<slug>. Readexplore.mdandwork.mdin full if they exist.- If
work.md §4or the user scope points to a single microservice/module, use that service directory as artifact root. - If the change spans multiple services or is explicitly repo-wide, use the repo root.
- If
- Announce the kind (Bug / Feature / Refactor), the scope one-liner from
explore.md §2, and whether/workreportedstatus: done | partial | blockedinwork.md §10re-entry header. - From
work.md §4 Changesandexplore.md §7 Proposed Changes, derive the endpoint target list — the minimal set of HTTP surfaces that must be probed:- Controllers /
@RequestMappingthat were edited or added. - Feign client methods that were added/extended (these imply an endpoint on the callee service that now has a new contract).
- Endpoints exercised by any test that was added/edited in
work.md §5.
- Controllers /
- For each target, record: service, method, path, auth required?, content-type, sample response envelope citation (
file:line). - Validate:
- At least one endpoint target was derivable. If zero targets, stop — the change had no HTTP surface and
/verifyis the wrong skill. - Each target's service exposes a reachable local/dev profile, or the user explicitly asked to verify an audit/stg target. Confirm ports/profile from the service's
CLAUDE.md, profile config, process command, or target URL. work.md §10status is notblocked. If blocked, stop and tell the user/workmust complete before/verifyruns.
- At least one endpoint target was derivable. If zero targets, stop — the change had no HTTP surface and
- Confirm the target environment:
- Default:
local/devservice onlocalhost,127.0.0.1,0.0.0.0, orhost.docker.internal. - Allowed by explicit user instruction:
auditorstg, including a locally bound instance running that profile. - Never allowed:
prodor any hostname/base URL that resolves to production.
- Default:
- Record the target env,
BASE_URL, and evidence that the user asked for audit/stg if not local/dev. If the target is ambiguous, stop and ask.
Output of this phase: a verification plan checkpoint, printed in chat, with:
- target env and proof it is allowed
- endpoint target list
- payload/variant plan
- harness/run-log artifact plan
- assertion plan
- subagent assignment plan
- existing authorization or the specific missing permission
Continue the authorized checks. Pause only dependent live actions when the environment, account, endpoint, or mutation scope needs a decision; preparation does not require another approval.
Phase 1 — Payload Sourcing
Follow payload-sourcing.md in this directory. Priority order, top wins:
- User-provided payloads — explicitly pasted in the conversation or attached to the ticket. Save each under
fixtures/<endpoint>.user-<label>.jsonverbatim (redact obvious PII before writing). - Saved fixtures — any
<artifact-root>/.backend/<YYYYMM>/<slug>/fixtures/*.jsonfrom a prior/verifyrun on this ticket. Reuse when the endpoint contract has not changed since (compareexplore.md §5B contractwith the fixture shape). - Live MySQL sampling — only if the prior two are insufficient. Read-only, dev-only,
LIMIT-bounded. Shapes are copied; PII is redacted to placeholders (__REDACTED_EMAIL__,__REDACTED_PHONE__). This procedure lives inpayload-sourcing.md. - Synthesized payloads — last resort. Only for boundary/negative variants where no real row would look that way (e.g. empty array, max-length string, invalid enum value). Every synthesized field must be justified in
verify.md §4.
For each endpoint target, produce at minimum three variants:
| Variant | Purpose | Example |
|---|---|---|
happy |
Representative valid request | Real row shape, expected 2xx |
boundary |
Edge of what schema allows | Max-length string, min/max numeric, empty-but-valid collection |
negative |
Request that must be rejected | Missing required field, wrong enum, unauth if endpoint requires auth |
Bug fixes get one additional mandatory variant:
| Variant | Purpose |
|---|---|
regression |
The exact payload that triggered the original bug per explore.md §5A.repro |
Write each variant to fixtures/<endpoint>.<variant>.json. For GET/DELETE requests without a JSON body, the fixture still records the full request shape: method, path, query parameters, path variables, headers that affect behavior, and expected assertions. Never commit raw PII — apply redaction before write.
Record fixture paths, source category, redaction decisions, and any sample-query shape used. A delegated verifier returns the same evidence.
Phase 2 — Harness Generation
Follow curl-harness.md in this directory. For each endpoint target, generate harness/<endpoint>.sh with this shape:
- Loads
_env.shwhich exportsBASE_URL,TOKEN(if needed), andCOMMON_HEADERS. - One
run_variant()invocation per variant fixture. curl -i --max-time 10 -s -S -o >(tee -a ../runs/run-<N>.log)— always includes-ito capture status + headers, always bounded by timeout.- Captures: status code, response body, elapsed time. Does not follow redirects unless the endpoint documents redirect behavior.
- Exits non-zero if any variant failed its declared assertion.
Declare assertions per variant inline in the shell script:
assert_status 200
assert_json_path '.data.userId' '<expected>'
assert_json_key_present '.data.createdAt'
assert_header 'Content-Type' 'application/json'
Assertion helpers are defined in harness/_assert.sh (generated once per ticket). Keep them pure bash + jq + grep. No Python, no Node — the harness must run in any local dev environment with a shell and jq installed.
Auth strategy per service family:
- Services behind an auth filter → obtain a dev credential from the project's auth authority in the dev profile, such as
GET /test/generate-jwt, for local/dev runs. For shared environments, use only the user-provided or already available environment token/session for that target; never mint or paste a prod token. The same token is reusable across other services when they share the same issuer or signing key. Full reference:jwt-auth-reference.mdin this directory — contains stack-neutral auth schemes plus ready-to-adapt_env.shand_preflight.shsnippets. - Feign-only internal endpoints (no external auth): still send the standard
X-Request-Idheader. - Services with no auth in the target profile: skip the token step but assert the profile/target really matches the recorded
TARGET_ENVwhen exposed (e.g.actuator/env/actuator/info, process command, or service banner). - Services with a different auth scheme must use their own section of
jwt-auth-reference.md; do not assume JWT applies everywhere.
Cache the token in _env.sh for the run; never paste it into fixture files. Tokens have exp — re-run _preflight.sh on every iteration (see curl-harness.md §Re-Run Protocol).
Do not generate harness files for endpoints you cannot reach in the selected target. If the target service cannot start or is unreachable (missing downstream, auth unavailable, wrong profile), stop, record it in verify.md §9 as [BLOCK], and ask the user.
If delegated, each verifier owns only its assigned harness files.
Phase 3 — Execution
- Start the target service(s) if not already running:
cd <service> && ./gradlew bootRun --args='--spring.profiles.active=dev'(in background or a separate terminal the user is already running), unless the user explicitly directed an already-running audit/stg instance.- Poll a health endpoint (
/actuator/healthor the service's documented readiness probe) until200 OKor until a 60s cap. Do not start timing tests before ready.
- Execute each
harness/<endpoint>.sh. Each run appends toruns/run-<N>.logwhere<N>is the current iteration (starts at 1; increments each time Phase 5 re-invokes/work). - Capture every request/response pair verbatim.
curl -iheaders + full body. Redact theAuthorization:header value in the log before committing.- If the endpoint is reachable, keep running the curl variants until happy, boundary, and negative payloads have all produced recorded HTTP results or a concrete app/contract failure is found.
- Unit tests, bytecode inspection, mapper SQL checks, and code reading are supplemental evidence only. They may explain or narrow a failure, but they do not satisfy
/verifyfor any reachable HTTP endpoint. - If auth/session/downstream state prevents a real happy-path curl, classify it as
FAIL-ENVorfail-user-required; do not mark the endpoint as passing based on non-HTTP evidence.
- Compute the variant result matrix:
endpoint variant status latency(ms) assertions result
POST /users/login happy 200 142 3/3 ✓
POST /users/login boundary 400 89 2/2 ✓ (expected 400)
POST /users/login negative 401 91 2/2 ✓
POST /users/login regression 500 154 1/3 ✗
- Never paraphrase the result matrix. It is copied verbatim into
verify.md §5.
If any service fails to start or a probe times out, record the actual error and stop — do not retry silently.
Record exact commands, run-log paths, matrix rows, and pass/fail classifications. Review any delegated evidence before incorporating it; missing evidence cannot become a passing claim.
Phase 4 — Triage
Classify the matrix:
| Classification | Condition | Next |
|---|---|---|
| PASS | All variants ✓; cross-service assertions in §6 pass; latency within bounds |
Phase 6 wrap-up, status: pass |
| FAIL-APP | ≥1 variant ✗ with 4xx/5xx or wrong body shape attributable to the service under test |
Phase 5 iteration (re-work) |
| FAIL-CONTRACT | Request shape rejected but explore.md §5B.contract said it should be accepted, OR response shape does not match §5B.contract.resp |
Phase 5 — contract drift; likely /explore re-run |
| FAIL-ENV | Port conflict, missing downstream, DB not reachable — not a code issue | Stop. Record in §9 [BLOCK]. Ask user. Do not re-invoke /work. |
| PASS-WITH-NOTES | Happy + negative pass, one boundary fails in a way the contract did not pin | verify.md §9 [GAP]; ask user whether to escalate |
For FAIL-APP and FAIL-CONTRACT, prepare a rework delta — a structured handoff to /work:
endpoint: <method> <path>
variant: <variant-name>
request: <fixture path>
expected: <status>, body path <path> == <value>, header <name>=<value>
observed: <status>, body <snippet>, header <name>=<value>
trace-hint: <service log excerpt or absence thereof>
likely-source: <file:line from work.md §4 that owns this behavior, if derivable>
This delta is the input to Phase 5. It is also saved into verify.md §7 for the run log.
Phase 5 — Iteration (bounded)
Iteration cap: 3 /work re-invocations per /verify session.
For each fail classification:
State the rework delta. If fixing the failure is already authorized, proceed within that scope; for verification-only requests, ask before changing source.
With existing or new authorization: invoke
/workwith explicit scope limited to the delta. Pass the delta as the opening message and point/workat the same<YYYYMM>/<slug>folder./workappends a new entry to itswork.md §2 Contract Adherence("rows added mid-flight via /verify rework delta #N"). Do not let/workwiden scope beyond the delta.On user reject / hold: stop. Write
verify.mdwithstatus: fail-user-requiredand the delta as the question.After
/workreturns, re-run Phase 3 (execution) with the same harness — do not regenerate fixtures unless the contract itself changed. Append toruns/run-<N+1>.log.Compare iteration N+1 to iteration N. Meaningful progress = at least one of:
- A previously failing variant now passes.
- The failing variant moved to a different, more specific failure (e.g. 500 → 400 with a validation message — indicates the service is now routing the request correctly but rejecting its content).
- The rework delta's
likely-sourceline was edited and the corresponding assertion's observed value changed (even if still wrong).
If none of these hold, the iteration did not make meaningful progress.
Escalation ladder:
iteration 1 fails → generate scoped rework delta; follow Phase 5 authorization
iteration 2 fails AND no progress vs iter 1
→ STOP the /work loop.
Ask user: (a) re-run /explore (contract may be wrong),
(b) accept verified scope + defer, or
(c) provide new evidence / payloads.
iteration 2 fails WITH progress
→ one more /work attempt allowed (iteration 3).
iteration 3 fails (any) → STOP. status: fail-escalated.
Write verify.md §9 [BLOCK] with the specific decision the user must make.
Do NOT re-invoke /work.
- If at any iteration the failure classification flips to FAIL-CONTRACT, skip the remaining
/workbudget and escalate to/exploreimmediately — the contract document is the root cause, not the code.
Phase 6 — Wrap Up (verify.md)
Write <artifact-root>/.backend/<YYYYMM>/<slug>/verify.md using verify-template.md in this directory. Required sections:
- §1 One-paragraph recap (prose — the only prose section, plain language primary).
- §2 Meta (kind/slug/yyyymm/status/iteration-count).
- §3 Verification Plan & Agent Work Log (approved plan + verifier subagent handoffs).
- §4 Endpoint Target List (matches Phase 0 output).
- §5 Payload Sources (origin of each fixture — user / saved / DB-sampled / synthesized, with redaction notes).
- §6 Results Matrix (verbatim from the last iteration's execution).
- §7 Cross-Service Checks (Feign consumers, SSE channels, Kafka payloads — what was probed and the result).
- §8 Iteration Trail (one row per
/workre-invocation with the delta and the delta's effect). - §9 Performance Observations (p95 latency per endpoint, if meaningfully measured).
- §10 Open Items (
[BLOCK]/[INFO]/[GAP]). - §11 Re-entry Header (how a future session reloads context).
Also:
- Each
harness/<endpoint>.shand eachfixtures/*.jsonremains in the ticket folder — they are reusable evidence. runs/run-<N>.logfiles stay. They are the audit trail. Do not prune between iterations.- Append a "Verification (/verify)" section to the existing
<artifact-root>/docs/features/<YYYY-MM-DD>-<slug>.mdor<artifact-root>/docs/bugs/...mdchange note written by/work, summarizing the verification in 3-5 lines of plain language. If the docs entry does not exist (standalone mode), do not create one.
After writing, print:
- Absolute path to
verify.md - Final status:
pass|fail-escalated|fail-user-required - A 3-5 line human summary of: endpoints probed, variants run, pass/fail counts, what (if anything) blocks merging.
- A clear explanation of what the main agent did and what each verifier subagent did.
Then STOP. Do not commit, push, or open a PR. /verify, like /work, ends at the filesystem.
Scope Boundaries
In scope for /verify |
Out of scope |
|---|---|
HTTP-level probing of endpoints touched in work.md §4 |
Load testing, chaos testing, long-running soak tests |
| Deriving payloads from read-only DB access for the selected non-prod target | Running any write query against dev/audit/stg/prod DB |
Re-invoking /work with a bounded delta after user consent |
Re-invoking /work with "just fix it" and no delta |
Re-invoking /explore on FAIL-CONTRACT after user consent |
Silently rewriting explore.md or work.md |
Writing verify.md and per-iteration run logs |
Modifying source code. /verify never edits src/ or test/ |
| Redacting PII before saving fixtures | Pasting real user data into any file under .backend/ |
| Appending a "Verification" section to today's docs entry | Creating a brand-new docs entry (that is /work's job) |
| Frontend E2E via browser automation (if a companion skill exists) | Frontend QA without a companion skill — out of scope, say so and stop |
| Optional bounded verifier delegation | Overlapping or unreviewed delegated work |
Integration with Other Skills
Sibling skills in this pipeline:
work(typical predecessor) — produceswork.mdwhose §4 / §5 / §7 define the endpoint target list and cross-service checks./verifyreads but never editswork.md.explore(rerun target on FAIL-CONTRACT) — if the contract is wrong, escalate here rather than patching in code.
Support files in this directory (always used):
payload-sourcing.md— Phase 1 payload sourcing procedure with PII redactioncurl-harness.md— Phase 2 harness template (_env.sh,_assert.sh, per-endpoint scripts) + Re-Run Protocoljwt-auth-reference.md— auth acquisition procedure for Phase 2 (currently written for one specific codebase's JWT scheme — adapt to your stack's auth flow)verify-template.md— Phase 6verify.mdoutput format
Optional companion skills (if also installed — e.g. superpowers):
This skill is self-contained — the plan gate, fresh-output rule, and verifier-subagent dispatch are inlined. The following are optional enhancers if present in your agent's skill registry:
verification-before-completion— alternative formulation of the "fresh output only" rule; applies at unit/integration layers where/verifydoes not operatesystematic-debugging— use when a FAIL-APP triage cannot identify a plausiblelikely-source; do not hand/worka rework delta without a call-chain hypothesistest-driven-development— not invoked directly by/verify, but any regression variant added here becomes a candidate test for the next/workpassdispatching-parallel-agents— alternative formulation of the parallel-endpoint dispatch technique for Phase 3 with 3+ independent endpointsfinishing-a-development-branch— use AFTER/verifyexits withstatus: pass, for commit / PR ceremonyjira-update/jira-ascli— use AFTER/verifyexits, for ticket status updates with verification evidence
Quick Reference
| Phase | Input | Output | Fail state → |
|---|---|---|---|
| 0. Load Contract | explore.md + work.md (or user spec) |
Verification plan + any delegated assignments; resolve missing authorization | No endpoints / blocked work → stop, ask user |
| 1. Payload Sourcing | Approved plan + DB read-only access (optional) | Verifier-created fixtures per variant, PII-redacted | Can't source real shape → ask user for samples |
| 2. Harness Generation | Fixtures + service CLAUDE.md | Verifier-created harness/*.sh + _env.sh + _assert.sh |
Service unreachable locally → [BLOCK], ask user |
| 3. Execution | Harness + running local service | Verifier-created runs/run-<N>.log + results matrix |
Service won't start → stop, record actual error |
| 4. Triage | Results matrix | Pass | FailApp | FailContract | FailEnv | PassWithNotes | FailEnv → stop, not a code issue |
| 5. Iteration | Rework delta | Re-run /work (up to 3x) or escalate |
No progress 2x → escalate to /explore or user |
| 6. Wrap Up | All above | verify.md + verifier work log + append to docs note |
Missing file → not done |
Citations & Redaction Discipline
- Every claim about the service's behavior must cite the exact
runs/run-<N>.log:linerange. - Every claim about the contract must cite
explore.md §5Bor the controller/DTOfile:line. - PII categories to redact before writing any file under
.backend/: email addresses (replace withuser+<id>@example.test), phone numbers, national ID, real student names (replace withstudent<id>), real school names (replace withschool<id>). Authorization:header values in run logs → replace withBearer __REDACTED__.- Cookies / session IDs → replace value with
__REDACTED__. - If a field you cannot classify appears in a sampled row, redact it to
__UNKNOWN__and note the field inverify.md §4— do not commit it.