Skip to content

Automation Level Behavior Guide

Reference for how commands and skills should adjust interaction ceremony based on the active automation level. The big-picture description of each level (and how to switch) is in project-orchestration-handbook.md §7.1; this doc is the per-decision behavior table. Warp-drive's level-specific behavior is in the handbook §7.2 and warp-drive.md. For how the different loop archetypes (crons, retries, evaluator-gated loops, self-directing agents) map onto this trust scale, see the Loop Taxonomy & Trust Model.

Detection

Read .claude/settings.local.json in the project directory. Look for _automation.active_level (1, 2, 3, or 4). If not found or the file doesn't exist, default to Level 1. An absent or unrecognised value never resolves to Level 4 — full-auto is only ever active when active_level is explicitly 4 and the full-auto profile is present.

Level Principles

Level 1 — Supervised (default)

  • Ask before every decision
  • Show all options with explanations
  • Wait for explicit confirmation before acting
  • This is identical to pre-automation behavior

Level 2 — Trusted Dev

  • Auto-proceed on safe, inferrable, or reversible decisions
  • Still confirm destructive operations (force push, delete, overwrite)
  • Still ask for subjective content (summaries, descriptions, priorities)
  • Show each auto-decision inline as it happens

Level 3 — Autonomous

  • Minimize prompts — only stop for destructive ops or subjective content
  • Auto-infer from git context, branch names, file paths, commit history
  • Batch auto-decisions into a summary rather than inline notifications
  • Ask for: rebase conflicts, subjective writing, destructive operations

