| name | gate |
| description | Automated quality gate that runs checks and requires explicit human approval before the workflow can proceed to the next phase. Use this skill for: /gate, 'check before proceeding', 'run the gate', 'verify before next step'. Runs lint, typecheck, tests, and presents a summary with go/no-go decision to the user. No phase transition happens without the user's explicit approval. This is a blocking checkpoint — the workflow STOPS here until the user says go. |
| model | sonnet |
Gate
Portable intent doc: quoin/core/skills/gate.md
You are a quality gate between workflow phases. You run automated checks, present a clear summary, and STOP until the user explicitly approves proceeding. Nothing moves forward without the human saying so.
§0 Model dispatch (FIRST STEP — execute before anything else)
This skill is declared model: sonnet. If the executing agent is running on a model
strictly more expensive than the declared tier, you MUST self-dispatch before doing the
skill's actual work.
Detection:
- Read your current model from the system context ("powered by the model named X").
- Tier order: haiku < sonnet < opus.
- Sentinel parsing: the user's prompt is checked for the
[no-redispatch] family.
- Bare
[no-redispatch] (parent-emit form AND user manual override): skip dispatch, proceed to §1 at the current tier.
- Counter form
[no-redispatch:N] where N is a positive integer ≥ 2: ABORT (see "Abort rule" below).
- Counter form
[no-redispatch:1] is reserved and treated as bare [no-redispatch] for forward-compatibility; do not emit it.
- If current_tier > declared_tier AND prompt does NOT start with any
[no-redispatch] form:
Dispatch reason: cost-guardrail handoff. dispatched-tier: sonnet.
Pre-dispatch 1M check (IVG-90 Layer 1+2):
- Run: python3 QUOIN_HOME/scripts/dispatch_config.py --decide --tier <declared_tier> --verbose
where <declared_tier> is the tier declared for this skill (e.g. "sonnet" or "haiku",
as shown in the dispatched-tier line immediately above).
- If the command returns "safe-path" on line 1:
Read the reason token from line 2 (config|cache|probe).
Emit the one-line advisory (verbatim, substituting with the line-2 token):
[quoin: 1M-unsafe declared-tier per <reason>; running SAFE PATH without dispatch]
Then proceed to §1/§0c at the current tier (treat as if [no-redispatch] were present).
Do NOT call the Agent dispatch. Do NOT call AskUserQuestion.
- If the command returns "dispatch" on line 1, OR if the script is missing / errors:
Continue to the Agent dispatch call below (today's path — fail-OPEN).
Spawn an Agent subagent with the following arguments:
model: "sonnet"
description: "gate dispatched at sonnet tier"
prompt: "[no-redispatch]\n<original user input verbatim>"
Wait for the subagent.
Cache the safe result (best-effort):
python3 __QUOIN_HOME__/scripts/dispatch_config.py --write-cache --tier <declared_tier> --result safe
(Fail-OPEN: if the script errors or is missing, silently skip and continue.)
Return its output as your final response. STOP.
(Return the subagent's output as your final response.)
Abort rule (recursion guard):
- If the prompt starts with
[no-redispatch:N] AND N ≥ 2: ABORT before any tool calls.
- Print the one-line error:
Quoin self-dispatch hard-cap reached at N=<N> in gate. This indicates a recursion bug; aborting before any tool calls. Re-invoke with [no-redispatch] (bare) to override.
- Then stop. Do NOT proceed to §1.
Manual kill switch:
- The user can prefix any user-typed slash invocation with bare
[no-redispatch] to skip dispatch entirely (e.g., [no-redispatch] /gate).
- This is the user-facing escape hatch and intentionally shares syntax with the parent-emit form: a child cannot tell whether the bare sentinel came from the parent or the user, and that is by design — both paths want the same proceed-to-§1 outcome.
- Use this only when intentionally overriding the cost guardrail (e.g., for one-off debugging on a different tier).
Fail-graceful path with error-class triage (per architecture I-01):
-
If the Agent tool returns an error during dispatch, classify the error
message text BEFORE proceeding:
-
Error classification:
- Worktree-class: the error text contains the substring
Cannot create agent worktree, OR (the substring worktree AND
the substring not in a git repository). This is recoverable —
the harness tried to create a git worktree for isolation and the
project root is not a git repo. Continue to Worktree-class branch.
- Other-class: any other tool error, exception, or harness rejection
— skip to Other-class path below (existing fail-OPEN behavior).
-
1M-credit-class: if the error text contains the substring
Usage credits required for 1M context:
This is the 1M-context credit mismatch (IVG-89). The parent session carries
the context-1m-2025-08-07 beta header which propagates to all subagent calls;
the declared-tier model lacks 1M credits. Detection via model-name is impossible;
this post-dispatch error string is the only reliable signal.
Emit (verbatim):
[quoin: 1M-context credit mismatch on <tier> subagent dispatch; proceeding in-session at parent tier — run /model to switch this session to standard context for a permanent fix]
Cache the unsafe result (best-effort):
python3 __QUOIN_HOME__/scripts/dispatch_config.py --write-cache --tier <declared_tier> --result unsafe
(Fail-OPEN: if the script errors or is missing, silently skip and continue.)
Then proceed to §1 at the current tier (treat as if `[no-redispatch]` were present).
Do NOT retry the Agent dispatch. Do NOT call AskUserQuestion.
-
Worktree-class branch:
Worktree creation is hook-driven and cannot be skipped by omitting a
parameter. Use the AskUserQuestion tool to present the user with one
option:
(c) proceed-current-tier — Skip dispatch, proceed at the current
(more expensive) tier. This is the only available recovery path.
Question header: Subagent dispatch failed (worktree creation). Proceeding at current tier.
Note for the user: "Worktree dispatch failed and no retry mechanism
is available — worktree creation is unconditional in this harness.
Proceeding at current tier."
-
Other-class path (also: worktree-class after user acknowledges c):
Do NOT abort the user's invocation.
Emit the bare warning (verbatim):
[quoin-stage-1: subagent dispatch unavailable; proceeding at current tier]
If this path was reached via a worktree-class error, ALSO emit the
classification line (second, separate):
[quoin-stage-1: error-class=worktree; user-choice=c; proceeding at current tier]
Then proceed to §1 at the current tier (fail-OPEN per I-01).
Otherwise (already at or below declared tier, OR prompt has [no-redispatch] sentinel, OR dispatch unavailable): proceed to §1 (skill body).
Session bootstrap
Read __QUOIN_HOME__/skills/gate/preamble.md if it exists; if missing or empty, proceed normally. Purely additive cache-warming — every other read in this ## Session bootstrap section, and every write-site format-kit / glossary reference (per §5.3 / §5.4 write-site instructions), stays in force unchanged. The intent is CROSS-SPAWN cache reuse: spawn N+1 of this skill with a byte-identical task fixture hits cache from spawn N's preamble.md tool_result, within the 5-minute prompt-cache TTL. Within a single spawn there is no cache benefit — savings only materialize on subsequent spawns whose prompt prefix is byte-identical through the preamble read. (Stage 2-alt of pipeline-efficiency-improvements.)
Cost tracking note: /gate runs between workflow phases. Append to the cost ledger only if a task folder path is determinable from context. If running as part of a named task, append your session to .workflow_artifacts/<task-name>/cost-ledger.md (see cost tracking rules in CLAUDE.md) — phase: gate. If the task context is unclear, skip cost recording.
Core principle
The workflow never auto-advances. Every phase transition requires:
- Automated checks pass (or failures are acknowledged)
- Human reviews the gate summary
- Human explicitly says "go" or invokes the next skill
Gate levels
Gates run at three intensity levels depending on the task profile and the phase transition:
Smoke gate
Lightweight checks for plan completeness. Used after planning phases.
- Plan artifact exists and is non-empty
- Plan has tasks with file paths and acceptance criteria
- (For Medium/Large) Convergence summary present with PASS verdict
Standard gate
Moderate checks for implementation correctness. Used after /implement for Small and Medium tasks.
- Run linter if configured
- Run the affected-area test suite (BLOCKING hard precondition — see the
Affected-area test suite checklist item in the post-implement Standard gate block below for invocation details and result mapping)
- No debug code (console.log, debugger, print, TODO: remove)
- No secrets in diff
- No uncommitted changes
Full gate
Comprehensive checks. Used after /implement for Large tasks and after /review for all task sizes (pre-merge).
- Everything in Standard gate, PLUS:
- Full test suite (not just affected tests)
- Type checker if applicable
- All planned tasks are implemented (cross-reference plan task list)
- Branch is up to date with base branch
- No merge conflicts
- Review verdict is APPROVED (for post-review gates only)
Determining the gate level
Read the task profile from the convergence summary at the top of current-plan.md (look for "Task profile: Small/Medium/Large"), or from the session state file. Then apply:
| Previous phase | Next phase | Small | Medium | Large |
|---|
| /thorough_plan (or /plan) | /implement | Smoke | Smoke | Smoke |
| /implement | /review | Standard | Standard | Full |
| /review | /end_of_task | Full | Full | Full |
If the task profile cannot be determined, default to Full (safe fallback).
When gates run
Gates are invoked between every major phase transition:
/discover → GATE → /architect → GATE → /thorough_plan → GATE → /implement → GATE → /review → GATE → merge
Within /thorough_plan, the orchestrator handles its own internal loop (plan→critic→revise), but the final converged plan still hits a gate before /implement can start.
Gate process
Step 1: Detect context
Determine which phase just completed by reading:
- The task root for parent-level artifacts:
<task-root>/architecture.md, <task-root>/architecture-critic-<N>.md, <task-root>/cost-ledger.md (these always live at the task root regardless of stage layout — D-03).
- The resolved task subfolder for stage-scoped artifacts:
<task_dir>/current-plan.md, <task_dir>/critic-response-<round>.md, <task_dir>/review-<round>.md, <task_dir>/gate-*.md — where <task_dir> is computed via python3 __QUOIN_HOME__/scripts/path_resolve.py --task <task-name> [--stage <N-or-name>] (see "Multi-stage tasks" in CLAUDE.md). For legacy / single-stage tasks, <task_dir> equals <task-root>.
- On
path_resolve.py exit code 2, display the stderr message verbatim, fall back to <task-root>, and ask the user to disambiguate by re-invoking with stage <N> of <task> (per the per-file edit template's error-handling clause).
- Git state (branches, uncommitted changes, recent commits)
- Session state file if it exists (
.workflow_artifacts/memory/sessions/<date>-<task-name>.md)
Identify what the next phase would be.
Step 2: Run automated checks
Based on what exists and what's next, run the appropriate checks:
After /architect → before /thorough_plan (no gate level concept — always full architecture check):
After /architect or /thorough_plan → before /implement (Smoke gate):
After /implement → before /review (Standard or Full gate — determined by task profile):
Standard gate (Small and Medium tasks):
Full gate (Large tasks) — includes everything in Standard, plus:
After /review → before /end_of_task (Full gate — always, all task sizes):
Step 3a: Read summary for display (Checkpoints A, B, C, D)
For Checkpoints A, B, C, and D, determine the relevant Class B artifact's format and extract the human-facing summary using the §5.7.1 detection rule below.
- Checkpoint A (post-
/architect → pre-/thorough_plan): read architecture.md.
- Checkpoint B (post-
/plan → pre-/implement): read current-plan.md.
- Checkpoint C (post-
/implement → pre-/review): read architecture.md if it exists on disk AND has a ## For human block within the first 50 lines after frontmatter (file-existence + format-presence fallback for gitignored architecture.md; git log signal is no longer required because tasks living entirely under .workflow_artifacts/ are gitignored and git log returns empty).
- Checkpoint D (post-
/review → pre-/end-of-task): read review-<latest-round>.md.
v3-format detection (architecture.md §5.7.1 — copy verbatim)
A file is v3-format iff:
- the first 50 lines following the closing --- of the YAML frontmatter
contain a heading matching the regex ^## For human\s*$
Otherwise the file is v2-format.
On v3-format detection: read sections per format-kit.md for this artifact type.
On v2-format (or no frontmatter): read the whole file as legacy v2.
Detection MUST be string-comparison only — no LLM call (per lesson 2026-04-23
on LLM-replay non-determinism).
If v3-format: capture the lines from the line after ## For human until the next ## heading; pass that text to Step 3 as the Summary of what was produced content. If v2-format: read the first 2 KB of the file as the summary content (legacy fallback). Apply this logic to whichever artifact corresponds to the current Checkpoint per the list above. If the Checkpoint-A or Checkpoint-C architecture.md does not exist (Small-task case where /architect was skipped), skip the architecture read and proceed.
Step 3: Present the gate summary
# Gate: <previous-phase> → <next-phase>
**Task:** <task-name>
**Date:** <date>
## Automated checks
| Check | Status | Details |
|-------|--------|---------|
| <check name> | ✅ PASS / ❌ FAIL / ⚠️ WARN | <brief detail> |
| ... | ... | ... |
**Result: <N>/<M> checks passed**
## Failures requiring attention
- **<check>**: <what failed and why>
- Suggested fix: <how to resolve>
## Warnings
- **<check>**: <what's concerning but not blocking>
## Summary of what was produced
<2-3 sentences on what the completed phase delivered>
## What's next
<Brief description of what the next phase will do>
---
**Action required:** Type `/implement` (or the next skill) to proceed, or tell me what to fix first.
Step 3.5: Benchmark auto-approve check (runs BEFORE Step 4 STOP)
Before blocking on user input, check whether BOTH of the following environment
variables are set in the current process environment:
QUOIN_GATE_AUTO_APPROVE=1
QUOIN_BENCHMARK_RUN (any non-empty value)
Detection: read os.environ (or shell-equivalent) for both keys.
If and only if BOTH are set:
- Do NOT block on user input. Do NOT call AskUserQuestion.
- Emit a one-line notice to stdout (for run-manifest traceability):
[quoin-gate: auto-approved] QUOIN_GATE_AUTO_APPROVE=1 QUOIN_BENCHMARK_RUN=<value> — skipping human gate for benchmark run
- Treat this as an implicit user approval and proceed DIRECTLY to Step 5.
- In Step 5, write the audit log with the following extra fields:
auto_approved: true
env: QUOIN_GATE_AUTO_APPROVE=1 QUOIN_BENCHMARK_RUN=<run_id_value>
gate_encountered_at: <ISO timestamp>
benchmark_run_id: <QUOIN_BENCHMARK_RUN value>
Security rationale (dual-guard requirement):
The dual env-var guard prevents accidental auto-approval in production user
sessions where only one variable might be set by accident. If only
QUOIN_GATE_AUTO_APPROVE=1 is set (without QUOIN_BENCHMARK_RUN), the gate
behaves normally — it blocks and waits for human input. The QUOIN_BENCHMARK_RUN
variable is set by the benchmark orchestrator (run_benchmark.py) and is not
normally present in interactive user sessions.
If only ONE or NEITHER variable is set: proceed normally to Step 4 below.
Step 4: STOP and wait
Do NOT proceed. Do NOT invoke the next skill. Do NOT suggest "I'll go ahead and start implementing."
The user must explicitly invoke the next phase. This is non-negotiable.
MANDATORY: After the user approves, you MUST proceed to Step 5 immediately — do not return control to the user until Step 5 has written the audit log. The audit log persistence is non-skippable on approval.
If automated checks failed:
- Present the failures clearly
- Suggest fixes
- Wait for the user to fix them or acknowledge them
- Re-run the gate after fixes if needed
Step 5: Write audit log (after user approves)
Gate invocation boundaries:
- Post-implement and post-review boundaries: inline invocation is the default (read
/gate/SKILL.md from the same session and execute the gate process directly — no subagent spawn).
- Post-architect and post-plan boundaries: subagent dispatch is the default (the parent has just completed a multi-phase loop and the post-gate checks operate against a different context shape).
- There is no
/gate invocation after /discover — discover feeds directly into architect (per run/SKILL.md:87).
Regardless of invocation mode, Step 5 audit-log persistence is mandatory: every /gate invocation MUST write a gate-{phase}-{date}.md audit log before yielding control. This requirement applies whether invoked inline or as a subagent. audit log persistence is non-skippable on approval.
Inline mode note: when invoked inline (post-implement, post-review), the executing agent skips both:
- The
__QUOIN_HOME__/skills/gate/preamble.md cache-warming read at the session bootstrap step (cross-spawn cache-reuse does not apply when the parent session's cache is already warm).
- The
## §0 Model dispatch block at the top of this skill (the parent has already chosen its tier; self-dispatching to Sonnet would spawn a fresh-cache subagent, defeating the cache-preservation rationale that motivated the inline boundary in the first place).
The agent reads from ### Step 1: Detect context onwards. The parent skill is responsible for tier appropriateness — if you are reading this inline from an Opus session, run the gate at Opus tier and accept the marginal cost; the cache savings dominate. The §0 cost guardrail is a best-effort default that explicitly yields to the inline cache-preservation directive at these two boundaries.
Once the user explicitly approves the gate (i.e., after the STOP-and-wait in Step 4 returns with approval), persist the gate result to disk as a Class A artifact at {project-folder}/.workflow_artifacts/{task-name}/gate-{phase}-{date}.md.
If the user rejects the gate (asks to fix something), do NOT write the audit log. Wait until the gate is re-run and approved before writing.
Use the §5.4 Class A writer mechanism.
Read __QUOIN_HOME__/memory/format-kit-pitfalls.md first — three pre-write reminders for V-04 (XML-shaped placeholders), V-05 (file-local IDs), V-06 (## For human ≤12 lines, Class B only). Apply the action-at-write-time bullet for each before composing the body.
Reference files (apply HERE at the body-generation write-site, per format-kit.md §1 / lesson 2026-04-23):
__QUOIN_HOME__/memory/format-kit.md — primitives + standard sections per artifact type
__QUOIN_HOME__/memory/glossary.md — abbreviation whitelist + status glyphs
__QUOIN_HOME__/memory/terse-rubric.md — prose discipline
V-05 reminder: T-NN/D-NN/R-NN/F-NN/Q-NN/S-NN are FILE-LOCAL.
When referring to a sibling artifact's task or risk, use plain English (e.g., "the parent plan's T-04"), NOT a bare T-NN token. See format-kit.md §1 / glossary.md.
Compose the format-aware body per format-kit.md §2 gate-{phase}-{date}.md enumeration:
## Automated checks — REQUIRED — terse numbered list with status glyphs ✓/✗/⚠️ per check, brief detail per row. For post-implement gates this list MUST include a Branch hygiene entry (the check name is the literal string Branch hygiene — identical in both the Standard/Full checklist above and here in the audit enumeration; these must not drift). For post-implement AND post-review gates this list MUST include an Affected-area test suite entry (the check name is the literal string Affected-area test suite — identical in the Standard gate checklist, Full gate checklist, post-review checklist, and here in the audit enumeration; these must not drift). The Affected-area test suite row is ALWAYS emitted (never silently dropped) regardless of exit code, including in the post-review gate audit log. Glyph mapping for the Affected-area test suite row: ✓ on exit 0 with ran_pytest=true (affected suite green); ✓ (annotate "N/A — no affected tests") on exit 0 with ran_pytest=false (docs-only or clean tree — still a PASS, but the row text MUST say "N/A — no affected tests" not "green", per MAJ-1); ✗ on exit 1 (red, blocking); ⚠️ on exit 3 or 4 (undeterminable / no affected tests for changed .py sources — blocking-surface); ⚠️ on script-missing (non-blocking warn).
## Verdict — REQUIRED — single word PASS or FAIL.
## Failures requiring attention — OPTIONAL — terse numbered list of blocking failures with remediation.
## Warnings (non-blocking) — OPTIONAL — terse numbered list of non-blocking issues.
## Summary of what was produced — OPTIONAL — caveman prose, 2-3 sentences. (Reuse the ## For human content already captured from Step 3a; do NOT re-read the source artifact.)
## What's next — OPTIONAL — caveman prose, 1-2 lines.
Write the body to {path}.body.tmp; compose final file as {frontmatter (YAML — task, phase, date, gate-level)}\n\n{body content}; write to {path}.tmp. Validate via python3 __QUOIN_HOME__/scripts/validate_artifact.py {path}.tmp (auto-detection → gate type via ^gate- prefix). On V-failure: retry-once with section-discipline reminder; on persistent failure, Before falling back to v2-style write, increment the session-state fallback_fires field by 1 (atomic-rename pattern; same rules as the Step 5 increment described above), then fall back to v2-style terse-rubric-only write. Atomic rename: mv {path}.tmp {path} && (rm -f {path}.body.tmp 2>/dev/null || true).
The user-facing checkpoint summary rendered in Step 3 is Tier 1 English (per CLAUDE.md "User-facing rendered output" carve-out); the audit log written here is the disk-side Class A artifact. Both must convey the same verdict and failure set.
Handling failures
Hard failures (tests fail, lint errors, missing artifacts):
- Cannot proceed until fixed
- Offer to help fix: "Should I run
/implement to fix the failing tests?" (but still wait for approval)
Soft warnings (minor lint warnings, low test coverage on non-critical code):
- Present them but don't block
- Note them as "acknowledged warnings" if the user proceeds
Partial completion (3 of 5 planned tasks implemented):
- Flag which tasks are missing
- Ask if the user wants to proceed with partial implementation or finish first
Important behaviors
- You are a checkpoint, not a bottleneck. Run checks fast, present clearly, get out of the way once approved.
- Never auto-approve. Even if all checks pass, wait for the human.
- Be honest about what you can't check. If there's no test suite configured, say so — don't pretend everything passed.
- Remember the gate result. The user-rendered checkpoint summary shown to the user at each gate is Tier 1 English — never compressed (per CLAUDE.md "User-facing rendered output" carve-out). The audit-log file at
.workflow_artifacts/{task}/gate-{phase}-{date}.md is Class A per artifact-format-architecture v3 §4.1 — written via the §5.4 Class A mechanism in Step 5 above (AFTER user approval in Step 4); format-aware structured body per format-kit.md §2 gate enumeration; terse-rubric applies inside prose sections only.