[BLOCKING] Execute skill steps in declared order. NEVER skip, reorder, or merge steps without explicit user approval.
[BLOCKING] Before each step or sub-skill call, update task tracking: set in_progress when step starts, set completed when step ends.
[BLOCKING] Every completed/skipped step MUST include brief evidence or explicit skip reason.
[BLOCKING] If Task tools are unavailable, create and maintain an equivalent step-by-step plan tracker with the same status transitions.
Quick Summary
Goal: Drive an integration-test suite to fully green by pairing /integration-test-verify with a combined fault-adjudication + /fix half in a recursive loop — each round runs a FRESH full /integration-test-verify over {scope} (the WHOLE system by default, or the target named in the prompt), and on ANY failure runs /debug-investigate and /integration-test-review (report-only) together to decide who is at fault, then /fix at the owning layer — stopping only when a fresh full verify passes its 2-consecutive-green-runs-without-DB-reset gate with zero failed tests, proven by actual runner output.
Summary:
- Each round = verify (find) + adjudicate (diagnose) +
/fix (resolve) + /changes-review (prove the fix is sound). /integration-test-verify reports pass/fail but must not own the fix; the adjudication pair decides test-wrong vs test-not-optimal vs source-wrong; /fix lands the change; /changes-review code-reviews that change before the next round. A round is incomplete until all four have run (or the verify returned zero failures).
- Steps (in order): (0) resolve
{scope} + Goal Contract → (0b) bind the convergence loop (protocol loop primary + optional /goal accelerator) → (1) round loop { snapshot → run /integration-test-verify INLINE over {scope} → on failure: /debug-investigate + /integration-test-review report-only → emit ONE Fault Verdict per failure → /fix at the owning layer → CONDITIONAL /changes-review on the round's fix diff when any fix landed → Round Integrity Check → log iteration } → (2) converge on a zero-failure fresh verify OR escalate → (3) terminal spec/doc sync + recap.
- Every fix gets code-reviewed in the round that lands it. Whenever a round applies ANY fix — source, test, scenario, or spec — that round runs
/changes-review (report-only, INLINE) over the round's fix diff; validated findings fold back into the SAME round's fix set. No fix applied → skipped with a recorded reason. — why: a green test cannot see a wrong-layer fix, a broken invariant elsewhere, or a security/performance regression.
- Default scope is the WHOLE SYSTEM. With no target in the prompt,
{scope} = every discovered integration-test project (testProjectPattern glob > testProjects list) — NOT the git-changed subset. The loop passes {scope} to /integration-test-verify explicitly so it never falls through to its change-scoped default (integration-test-verify/SKILL.md:132,159).
- Convergence: stop ONLY when a fresh full
/integration-test-verify over the CURRENT (post-fix) code reports zero failed tests across 2 consecutive runs without a DB reset, with real runner output — never a stale green predating the last fix.
- Inline invariant: run
/integration-test-verify, /debug-investigate, and /integration-test-review via the Skill tool, NEVER the Agent tool. /debug-investigate requires its /why-review gate in the same session/main agent (debug-investigate/SKILL.md:34), and /integration-test-review self-binds its own fix + re-review obligations — a sub-agent cannot own or carry either back to this loop. Their OWN internal fan-outs (verify's integration-tester per-project sub-agents, integration-test-review's phase agents) stay sub-agents by their own design, so context stays bounded.
- No fake green — Round Integrity Check: a round converges only if the executed test count did not shrink and the skipped count did not grow versus the prior round. Deleting, skipping, or narrowing tests is a REGRESSION, never convergence.
- Bounded: round cap default 3; failing count not shrinking across 2 rounds, or cap hit with failures still open → STOP & escalate via
AskUserQuestion. Increasing failures → STOP (fixes regressing). Environment/infrastructure fault → BLOCKED, escalate immediately — never loop against an unhealthy system.
Why this skill exists (READ FIRST — it is the whole justification): the obligation to loop already exists as prose scattered across three skills, with no mechanism behind it. /integration-test-verify says "After fixing → re-run the full 2-run verify sequence" (integration-test-verify/SKILL.md:238) and its SYNC:integration-test-execution-discipline §5 says "Loop until the whole suite is green" (:404) — but there is no round cap, no Goal Contract, no shrinking-failures gate, and no escalation path, so an agent that fixes one test and reports success is not violating anything mechanical. Worse, the fix half is triple-owned and undefined: /integration-test-review fixes tests and re-reviews itself (P5–P8), /fix --target=test runs its own unbounded "if tests fail, repeat from step 2" (fix/SKILL.md:218), and verify's own failure protocol says fix-and-re-run (:232-238) — three overlapping loops that can double-fix the same failure or each assume another owns it. This skill makes the loop a bounded, evidence-gated convergence contract with one owner: verify FINDS, the /debug-investigate + /integration-test-review pair ADJUDICATES fault, /fix RESOLVES, and a fresh full verify RE-PROVES — with a Round Integrity Check so the suite can never go "green" by losing tests. Without it, "tests failed, then something fixed them" ships on a single green run over a hand-picked subset.
Workflow: resolve {scope} (whole system by default) + Goal Contract → bind the convergence loop → round loop { run /integration-test-verify INLINE → on failure run /debug-investigate + /integration-test-review report-only → emit Fault Verdict → /fix at owning layer → conditional /changes-review on the round's fix diff → Round Integrity Check → log iteration } → converge when a fresh full verify is 2/2 green with zero failures → terminal /spec [mode=sync] + /docs-update + recap.
Key Rules:
- Each round pairs verify (find) + adjudicate (diagnose) +
/fix (resolve) + /changes-review (review the fix). Never skip the adjudication half and jump straight to a fix — an unadjudicated failure gets "fixed" by whatever is nearest, which is almost always the assertion.
- CONDITIONAL
/changes-review every round that lands a fix. Working tree changed vs the round's snapshot → run /changes-review INLINE, report-only, scoped to the round's fix diff; validate its findings and fold them into the SAME round's fix set; unfixable validated findings → STOP & escalate. Working tree unchanged → skip with a recorded reason. NEVER let a round's fixes reach the next round un-reviewed.
- Default
{scope} = the WHOLE system; a target named in the prompt narrows it. Pass {scope} to /integration-test-verify EXPLICITLY every round — never let it fall back to git auto-detect.
- MUST run INLINE via the
Skill tool — NEVER dispatch /integration-test-verify, /debug-investigate, /integration-test-review, or /changes-review as a sub-agent (their in-session gates are lost). Their internal fan-outs remain sub-agents by their own design.
/integration-test-review runs REPORT-ONLY. It performs its 8-gate review and STOPS before its P5 fix / P6 re-review / P7 build-and-run — the loop owns fixing and re-running. If it cannot be constrained and self-fixes anyway, treat that as this round's fix half and skip the /fix step for that round — never double-fix.
- One written Fault Verdict per failure BEFORE any edit —
TEST-WRONG · TEST-NOT-OPTIMAL · SOURCE-WRONG · ENVIRONMENT-BLOCKED · AMBIGUOUS — with file:line evidence and confidence. AMBIGUOUS → AskUserQuestion, never a silent pick.
- NEVER force green. No weakened or removed assertions, no skip annotations, no widened assertion timeouts, no retries around a failing assertion, no repository-hacked domain data, no narrowed scope. Fix the SCENARIO (an ARRANGE barrier on a real observable) or the product defect.
- Convergence = a fresh full verify over the post-fix code, 2/2 green, zero failures, real runner output, Round Integrity Check passed. All five, or it is not converged.
- Round cap (default 3); failures not shrinking across 2 rounds, increasing, or cap hit with failures open → STOP & escalate via
AskUserQuestion. ENVIRONMENT-BLOCKED → escalate immediately; never loop against an unhealthy system.
First Principle — Convergence, Not Motion
A round that changes the code is progress only if the next fresh verify has fewer failing tests.
The loop exists to reach a fixed point (a whole suite that is green twice in a row), not to keep editing until something passes.
If the failing count stops shrinking, that is a signal to escalate, not to spin another round.
And a suite that got greener by having fewer tests did not converge — it regressed.
Step 0 — Resolve Verification Scope + Goal Contract (FIRST ACTION)
Read docs/project-config.json → integrationTestVerify before anything else (the same config /integration-test-verify obeys, integration-test-verify/SKILL.md:74-92). You need quickRunCommand, testProjectPattern, testProjects, systemCheckCommand, startupScript, and referenceDocs to resolve scope and to read the project's integration-test reference docs.
Resolve {scope} — WHOLE SYSTEM by default:
| Prompt |
{scope} |
| No target named (default) |
Every integration-test project discoverable via testProjectPattern glob > testProjects list. The WHOLE system. |
| Names a suite/project/module/feature |
Only the test projects covering that target, resolved from the same config; state which projects the target maps to and how you resolved it. |
| Names a diff/branch/PR |
The test projects covering that change set — this is the ONLY case where change-scoping is correct, and it must be explicit in the prompt. |
NEVER let /integration-test-verify resolve scope by itself. Its Step 3 priority ends in git auto-detect and "Only run projects relevant to the current change" (integration-test-verify/SKILL.md:132,159) — correct when it is a workflow step after an edit, WRONG as this loop's default. Pass {scope} explicitly in the invocation every round. — why: a loop that silently verifies only the changed subset reports "all green" for a system it never ran.
Record {scope} as a stable string (the resolved project list). The scope is FIXED for the whole loop — it never narrows as rounds progress. If a fix legitimately ADDS a test project, widen {scope} and say so in the Iteration Log; narrowing it is forbidden.
Resolve/create the Goal Contract per SYNC:goal-contract-satisfaction-loop (plans/goals/{YYMMDD-HHmm}-{slug}/goal.md, template .claude/templates/goal-contract-template.md). Its single required Success Criterion:
A fresh full /integration-test-verify over {scope} reports zero failed tests across 2 consecutive runs without a DB reset, evidenced by actual test-runner output (Passed/Failed/Skipped counts), with no test deleted, skipped, or weakened to get there.
Record in Constraints: {scope} (the project list), the round cap (default 3), the baseline executed/skipped test counts once round 1 reports them, and quickRunCommand.
Step 0b — Bind the Convergence Loop (protocol-first; /goal is an optional accelerator)
The convergence loop is bound by TWO layers. The protocol loop (Steps 1–2) is the BINDING mechanism and MUST be self-driven by you, the running agent, on every host — with or without any command or hook. The /goal command is an OPTIONAL accelerator layered on top; it is never the primary mechanism, and its absence NEVER weakens the loop. This mirrors the project rule that hooks/trackers are accelerators only — correctness must not depend on them.
1. Protocol loop — ALWAYS binding (hook/command-independent). You are personally responsible for not stopping until the loop converges or bounded-escalates. This binds Claude, Codex, and Copilot equally, whether or not /goal exists:
Repeatedly run /integration-test-verify INLINE over {scope} (passed explicitly, never re-derived). After each run, if ANY test failed, adjudicate every failure with /debug-investigate + /integration-test-review (report-only) into ONE Fault Verdict, apply the fix via /fix at the owning layer, then re-run a FRESH full /integration-test-verify over {scope}. Do NOT stop while the last verify still reported a failing test. Converge ONLY when a fresh full verify reports zero failures across 2 consecutive runs without a DB reset AND the Round Integrity Check passes (executed test count not shrunk, skipped count not grown). Cap at {N=5} rounds; if the failing count does not shrink across 2 consecutive rounds, failures increase, the cap is hit with failures still open, or any failure is ENVIRONMENT-BLOCKED → STOP and escalate via AskUserQuestion. Never loop open-ended, and NEVER reach green by weakening, skipping, deleting, or de-scoping a test.
Treat this as a standing obligation you re-read at every Step 2 checkpoint — NOT a one-time note you can rationalize away after the first fix cycle. The Goal Contract's required Success Criterion (Step 0) is its durable, host-independent record.
2. /goal command — invoke as an accelerator WHEN AVAILABLE. If a /goal command exists and you are permitted to run it in this environment, ALSO invoke it (a real tool/command call, NOT a paraphrase, NOT a Goal Contract file substituted for it) with the SAME condition, so a session Stop hook mechanically enforces the loop:
/goal integration-test green convergence loop: repeatedly run /integration-test-verify INLINE over {scope} (passed explicitly). If any test failed → adjudicate each failure with /debug-investigate + /integration-test-review (report-only) into one Fault Verdict, fix via /fix at the owning layer, and run another round. If a fresh full verify reports zero failures across 2 consecutive runs without DB reset AND executed test count has not shrunk and skipped count has not grown → CONVERGED, run the terminal /spec [mode=sync] + /docs-update and clear the gate. Do NOT stop while the last verify still reported a failing test. Cap at {N=5} rounds; if the failing count does not shrink across 2 consecutive rounds, failures increase, the cap is hit with failures open, or a failure is ENVIRONMENT-BLOCKED → STOP and escalate via AskUserQuestion. Never loop open-ended; never reach green by weakening, skipping, deleting, or de-scoping a test.
The /goal Stop hook blocks stopping until the condition holds and auto-clears when met — do not tell the user to clear it.
If /goal is unavailable, unregistered, or not permitted (e.g. Codex/Copilot, or a Claude run without the command): DO NOT error, DO NOT block, and DO NOT invent a stand-in gate. Record ONE line in the Goal Contract — /goal accelerator unavailable — loop bound by protocol (Steps 1–2) + this Goal Contract — and proceed. The protocol loop above plus the Goal Contract are the same gate, enforced by discipline instead of a hook.
Nested gates (by design, safe): each inner /debug-investigate self-binds its own /why-review validation gate that clears when its root cause is validated, and /integration-test-review runs REPORT-ONLY so its P5 fix / P6 re-review loop is deferred to this caller — no inner fix gate is installed. THIS outer loop owns the single convergence gate. All self-clear on satisfaction — no orphaned gate. Do NOT tell the user to clear any of them.
Step 1 — Round Loop (verify → adjudicate → fix → review → integrity-check → log)
Each round couples four halves — verify to find, adjudicate to diagnose, fix to resolve, /changes-review to prove the fix itself is sound. For each round R (starting at 1), do ALL of:
Snapshot before: record the working-tree fingerprint — git status --porcelain + git diff --stat. This is the fixes-applied baseline for the round and the objective backstop for convergence detection (Step 2).
Run /integration-test-verify INLINE via the Skill tool (NEVER the Agent tool), passing {scope} explicitly so it skips its own scope derivation. It runs its full contract: system check → the named projects → the 2-consecutive-green-runs-without-DB-reset gate → a report with real Passed/Failed/Skipped counts and failing test names. Let it fan out its own integration-tester sub-agents per isolated project (its design, integration-test-verify/SKILL.md:188-206) — that fan-out is bounded and correct. Tell it explicitly that this run IS a round of this loop, so it returns its counts + failing names to this loop instead of recommending /workflow-integration-test-green as a next step — why: that recommendation is correct for a standalone verify but circular here, and would restart the loop that is already running.
Record the round's counts: executed, passed, failed, skipped — per project and total, from actual runner output. These feed the Round Integrity Check (1.8) and the shrinking-failures gate (Step 2). No output = no counts = no claim.
If failures = 0 and the 2-run gate was green → this round converged; go to Step 2 (no adjudication or fix half needed).
If failures > 0 — ADJUDICATE (the combined half). Run BOTH, INLINE, in this order, per failure or per failure cluster:
(a) /debug-investigate — trace the failure end-to-start to the defect's owning layer, producing a file:line root cause with a confidence score, validated through its own /why-review gate. It is investigation-ONLY — it never patches (debug-investigate/SKILL.md:22).
(b) /integration-test-review — REPORT-ONLY — scoped to the failing tests and the production code they exercise. Its 8 gates supply the test-side verdict: G1 assertion value (mutation probe), G2 data state, G3 repeatability, G4 domain logic (does the test assert only what the handler writes?), G5 spec traceability, G6 three-way sync, G7 change coverage, G8 scenario fidelity. Direct it to STOP after its findings report — no P5 fix, no P6 re-review, no P7 build-and-run; this loop owns fixing and re-running.
Combine (a) + (b) into ONE written Fault Verdict per failure, BEFORE any edit:
| Verdict |
Meaning |
Evidence required |
Resolution |
| TEST-WRONG |
The test encodes a stale or incorrect assertion, setup, or expectation that contradicts intended behavior |
The governing spec (§3 AC / §4 BR / §5 invariant / §8 TC) or the handler source shows the production behavior is correct and the test is not (file:line) |
Fix the test at its root. NEVER weaken an assertion, add a skip, or relax a timeout. |
| TEST-NOT-OPTIMAL |
The test is directionally right but mis-specified — unrealistic scenario, compressed actor pacing, blind sleep, missing ARRANGE barrier, shared-state repeatability defect, smoke-only or DI-resolution-only assertion |
The failing G3/G8 gate plus the ARRANGE block read as a production trace (file:line) |
Repair the SCENARIO — add an ARRANGE-phase settle barrier polling a real observable, unique data per run, real use-case setup. NEVER a widened assertion timeout or a retry around the assertion. |
| SOURCE-WRONG |
Production code violates the spec's intended behavior or a clear invariant |
/debug-investigate's traced root cause at the invariant-owning layer (file:line, confidence ≥60%) |
Fix the source at the lowest owning layer (Entity > Service > Handler), never the crash site. Keep or strengthen the test that caught it, and route the changed source into /changes-review before declaring PASS (integration-test-verify/SKILL.md:294). |
| ENVIRONMENT-BLOCKED |
Infrastructure, services, containers, or data fixtures are not ready — the system, not the code, is failing |
The systemCheckCommand output or the runner error naming the unavailable dependency |
STOP the loop and escalate. Point the user at startupScript. NEVER change a test because the system was down (integration-test-verify/SKILL.md:296). |
| AMBIGUOUS |
Intended behavior is unclear — no spec covers it, the spec is silent, or spec and code disagree with no tiebreaker |
State exactly what is undetermined and which artifacts you checked |
AskUserQuestion before editing either side. NEVER silently pick source or test just to make the suite pass. |
Intermittent failures (red in one run of the 2-run gate, green in the other) use the three-way flake adjudication instead — (a) unrealistic scenario / compressed pacing, (b) harness topology amplification, (c) genuine product race — per integration-test-verify/SKILL.md:298-316. Record the verdict with evidence BEFORE any change; do NOT file (c) until (a) and (b) are ruled out.
Run /fix on the adjudicated verdicts (failures > 0 only) — this is the half the loop owns. Resolve each at its owning layer, routed by verdict: SOURCE-WRONG → /fix (its --target routing) or a direct edit at the lowest invariant-owning layer, then /prove-fix; TEST-WRONG / TEST-NOT-OPTIMAL → repair the test or scenario at its root; a missing §8 TC surfaced by G5/G7 → /spec [mode=tests]; a spec divergence → adjudicate per SYNC:spec-drift-adjudication (/spec [update] for SPEC-STALE, a BLOCKING fix for CODE-WRONG). Fix ONLY adjudicated verdicts — never an unadjudicated guess.
If /integration-test-review could not be constrained to report-only and already applied its P5 fixes, treat those as this round's fix half (detect fixes-applied against the 1.1 snapshot) and SKIP this step for that round — never double-fix the same failure.
CONDITIONAL — run /changes-review on the round's fix diff, when (and only when) the round applied ANY fix. Compare the working tree against the 1.1 snapshot: unchanged → SKIP this sub-step and record No fix applied this round — /changes-review skipped. Changed → run it, every round, on every round's fixes.
- Scope = the round's fix diff, not the whole branch: exactly the files this round changed since the 1.1 snapshot (source fixes, test fixes, scenario repairs, spec/TC edits alike). — why: the round's own changes are the only thing the prior rounds' reviews have not already seen.
- Run it INLINE via the
Skill tool, REPORT-ONLY — its full dimensional review, then STOP before its Phase 7 self-fix / Phase 7.5 holistic / Phase 8 docs-update (the documented $workflow-review-changes boundary where the caller owns fixing, changes-review/SKILL.md:52,204). NEVER dispatch it as a sub-agent — it self-binds its own review-loop obligations, which a sub-agent cannot own or carry back (changes-review-loop/SKILL.md:37). Its own Phase 0.7 dimensional reviewers stay sub-agents by its design.
- Validate, then fold the surviving findings into THIS round's fix set — run
/why-review --validate-findings over its report and apply every VALIDATED finding at its owning layer, exactly as in 1.6. The next round's fresh full verify is what re-proves them, so the test loop stays the single convergence engine — do NOT open a nested review→fix loop here.
- Unfixable validated findings → STOP & escalate via
AskUserQuestion (Step 2). A round that leaves a validated review finding open has not finished, even if its tests went green.
- This subsumes the
SOURCE-WRONG per-verdict routing in 1.5: that verdict already demands the changed source reach /changes-review before PASS (integration-test-verify/SKILL.md:294). Running it once per round over the whole fix diff satisfies that obligation AND extends it to test-side and spec-side fixes — do not run it twice for the same diff.
— why: the loop's own convergence signal is "the tests went green", and a fix that greens a test can still be wrong in every way a test cannot see — wrong layer, broken invariant elsewhere, dead code, a leaked domain concept, a security or performance regression. Without a per-round review, every fix this loop lands ships un-code-reviewed on the strength of a green suite alone.
Round Integrity Check (no fake green) — BLOCKING before the round can count as progress. Compare this round's counts (1.3) against the prior round's:
| Signal |
Meaning |
Action |
| Executed test count decreased |
Tests were deleted, renamed out of discovery, filtered out, or the scope narrowed |
REGRESSION → STOP & escalate. Restore the tests. A smaller suite is not a greener suite. |
| Skipped count increased |
A failure was hidden behind a skip annotation |
REGRESSION → STOP & escalate. Remove the skip and adjudicate the failure properly. |
{scope} project list shrank |
The loop de-scoped its way to green |
REGRESSION → STOP & escalate. {scope} is fixed (Step 0.3). |
| Counts stable or grown, failures shrinking |
Genuine progress |
Continue to Step 2. |
— why: unlike a review loop, a test loop has a cheap fake exit — remove what fails. This check is the only thing standing between "converged" and "quietly deleted the hard tests".
Append an Iteration Log entry to the Goal Contract: round number, per-project executed/passed/failed/skipped counts, the failing test names, each Fault Verdict with its file:line evidence and confidence, the fixes applied (file:line), the /changes-review verdict for the round's fix diff (or the explicit skip reason when no fix landed), the Round Integrity Check result, and remaining gaps.
Step 2 — Convergence & Escalation Gate
Evaluate after every round:
| Condition |
Action |
Fresh full /integration-test-verify over {scope} reported zero failures across 2 consecutive runs without a DB reset, AND the Round Integrity Check passed, AND the working tree is unchanged by that final verify pass |
CONVERGED → mark the required criterion PASS in the Goal Satisfaction matrix (attaching the runner output) → clear the /goal gate → go to Step 3. |
Failures > 0 AND round < N AND the failing count shrank vs the prior round AND integrity held |
Apply the adjudicated fixes (Step 1.6), then run round R+1 (fresh full re-verify over the SAME {scope}). |
| Failing count did not shrink across 2 consecutive rounds (same/increasing count) |
STOP & escalate via AskUserQuestion — a non-converging loop is a signal, not a reason to spin. |
Round cap N hit with failures still open |
STOP & escalate via AskUserQuestion — report the still-failing tests with their Fault Verdicts; do not silently continue. |
| Any failure adjudicated ENVIRONMENT-BLOCKED |
STOP & escalate immediately — mark the criterion BLOCKED with a user-facing reason and point at startupScript. Never loop against an unhealthy system. |
| Any failure adjudicated AMBIGUOUS |
PAUSE and AskUserQuestion before the fix — resume the loop with the user's answer. |
| Round Integrity Check failed (tests lost, skips added, scope narrowed) |
STOP & escalate — restore the lost coverage first; this is a regression, not progress. |
The round's /changes-review (1.7) left validated findings unfixed |
STOP & escalate via AskUserQuestion — a green suite does not clear an open, validated review finding on the fix that greened it. |
Increasing failures = STOP. If round R has MORE failing tests than round R-1, the fixes are regressing the system — STOP and escalate immediately. Never trade one green test for two new red ones across rounds.
Step 3 — Terminal Spec/Doc Sync + Recap
Terminal sync (MANDATORY once converged, when running STANDALONE). The loop deferred all downstream sync while it churned, so close it now, in order:
/spec [mode=sync] — reconcile §8 TCs ↔ the executing test code; update every CoveredBy field for tests the loop changed or added.
/docs-update — update impacted docs: the integration-test reference doc, feature-doc evidence fields, and version history if coverage changed materially.
When this skill runs as a step inside a workflow that already declares /spec [mode=sync], /scan --target=integration-tests, and /docs-update (e.g. workflow-integration-test-green), SKIP this sub-step and let the workflow own it — say so explicitly in the recap. — why: running the same sync twice churns the same files and hides which pass actually made the change.
Recap. Emit a concise convergence recap: rounds run, the shrinking failing-count sequence, each round's Fault Verdicts and the fixes applied, the final zero-failure runner output (both runs), the Round Integrity Check trail (executed/skipped counts per round), and the Goal Satisfaction matrix (required criterion PASS). Point to each round's report under plans/reports/ and the Goal Contract Iteration Log. Do NOT commit or push unless the user explicitly asks.
Convergence Detection — Why Five Conditions
A round converges ONLY when all five hold. Each closes a distinct way a test loop lies to itself:
- Fresh verify over the post-fix code — a green report from a run that predates the last fix proves nothing about that fix. Every applied fix invalidates the prior verdict; re-run, never reuse.
- Zero failed tests — not "only known failures left", not "the important ones pass". A single red test is an unconverged loop.
- 2 consecutive green runs without a DB reset — the gate
/integration-test-verify already owns (integration-test-verify/SKILL.md:44,169). One green run hides order-dependent and state-leak flakiness, which is exactly what a fix cycle tends to introduce.
- Real runner output — Passed/Failed/Skipped counts and names. "Looks like it passed" is theater (
integration-test-verify/SKILL.md:339).
- Round Integrity Check passed — the executed count did not shrink, the skipped count did not grow,
{scope} did not narrow. This is the condition the other four cannot see: a suite can satisfy 1–4 perfectly by having quietly lost the tests that failed.
Working-tree-unchanged backstop: the converging verify pass must land no fix. A "clean" verdict that still mutated files means the round DID fix things → run another round to re-prove clean.
When failures remain but cannot be fixed (product decision, unclear intent, environment) → escalate, do not loop. Convergence is a fixed point, not a single green read.
IMPORTANT MANDATORY sequence: Step 0 (resolve {scope} — WHOLE SYSTEM by default — + Goal Contract) → Step 0b (bind the convergence loop: protocol loop primary + optional /goal accelerator) → Step 1 (round loop: /integration-test-verify INLINE → on failure /debug-investigate + /integration-test-review report-only → ONE Fault Verdict per failure → /fix at the owning layer → CONDITIONAL /changes-review on the round's fix diff when any fix landed → Round Integrity Check → log) → Step 2 (converge on a zero-failure 2/2-green fresh verify / escalate on non-progress, blocked environment, or lost coverage) → Step 3 (terminal /spec [mode=sync] + /docs-update when standalone + recap).
Goal Contract Satisfaction Loop — Persist the user goal in an external file, execute against it, and loop review/fix until every saved required criterion passes or a blocker escalates. Bounded closed loop — NEVER open-ended autonomous exploration.
- Resolve the active goal (in order): active plan
goal.md → plans/goals/{YYMMDD-HHmm}-{slug}/goal.md → create a new Goal Contract from the current user request (template: .claude/templates/goal-contract-template.md).
- Required sections: Original Request, Purpose, Success Criteria (checkboxes; mark required vs optional), Constraints, Evidence Required, Iteration Log, Goal Satisfaction matrix.
- Before work: read the active goal and map planned work to saved success criteria — execution serves the saved criteria, never chat memory alone.
- After execution/verification: append an Iteration Log entry — result, evidence references (
file:line, command output, report path), remaining gaps.
- Review gate: emit a Goal Satisfaction matrix —
| Success Criterion | Evidence | Status | with PASS/FAIL/BLOCKED. Overall PASS requires every required criterion PASS.
- Loop rule (retry): required criterion FAIL → validate the gap is real → fix → re-review only the affected criteria. Stop cleanly when all required criteria PASS.
- Escalation rule (stop): two consecutive iterations with no criterion progressing, or a blocker needing user input → mark the criterion BLOCKED with a user-facing reason and escalate. NEVER loop indefinitely.
- Skip rule: tiny conversational tasks may skip the goal file ONLY with a recorded one-line reason. User-accepted gate skips are recorded in the goal file with reason and scope.
- Security: NEVER store secrets, tokens, credentials, or private customer data in goal files — store evidence references and redact sensitive values.
Blocked until: active goal resolved (or skip reason recorded) · saved success criteria read before edits · iteration evidence appended after execution · Goal Satisfaction matrix emitted before any PASS verdict.
Test-Failure Fault Adjudication — When a test fails (or you are deb
…(truncated)
1---2name: integration-test-verify-loop3description: [Testing] Use when you need to drive an integration-test suite to fully green — each round runs /integration-test-verify (whole system by default, or the target named in the prompt), and on ANY failure combines /debug-investigate + /integration-test-review (report-only) to adjudicate the fault (test wrong · test not optimal · source wrong), then /fix to resolve it at the owning layer, then /changes-review on that round's fix diff, then re-runs a FRESH full verify — looping until the whole suite passes its 2-consecutive-green-runs gate with zero failures.4---5
6<!-- PROMPT-ENHANCE:STEP-TASK-ANCHOR:START -->
7
8> **[BLOCKING]** Execute skill steps in declared order. NEVER skip, reorder, or merge steps without explicit user approval.
9> **[BLOCKING]** Before each step or sub-skill call, update task tracking: set `in_progress` when step starts, set `completed` when step ends.
10> **[BLOCKING]** Every completed/skipped step MUST include brief evidence or explicit skip reason.
11> **[BLOCKING]** If Task tools are unavailable, create and maintain an equivalent step-by-step plan tracker with the same status transitions.
12
13<!-- PROMPT-ENHANCE:STEP-TASK-ANCHOR:END -->
14
15## Quick Summary
16
17**Goal:** Drive an integration-test suite to **fully green** by pairing `/integration-test-verify` with a combined fault-adjudication + `/fix` half in a recursive loop — each round runs a FRESH full `/integration-test-verify` over `{scope}` (**the WHOLE system by default**, or the target named in the prompt), and on ANY failure runs `/debug-investigate` **and** `/integration-test-review` (report-only) together to decide _who is at fault_, then `/fix` at the owning layer — stopping only when a fresh full verify passes its **2-consecutive-green-runs-without-DB-reset** gate with **zero failed tests**, proven by actual runner output.
18
19**Summary:**
20
21- **Each round = verify (find) + adjudicate (diagnose) + `/fix` (resolve) + `/changes-review` (prove the fix is sound).** `/integration-test-verify` reports pass/fail but must not own the fix; the adjudication pair decides _test-wrong vs test-not-optimal vs source-wrong_; `/fix` lands the change; `/changes-review` code-reviews that change before the next round. A round is incomplete until all four have run (or the verify returned zero failures).
22- **Steps (in order):** (0) resolve `{scope}` + Goal Contract → (0b) bind the convergence loop (protocol loop primary + optional `/goal` accelerator) → (1) round loop { snapshot → run `/integration-test-verify` INLINE over `{scope}` → **on failure:** `/debug-investigate` + `/integration-test-review` report-only → emit ONE Fault Verdict per failure → `/fix` at the owning layer → **CONDITIONAL `/changes-review` on the round's fix diff when any fix landed** → Round Integrity Check → log iteration } → (2) converge on a zero-failure fresh verify OR escalate → (3) terminal spec/doc sync + recap.
23- **Every fix gets code-reviewed in the round that lands it.** Whenever a round applies ANY fix — source, test, scenario, or spec — that round runs `/changes-review` (report-only, INLINE) over the round's fix diff; validated findings fold back into the SAME round's fix set. No fix applied → skipped with a recorded reason. — why: a green test cannot see a wrong-layer fix, a broken invariant elsewhere, or a security/performance regression.
24- **Default scope is the WHOLE SYSTEM.** With no target in the prompt, `{scope}` = **every** discovered integration-test project (`testProjectPattern` glob > `testProjects` list) — NOT the git-changed subset. The loop passes `{scope}` to `/integration-test-verify` **explicitly** so it never falls through to its change-scoped default (`integration-test-verify/SKILL.md:132,159`).
25- **Convergence:** stop ONLY when a **fresh full** `/integration-test-verify` over the CURRENT (post-fix) code reports **zero failed tests across 2 consecutive runs without a DB reset**, with real runner output — never a stale green predating the last fix.
26- **Inline invariant:** run `/integration-test-verify`, `/debug-investigate`, and `/integration-test-review` via the `Skill` tool, NEVER the `Agent` tool. `/debug-investigate` requires its `/why-review` gate **in the same session/main agent** (`debug-investigate/SKILL.md:34`), and `/integration-test-review` self-binds its own fix + re-review obligations — a sub-agent cannot own or carry either back to this loop. Their OWN internal fan-outs (verify's `integration-tester` per-project sub-agents, `integration-test-review`'s phase agents) stay sub-agents by their own design, so context stays bounded.
27- **No fake green — Round Integrity Check:** a round converges only if the executed test count did **not shrink** and the skipped count did **not grow** versus the prior round. Deleting, skipping, or narrowing tests is a REGRESSION, never convergence.
28- **Bounded:** round cap default 3; failing count not shrinking across 2 rounds, or cap hit with failures still open → **STOP & escalate** via `AskUserQuestion`. Increasing failures → STOP (fixes regressing). Environment/infrastructure fault → **BLOCKED**, escalate immediately — never loop against an unhealthy system.
29
30**Why this skill exists (READ FIRST — it is the whole justification):** the obligation to loop already exists as **prose scattered across three skills**, with no mechanism behind it. `/integration-test-verify` says _"After fixing → re-run the full 2-run verify sequence"_ (`integration-test-verify/SKILL.md:238`) and its `SYNC:integration-test-execution-discipline` §5 says _"Loop until the whole suite is green"_ (`:404`) — but there is **no round cap, no Goal Contract, no shrinking-failures gate, and no escalation path**, so an agent that fixes one test and reports success is not violating anything mechanical. Worse, the fix half is **triple-owned and undefined**: `/integration-test-review` fixes tests and re-reviews itself (P5–P8), `/fix --target=test` runs its own unbounded _"if tests fail, repeat from step 2"_ (`fix/SKILL.md:218`), and verify's own failure protocol says fix-and-re-run (`:232-238`) — three overlapping loops that can double-fix the same failure or each assume another owns it. This skill makes the loop a **bounded, evidence-gated convergence contract with one owner**: verify FINDS, the `/debug-investigate` + `/integration-test-review` pair ADJUDICATES fault, `/fix` RESOLVES, and a fresh full verify RE-PROVES — with a Round Integrity Check so the suite can never go "green" by losing tests. Without it, "tests failed, then something fixed them" ships on a single green run over a hand-picked subset.
31
32**Workflow:** resolve `{scope}` (whole system by default) + Goal Contract → bind the convergence loop → **round loop** { run `/integration-test-verify` INLINE → on failure run `/debug-investigate` + `/integration-test-review` report-only → emit Fault Verdict → `/fix` at owning layer → conditional `/changes-review` on the round's fix diff → Round Integrity Check → log iteration } → converge when a fresh full verify is 2/2 green with zero failures → terminal `/spec [mode=sync]` + `/docs-update` + recap.
33
34**Key Rules:**
35
36- **Each round pairs verify (find) + adjudicate (diagnose) + `/fix` (resolve) + `/changes-review` (review the fix).** Never skip the adjudication half and jump straight to a fix — an unadjudicated failure gets "fixed" by whatever is nearest, which is almost always the assertion.
37- **CONDITIONAL `/changes-review` every round that lands a fix.** Working tree changed vs the round's snapshot → run `/changes-review` INLINE, report-only, scoped to the round's fix diff; validate its findings and fold them into the SAME round's fix set; unfixable validated findings → STOP & escalate. Working tree unchanged → skip with a recorded reason. NEVER let a round's fixes reach the next round un-reviewed.
38- **Default `{scope}` = the WHOLE system**; a target named in the prompt narrows it. Pass `{scope}` to `/integration-test-verify` EXPLICITLY every round — never let it fall back to git auto-detect.
39- **MUST run INLINE via the `Skill` tool — NEVER dispatch `/integration-test-verify`, `/debug-investigate`, `/integration-test-review`, or `/changes-review` as a sub-agent** (their in-session gates are lost). Their internal fan-outs remain sub-agents by their own design.
40- **`/integration-test-review` runs REPORT-ONLY.** It performs its 8-gate review and STOPS before its P5 fix / P6 re-review / P7 build-and-run — the loop owns fixing and re-running. If it cannot be constrained and self-fixes anyway, treat that as this round's fix half and skip the `/fix` step for that round — never double-fix.
41- **One written Fault Verdict per failure BEFORE any edit** — `TEST-WRONG` · `TEST-NOT-OPTIMAL` · `SOURCE-WRONG` · `ENVIRONMENT-BLOCKED` · `AMBIGUOUS` — with `file:line` evidence and confidence. `AMBIGUOUS` → `AskUserQuestion`, never a silent pick.
42- **NEVER force green.** No weakened or removed assertions, no skip annotations, no widened assertion timeouts, no retries around a failing assertion, no repository-hacked domain data, no narrowed scope. Fix the SCENARIO (an ARRANGE barrier on a real observable) or the product defect.
43- **Convergence = a fresh full verify over the post-fix code, 2/2 green, zero failures, real runner output, Round Integrity Check passed.** All five, or it is not converged.
44- **Round cap (default 3)**; failures not shrinking across 2 rounds, increasing, or cap hit with failures open → **STOP & escalate** via `AskUserQuestion`. `ENVIRONMENT-BLOCKED` → escalate immediately; never loop against an unhealthy system.
45
46---
47
48## First Principle — Convergence, Not Motion
49
50> A round that changes the code is progress **only if** the next fresh verify has fewer failing tests.
51> The loop exists to reach a fixed point (a whole suite that is green twice in a row), not to keep editing until something passes.
52> If the failing count stops shrinking, that is a signal to **escalate**, not to spin another round.
53> And a suite that got greener by having fewer tests did not converge — it regressed.
54
55---
56
57## Step 0 — Resolve Verification Scope + Goal Contract (FIRST ACTION)
58
591. **Read `docs/project-config.json` → `integrationTestVerify`** before anything else (the same config `/integration-test-verify` obeys, `integration-test-verify/SKILL.md:74-92`). You need `quickRunCommand`, `testProjectPattern`, `testProjects`, `systemCheckCommand`, `startupScript`, and `referenceDocs` to resolve scope and to read the project's integration-test reference docs.
602. **Resolve `{scope}` — WHOLE SYSTEM by default:**
61
62 | Prompt | `{scope}` |
63 | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
64 | **No target named** (default) | **Every** integration-test project discoverable via `testProjectPattern` glob > `testProjects` list. The WHOLE system. |
65 | Names a suite/project/module/feature | Only the test projects covering that target, resolved from the same config; state which projects the target maps to and how you resolved it. |
66 | Names a diff/branch/PR | The test projects covering that change set — this is the ONLY case where change-scoping is correct, and it must be explicit in the prompt. |
67
68 > **NEVER let `/integration-test-verify` resolve scope by itself.** Its Step 3 priority ends in git auto-detect and _"Only run projects relevant to the current change"_ (`integration-test-verify/SKILL.md:132,159`) — correct when it is a workflow step after an edit, WRONG as this loop's default. Pass `{scope}` explicitly in the invocation every round. — why: a loop that silently verifies only the changed subset reports "all green" for a system it never ran.
69
703. **Record `{scope}` as a stable string** (the resolved project list). The scope is FIXED for the whole loop — it never narrows as rounds progress. If a fix legitimately ADDS a test project, widen `{scope}` and say so in the Iteration Log; narrowing it is forbidden.
714. **Resolve/create the Goal Contract** per `SYNC:goal-contract-satisfaction-loop` (`plans/goals/{YYMMDD-HHmm}-{slug}/goal.md`, template `.claude/templates/goal-contract-template.md`). Its single **required** Success Criterion:
72
73 > _A fresh full `/integration-test-verify` over `{scope}` reports **zero failed tests** across **2 consecutive runs without a DB reset**, evidenced by actual test-runner output (Passed/Failed/Skipped counts), with no test deleted, skipped, or weakened to get there._
74
75 Record in **Constraints**: `{scope}` (the project list), the round cap (default 3), the baseline executed/skipped test counts once round 1 reports them, and `quickRunCommand`.
76
77## Step 0b — Bind the Convergence Loop (protocol-first; `/goal` is an optional accelerator)
78
79The convergence loop is bound by TWO layers. The **protocol loop (Steps 1–2) is the BINDING mechanism** and MUST be self-driven by you, the running agent, on every host — with or without any command or hook. The **`/goal` command is an OPTIONAL accelerator** layered on top; it is never the primary mechanism, and its absence NEVER weakens the loop. This mirrors the project rule that hooks/trackers are accelerators only — correctness must not depend on them.
80
81**1. Protocol loop — ALWAYS binding (hook/command-independent).** You are personally responsible for not stopping until the loop converges or bounded-escalates. This binds Claude, Codex, and Copilot equally, whether or not `/goal` exists:
82
83> Repeatedly run `/integration-test-verify` INLINE over `{scope}` (passed explicitly, never re-derived). After each run, if ANY test failed, adjudicate every failure with `/debug-investigate` + `/integration-test-review` (report-only) into ONE Fault Verdict, apply the fix via `/fix` at the owning layer, then re-run a FRESH full `/integration-test-verify` over `{scope}`. Do NOT stop while the last verify still reported a failing test. Converge ONLY when a fresh full verify reports zero failures across 2 consecutive runs without a DB reset AND the Round Integrity Check passes (executed test count not shrunk, skipped count not grown). Cap at `{N=5}` rounds; if the failing count does not shrink across 2 consecutive rounds, failures increase, the cap is hit with failures still open, or any failure is ENVIRONMENT-BLOCKED → STOP and escalate via `AskUserQuestion`. Never loop open-ended, and NEVER reach green by weakening, skipping, deleting, or de-scoping a test.
84
85Treat this as a standing obligation you re-read at every Step 2 checkpoint — NOT a one-time note you can rationalize away after the first fix cycle. The Goal Contract's required Success Criterion (Step 0) is its durable, host-independent record.
86
87**2. `/goal` command — invoke as an accelerator WHEN AVAILABLE.** If a `/goal` command exists and you are permitted to run it in this environment, ALSO invoke it (a real tool/command call, NOT a paraphrase, NOT a Goal Contract file substituted for it) with the SAME condition, so a session Stop hook mechanically enforces the loop:
88
89```
90/goal integration-test green convergence loop: repeatedly run /integration-test-verify INLINE over {scope} (passed explicitly). If any test failed → adjudicate each failure with /debug-investigate + /integration-test-review (report-only) into one Fault Verdict, fix via /fix at the owning layer, and run another round. If a fresh full verify reports zero failures across 2 consecutive runs without DB reset AND executed test count has not shrunk and skipped count has not grown → CONVERGED, run the terminal /spec [mode=sync] + /docs-update and clear the gate. Do NOT stop while the last verify still reported a failing test. Cap at {N=5} rounds; if the failing count does not shrink across 2 consecutive rounds, failures increase, the cap is hit with failures open, or a failure is ENVIRONMENT-BLOCKED → STOP and escalate via AskUserQuestion. Never loop open-ended; never reach green by weakening, skipping, deleting, or de-scoping a test.
91```
92
93The `/goal` Stop hook blocks stopping until the condition holds and auto-clears when met — do not tell the user to clear it.
94
95**If `/goal` is unavailable, unregistered, or not permitted** (e.g. Codex/Copilot, or a Claude run without the command): DO NOT error, DO NOT block, and DO NOT invent a stand-in gate. Record ONE line in the Goal Contract — `/goal accelerator unavailable — loop bound by protocol (Steps 1–2) + this Goal Contract` — and proceed. The protocol loop above plus the Goal Contract are the same gate, enforced by discipline instead of a hook.
96
97> **Nested gates (by design, safe):** each inner `/debug-investigate` self-binds its own `/why-review` validation gate that clears when its root cause is validated, and `/integration-test-review` runs REPORT-ONLY so its P5 fix / P6 re-review loop is deferred to this caller — no inner fix gate is installed. THIS outer loop owns the single convergence gate. All self-clear on satisfaction — no orphaned gate. Do NOT tell the user to clear any of them.
98
99## Step 1 — Round Loop (verify → adjudicate → fix → review → integrity-check → log)
100
101Each round couples four halves — **verify to find, adjudicate to diagnose, fix to resolve, `/changes-review` to prove the fix itself is sound.** For each round `R` (starting at 1), do ALL of:
102
1031. **Snapshot before:** record the working-tree fingerprint — `git status --porcelain` + `git diff --stat`. This is the fixes-applied baseline for the round and the objective backstop for convergence detection (Step 2).
1042. **Run `/integration-test-verify` INLINE** via the `Skill` tool (NEVER the `Agent` tool), passing `{scope}` **explicitly** so it skips its own scope derivation. It runs its full contract: system check → the named projects → the **2-consecutive-green-runs-without-DB-reset** gate → a report with real Passed/Failed/Skipped counts and failing test names. Let it fan out its own `integration-tester` sub-agents per isolated project (its design, `integration-test-verify/SKILL.md:188-206`) — that fan-out is bounded and correct. **Tell it explicitly that this run IS a round of this loop**, so it returns its counts + failing names to this loop instead of recommending `/workflow-integration-test-green` as a next step — why: that recommendation is correct for a standalone verify but circular here, and would restart the loop that is already running.
1053. **Record the round's counts:** executed, passed, failed, skipped — per project and total, from **actual runner output**. These feed the Round Integrity Check (1.8) and the shrinking-failures gate (Step 2). No output = no counts = no claim.
1064. **If failures = 0** and the 2-run gate was green → this round converged; go to Step 2 (no adjudication or fix half needed).
1075. **If failures > 0 — ADJUDICATE (the combined half). Run BOTH, INLINE, in this order, per failure or per failure cluster:**
108
109 **(a) `/debug-investigate`** — trace the failure end-to-start to the defect's owning layer, producing a `file:line` root cause with a confidence score, validated through its own `/why-review` gate. It is investigation-ONLY — it never patches (`debug-investigate/SKILL.md:22`).
110
111 **(b) `/integration-test-review` — REPORT-ONLY** — scoped to the failing tests **and the production code they exercise**. Its 8 gates supply the test-side verdict: G1 assertion value (mutation probe), G2 data state, G3 repeatability, G4 domain logic (does the test assert only what the handler writes?), G5 spec traceability, G6 three-way sync, G7 change coverage, G8 scenario fidelity. **Direct it to STOP after its findings report** — no P5 fix, no P6 re-review, no P7 build-and-run; this loop owns fixing and re-running.
112
113 **Combine (a) + (b) into ONE written Fault Verdict per failure, BEFORE any edit:**
114
115 | Verdict | Meaning | Evidence required | Resolution |
116 | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
117 | **TEST-WRONG** | The test encodes a stale or incorrect assertion, setup, or expectation that contradicts intended behavior | The governing spec (§3 AC / §4 BR / §5 invariant / §8 TC) or the handler source shows the production behavior is correct and the test is not (`file:line`) | Fix the test at its root. NEVER weaken an assertion, add a skip, or relax a timeout. |
118 | **TEST-NOT-OPTIMAL** | The test is directionally right but mis-specified — unrealistic scenario, compressed actor pacing, blind sleep, missing ARRANGE barrier, shared-state repeatability defect, smoke-only or DI-resolution-only assertion | The failing G3/G8 gate plus the ARRANGE block read as a production trace (`file:line`) | Repair the SCENARIO — add an ARRANGE-phase settle barrier polling a real observable, unique data per run, real use-case setup. NEVER a widened assertion timeout or a retry around the assertion. |
119 | **SOURCE-WRONG** | Production code violates the spec's intended behavior or a clear invariant | `/debug-investigate`'s traced root cause at the invariant-owning layer (`file:line`, confidence ≥60%) | Fix the source at the **lowest owning layer** (Entity > Service > Handler), never the crash site. **Keep or strengthen** the test that caught it, and route the changed source into `/changes-review` before declaring PASS (`integration-test-verify/SKILL.md:294`). |
120 | **ENVIRONMENT-BLOCKED** | Infrastructure, services, containers, or data fixtures are not ready — the system, not the code, is failing | The `systemCheckCommand` output or the runner error naming the unavailable dependency | **STOP the loop and escalate.** Point the user at `startupScript`. NEVER change a test because the system was down (`integration-test-verify/SKILL.md:296`). |
121 | **AMBIGUOUS** | Intended behavior is unclear — no spec covers it, the spec is silent, or spec and code disagree with no tiebreaker | State exactly what is undetermined and which artifacts you checked | **`AskUserQuestion` before editing either side.** NEVER silently pick source or test just to make the suite pass. |
122
123 **Intermittent failures (red in one run of the 2-run gate, green in the other) use the three-way flake adjudication instead** — (a) unrealistic scenario / compressed pacing, (b) harness topology amplification, (c) genuine product race — per `integration-test-verify/SKILL.md:298-316`. Record the verdict with evidence BEFORE any change; do NOT file (c) until (a) and (b) are ruled out.
124
1256. **Run `/fix` on the adjudicated verdicts** (failures > 0 only) — this is the half the loop owns. Resolve each at its owning layer, routed by verdict: `SOURCE-WRONG` → `/fix` (its `--target` routing) or a direct edit at the lowest invariant-owning layer, then `/prove-fix`; `TEST-WRONG` / `TEST-NOT-OPTIMAL` → repair the test or scenario at its root; a missing §8 TC surfaced by G5/G7 → `/spec [mode=tests]`; a spec divergence → adjudicate per `SYNC:spec-drift-adjudication` (`/spec [update]` for SPEC-STALE, a BLOCKING fix for CODE-WRONG). Fix ONLY adjudicated verdicts — never an unadjudicated guess.
126
127 > **If `/integration-test-review` could not be constrained to report-only and already applied its P5 fixes**, treat those as this round's fix half (detect fixes-applied against the 1.1 snapshot) and SKIP this step for that round — never double-fix the same failure.
128
1297. **CONDITIONAL — run `/changes-review` on the round's fix diff, when (and only when) the round applied ANY fix.** Compare the working tree against the 1.1 snapshot: unchanged → SKIP this sub-step and record `No fix applied this round — /changes-review skipped`. Changed → run it, every round, on every round's fixes.
130 - **Scope = the round's fix diff**, not the whole branch: exactly the files this round changed since the 1.1 snapshot (source fixes, test fixes, scenario repairs, spec/TC edits alike). — why: the round's own changes are the only thing the prior rounds' reviews have not already seen.
131 - **Run it INLINE via the `Skill` tool, REPORT-ONLY** — its full dimensional review, then STOP before its Phase 7 self-fix / Phase 7.5 holistic / Phase 8 docs-update (the documented `$workflow-review-changes` boundary where the caller owns fixing, `changes-review/SKILL.md:52,204`). NEVER dispatch it as a sub-agent — it self-binds its own review-loop obligations, which a sub-agent cannot own or carry back (`changes-review-loop/SKILL.md:37`). Its own Phase 0.7 dimensional reviewers stay sub-agents by its design.
132 - **Validate, then fold the surviving findings into THIS round's fix set** — run `/why-review --validate-findings` over its report and apply every VALIDATED finding at its owning layer, exactly as in 1.6. The next round's fresh full verify is what re-proves them, so the test loop stays the single convergence engine — do NOT open a nested review→fix loop here.
133 - **Unfixable validated findings → STOP & escalate** via `AskUserQuestion` (Step 2). A round that leaves a validated review finding open has not finished, even if its tests went green.
134 - **This subsumes the `SOURCE-WRONG` per-verdict routing** in 1.5: that verdict already demands the changed source reach `/changes-review` before PASS (`integration-test-verify/SKILL.md:294`). Running it once per round over the whole fix diff satisfies that obligation AND extends it to test-side and spec-side fixes — do not run it twice for the same diff.
135
136 — why: the loop's own convergence signal is "the tests went green", and a fix that greens a test can still be wrong in every way a test cannot see — wrong layer, broken invariant elsewhere, dead code, a leaked domain concept, a security or performance regression. Without a per-round review, every fix this loop lands ships un-code-reviewed on the strength of a green suite alone.
137
1388. **Round Integrity Check (no fake green) — BLOCKING before the round can count as progress.** Compare this round's counts (1.3) against the prior round's:
139
140 | Signal | Meaning | Action |
141 | ------------------------------------------ | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
142 | Executed test count **decreased** | Tests were deleted, renamed out of discovery, filtered out, or the scope narrowed | **REGRESSION → STOP & escalate.** Restore the tests. A smaller suite is not a greener suite. |
143 | Skipped count **increased** | A failure was hidden behind a skip annotation | **REGRESSION → STOP & escalate.** Remove the skip and adjudicate the failure properly. |
144 | `{scope}` project list **shrank** | The loop de-scoped its way to green | **REGRESSION → STOP & escalate.** `{scope}` is fixed (Step 0.3). |
145 | Counts stable or grown, failures shrinking | Genuine progress | Continue to Step 2. |
146
147 — why: unlike a review loop, a test loop has a cheap fake exit — remove what fails. This check is the only thing standing between "converged" and "quietly deleted the hard tests".
148
1499. **Append an Iteration Log entry** to the Goal Contract: round number, per-project executed/passed/failed/skipped counts, the failing test names, each Fault Verdict with its `file:line` evidence and confidence, the fixes applied (`file:line`), the `/changes-review` verdict for the round's fix diff (or the explicit skip reason when no fix landed), the Round Integrity Check result, and remaining gaps.
150
151## Step 2 — Convergence & Escalation Gate
152
153Evaluate after every round:
154
155| Condition | Action |
156| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
157| Fresh full `/integration-test-verify` over `{scope}` reported **zero failures across 2 consecutive runs without a DB reset**, AND the Round Integrity Check passed, AND the working tree is unchanged by that final verify pass | **CONVERGED** → mark the required criterion PASS in the Goal Satisfaction matrix (attaching the runner output) → clear the `/goal` gate → go to Step 3. |
158| Failures > 0 AND round `< N` AND the failing count shrank vs the prior round AND integrity held | Apply the adjudicated fixes (Step 1.6), then run round `R+1` (fresh full re-verify over the SAME `{scope}`). |
159| Failing count did **not shrink** across 2 consecutive rounds (same/increasing count) | **STOP & escalate** via `AskUserQuestion` — a non-converging loop is a signal, not a reason to spin. |
160| Round cap `N` hit with failures still open | **STOP & escalate** via `AskUserQuestion` — report the still-failing tests with their Fault Verdicts; do not silently continue. |
161| Any failure adjudicated **ENVIRONMENT-BLOCKED** | **STOP & escalate immediately** — mark the criterion BLOCKED with a user-facing reason and point at `startupScript`. Never loop against an unhealthy system. |
162| Any failure adjudicated **AMBIGUOUS** | **PAUSE and `AskUserQuestion`** before the fix — resume the loop with the user's answer. |
163| Round Integrity Check failed (tests lost, skips added, scope narrowed) | **STOP & escalate** — restore the lost coverage first; this is a regression, not progress. |
164| The round's `/changes-review` (1.7) left **validated findings unfixed** | **STOP & escalate** via `AskUserQuestion` — a green suite does not clear an open, validated review finding on the fix that greened it. |
165
166> **Increasing failures = STOP.** If round `R` has MORE failing tests than round `R-1`, the fixes are regressing the system — STOP and escalate immediately. Never trade one green test for two new red ones across rounds.
167
168## Step 3 — Terminal Spec/Doc Sync + Recap
169
1701. **Terminal sync (MANDATORY once converged, when running STANDALONE).** The loop deferred all downstream sync while it churned, so close it now, in order:
171 - **`/spec [mode=sync]`** — reconcile §8 TCs ↔ the executing test code; update every `CoveredBy` field for tests the loop changed or added.
172 - **`/docs-update`** — update impacted docs: the integration-test reference doc, feature-doc evidence fields, and version history if coverage changed materially.
173
174 > **When this skill runs as a step inside a workflow that already declares `/spec [mode=sync]`, `/scan --target=integration-tests`, and `/docs-update`** (e.g. `workflow-integration-test-green`), SKIP this sub-step and let the workflow own it — say so explicitly in the recap. — why: running the same sync twice churns the same files and hides which pass actually made the change.
175
1762. **Recap.** Emit a concise convergence recap: rounds run, the shrinking failing-count sequence, each round's Fault Verdicts and the fixes applied, the final zero-failure runner output (both runs), the Round Integrity Check trail (executed/skipped counts per round), and the Goal Satisfaction matrix (required criterion PASS). Point to each round's report under `plans/reports/` and the Goal Contract Iteration Log. Do NOT commit or push unless the user explicitly asks.
177
178---
179
180## Convergence Detection — Why Five Conditions
181
182A round converges ONLY when **all five** hold. Each closes a distinct way a test loop lies to itself:
183
1841. **Fresh verify over the post-fix code** — a green report from a run that predates the last fix proves nothing about that fix. Every applied fix invalidates the prior verdict; re-run, never reuse.
1852. **Zero failed tests** — not "only known failures left", not "the important ones pass". A single red test is an unconverged loop.
1863. **2 consecutive green runs without a DB reset** — the gate `/integration-test-verify` already owns (`integration-test-verify/SKILL.md:44,169`). One green run hides order-dependent and state-leak flakiness, which is exactly what a fix cycle tends to introduce.
1874. **Real runner output** — Passed/Failed/Skipped counts and names. "Looks like it passed" is theater (`integration-test-verify/SKILL.md:339`).
1885. **Round Integrity Check passed** — the executed count did not shrink, the skipped count did not grow, `{scope}` did not narrow. This is the condition the other four cannot see: a suite can satisfy 1–4 perfectly by having quietly lost the tests that failed.
189
190**Working-tree-unchanged backstop:** the converging verify pass must land no fix. A "clean" verdict that still mutated files means the round DID fix things → run another round to re-prove clean.
191
192When failures remain but cannot be fixed (product decision, unclear intent, environment) → **escalate**, do not loop. Convergence is a fixed point, not a single green read.
193
194---
195
196**IMPORTANT MANDATORY sequence:** Step 0 (resolve `{scope}` — WHOLE SYSTEM by default — + Goal Contract) → Step 0b (bind the convergence loop: protocol loop primary + optional `/goal` accelerator) → Step 1 (round loop: `/integration-test-verify` INLINE → on failure `/debug-investigate` + `/integration-test-review` report-only → ONE Fault Verdict per failure → `/fix` at the owning layer → CONDITIONAL `/changes-review` on the round's fix diff when any fix landed → Round Integrity Check → log) → Step 2 (converge on a zero-failure 2/2-green fresh verify / escalate on non-progress, blocked environment, or lost coverage) → Step 3 (terminal `/spec [mode=sync]` + `/docs-update` when standalone + recap).
197
198<!-- SYNC:goal-contract-satisfaction-loop -->
199
200> **Goal Contract Satisfaction Loop** — Persist the user goal in an external file, execute against it, and loop review/fix until every saved required criterion passes or a blocker escalates. Bounded closed loop — NEVER open-ended autonomous exploration.
201>
202> 1. **Resolve the active goal** (in order): active plan `goal.md` → `plans/goals/{YYMMDD-HHmm}-{slug}/goal.md` → create a new Goal Contract from the current user request (template: `.claude/templates/goal-contract-template.md`).
203> 2. **Required sections:** Original Request, Purpose, Success Criteria (checkboxes; mark required vs optional), Constraints, Evidence Required, Iteration Log, Goal Satisfaction matrix.
204> 3. **Before work:** read the active goal and map planned work to saved success criteria — execution serves the saved criteria, never chat memory alone.
205> 4. **After execution/verification:** append an Iteration Log entry — result, evidence references (`file:line`, command output, report path), remaining gaps.
206> 5. **Review gate:** emit a Goal Satisfaction matrix — `| Success Criterion | Evidence | Status |` with PASS/FAIL/BLOCKED. Overall PASS requires every required criterion PASS.
207> 6. **Loop rule (retry):** required criterion FAIL → validate the gap is real → fix → re-review only the affected criteria. Stop cleanly when all required criteria PASS.
208> 7. **Escalation rule (stop):** two consecutive iterations with no criterion progressing, or a blocker needing user input → mark the criterion BLOCKED with a user-facing reason and escalate. NEVER loop indefinitely.
209> 8. **Skip rule:** tiny conversational tasks may skip the goal file ONLY with a recorded one-line reason. User-accepted gate skips are recorded in the goal file with reason and scope.
210> 9. **Security:** NEVER store secrets, tokens, credentials, or private customer data in goal files — store evidence references and redact sensitive values.
211>
212> **Blocked until:** active goal resolved (or skip reason recorded) · saved success criteria read before edits · iteration evidence appended after execution · Goal Satisfaction matrix emitted before any PASS verdict.
213
214<!-- /SYNC:goal-contract-satisfaction-loop -->
215
216<!-- SYNC:test-failure-fault-adjudication -->
217
218> **Test-Failure Fault Adjudication** — When a test fails (or you are deb
219
220…(truncated)