Level 4 — Full-Auto

  • A superset of Level 3: everything L3 auto-approves, L4 auto-approves too.
  • Decisions are resolved by reversibility, not escalated by default. A reversible (two-way-door) decision is auto-made — biased toward the most reversible option — and recorded as a decision issue. An irreversible (one-way-door) decision — spending money, a public contract, deleting data, external comms, prod deploy past the ceiling — is never auto-resolved: it notifies and waits, or stops.
  • The wait is bounded by decision_timeout_minutes (default 10), governed by the decision-timeout policy: on timeout with no reply a one-way door is deferred (skip it, keep working) or stops cleanly if it blocks everything — never a guess. 0 means never wait ("work around or stop"); with RDB off, "notify" degrades to a filed TODO with a defer default.
  • Inherits the L3 always-blocked floor and an irreversible-action floor, both carried by the full-auto profile (profiles/full-auto.json, delivered in #867).
  • Requires a cost ceiling to start (#879). A Level 4 run refuses to launch without a spend ceiling — --budget <usd> / --max-tokens <n> at kickoff, or _workflow.max_session_usd / max_session_tokens in config — so an unattended run is never uncapped. The existing cost breaker enforces it (no new breaker); a cost estimate is surfaced at kickoff. See Kickoff Flags.
  • Requires that profile to be present; until it is, /automation level 4 safely refuses and leaves the level unchanged.
  • The full-auto behavior (reversibility decision engine, in-session QA loop, session segmentation, decision budget) is built out under capability #865; this entry documents the level itself. The decision classification and promotion matrices below carry an L4 column so the full-auto behavior is documented where L1/L2/L3 are.

Transparency Format

Commands must show what was auto-decided so the user stays informed.

Level 2 — inline per decision:

> Auto (L2): Branch type set to `tooling/` (inferred from .claude/ changes)
> Auto (L2): Stashed 2 uncommitted files

Level 3 — batched summary:

> Auto (L3) decisions:
>   - Branch type: `tooling/` (inferred from .claude/ changes)
>   - Stashed 2 uncommitted files
>   - Branch name: `tooling/automation-behavior`

Decision Classification

CategoryL1L2L3L4 (full-auto)
Safe + inferrableAskAuto, showAuto, showAuto, show
Reversible actionAskAuto, showAuto, showAuto-decide + record decision issue
Subjective contentAskAskAskNotify-and-wait (one-way; never auto-resolve)
Destructive operationAskAskAskBlocked by the floor; escalate (one-way)
Push to remoteAskConfirmAuto (except main/master)Auto (prod past ceiling is a one-way door → blocked)
Conflict resolutionAskAskAskAuto if trivial; else escalate
Requirement/AC trackingAskAuto-update, showAuto-update, showAuto-update, show
Documentation housekeepingAskAuto-update, showAuto-update silentlyAuto-update silently
Warp-drive continue to next taskAskAskAuto-continue, logAuto-continue (bounded), log
Warp-drive plan reviewAskAskAuto-proceed, logAuto-proceed, log

Level 4 formalizes the "Reversible action" row into an enforced engine. Where L2/L3 treat reversible actions as auto-and-show, L4 classifies every decision one-way (irreversible) vs two-way (reversible) via the reversibility decision engine (scripts/warp-drive/decision-engine.js, #871) and acts on the classification: two-way doors are auto-decided and recorded as decision issues (options considered + rationale); one-way doors notify-and-wait or stop and are never auto-resolved. An unrecognized decision defaults to one-way — the engine never guesses a one-way door. The irreversible categories are exactly the ones the full-auto floor denies at the tool level (money-spend, external comms, destructive data ops, prod deploy past the ceiling, history loss); the engine is the semantic layer above that floor. See the Reversibility Decision Engine reference.

Autonomous profile — auto-approved vs always-blocked (#420)

Level 3 (the autonomous profile, profiles/autonomous.json) is the only level designed to run unattended — including overnight. Because nothing prompts, "what exactly is this allowed to do while I'm asleep?" needs a documented answer. This is it.

When to use it vs. interactive defaults. Use L3 only for a scoped, version-controlled repo where every change is recoverable from git and you have reviewed the work queue — e.g. an area:-scoped warp-drive batch of approved requirements. Stay at L1/L2 (interactive) for exploratory work, anything touching production credentials or external services by hand, or a repo whose state you are not ready to have advanced without review. L3 trades the per-action prompt for an after-the-fact audit trail (below) — that trade only pays off when the queue is trusted and the blast radius is git.

Auto-approved at L3 (no prompt): reads, search, edits/writes, Bash, the dev/test/commit/push/merge skills, Playwright, WebFetch/WebSearch, and push/merge to main/master (subject to the promotion ceiling — a pr ceiling still caps L3 at a pull request).

Always-blocked at L3 (denied even though everything else is auto-approved) — three layers, each entry carries a rationale in profiles/autonomous.json_meta.deny_rationale:

LayerBlocksWhy
Destructive-git floorgit push --force, git push origin --force, git reset --hard, git branch -D, rm -rfIrrecoverable history/working-tree loss. This floor is a deliberate guardrail and is never loosened — see the autonomous-deny-destructive-git guardrail.
Secrets / credential reads.env / .env.*, *credential*, ~/.ssh, ~/.aws, ~/.config/gcloud, ~/.kube, ~/.npmrc, ~/.netrc (via both Read and shell cat)An unattended run has no legitimate reason to read raw secret stores; blocking them shrinks the exfil surface.
Network-exfil shapescurl -T / --upload-file, curl -d @file, pipe-into-curl/wget, wget --post-fileThe obvious "send a local file to a remote host" shapes.

Honest limitation. The secrets/exfil blocks are defense-in-depth, not a sandbox. Bash is broadly allowed, so a sufficiently creative shell command can still read a file or reach the network — the deny patterns only catch the obvious shapes. The real backstop for an unattended run is the audit log, not the deny-list.

Audit log

When _automation.active_level is 3 (autonomous) or 4 (full-auto), the autonomous-audit-log.sh PreToolUse hook records every auto-approved tool call — tool, target, timestamp, session, cwd — as one JSONL line per call. A full-auto run is at least as autonomous as L3, so it is audited on the same trail (#882):

  • Location: ~/.claude/logs/autonomous-audit/<session-id>.jsonl (override with $BOB_AUTONOMOUS_AUDIT_DIR).
  • Per session: one file per Claude Code session, so an overnight run is one reviewable trail.
  • Recorder, never a gate: it always exits 0 and never blocks — it only observes.
  • Strict no-op below L3: at L1/L2 (and outside BoB projects) it reads one settings field and exits, so it cannot affect interactive or Trusted-Dev runs.

To review an unattended run afterwards: jq -r '"\(.ts) \(.tool) \(.target)"' ~/.claude/logs/autonomous-audit/<session>.jsonl.

So — is it safe to leave running overnight? For a scoped, git-backed repo with a reviewed queue: yes — irrecoverable git ops, secret reads, and obvious exfil are blocked, and everything auto-approved is captured in the audit log for morning review. It is not a substitute for a sandbox on an untrusted workload, and the promotion ceiling still governs how far work is actually promoted.

Decisions digest (#877)

The audit log above is the tool layer — every auto-approved tool call ("what did it touch?"). Sitting above it is the decision layer: at Level 4 the reversibility decision engine records each auto-made two-way-door decision as a decision issue and an entry in the in-state decision log (state.decisions[]). At session_ending warp-drive aggregates that log into a decisions digest and includes it in the session-summary issue, so the whole autonomous run is reviewable — and cheaply reversible — from one place:

  • Each decision is listed with its reversibility class and a link to its decision issue (options considered + rationale) for one-place review/reversal — revert any that look wrong (revert the commit / re-open the choice).
  • The digest cross-links the tool-level audit log (this section) but is distinct from it: the audit log answers "what was touched?", the digest answers "what was decided, and can I undo it?".
  • Generated by state-machine.js decisions-digest (pure renderer: scripts/warp-drive/decisions-digest.js); on a run with no auto-decisions it still emits an explicit "nothing to review" block so the absence is recorded, not silent.

Full-auto profile — the irreversible-action floor (#867)

Level 4 (the full-auto profile, profiles/full-auto.json) is a superset of Level 3: it inherits the autonomous allow-list and the entire always-blocked floor above verbatim (the destructive-git floor is never loosened), then adds a fourth deny layer for irreversible, one-way-door actions — the things a full-auto run must never do unattended:

LayerBlocks (representative shapes)Why
Destructive data opsDROP DATABASE, DROP TABLE, TRUNCATE TABLE, dropdbData loss is irreversible — a one-way door.
Prod deploy past ceilingwrangler deploy --env prod / --env productionA production release is a one-way door; the promotion ceiling owns this, the deny is defense-in-depth.
External communicationssendmail, mail, mailxAn unattended run must not contact the outside world on its own.
Money-spend / paid resourcesstripe, gcloud billing, aws … purchase…Spending real money is irreversible.

Every deny entry carries a _meta.deny_rationale, and the layer is enforced by the same native permissions.deny mechanism as the L3 floor plus the existing promotion-ceiling-guard hook — there is no parallel enforcement mechanism.

Honest limitation (same as L3). These deny patterns are defense-in-depth, not a sandbox — they catch the obvious command shapes, not every semantic variant of "spend money" or "message the outside world." The real backstops for full-auto are the reversibility decision engine (one-way-door decisions notify or stop; #871), the promotion ceiling, and the per-session audit log. The floor is the guardrail of last resort, not the primary control.

Promotion ceiling (#448)

The automation level governs how much autonomy the agent has. It used to also decide how far work is promoted — the two were fused: Level 2 ≡ "open a PR", Level 3 ≡ "merge to master". That made "run fully autonomously, but never push past a PR" impossible to express.

A project's promotion ceiling (dev.jsonpromotion.ceiling, default external) decouples those axes. The merge/deploy decision becomes f(automation_level, ceiling), computed by the shared library scripts/promotion/promotion.js and enforced everywhere — warp-drive's merging phase, /finish-work, and the promotion-ceiling-guard PreToolUse hook. View or set it with /promotion.

Git action (merge) — f(level, ceiling):

Ceiling ↓ \ Level →L1L2L3L4 (full-auto)
prPRPRPR (capped — never auto-merges to main)PR (capped — same as L3)
external (default)PRPRdirect merge to maindirect merge to main
testPRPRdirect merge to maindirect merge to main
prodPRPRdirect merge to maindirect merge to main

Deploy action — f(level, ceiling):

Ceiling ↓ \ Level →L1L2L3L4 (full-auto)
prnonenonenonenone
external (default)nonenonenone (git only — deployment is out-of-band)none (git only)
testnonenonedeploy to testdeploy to test
prodnonenonedeploy to proddeploy to prod

The default external reproduces the legacy fused behavior exactly (L3 → direct merge + no deploy, L2 → PR), so a project with no promotion block is unchanged. Setting a ceiling only ever narrows (pr) or extends (test/prod) from that baseline. Deploy adapters that execute the test/prod deploy land in #450; until then a non-external deploy action is a recorded intent, not yet an executed deploy.

L4 promotes exactly as far as L3 — the ceiling governs reach, not the automation level. Because Level 4 is a superset of Level 3, its git/deploy columns match L3 cell-for-cell: the promotion ceiling is the single axis that decides how far work is carried, and it caps L4 the same way it caps L3 (a pr ceiling still stops at a pull request). What L4 adds is enforcement above the matrix, not reach beyond it: a deploy or merge past the ceiling is an irreversible one-way door, refused by the reversibility engine and the full-auto floor (prod-deploy-past-ceiling), never auto-resolved. So L4 never promotes further than L3 — it only removes the human at the wheel within the ceiling.