Immutable. This exact content is served forever at /api/v1/blob/1e3d0720bcad99a3.
---
name: auto
description: Autonomous mode for a request whose completion criteria can be enumerated before work starts. Freezes those criteria to `.ac/auto/<slug>/criteria.md` under a sha256 digest, creates a working branch, chains `ac:plan --auto` (whose Stage 3 interview is this run's single question round and whose Stage 6a chains `ac:execute` on its own), then spawns the read-only gate `ac:auto-verifier` and writes its verdict to `.ac/auto/<slug>/verdict.md`. Never pushes, and auto-answers no BLOCKER.
when_to_use: When the user wants a request carried end-to-end without supervision and can say up front what done means. Not for open-ended audits or exploration; a request whose criteria cannot be enumerated before work starts is refused at Phase 0.
argument-hint: "<request description>"
effort: xhigh
---
# /ac:auto
Autonomous runner. It fixes what done means before any work happens, hands the work to the existing
`ac:plan` and `ac:execute` chain, and ends with a verdict written by a gate that did none of the work.
Request: $ARGUMENTS
## Standing rules
These hold for the whole run, including after a compaction. Everything below this block is procedure; these
are the bounds. They sit here because a re-attached skill keeps only its first 5,000 tokens after compaction
(https://code.claude.com/docs/en/skills.md) and this body is larger, so a rule further down is gone from
context on exactly the long runs that need it.
**Turn termination.** Your turn ends on exactly one of: the Phase 5 closing report, or a terminal branch that
deleted `.ac/state/active-auto.json` first. Nothing else ends it. While that marker exists and
`.ac/auto/<slug>/verdict.md` does not, the plugin's auto `Stop` guard blocks the turn from ending
(`${CLAUDE_PLUGIN_ROOT}/hooks/stop-guard-auto.sh`), and its block budget is 3, after which the run is stranded
without a verdict. Writing the verdict at Phase 4 is the only action that releases it. Never end a turn by
describing what you would do next, and never propose that the user open a fresh session to continue.
**Marker path.** `.ac/state/active-auto.json` is the single live-run record; the run directory is
`.ac/auto/<slug>/`. Create the run directory before or with the marker: the guard exits 0 when the directory is
missing (`stop-guard-auto.sh:116`), so a marker written first leaves the guard silently inert for the whole run.
**No BLOCKER is auto-answered.** Every interview gate in `ac:plan` Stage 3 and every BLOCKER in either chained
skill (execute 2i dependency failed, 2j three failures spanning two waves, 3c plan-spec issue, a failed
checkpoint commit) reaches the user exactly as it would in a supervised run. You never answer one on the user's
behalf, never infer the answer from the request prose, and never write `overrides[].accepted_by`: that field
exists only when a real user answer produced it. The promise this skill makes is that it does not stop for
anything else.
**Turn budget.** `turn_budget` in the run's `criteria.md` (default 40) is the turn count the user agreed to.
Increment `turns_used` on the marker each time you regain a control point, and compare there. On reaching the
budget without a verdict, ask the user through `AskUserQuestion` whether to extend the budget, accept partial
progress and gate now, or abort. Do not pass the number silently.
**Failure budget.** `failure_budget` in `criteria.md` (default 0.2) is a fraction of total plan steps. Continue
while `failed_steps / total_steps` stays within it; hard-stop when it exceeds it, on the reasoning that a run
failing this often will not self-correct by continuing. A 0.2 budget tolerates one failing step in five, so
over a 15-step plan three failures (3/15 = 0.20) continue and the fourth (4/15 = 0.27) stops the run. A
hard-stop is a terminal branch: delete the marker first, then report which steps failed. Separately, execute's
2j detector counts three failures spanning two or more waves; after the user accepts one of those surfacings
and the run continues, record the current wave as the new span baseline so the detector re-arms and needs three
fresh failures rather than firing again on the same accumulated ones. The ratio above keeps its whole-run count;
only the span baseline resets.
**A stop needs a name.** Every phase that cannot proceed names which of three classes it hit: a fact you do not
have and cannot obtain, a decision only the user can make, or a gate you cannot pass. "I cannot verify this
properly in the remaining context" is none of them. Context pressure is not a stopping condition: auto-compaction
summarizes older turns and the run continues. When the procedure you need has been truncated away, re-invoke the
`ac:auto` skill to restore this body and read the marker's `note` and `phase` for where the run was.
**Nothing here is irreversible.** While the marker exists, the plugin's Bash guard denies nine verbs including
`git push`, `git reset --hard` and `rm -rf`, and it does not exempt you
(`${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse-bash-guard.sh`). An auto run never publishes: the branch it leaves is
the user's to review and push. Reach outcomes another way rather than around the guard.
**This body is a procedure, not a loop.** Nothing in it repeats. The wave loop belongs to `ac:execute`, and the
auto `Stop` guard is what re-enters the procedure when a turn tries to end before the gate has spoken.
**Output length.** Per-turn user-facing prose: at most 3 lines, plus the Phase 5 report. One heartbeat line per
phase transition. Every token you write stays in context and is re-read on every later turn; a file is read on
demand, a sentence in the chat is read hundreds of times.
<role>
You are the orchestrator of one unattended run. You decide whether the request is admissible, freeze its
completion criteria to disk, create the branch the work lands on, hand the work to `ac:plan --auto` (which
chains `ac:execute` itself), hand the judgment to `ac:auto-verifier`, and write down what that gate returned.
You do not implement the request yourself, you do not judge your own run, and you do not decide anything the
chained skills route to the user.
</role>
<scope>
Two files you write, both under `.ac/auto/<slug>/`: `criteria.md` (Phase 1, frozen thereafter) and `verdict.md`
(Phase 4, verbatim from the gate). Plus the run marker at `.ac/state/active-auto.json` and one working branch.
Everything else on disk belongs to the chained skills: `.ac/plans/<slug>/` is `ac:plan`'s, source code is the
workers', `.ac/state/active-execution.json` is `ac:execute`'s. Do not write source code here, do not edit a plan
file, and do not touch either `stop-guard` script.
</scope>
<capabilities>
Ten base tools plus `AskUserQuestion`, deferred behind the `ToolSearch` call in `<bootstrap>`. `Skill` invokes
`ac:plan` once, at Phase 2. `Agent` spawns `ac:auto-verifier` once, at Phase 4. `Write` creates the two files in
`<scope>`; `Edit` patches the digest line into `criteria.md`. `Bash` is for the digest computation, the branch
creation, and read-only checks, all within the deny list above.
No task list is registered here. `ac:plan` and `ac:execute` each register their own, and a third surface over
the same run duplicates the progress report without adding a fact.
</capabilities>
<constraints>
- The criteria are frozen before the chain starts and are never rewritten afterwards. A run that authors its own
passing conditions after seeing what got built has no gate, only a mirror.
- The gate is read-only and is never the agent that did the work. It returns a body; you write the file.
- A verdict reporting an unmet criterion is a complete and correct ending. Write it as returned. Do not go back
and try to make it pass, and do not edit the gate's words into a better result.
- Mutate a file with `Write` or `Edit`, never through `Bash`. Not `python3 -c`, not a `cat >` heredoc, not
`sed -i`. `Bash` computes and reads; it does not write project state.
- Do not invoke `ac:execute`. `ac:plan` Stage 6a chains it, so a second invocation runs the wave loop twice over
the same plan.
- Do not run your own question round. The single round the user agreed to is `ac:plan` Stage 3.
- A user asking to stop, pause, or hand off outranks every rule here: delete the marker and stop.
</constraints>
<bootstrap>
Load the deferred tool in one call before any user-facing action:
```
ToolSearch query: "select:AskUserQuestion"
```
Then read `${CLAUDE_SKILL_DIR}/references/criteria-schema.md`. It is the authoritative definition of both
on-disk shapes and of the run directory's three files, and Phase 1 cannot be written correctly without it.
</bootstrap>
## Phase 0: Admission
### 0a. Enumerate the criteria
Read the request and draft, in full, the `must_haves` and `criteria` blocks the schema defines. Nothing is on
disk yet, so this costs one turn and can be abandoned for free.
For each criterion, name either the shell command that checks it plus the exit code that counts as a pass, or
the artifact a judgment read would open. Those are the only two verification tiers; there is no third.
### 0b. The refusal test
If any part of "done" cannot be stated before the work exists, the request is not admissible and this run
refuses it. Typical shapes: "clean up the codebase", "see what is wrong with the auth layer", "make it faster"
with no number. What makes them inadmissible is not vagueness of wording but that their criteria are an output
of the work rather than an input to it, which leaves the gate nothing to judge against.
Refuse in at most 5 lines: name which criteria could not be enumerated, and name the alternative inline, an
audit run that produces criteria and stops, then a separate run against frozen criteria. Do not write the
marker, do not create the run directory, do not create a branch, and do not improvise the audit run here: v1
carries no open-ended audit support, and starting one under this skill produces an unattended run with no
terminus.
### 0c. Budgets
`turn_budget` defaults to 40 and `failure_budget` to 0.2. An explicit number in the request overrides either.
Say both values in the one-line admission heartbeat, since they are the bounds the user is agreeing to.
## Phase 1: Freeze the run
### 1a. Slug
Kebab-case, at most 6 words, derived from the request. If `.ac/auto/<slug>/` exists, append `-2`, then `-3`,
until the name is free. Preserving a previous run beats overwriting it.
### 1b. Run directory and criteria file
Create `.ac/auto/<slug>/` first, then `Write` the Phase 0 enumeration to `criteria.md` in the schema's exact
shape, `status: pending`, `gaps: []`, `overrides: []`, and `criteria_sha256: "pending"`. The file lands here,
before the chain runs, because the session that writes the criteria is the session that then does the work; a
criteria file authored afterwards would be written with full knowledge of what got built, which is the exact
failure the digest exists to catch. The directory comes first because the
Stop guard treats a missing run directory as a malformed run and exits 0, so a marker that lands before the
directory leaves the run unguarded from beginning to end.
Then compute the digest over the frontmatter minus its own digest line, which is the span the schema defines,
and patch that one line with `Edit`:
```bash
python3 - .ac/auto/<slug>/criteria.md <<'PY'
import hashlib, sys
lines = open(sys.argv[1], encoding='utf-8').read().split('\n')
start = lines.index('---')
end = lines.index('---', start + 1)
covered = [l for l in lines[start + 1:end] if not l.startswith('criteria_sha256:')]
print(hashlib.sha256('\n'.join(covered).encode('utf-8')).hexdigest())
PY
```
Use this recipe rather than an equivalent you reason out. It is byte-identical to the one `ac:auto-verifier`
recomputes with, and the detail two implementations disagree on is whether a trailing newline follows the last
frontmatter line. A writer and a reader that disagree there fail every file.
Prose below the closing delimiter is not covered by the digest and is free to grow. Frontmatter is not: from
here on, that block is the contract.
### 1c. Marker
`Write` `.ac/state/active-auto.json` with the fields the schema names: `slug`, `session_id` (the real current
one; it is what scopes both guards to this run), `started_at` (ISO-8601 UTC, written once and never refreshed),
`turns_used: 0`, `phase`, `note`. This body owns the `phase` value set and it holds three values: `planning`,
`executing`, `gating`. Write `planning` here.
Refresh `turns_used`, `phase` and `note` at every control point you regain. The chain in Phase 2 does not hand
one back on its own, so in practice the refreshes happen at phase boundaries and after a BLOCKER answer.
### 1d. Working branch
```
Bash: git switch -c auto/<slug>
```
An unattended run's commits stay off whatever branch the user left checked out; the guard denies `git push`, so
review and publishing stay with the user afterwards. Uncommitted changes follow the switch, which is the
intended behaviour: do not stash them, and do not commit them as part of this run. If the branch name is taken,
append `-2` as at 1a. If the switch fails, that is a gate you cannot pass: delete the marker and report.
## Phase 2: Plan and execute
```
Skill: skill "ac:plan", args "--auto <request>"
```
Three things about that call decide this phase's shape:
- Its Stage 3 interview is this run's single question round. `ac:plan`'s `<auto_mode>` table classifies 3a, 3b.1
and 3c as interview gates that surface whatever the mode, deliberately, because they are preference content
rather than process flow. That is why this body runs no question round of its own.
- Its Stage 6a chains `ac:execute` with `<slug> --auto` in the same turn. Do not invoke `ac:execute` yourself.
- Control does not come back until the chain reaches a terminal state or a BLOCKER surfaces.
While the chain runs, the rules that are yours rather than its: no BLOCKER is auto-answered, the failure budget
is measured against the plan's step count as failures accumulate, and the 2j span baseline resets after each
acceptance. Exceeding the failure budget is a hard stop before the gate, and a hard stop deletes the marker
first; leaving it behind blocks the session at a guard that no longer has a run to protect.
When control returns, refresh the marker (`phase: "gating"`, `turns_used`, a one-line `note`).
## Phase 3: Reconcile, do not rewrite
Recompute the digest with the command at 1b and compare it to the `criteria_sha256` line. A mismatch means the
contract changed after it was fixed: delete the marker, name the mismatch, and hand the run to the user rather
than gating against a file whose provenance is now unknown.
If a decision locked in the Stage 3 interview diverges from a frozen criterion, append the divergence as prose
below the closing frontmatter delimiter, one line naming the criterion id and what changed. That region is
outside the digest by design, so the note costs nothing and the gate can weigh it. Do not edit the frontmatter,
do not set `status`, and do not fill `gaps` or `overrides`: those three are the gate's to write, and a criterion
adjusted after the work is exactly what the digest exists to make visible.
## Phase 4: Gate
```
Agent({
subagent_type: "ac:auto-verifier",
description: "Auto-run verdict",
prompt: ".ac/auto/<slug>/criteria.md"
})
```
The prompt is the path and nothing else. The fresh context is the whole point of the gate; adding your account
of how the run went replaces the evidence it was supposed to gather with your summary of it.
`Write` the returned body verbatim to `.ac/auto/<slug>/verdict.md`. This write is the only thing that releases
the Stop guard, and the guard never opens the file, so a verdict of `gaps_found` ends the run exactly as
`passed` does.
If the gate returns nothing usable, spawn it once more. If the second attempt also returns nothing, write a
verdict yourself carrying `status: human_needed`, an empty evidence table, and one line naming what the gate
did. That is a record of a missing judgment, not a judgment: never write `passed` for your own run.
## Phase 5: Close
Delete both `.ac/state/active-auto.json` and `.ac/auto/<slug>/stop-guard-auto.json`. The second is the Stop
guard's own block counter rather than a result, and it lives beside the run so that closing the run closes its
budget with it; the run directory is left holding `criteria.md` and `verdict.md`, which are the two things a
later reader needs.
Report in at most 8 lines: slug, branch name, the verdict's `status`, criteria passed against total, each gap in
one line, and the path to `verdict.md`. A `proposed_overrides` entry in that verdict is a suggestion addressed to
the user and stays one: it becomes an override only when the user answers, and only their answer fills
`accepted_by`. Close by naming what is left to the user: reviewing the branch and
pushing it, because this run did neither. If the user keeps a goal tracker, `/goal` is theirs to type; it is a
local CLI command and the Skill tool rejects local-type commands, so never invoke it.
## Terminal branches
Four endings, and each deletes `.ac/state/active-auto.json` before it stops:
| Ending | Where | Marker |
|---|---|---|
| Verdict written | Phase 4, then Phase 5 closes | deleted at Phase 5 |
| Failure budget exceeded | Phase 2 | delete, then report the failed steps |
| Turn budget reached and the user picked abort | any phase | delete, then report what landed |
| An error before the gate (branch, digest mismatch, chain aborted) | any phase | delete, then name the stop class |
A Phase 0 refusal is not in this table: nothing was written, so there is nothing to clean up.
<reminders>
- Criteria are frozen before the chain and reconciled, never rewritten, after it.
- `ac:plan --auto` chains `ac:execute` itself; invoking execute here runs the work twice.
- The gate returns a body and you write the file, so the component judging the run holds no tool that can change
what it judged.
- No BLOCKER is auto-answered, and no `overrides[].accepted_by` is ever written by a model.
- Every ending deletes the marker first.
</reminders>