Governed autonomous agent operation. This plugin is the capability-distribution home for the AI-adoption-ladder contract set: it ships the tool-agnostic contracts an adopting org binds to its own repositories, tools, and policies, plus a guided-setup skill that discovers the org's state and records that binding.
Out of scope: signed agent-run artifact attestation (SLSA-style proof of which prompts and
skills produced a commit); see
docs/out-of-scope/agent-run-artifact-attestation.md.
Node.js on PATH. Every hook row runs through node hooks/exec-bash.mjs, and Claude Code's native
binary neither ships nor uses Node
(setup, fetched 2026-09-29), so without node the hooks
do not launch and the lane-stop gate is not enforced. The setup check reports whether node
resolves. The hooks also use Bash (Git Bash on native Windows) and jq; without jq they fail open.
-
Topology contracts (
reference/): role topology for the repositories an adoption spans, the binding-seam shape that maps contract roles to an org's real instances, and the wiring-vs-advisor principle governing how setup lands changes. -
Telemetry contract (
reference/telemetry.md): standards-pinned OTLP from every execution context, theautonomy.work_item.urljoin attribute, one causal tree by context propagation, sink classes with a zero-cost file-artifact default, plus the setup telemetry slice, its snippet templates, and the emission-conformance check. -
Return-accounting convention (
reference/return-accounting.md): the two human-attested return questions captured as a tracker-resident record at the task boundary of autonomous-class work, joinable to cost telemetry by the join attribute, plus the setup capture slice and its close-boundary templates. Agents prompt and aggregate; they never estimate the human fields. -
Trigger-dispatch contract (
reference/trigger-dispatch.md): four signal-surface classes normalized by adapters into the governed work-item queue under six class-generic obligations, a schema-versioned signal envelope, security-surface work-class stamping, and one dispatch entrypoint (push kick + scheduled drain through the queue seam's race-safe lease), plus the setup trigger/dispatch slice, its adapter and acknowledgment templates, and the signal-envelope conformance check. -
Guardrail matrix (
reference/guardrails.md): five semantic work classes (C1–C5) crossed with six enforcement columns: isolation floor, verification layers, verification topology, merge policy, cost tier, escalation, as one progressive-disclosure hub with on-demand leaves (isolation ladder, work classes, security review, verification topology, admission policy), human-ratified promotion with automatic fail-closed demotion, and a two-surface binding split by governance sensitivity (security axes on the settings-as-code home outside agent blast radius; non-security remaps repo-local), plus the contract-owned security-binding schema and its semantic check, and the setup guardrail slice that detects substrates per surface, live-validates isolation with an in-boundary probe before binding, folds in security-review wiring, and fail-closes autonomous dispatch where noL2substrate exists. -
Standing-routine catalog (
reference/routines.md): the routine classes an adopting org can stand up as governed background maintenance, a progressive-disclosure hub whose glance-layer table classifies every class (judgment, output, access → derived guardrail row) under contract-owned catalog-to-matrix mapping rules, withreference/routines/definition leaves for the v1 subset and the invariant that a routine is a scheduledtemporal-class trigger adapter behind the governed queue, never a private execution or merge path, plus the setup routine slice that discovers scheduling surfaces, wires the free CI-cron/local-scheduler defaults as reviewable changes, homes each routine's work-class mapping on the security surface, and detect-diff-reconciles existing org schedulers and bots instead of duplicating them. -
Routine prerequisite resolution (
reference/prerequisite-resolution.md): fail-closed, per-identity-per-surface verdicts (supported/conditional/unsupported/unknown) for which catalog identities can run against a repository, composing owning seams rather than a new prober, withdeferred(<trigger>)(the row's own join trigger) markingjoin:rows that have no identities yet. Per-identity facts live in eachv1leaf;generated/identity-prerequisites.jsonis the drift-gated emission derived from those leaves (generator underskills/setup/scripts/);skills/setup/scripts/resolve-prerequisites.mjsis the deterministic per-surface resolver; the setup skill's prerequisite-resolution slice (check/apply) consumes it. -
Runner design pack (
reference/runner.md): the architect-ready design contract for the autonomous-drain runner, the composition spine and its eight seams, the lifecycle state model, the two-family stop-criteria taxonomy with terminal-handoff escalation and severity-routed notification fan-out, the matrix-derived launch backend set, and the topology ownership seam map, as a progressive-disclosure hub withreference/runner/leaves. Design only, the build stays gated on the charter's own triggers and the runner-execution home stays unborn; setup records nothing runner-specific beyond the escalation notification routes (severity axis + personal-push tier) bound through the security binding. -
Autonomous-pipeline reminder (
reference/autonomous-pipeline-reminder.md): a drop-in standing reminder for an adopting org's own pipeline, against the two stopping failures a pipeline cannot recover from, a turn ending on unexecuted intent, and a turn stopping to ask permission nobody is there to give. States where it does not apply (an attended lane wants the opposite posture) and what thelane-stop-gatehook does and does not cover of it. One clause deterministically, the rest by instruction alone.Provenance. The clause set is this repository's own wording of guidance in Anthropic's Claude Fable 5 prompting guide, section "Rare cases of early stopping", folded together with the companion checkpoint instruction that section asks to be paired with it (https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5, fetched 2026-08-08). The evidence-before-a-state-changing-command sentence and the recover-instead-of-stopping sentence carry the two behaviors the Claude Fable 5.1 prompting guide adds in its section "Finish the whole task" (https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1, fetched 2026-09-06). Both are authored locally rather than reproduced, per this repository's rule against hand-copying upstream content. The citation lives here rather than in the contract file because
reference/docs are written in surface classes and may not name vendors. Recheck trigger: either section changing its clause set, a later model guide restating this guidance in materially different terms, or a model release that supersedes Claude Fable 5.1. -
Guided setup (
/autonomy:setup): discovery-first interview of the adopting org's state, covering role homes, substrate availability, and budget posture, that writes a schema-versioned binding under.claude/autonomy/as reviewable changes. Never assumes any particular org or repo shape.
Each capability below lands with its own work package. None ships before its contracts are locked: no step-skipping, and trust before scale.
| Capability | Trigger |
|---|---|
| Fleet adapter materializations (reusable workflows, labels, drain routine) | Work-item backlog, post trigger-package graduation. |
| Fleet guardrail materializations (binding instances, workflow gates, scanner wiring) | Work-item backlog, post guardrail-package graduation. |
| Fleet routine stand-up + existing-scheduler reconciliation | Work-item backlog, post routine-package graduation. |
| Vendor-binding capability templates (routine/workflow files) | Build stage, post-architect. |
| Cost enforcement (hard spend caps; cost tiers stay policy vocabulary until then) | 3→4 transition work begins. |
| Runner charter execution pack (design pack shipped) | The runner build trigger fires (charter's own conditions). |
| Trigger | Action |
|---|---|
Role vocabulary changes in reference/role-topology.md |
Update the org-policy home's binding instance doc to the new vocabulary version. |
A second plugin consumes .claude/autonomy/ config |
Graduate the binding schema to a versioned concern contract per the marketplace's concern-named-folder convention. |
| A second repository consumes the security binding | Stand up a mechanical cross-repo binding drift check. |
hooks/lane-stop-gate.sh makes "a lane that stops itself before its goal is met is a bug" a
mechanism instead of a prompt admonition. On every stop attempt of an opted-in lane it does a
deterministic completion self-check; if completion is not explicitly signaled it blocks the first
stop with a re-injected self-check (keep going, or declare done), and if the lane stops anyway it
allows the stop and alerts the operator via hooks/lane-notify.sh (OS toast + terminal bell/OSC 9,
local machine only).
Completion is signaled in two ways (a shell hook cannot re-run the /goal evaluator model): the exact
sentinel token in the agent's final message, or a marker file. The marker is consumed (deleted) when
it authorizes a stop, one marker, one stop, so a file left in the checkout by a prior completed
run never authorizes the stops of a later lane run. The gate is the settings-scoped,
cross-session sibling of /goal's session-only completion condition. Use /goal for a single
session, this gate for a standing lane.
Default OFF, a Stop-blocking hook must never engage for an interactive session.
Config is honored from trusted sources only (#1784). The gate never takes its config off the
bare CLAUDE_PLUGIN_OPTION_* environment: for an unconfigured key, a watched repository's own
.claude/settings.json env block populates that variable freely, and a gate whose enablement (or
sentinel, or marker path) the watched repository controls is not a gate
(docs/conventions/hook-config-delivery). Per-key precedence, mirroring Claude Code's own settings
merge:
- Managed settings (fixed root-owned paths +
managed-settings.d/drop-ins), an org can veto withlane_stop_gate_enabled: false. Server-managed settings are deliberately excluded. Their only on-disk artifact is the user-writable cache~/.claude/remote-settings.json, which fails the root-owned trust test (the page itself calls the channel "a client-side control, not a security boundary"), so an org vetoing via the server channel must also deliver an endpointmanaged-settings.jsonto veto lanes (the gate reads that file directly; Claude Code itself ignores endpoint sources when server keys arrive). - The per-session arm record, the
claude-opslane launcher arms a lane at launch: give the lane asettingsobject requesting the gate in its lanes-config entry (see that skill'scontext/config.md), and the launcher runs this plugin'shooks/lane-stop-gate-arm.sh(writing a record under the plugin's own install-derived data directory) and injects the random record id aslane_stop_gate_arm_idin the session's--settings. The id is a capability pointer, never authority: the gate validates it, honors only its own store, binds it to the first presenting session, and expires it after 7 days. The record is not consumed on a stop, a lane is one session across many/loopcycles, each of whose stops must stay gated, so it lives for the claiming session and is retired by TTL plus the launcher's relaunch sweep. To arm a hand-launched session, run the arm helper from the installed plugin the same way, then pass the id via--settings '{"pluginConfigs":{"autonomy@<marketplace>":{"options":{"lane_stop_gate_arm_id":"<id>"}}}}'. - User
settings.json, located from the hook's own install path, a persistent enable that also gates interactive sessions, which defeats the default-OFF design; prefer the launcher.
A --settings-only lane_stop_gate_enabled=true is not honored; arm a lane through the
launcher instead. That value reaches the hook only as the forgeable env mirror. The gate says so with a visible
notice (once per session and agent, renewed every eighth skip) instead of disengaging silently, which is also how a stale (pre-arming)
lane launcher surfaces. A --plugin-dir checkout install has no trusted user-settings or record
location, so only managed settings can enable the gate there.
It is fail-open (unreadable stdin / missing jq / a SubagentStop never trips it) and bounded
against runaway by the stop_hook_active one-nudge guard plus Claude Code's consecutive-block cap.
It catches a graceful self-stop only: a closed laptop, a killed process, or /loop expiry emit no
Stop event.
When the consuming repo sets HOOK_TELEMETRY_SINK, the gate emits one fire-and-forget envelope per
evaluated outcome (hook: "lane-stop-gate"; payload contract in the marketplace's hook-telemetry
convention, data/lane-stop-gate.schema.json), so premature lane stops are measurable fleet-wide.
The payload is a fixed vocabulary, never the sentinel token, marker path, cwd, or branch.
lane-stop-gate.sh fires on every Stop, so its default path (no gate footprint in any settings
file, which is every interactive session) draws on the 500 ms per-turn ceiling in the marketplace's
hook-budget convention. Counted with strace -f -e trace=clone,clone3,fork,vfork,execve from a
staged install on Linux, 2026-09-06, autonomy 0.23.1 against 0.22.29. Process creations are the
drift-immune proxy #3508 asks for: a spawn costs about 1 ms on the measuring host and 180 to
2,841 ms on the affected Windows hosts, where the wall-clock share the convention binds still needs
measuring.
| Path | Creations before | After | Launches before | After |
|---|---|---|---|---|
Default: no gate footprint anywhere (every interactive Stop) |
4 | 0 | 2 (grep, uname) |
0 |
| Enabled by user settings, first stop, no signal (block) | 48 | 10 | 18 | 5 |
| Enabled, sentinel on its own line (allow) | 44 | 9 | 16 | 4 |
| Enabled, second stop after the nudge (allow, notify) | 54 | 10 | 21 | 5 |
| Enabled, marker file present (allow, consume) | 51 | 12 | 19 | 6 |
| Armed by the launcher, first stop (block) | 60 | 11 | 20 | 5 |
The table counts lane-stop-gate.sh alone, run as bash lane-stop-gate.sh. Through hooks.json
each Stop also starts a node process (hooks/exec-bash.mjs), which spawns that bash, so the
launcher adds one node process to every row. That process, and the threads node starts, are not
counted here.
The default path creates no process: the suite pins 0 creations and 0 launches for the script.
The enabled paths still run uname -s, the managed-settings platform primitive ($OSTYPE is a
variable a repository's env block can set). Of the enabled block path's 10 creations, 4 are
hook::buffer_stdin_to in the synced shared library (its capture, its read-slice probe and its
printf | jq -e validation pass); the hook's own 6 are the one payload jq pass (3),
uname, one settings jq and the block-decision jq. The suite pins these counts by trace where
strace is available.
| userConfig option | Default | Effect |
|---|---|---|
lane_stop_gate_enabled |
false |
Opt this session's lane into the gate. |
lane_stop_gate_sentinel |
LANE-STOP-OK |
Token the agent emits alone on its own line to declare the goal met. |
lane_stop_gate_marker |
(unset) | Marker file whose existence also authorizes a stop (absolute, or relative to the session cwd). Consumed on use. |
lane_stop_gate_arm_id |
(unset) | Launcher-written arm-record id (capability pointer, never authority). Not set by hand. |
lane_notify_enabled |
true |
Master switch for the operator alert. |
lane_notify_os_toast_enabled |
true |
OS-native toast channel (macOS, or Linux with notify-send); no effect on Windows. |
lane_notify_terminal_enabled |
true |
Terminal bell + OSC 9 channel. |
Setup writes tracked config to .claude/autonomy/ in the consuming repo, named for the concern so
the config outlives any plugin restructure. Personal overlays follow the marketplace overlay
convention: the recursive .claude/**/*.local.* line keeps them gitignored; layers resolve per the
binding-seam ladder: user-global → org binding (when pointed) → project → local overlay, additively.
Generated from this plugin's .claude-plugin/plugin.json. Every option Claude Code
will prompt for when the plugin is enabled, with the environment variable each hook
reads it from.
| Option | Type | Default | Environment variable | Description |
|---|---|---|---|---|
lane_stop_gate_enabled |
boolean | false |
CLAUDE_PLUGIN_OPTION_LANE_STOP_GATE_ENABLED |
Opt an autonomous lane into the deterministic Stop-hook completion gate. Default OFF, because a Stop-blocking hook must never engage for an interactive session. Honored from user or managed settings only (the gate reads those files itself); per-session lanes are armed by the claude-ops lane launcher instead. The env mirror is never authority (#1784). |
lane_stop_gate_sentinel |
string | "LANE-STOP-OK" |
CLAUDE_PLUGIN_OPTION_LANE_STOP_GATE_SENTINEL |
The exact token the agent emits in its final message to declare the lane's goal met and authorize a stop. Matched only when alone on its own line. Honored from user/managed settings or the launcher's arm record, never the bare environment. |
lane_stop_gate_marker |
string | (none) | CLAUDE_PLUGIN_OPTION_LANE_STOP_GATE_MARKER |
Optional path to a completion-marker file whose existence also authorizes a stop (absolute, or relative to the session cwd). Empty disables the file signal. Honored from user/managed settings or the launcher's arm record, never the bare environment. |
lane_stop_gate_arm_id |
string | (none) | CLAUDE_PLUGIN_OPTION_LANE_STOP_GATE_ARM_ID |
Written by the lane launcher at launch: names this session's arm record in the plugin's own data directory (hooks/lane-stop-gate-arm.sh). A capability pointer, never authority by itself: the gate validates it, honors only a record in its install-derived store, and binds it to the first presenting session. Not set by hand. |
lane_notify_enabled |
boolean | true |
CLAUDE_PLUGIN_OPTION_LANE_NOTIFY_ENABLED |
Master switch for the operator alert fired when a lane stops without signaling completion. |
lane_notify_os_toast_enabled |
boolean | true |
CLAUDE_PLUGIN_OPTION_LANE_NOTIFY_OS_TOAST_ENABLED |
OS-native desktop toast for the lane-stop alert: macOS (osascript) or Linux (requires notify-send). No effect on Windows, where the terminal channels carry the alert. |
lane_notify_terminal_enabled |
boolean | true |
CLAUDE_PLUGIN_OPTION_LANE_NOTIFY_TERMINAL_ENABLED |
Audible bell + OSC 9 notification written to the controlling terminal for the lane-stop alert. |
verification_lens_pool |
string | "specification,adversarial,contract,regression,evidence" |
CLAUDE_PLUGIN_OPTION_VERIFICATION_LENS_POOL |
Ordered, comma-separated pool of verification lenses the model-adjudicated checker slots draw from, one distinct lens per slot, in pool order. Tokens come from the closed vocabulary in the verification-topology contract leaf; an unrecognized token is recorded as unresolved and draws no lens, and a pool shorter than a class's model-adjudicated slot count leaves the remaining slots unlensed rather than repeating a lens. The pool contributes to no count: how many checkers a class runs, how they must differ, and whether one must be cross-vendor are floors on the org's security binding, outside this setting's reach. |
visual_narration_enabled |
boolean | false |
CLAUDE_PLUGIN_OPTION_VISUAL_NARRATION_ENABLED |
Run the advisory visual narration lane: strictly downstream of deterministic detection, it writes a plain-language account of a difference the deterministic layer already found and attaches it to the run record for the human gate. Advisory only: it emits no verdict, fills no checker slot, is counted by no floor, and never gates a transition; no cell anywhere names it as authority. Default OFF: it is inert without an upstream deterministic comparator, and each narrated artifact is a metered vision-model call. |
Three supported routes, in the order most people want them:
-
Interactively. Claude Code prompts for declared options when you enable the plugin. To change them later:
/plugin configure autonomy@<marketplace>. -
Headless. Repeat
--configfor each option. Replace<marketplace>with the marketplace you installed this plugin from:claude plugin install autonomy@<marketplace> -s <scope> --config lane_stop_gate_enabled=<value>
The same command reconfigures a plugin that is already installed: it prints
already installedand still writes the value. The short-circuit message is about the install, not the config write. Do notclaude plugin uninstallto reconfigure: uninstalling drops this plugin's whole storedpluginConfigsentry, resetting every option in the table above to its default.-sdefaults touser, so pass the scopeclaude plugin listreports for this plugin. The verified-version record lives in this marketplace's plugin-reconfiguration convention (docs/conventions/plugin-reconfiguration/README.md).The value is stored immediately; the session you are in does not change. Hooks are handed their
CLAUDE_PLUGIN_OPTION_*when the session starts, so start a fresh Claude Code session before expecting new behavior. A check run in the old session still reports the old value, and that is not a failed write. -
By hand, in settings. Add the value under
pluginConfigsin your user settings (~/.claude/settings.json):{ "pluginConfigs": { "autonomy@<marketplace>": { "options": { "lane_stop_gate_enabled": <value> } } } }Plugin option values are read from user,
--settings, and managed settings only, not from a project's.claude/settings.json. To vary behavior per repository, enable or disable the plugin in that project'senabledPluginsinstead of setting an option there.
Do not set the CLAUDE_PLUGIN_OPTION_* variables yourself. They are how Claude Code
hands a configured value to a hook process; the value comes from the routes above.
- User configuration: the
userConfigschema and theCLAUDE_PLUGIN_OPTION_<KEY>export - Plugin install options: the
--configflag's reference entry - Plugins and skills settings:
enabledPlugins,extraKnownMarketplaces,pluginConfigs - Settings files and who they affect: user vs project vs local precedence
- Manage installed plugins: enabling, disabling,
/plugin list