mode-autonomous
Skill1 starsChanged 3 months agoMITView on GitHub
The autonomous implementation driver (/foundry:mode-autonomous). WRAP composing the native /loop (outer session cadence) + the foundry-release-wave Workflow (per-wave fan-out) + the native merge floor (ci.yml + btb-gates). Replaces impl-wizard's impl-progress.yaml wave-state with the Workflow journal + native scheduling. Trigger to drive an authorized release's atoms toward merge (the auto-merge grant was RESTORED 2026-08-13 by operator decision, bounded by the git-discipline hook's checks-green clause — --admin stays blocked outright and a plain merge needs every check passing). NOT /foundry:command-deck, which is the PROGRAMME-level clock — a recurring watcher armed over one release that re-measures, dispatches and reports once per tick; reach for this one when you are driving an already-authorized release's atoms through implementation right now, and for the command deck when you want a programme watched unattended.
In this repository71 other files it gives its agents.
- AGENTS.mdAGENTS.md
- llms.txtllms.txt
- amendSkill
- auditSkill
- authorize-releaseSkill
- authorizeSkill
- certify-localSkill
- certify-stagingSkill
- coherence-checkSkill
- command-deckSkill
- contextSkill
- cut-releaseSkill
- dashboards-as-codeSkill
- data-tier-cutoverSkill
- decommission-gateSkill
- deploy-statusSkill
- dispatchSkill
- doctorSkill
- drift-sweepSkill
- env-hygieneSkill
- extract-specSkill
- fleetSkill
- grounding-conformanceSkill
- id-applySkill
- id-architectSkill
- id-baselineSkill
- id-discoverSkill
- id-documentSkill
- id-driftSkill
- id-impactSkill
- id-implementSkill
- id-importSkill
- id-planSkill
- id-promoteSkill
- id-reviewSkill
- id-rollbackSkill
- id-simulateSkill
- id-syncSkill
- id-testSkill
- id-validateSkill
- id-verifySkill
- indexSkill
- infra-sandboxed-applySkill
- initSkill
- intakeSkill
- learn-captureSkill
- learn-distillSkill
- merge-when-greenSkill
- mode-interactiveSkill
- modeSkill
- post-upgradeSkill
- releaseSkill
- relockSkill
- report-citation-graphSkill
- reposSkill
- research-captureSkill
- research-firstSkill
- revertSkill
- sd-debugSkill
- sd-discoverSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 109
Every dispatched atom's worktree/branch shape, PR target, and delete-after-merge timing are one self-contained block, authored once at …
- Very specific: line 111
Read it before landing an atom's PR: it is what decides whether the target is main or the release's release/<version> integration branch …
- Distinctive: line 222
Recommend against interest: When the evidence does not support what was asked for, say so and give the strongest case for the rejected …
- Distinctive: line 226
Correct the record where it lives: When a later finding falsifies an earlier one, amend it at its source with the superseded text struck …
- Distinctive: line 230
Relax no floor; grant yourself no authority: Never widen an authorized surface to close a finding: park it, with its tradeoff and what …
- Very specific: line 247
Precondition: every atom in the release is state AUTHORIZED (the front-authorization gate).
- Distinctive: line 280
Closeout: when every atom is merged + walked.
- Very specific: line 290
10.15 hours: WHEN the session posture is an autonomous lane AND fork_policy=two-way-auto (resolved via python3 …
- Very specific: line 319
WHEN fork_policy=park (the default) or the session posture is not an autonomous lane, every fork parks for the operator exactly as today — …
- Very specific: line 323
Every auto-answer is appended, append-only, to .foundry/auto-answers.jsonl (interim surface for the next operator touchpoint, pending the …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/foundry:mode-autonomous
The autonomous driver. Replaces the bespoke impl-wizard
wave-state engine (impl-progress.yaml — the
silent-halt source) with native primitives:
- outer cadence → native
/loop(orScheduleWakeup): one tick per wave; the loop survives session boundaries and resumes from the durable state (the release manifest + the native-floor verdicts — theci.ymlbattery +btb-gates), not an uncommitted YAML counter. - per-wave fan-out → the native
Workflowtool viaworkflows/release-wave.js(implement → verifypipeline, journaled,resumeFromRunId). SINGLE-REPO only. For a MULTI-REPO release (atoms whose authorized contracttarget_repois a product-repo KEY), theWorkflowsandbox cannot write the per-spawn dispatch manifest, so drive the wave as per-atom/foundry:dispatchon the/loopcadence (each writes its manifest before the spawn); theWorktreeCreatehook redirects the worker into the product repo and the native floor (ci.yml + btb-gates) runs against that product repo's own PR. See/foundry:dispatch→ Multi-repo dispatch. NativeWorkflow/Agentfan-out is the unconditional DEFAULT (feat-foundry-dispatch-on-native- workflow, AC-DNW-1/-2); the bespoke process-spawn fallback (foundry-fanout/foundry-spawn-worker+ theFOUNDRY_DISPATCHswitch) was REMOVED — the driver has exactly one path. merge authority → an earlier realignment release: the former
noninteractiveauto-merge grant was WITHDRAWN (see the 2026-08-13 restoration below). The merge-gate PASS verdict it hinged on no longer exists — the merge signals are now the native floor (ci.yml's pytest battery + graph selftests + doctor, plusbtb-gates'spec-link/security-pathchecks), which is server-side required on this repo'smain. The earlier claim here — that a preflight found branch protection unavailable on this plan — was STALE; protection is applied. It is CLASSIC protection rather than a ruleset, soscripts/foundry_tier_preflight.pyreads it asTIER-B (classic-protection): unverifiable from a read-only token, NOT advisory. The exact required set is deliberately NOT restated here —skills/init/SKILL.mdstep 5 is the single source, and a live configuration copied into two files is a claim that rots in one of them. Server-side checks are still not a grant of unattended self-merge — they bound what CAN merge, not who DECIDES to: the operator merges, or an agent merge is governed byhooks/foundry-git-discipline.sh's deterministicghclause (gh pr merge --adminis BLOCKED outright; a plaingh pr merge <n>is allowed only whengh pr checks <n>reports every check passing). The auto-merge grant remained WITHDRAWN until 2026-08-13 — see the restoration immediately below. Restoring it was an authorization change, not a consequence of this correction, and it is the operator's to make — seedocs/merge-floor.md.RESTORED 2026-08-13 (operator decision, recorded in the command-deck-watcher authorization). The auto-merge grant is RESTORED, bounded by the
ghclause above rather than by anything new:--adminstays blocked outright, and a plaingh pr merge <n>is allowed only whengh pr checks <n>reports every check passing. The driver may therefore land its own atoms on an affirmative success conclusion from the forge for the head commit — and on nothing else. An absent, empty, pending,neutralorskippedconclusion is NOT evidence, and neither is any result the worker that produced the commit reports about itself (feat-foundry-fleet-command-deck-watcher, AC-CDW-10).AC-CDW-10 IS STRICTER THAN THE HOOK, AND THAT GAP IS THE DRIVER'S TO CLOSE. The hook blocks on a non-zero
gh pr checksexit or anyfail/pendingrow — butgh pr checksexits 0 when every check isskippedorneutral, and neither word matches its convicting pattern. So a PR whose required contexts were all skipped (apaths-ignorefilter, say) passes the hook having run nothing. The hook is the floor, not the ceiling: before merging, callfoundry_command_deck.may_land(<conclusion>)and land only onsuccess. The empty-check-set case is the one the hook does cover — a repo with no CI makesgh pr checksexit non-zero, the clause refuses, and the merge is correctly the operator's.
The tick contract (feat-foundry-fleet-command-deck-watcher)
The driver above says WHAT to compose. This says when to wake, what a tick does, and when there is nothing to do — the part whose absence made it run once in thirty days while 37 of 52 resumes were the agent stopping silently after finishing work.
Resolve the programme first. /foundry:command-deck <programme> — or this skill invoked with a
programme name. Resolution goes through scripts/foundry_command_deck.py, which delegates to
foundry_release.load_release (slug-only, containment-checked). Given no programme that resolves to
exactly one release manifest, list the in-flight programmes and drive nothing — never guess, because
ready_set auto-starts what resolution returns and a near-miss name would start a different
programme's atoms unattended.
Each tick, in order:
- Census. Re-derive the ready-set:
foundry_command_deck.ready_set(...). It is recomputed every tick from the manifest and the Task graph, so an atom that becomes ready on the hundredth tick is in the hundredth tick's set. It excludes any atom whose contract does not re-derive as authorized, and it respects the wave barrier, so file-overlapping atoms never start concurrently. - Act on completion in the same tick. A finished worker is verified, landed, or followed up in the tick that observes it — never noted for later.
- Reconcile the native Task graph. It is the run state, together with the release manifest it is regenerable from. Regenerate it only when it is absent: a present graph's transitions ARE the started-ness, and regenerating a present graph destroys them. Build no second tracker.
- Start what is ready, up to the wave barrier.
- Emit one executive status: what was accomplished, what is next, what is blocking. Terse, imperative, once.
- Schedule the next wake.
foundry_command_deck.wake_seconds(...). Harness-tracked work re-invokes the session on completion, so polling for it is waste — use the long fallback heartbeat (>= 1200s) to survive work that hangs or never notifies. Use a matched, shorter interval only for state the harness cannot observe (a deploy, an external queue). When both are awaited, the shorter wins. A PR's checks are NOT this case — never wake early to hand-pollgh pr checksyourself; arm/foundry:merge-when-green <pr> --release <id> --watch(skills/merge-when-green/SKILL.md) and let its nativeMonitornotify the session on the next state change instead.--release <id>is auto-derived when omitted (the single active release's own manifest), but name it explicitly here — the driver already knows which release it is landing. - Idle honestly. A tick is idle iff the ready-set is empty AND no worker is running —
foundry_command_deck.is_idle(...), a predicate, not a judgement. On an idle tick say so in one line and stop. Create, dispatch and record nothing. This is load-bearing, not politeness: a loop with nothing to do invents work to look busy, and a fabricated task in a governance programme is worse than an idle tick.
Branch and worktree discipline
Every dispatched atom's worktree/branch shape, PR target, and delete-after-merge timing are one
self-contained block, authored once at context/branch-discipline.md — cited here, never copied.
Read it before landing an atom's PR: it is what decides whether the target is main or the
release's release/<version> integration branch (/foundry:merge-when-green refuses the wrong
one), and when the worktree/branches are safe to delete.
Landing, and what counts as evidence
Land on the forge's own affirmative success conclusion for the head commit and on nothing else —
foundry_command_deck.may_land(<conclusion>), which returns true only for success. The
git-discipline hook is the floor, not the ceiling: it admits a PR whose checks were all skipped or
neutral, because gh pr checks exits 0 for those. Closing that gap is the driver's obligation, not
the hook's. A task notification, a tool result, or your own prior message is never evidence that
checks passed, and never operator consent. Wait via /foundry:merge-when-green <pr> --release
<id> (skills/merge-when-green/SKILL.md), never a hand-rolled sleep-then-poll loop — it polls
the same live queries and merges through the same already-permitted gh pr merge --squash shape
the instant they go green, and escalates once (with evidence) rather than spinning forever when no
check will ever report.
Merged is not applied. An atom with a live surface is not complete while the deploy observation for
its merged commit reports the artifact stale or not rolled (/foundry:deploy-status, which already
cross-checks deployed-artifact identity against the expected merged commit). Report the two states
distinctly; an SCP was once coded, reviewed, gated and merged and was still not in effect days later.
Walk preconditions to ground before promising a completion. The declared dependency list is not the precondition list — an apply reported "one command away" was not, because the state backend it needed sat in a different, still-open, red PR.
Handing a command to the operator
Consult .foundry/permissions.yaml FIRST, before surfacing any permission request
(feat-foundry-authorization-standing-grants-as-policy, AC-SGP-5). The operator's standing grants —
"proceed on green CI," "drive this forward" — live there, one file the operator edits and the
agent never does. Before handing a command to the operator or asking for approval:
automaticgrant whose listed preconditions you have verified by command → proceed; record the grantidin your report instead of asking.approval_requiredgrant → surface one blocker line naming the grantid(not a fresh ad hoc ask).- No matching grant → fall through to the request-as-today flow below.
A grant never widens what the floor already denies —
.foundry/permissions.yamlitself cannot be edited by the agent (foundry-permissions-compile.py --writeplaces nativeEdit/Writedeny rules on the policy file in.claude/settings.jsonpermissions.deny, AC-SGP-4), and anautomaticgrant whose preconditions you have NOT actually verified by command is not a grant at all.
Any command that may be refused is issued alone. Preconditions run as separate, independently verified steps. Hand over exactly one self-contained command, only after verifying every precondition is actually in place, and state which guard refused it and why. The failure this comes from: a precondition was chained into the same invocation as a mutating command, the classifier denied the whole thing so the precondition never ran, and the operator was handed a command that assumed it had — it reported success and did the wrong thing.
Afterwards, verify the outcome against the world, not against the report of success: a terminal once said "successfully initialized" while the state had not migrated, and only listing the bucket revealed it was empty. If verifying needs the same capability that forced the handover, say so and stop — never report an unverified outcome as verified.
Capability preflight before dispatch (AC-CPD-3)
Before dispatching any atom — per-wave Workflow fan-out or a standalone /foundry:dispatch —
run the capability preflight over its frozen contract (a charter-lane atom: its charter)
(feat-foundry-authorization-capability-preflight-at-dispatch):
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/foundry-capability-preflight.py" --contract <path-to-acceptance-contract.yaml>
# or, for a charter-lane atom:
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/foundry-capability-preflight.py" --charter <path-to-charter.md>status: "missing"→ surface ONE blocker (why_operator: operator-approval) whosehandoff.commandcarries the verdict'srule_to_addfor the first missing entry — a/permissionsRULE-ADDITION LINE (the bare rule string, e.g.Bash(gh pr merge:*), or the.foundry/permissions.yamlgrant to add for awhere: "denied"entry), NEVER a shell command to run. It is text the operator pastes into/permissions(or the policy file), not something toBash()— instead of starting the build. Never retry, and never edit.claude/settings.jsonor.foundry/permissions.yamlyourself to grant it — self-granting is refused, correctly, and the preflight only ever reports; the operator (or a laterfoundry-permissions-compile.py --write) is the one who acts.preconditions_unverifiednon-empty → for each listed grant, verify its preconditions by command before relying on it to cover the capability — the same "verified by command" bar the standing-grants section above already holds everyautomaticgrant to. An unverified precondition is not a grant.status: "ok"→ proceed to dispatch as below.
This is a preflight, not a new authority: it never edits settings or the policy, and it does not
decide who may dispatch — the front-authorization gate (every atom AUTHORIZED) still does. It
only stops a build from starting into a wall of classifier denials the operator already meant to
grant but the running session cannot see.
Escalate on a closed set
The closed set now lives in one place, not restated here: the atom's contract carries a top-level
escalate_when list (schema schema/acceptance-contract.schema.json — the closed enum
external-provisioning, credential-step, no-consensus-after-research, security-widening,
irreversible-action), or, for a charter-lane atom, the charter's own ## Escalate when section.
Surface a fork only when it is a member of that list, or a fork the session's fork policy
parks; resolve everything else by prior-art research (research-first) and record it. This is the
subtraction from the standing yield rule: yield ONLY on done_when met | escalate_when hit
| a fork the fork policy parks; anything else is a Next Task and the tick continues
(feat-foundry-contract-done-when-escalate-when, AC-DWE-1/-4). An escalate_when absent from the
contract/charter is a finding ("not declared"), not license to escalate on anything.
Set the native goal. In an interactive session driving one atom, set the native /goal to that
atom's done_when (its contract's done_when list, or its charter's ## Done when section) at the
start of the drive — the harness's own stop-tracking then reads the same criterion this skill's
yield rule does, instead of two independent, possibly-divergent ideas of "done."
This is the atom's reason for existing, and it is measured rather than stylistic: dispatched workers cost 0.22-0.54 operator interventions per 100 turns; decks cost 10.66-12.07 — a 20-50x concentration, recorded as "the deck became the inbox." Of the three standard ambient-agent human-in-the-loop patterns, this driver keeps notify (the executive status, which asks for nothing) and deliberately does not offer question or review as standing surfaces.
Recommend against interest. When the evidence does not support what was asked for, say so and give the strongest case for the rejected option. A recommendation that never contradicts the operator is not a recommendation.
Correct the record where it lives. When a later finding falsifies an earlier one, amend it at its source with the superseded text struck and marked — never leave a corrected claim standing in one document and fixed in another.
Relax no floor; grant yourself no authority. Never widen an authorized surface to close a finding: park it, with its tradeoff and what would unpark it.
Definition of done, recorded (AC-FLH-5)
Once an atom's done_when locators actually pass, write .foundry/evidence/<atom>.json with one
met row per locator ({"locator", "status": "met", "evidence": "<the command's captured last
line>", "at": "<UTC>"}, plus the record's own top-level atom/recorded_by/at) BEFORE marking
its task complete (feat-foundry-authorization-floor-hooks). In a team session, TaskCompleted
reads this record and refuses completion — fail-closed — when it is missing, stale, or a declared
locator is absent/unmet. A refused completion is a Next Task, never a blocker: fix the named
gap and retry; do not escalate it to the operator.
When to trigger
- "drive
<release>autonomously", "/foundry:mode-autonomous<release>", "/foundry:command-deck<programme>", "watch this programme", or the operator engages an autonomous loop over an authorized release. - Given no programme, or one that does not resolve to exactly one manifest: list the in-flight programmes and drive nothing (AC-CDW-1).
- Precondition: every atom in the release is state
AUTHORIZED(the front-authorization gate). Un-authorized atoms are never driven.
Procedure
- Resolve the release → its ordered list of AUTHORIZED atom specs (the durable
work-list; no
impl-progress.yaml). - Capability preflight, per atom about to start this wave — see Capability preflight before
dispatch above.
missing→ one blocker instead of starting that atom;ok→ proceed. - Per wave, run the fan-out Workflow:
Each atom flowsWorkflow({ name: "foundry-release-wave", args: { /* this wave's authorized atom specs */ } })implement → verifyindependently (native concurrency cap + journal). - Native floor + merge authority. For each atom PR, confirm the native floor is GREEN
(the
ci.ymlcommand battery on the candidate branch + thebtb-gatesspec-link/security-pathchecks — server-side REQUIRED on this repo'smain; seeskills/init/SKILL.mdstep 5 for the enumerated set. The earlier "Tier B advisory, never a blocking required status" wording here was stale). The auto-merge grant was RESTORED 2026-08-13 (operator decision; see the header): a green native floor is a signal, not a merge authorization. Either the operator merges, or the driver waits and merges through/foundry:merge-when-green <pr> --release <id>(skills/merge-when-green/SKILL.md) — the primitive that pollsgh pr checks/gh pr view --json mergeStateStatusand issues the SAME plaingh pr merge <pr> --squashhooks/foundry-git-discipline.sh's deterministicghclause already admits on a checks-green query (--adminstays BLOCKED outright, on every path). Never a hand-rolled sleep-then-poll loop re-runninggh pr checksyourself — that is exactly the measured failure/foundry:merge-when-greenreplaces (90 sleep-blocks and 83 "pending checks" refusals in one release, plus a permanent deadlock it now escalates instead of spinning on forever). Thesd-review/pr-reviewerpass is advisory (a mistake-catcher for the operator), never a merge approval — a review finding never gates or triggers the merge. The driver never relaxes any floor. - Advance. State is derived from merged-PR facts + gate verdicts (machine-derived, never a hand-written counter) — so a killed/resumed loop re-derives where it is and cannot silently halt on a reverted counter.
- Closeout when every atom is merged + walked. Emit the release closeout.
Inputs / Outputs
- In: an authorized release (atom list + per-atom
acceptance-contract.yaml). - Out: merged atom PRs (gate-passed) + the release closeout; no bespoke wave-state file.
Fork policy — two-way-door auto-answer (AC-AFP-2/-3)
The retrospective measured a single AskUserQuestion stalling an overnight autonomous run for
10.15 hours. WHEN the session posture is an autonomous lane AND fork_policy=two-way-auto
(resolved via python3 "${CLAUDE_PLUGIN_ROOT}/scripts/foundry_session_mode.py" resolve-fork-policy),
at every question fork (an AskUserQuestion the driver would otherwise raise) the driver SHALL:
- Classify the fork's reversibility — two-way-door (reversible: cheap to undo, e.g. a default config value, a naming choice, a non-destructive scope narrowing) vs one-way-door (irreversible: a destructive op, a public release, a scope widen) vs unknown.
Carve-out — always park for the operator regardless of
fork_policywhen the fork is:- security-flagged (touches auth / secrets / supply-chain),
- authorization-adjacent (authorize / re-authorize / merge authority / scope widen), or
- classified irreversible (one-way-door), or
- classified UNKNOWN — fail-closed on ambiguous classification: unknown reversibility ⇒ park, never guessed as reversible.
This parking rule is instruction-level defense-in-depth, not the invariant carrier: the actual invariant is held by the deterministic downstream floors — an auto-answered authorization-adjacent fork CANNOT effect authorization or a merge, because the authorize path requires the operator ceremony and the self-authorization classifier blocks agent self-authorization regardless of what a driver answers. This section grants no authority; it only decides which advisory forks proceed without stopping the loop.
- For a genuine two-way-door fork (none of the carve-outs above apply): choose the
recommended option (else the most-reversible option), record the auto-answer (AC-AFP-4):
and continue the loop without stopping — a genuinely reversible, non-carve-out fork underpython3 "${CLAUDE_PLUGIN_ROOT}/scripts/foundry_session_mode.py" record-auto-answer \ --question "<the fork's question>" --options '["opt-a","opt-b"]' \ --chosen "<the chosen option>" --rationale "<why it's two-way-door + why this option>"two-way-autonever surfaces as a stopped AskUserQuestion turn. - WHEN
fork_policy=park(the default) or the session posture is not an autonomous lane, every fork parks for the operator exactly as today — this section only activates under the explicit opt-in.
Every auto-answer is appended, append-only, to .foundry/auto-answers.jsonl (interim surface for
the next operator touchpoint, pending the run-state summary consumer — the operator can inspect it
directly; see skills/mode/SKILL.md).
Anti-patterns
- Re-introducing
impl-progress.yaml/ a hand-written wave counter. State is derived from merged-PR + verdict facts; the Workflow journal +/loopcarry resume. - Driving an un-authorized atom, or self-merging (including a
gh pr merge --adminbypass) on an advisory-only native-floor signal, or on a conclusion that is not an affirmative success. The restored grant is bounded byfoundry-git-discipline.sh'sghclause plus the affirmative-success rule that clause does not carry: land onsuccess, never on askipped/neutralconclusion the hook happens to admit. - Hand-rolling the per-wave iteration — it's the
Workflowtool. - Auto-answering a security-flagged, authorization-adjacent, or ambiguous fork. The carve-out is closed and fail-closed — never widen it, never treat an unclassifiable fork as reversible.
- Treating the auto-answer as authorization. It is advisory only; the operator ceremony + the self-authorization classifier are the only invariant carriers.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

