Quality Gate — Convergence Loop
Replaces the one-shot "review ×3" with a bounded loop that produces an auditable verdict. The user reads the gate file instead of the diff.
Inputs:
- The diff to gate:
git diff <base>...HEAD, where<base>is designated by the caller or resolved from the remote HEAD/default branch without assuming a branch name. An ambiguous base is a blocker. - The validated plan / acceptance criteria, when the caller has one.
.agents/verification.yaml— if missing, run theproject-probeskill first.- The task level (0-4). Default: 2. The caller passes it; level 0 changes are not gated (no gate file).
- The mode: integrated (called by dev-workflow or ship-workflow — the loop fixes autonomously) or standalone (invoked via /gate or directly by the user — report first, the user arbitrates every fix; see step 4).
Output: a v2 envelope docs/quality/GATE-<YYYY-MM-DD>-<slug>.yaml, its JSON proof payload under docs/quality/proofs/, and a short summary to the caller. Both evidence files are committed together and must pass the skill-owned gate_verify.py verify resource.
Resolve skill:quality-gate/scripts/run-python310.sh and
skill:quality-gate/scripts/gate_verify.py through the active runtime's skill registry to absolute
paths before invoking the shell. Never require the project under review to contain Skillz tooling.
An absent or incompatible resource is tooling-unavailable, not CONCERNS, and cannot be waived as
a product-quality risk.
Loop bounds by level
| Level | Max rounds | Review lenses |
|---|---|---|
| 1 | 1 | one generalist reviewer with a quick structural-smell check |
| 2 | 3 | correctness+security · readability · performance · final thermo-nuclear-code-quality-review |
| 3-4 | 4 | level-2 lenses + design-audit / seo-geo-audit / a11y-enforcer for the surfaces the caller detected; thermo-nuclear-code-quality-review still runs last |
One round
EXECUTION EVIDENCE — always first, never skipped. Run every command in the manifest's
commands. If the harness provides theverifyskill, drive the app's real affected flow (not just tests); otherwise use the manifest'stestability.runtime_verifycommand to launch the app and drive the affected flow yourself. Any red → fix immediately → restart the round. A restart consumes a round from the cap; if execution evidence cannot be made green within the cap, the verdict isFAIL. (At level 1 the single-round exception below still applies: fixing and re-running green within that round is allowed and does not consume a second round.) Record each command and its actual result; a claim without the executed command's output is worthless. If the diff touches only docs/config with no runtime surface, still run the manifest commands and note the limitation inabsents— never skip silently.MULTI-LENS REVIEWS — fresh contexts. Each lens reviews the diff + plan only (no session history). Findings are classified P0 (must fix) / P1 (should fix) / P2-P3 (note). The lens order is deliberate:
- Core lenses: correctness+security, readability, performance.
- Conditional domain lenses:
design-audit,seo-geo-audit,a11y-enforceronly when Phase 1 detected those surfaces. - Final structural lens:
thermo-nuclear-code-quality-reviewfor level ≥ 2. This pass runs after the other lenses so it can judge the final implementation shape without duplicating their domains. It must ignore issues already covered as correctness, security, performance, UI/DS, SEO/GEO or a11y unless the same issue also creates a distinct structural maintainability regression. It only reports abstraction debt, giant-file growth, spaghetti branching, boundary leaks, unnecessary wrappers/casts, non-atomic orchestration, and missed simplification moves. Runtime capabilities:
- Claude Code: use the native
/code-reviewskill as the primary correctness lens (its CONFIRMED/PLAUSIBLE verdicts feed step 3 directly — CONFIRMED skips re-verification). Dispatch the remaining lenses as parallel subagents when useful, but keepthermo-nuclear-code-quality-reviewas the final pass after their outputs are available. - Sequential runtimes (Codex CLI, OpenCode, Gemini): run the lenses one at a time in the order above, with an explicit mental reset between lenses. Run
thermo-nuclear-code-quality-reviewlast and de-duplicate it against already-recorded findings before step 3.
ADVERSARIAL COUNTER-VERIFICATION — new findings only. Maintain a findings registry across rounds. Stable id:
<file>:<category>:<8-char-hash-of-quoted-excerpt>.- A finding already in the registry (confirmed or refuted) is not re-verified and not counted as new.
- Each NEW finding goes to an independent verifier whose explicit job is to REFUTE it against the actual code. Uncertain → refuted (bias against false positives) — EXCEPT security findings (injection, auth bypass, secret exposure, trust-boundary violations): an uncertain security finding stays confirmed until positively disproven.
- Confirmed → fix queue. Refuted → registry, never returns.
FIX confirmed P0/P1, then return to step 1. P2/P3 go to the gate file as notes, not fixes (no scope creep).
- Integrated mode: the orchestrator fixes autonomously — it has the context and the loop's job is to converge without human input.
- Standalone mode: NEVER modify a file before the user chooses. After counter-verification, present the detailed report first — one entry per finding: file:line, severity (P0-P3), confirmed/refuted with the verifier's reason, and the proposed fix (quoted). Then ask: [A] apply all confirmed P0/P1 and continue the loop | [S] select which findings to fix | [R] report only — write the gate file with the current verdict (unfixed confirmed P0/P1 ⇒ FAIL or CONCERNS per the verdict rules) and stop. On later rounds, present only the new findings (the delta) before fixing.
Convergence: two consecutive rounds with zero new confirmed P0/P1 findings → verdict (P2/P3 notes never count toward convergence). Cap reached without convergence → verdict CONCERNS, remaining findings listed. Never loop past the cap.
Level-1 exception (cap = 1 round): the verdict is decided on that single round — confirmed findings fixed + execution evidence re-run green → PASS. The Verdict-rules preconditions still apply: without at least one real executable proof, the verdict caps at CONCERNS even here.
Verdict rules
PASSrequires ALL of: every available executable evidence green · zero confirmed P0/P1 findings remaining (confirmed P2/P3 are recorded as notes and do not block PASS) · at least one real executable proof (tests or runtime verify). A project with no executable evidence at all caps atCONCERNS— the gate cannot claim more than it knows.FAIL: confirmed P0 remaining that could not be fixed within the cap.CONCERNS: cap reached without convergence, or executable evidence too weak for PASS, or unfixed confirmed P1.WAIVED: only on explicit user request, with the reason recorded in the gate file.
Gate v2 evidence and integrity
# docs/quality/GATE-2026-07-05-auth-refresh.yaml
schema_version: 2
verdict: "PASS"
level: 2
base_sha: "<full 40-char code base SHA>"
head_sha: "<full 40-char last code SHA before evidence commit>"
code_diff_hash: "<sha256 of git diff base...head>"
code_diff_exclusions: ["CHANGELOG.md"]
proof_payload: "docs/quality/proofs/2026-07-05-auth-refresh.json"
proof_payload_hash: "<sha256 of exact JSON bytes>"
integrity_sha256: "<self-integrity hash written by gate seal>"
The proof payload is strict JSON (schema_version: 1) with the manifest fingerprint, one execution
entry for every command in .agents/verification.yaml, absences, opinion findings, rounds and
autonomous decisions. Every execution records the exact command, status and exit code. A PASS
payload contains no invented command, no missing command and no non-passing status.
A WAIVED payload additionally contains the exact human decision:
{"waiver":{"reason":"...","scope":"...","approved_by":"human","approved_at":"<ISO-8601>"}}
The verifier rejects missing, partial or empty waiver metadata. Other verdicts must not carry a
waiver object. A waiver remains visibly WAIVED; it never becomes PASS.
base_sha and head_sha identify the code diff. Because a committed gate cannot contain the SHA
of its own commit, head_sha is the final code commit before the evidence-only commit. Verification
accepts current HEAD == head_sha or descendants whose entire delta is limited to the exact gate,
its named proof payload and CHANGELOG.md. Any other path, including another file below
docs/quality/, makes the gate stale.
The sole permitted code-diff exclusion is the exact CHANGELOG.md path. There is no blanket
docs/quality exclusion. Build the JSON payload, compute its byte hash, create the YAML with a
64-zero integrity placeholder, then run:
bash "skill:quality-gate/scripts/run-python310.sh" "skill:quality-gate/scripts/gate_verify.py" seal docs/quality/GATE-<date>-<slug>.yaml
git add docs/quality/GATE-<date>-<slug>.yaml docs/quality/proofs/<date>-<slug>.json
git commit -m "chore(quality): gate <slug>"
bash "skill:quality-gate/scripts/run-python310.sh" "skill:quality-gate/scripts/gate_verify.py" verify docs/quality/GATE-<date>-<slug>.yaml --root .
Never hand-edit a sealed gate or its proof. Regenerate and reseal instead. A v1 gate is
legacy-evidence, not stale merely because its schema is old. During the v6.1 compatibility window,
the verifier may classify it legacy-valid only when --allow-legacy is explicit and its historical
diff hash can still be recomputed against an explicit or locally detected base ref. Otherwise create
a v2 gate; do not request a quality waiver for schema migration or missing tooling. A future GitHub
Check may invoke the same verifier; it remains non-blocking until local rollout evidence is complete.
decisions_prises_en_ton_nom lists every autonomous deviation from the validated plan. For levels 3-4 the calling workflow must show this section to the user before proposing ship — it is the only careful read left to the human.
Anti-patterns
- Claiming a command is green without showing its executed output.
- Re-verifying or re-counting registry findings (the loop never converges).
- Skipping execution evidence because "only docs changed".
- Fixing P2/P3 style findings during the loop (scope creep — note them instead).
- Looping past the cap, or emitting PASS on opinion alone.
- Modifying any file in standalone mode before the user has arbitrated the report.