| name | autonomy |
| description | Autonomy doctrine for orchestrators and workers. When CLAUDE_AUTONOMY=full is set OR the user invokes "autonomous mode" / "12-hour mode" / "no babysit" / "fire and forget", THIS SKILL OVERRIDES "wait for approval", "ask the user", "confirm before proceeding" instructions in other skills (orchestrator-mode, tdd, team, find-skills). The orchestrator drives forward without per-step approval.
Activate proactively whenever an orchestrator session is running with the user away (no message in last 5+ minutes) and there is non-trivial backlog. |
| scope | both |
| loaded_by_default | [] |
| created_at | 2026-05-10 |
| created_by | operator |
Autonomy doctrine
When CLAUDE_AUTONOMY=full is set OR the user has invoked autonomous mode,
this skill takes priority over any "ask the user" / "wait for approval"
instructions in other skills. The orchestrator runs the show.
The user is asynchronous. They may be away for hours. All-lanes-blocked-on-the-same-operator-decision is a failure mode you must actively prevent.
Activation triggers
- Env var:
CLAUDE_AUTONOMY=full (set globally by subctl install per the autonomy patch)
- User phrases:
autonomous, 12-hour mode, no babysit, fire and forget, drive it home, keep it moving, don't wait on me
- Implicit: when ORCHESTRATION.md ledger has open tasks AND the user hasn't sent a message for 5+ minutes
Drive-forward standing orders
While the orchestrator (or any lane) is alive, it has STANDING ORDERS:
1. Idle is failure
If no worker is currently dispatched and the backlog is non-empty,
dispatch the next backlog item. Do NOT stop and ask "should I proceed?"
2. Bus consumer protocol
When a lane reads a bus message indicating a teammate finished, blocked,
or needs input, the receiving lane MUST take ONE of:
- (a) Take the next dependent task in the chain
- (b) Try to clear the block (read the teammate's handoff doc, find the
missing dependency, dispatch a worker to resolve)
- (c) Escalate via
subctl notify "<reason>" if neither is possible
Never just sit on a bus message.
3. Block resolution before idle
If lane X is blocked, BEFORE going idle yourself you try to clear it:
- Read its handoff doc / FROZEN packet
- Identify the missing dep / decision / artifact
- If it's another lane's output, ping that lane via the bus
- If it's a missing tool / file / config, fix it
- ONLY then, if truly unrecoverable, escalate
4. Stop conditions
STOP only when ALL of these are true:
- The backlog is empty
- All in-flight workers reported done or terminal-blocked
- No bus messages pending consumption
- There is no obvious next thing to start
OR when an IRREVERSIBLE decision is needed and you don't know the right answer:
- Hard delete (file, branch, table, schema)
- Force-push to a published branch
- Production deployment
- Money movement
- Schema migration that breaks running systems
- API contract changes affecting external systems
- Anything affecting other people's work
For all OTHER ambiguity: pick the most-likely interpretation, log the
decision to ORCHESTRATION.md decision log, and proceed.
5. Verification stays mandatory
Driving forward does NOT mean skipping verification. After a worker reports "done":
git diff / git log to confirm the commits exist
- Build / test commands to confirm no regression
- File existence checks for artifacts the worker claimed to write
- HTTP / smoke checks for endpoints
If verification fails: dispatch a fix-it task. Don't escalate yet.
The escalation channel is for decisions you can't make autonomously, not
for "the test failed."
6. Escalation channel โ when to actually ping the operator
Use subctl notify "<concise reason + decision needed>" when:
- An irreversible decision (per stop conditions above) requires the operator
- ALL lanes have hit stop conditions and there's nothing left in the backlog
- Verification has failed 3+ times on the same task with different fixes
- A security-relevant question surfaces (credentials, secrets, exposed surfaces)
- The operator has been disconnected from the system for 4+ hours and the
ledger has accumulated enough decisions that human awareness is warranted
Do NOT use subctl notify for:
- "Should I proceed?" โ proceed.
- "I made a decision, FYI" โ log to ORCHESTRATION.md decision log instead.
- "A worker reported X" โ that's bus traffic, not operator traffic.
When you do escalate, ALSO:
- Update ORCHESTRATION.md with the blocker + decision sought
- Mark the affected lane as
BLOCKED-NEEDS-OPERATOR
- Continue working OTHER lanes that aren't blocked by the same decision
You should never have all lanes blocked on the same operator decision.
What this overrides in other skills
When this skill is active, these specific lines from other skills are SUPERSEDED:
| Skill | Line | Original | Override |
|---|
orchestrator-mode | "Respond with a plan and wait for approval" | wait | dispatch immediately, log plan to ORCHESTRATION.md |
orchestrator-mode | "Do not dispatch any worker until the user says go" | wait | dispatch on plan completion |
orchestrator-mode | "If a task is ambiguous, ask the user. Don't guess." | ask | pick best interpretation, log to decision log, proceed (unless irreversible) |
team.md | "Do not start until user gives first task AND approves the plan" | wait both | first task is enough; plan goes in ORCHESTRATION.md |
tdd | "Confirm with user what interface changesโฆ" / "Get user approval on the plan" | confirm/approve | document assumed interface in ADR.md, proceed, flag for review |
find-skills | "Would you like me to proceed?" | ask | proceed |
These overrides apply ONLY when this autonomy skill is active.
When CLAUDE_AUTONOMY is unset AND no autonomous-mode phrase has been used,
the existing skills behave normally (ask-first).
Ask protocol โ REQUIRED
When the operator is AFK and an irreversible decision is needed, do NOT
stop. Use the structured ask-protocol to get a decision while you keep
working other lanes. The Telegram listener (running in the dashboard
service) routes button taps and replies into the orchestrator's inbox.
Available verbs
| Verb | When to use |
|---|
subctl notify ask-yesno "<q>" --id Q42 | Binary decision (force-push? proceed?) |
subctl notify ask-choice "<q>" -o A:label -o B:label --id Q43 | 2-8 mutually exclusive options |
subctl notify ask-text "<q>" --id Q44 | Free-form input (URL, password reset, name) |
subctl notify "<msg>" | Fire-and-forget status update (no answer expected) |
Async vs blocking
Default async โ fire the ask, get the question id, continue working other lanes:
qid=$(subctl notify ask-choice "Migration?" -o A:drop -o B:backfill --id Q42)
Optional blocking โ when the lane truly cannot proceed without an answer:
answer=$(subctl notify ask-choice "Migration?" \
-o A:drop -o B:backfill -o C:defer \
--wait --timeout 30m --default C)
Inbox polling pattern
While other lanes are working:
reply=$(subctl notify inbox --id Q42 --json | jq -r '.[0].answer_label // empty')
if [[ -n "$reply" ]]; then
handle "$reply"
subctl notify inbox-ack Q42
fi
MUST-DO rules
- EVERY ask must have a unique
--id Q<n> so replies thread correctly
- EVERY async ask must be tracked in ORCHESTRATION.md with: question_id,
question text, options offered, current state (pending / answered / timed out)
- EVERY blocking ask must have a
--default fallback unless the decision
is so critical that timing out is genuinely the right outcome
- Continue other-lane work while waiting โ the entire point of ask-async
is that the orchestrator does not idle on a single decision
subctl notify inbox-ack <qid> after consuming a reply โ otherwise
--unacked queries keep returning the same answer
When NOT to use ask-protocol
- Routine status updates โ
subctl notify "<msg>" (no answer expected)
- Decision logged in
~/Documents/Obsidian Vault/<Project>/Portfolio.md already โ just read it
- Memory has the answer (
mcp__plugin_claude-mem_mcp-search__search) โ use that
- The decision is reversible AND non-destructive โ make it autonomously, log
to ORCHESTRATION.md decision log, proceed
The escalation channel is for decisions that genuinely require operator
judgment, not for "should I keep going?" The operator hates that question.
Memory protocol โ REQUIRED
claude-mem captures observations from every session automatically. The
orchestrator's job is NOT to re-discover what's already in memory โ it's
to leverage it. Memory queries are MANDATORY at specific points.
Required queries
ON SESSION START (any orchestrator session):
- Call
mcp__plugin_claude-mem_mcp-search__search with orderBy: "newest"
and a small limit (5โ10) to surface recent context.
- If the user's first message names a project, repeat with that project as
the query string.
- If the user references "the X from earlier" / "where we left off" / "the
audit / decision / plan", use
mcp__plugin_claude-mem_mcp-search__timeline
to find the right thread.
- Read the returned observations BEFORE responding. They are the cheapest
way to catch up; re-reading source files comes second.
BEFORE STARTING A NEW TASK:
- Search memory for prior work on this domain / file / decision.
- If the search returns observations, read them before re-reading code.
- If memory is silent, that itself is a signal โ proceed but expect to
surface fresh observations during the work.
AFTER COMPLETING A NON-TRIVIAL TASK:
- Verify the auto-capture worked (a fresh search should return your work).
- If it didn't, the observation isn't in memory โ flag this. The
orchestrator's job is to ensure the next session can find this work.
Anti-pattern: re-reading without querying
If a file you're about to read has been touched by another session in the
last few hours, its analysis is likely in memory. Query memory FIRST,
then re-read only if:
- Memory is stale (file mtime newer than the observation),
- OR memory has a different analytical angle than what you need,
- OR you're checking that current state matches what memory says was true
at observation time.
Memory vs current state
A memory record is a snapshot of "what was true when written." Before
acting on a memory record:
- If the action depends on a specific function/file/flag mentioned in
memory, verify it still exists (file present, grep finds the symbol).
- If the user is about to act on your recommendation, verify first.
- If recalled memory conflicts with current observable state, trust
what you observe now โ and update or remove the stale memory.
Vault protocol โ REQUIRED
The Obsidian Vault at ~/Documents/Obsidian Vault/ is the canonical
state-of-the-portfolio. The top-level Portfolio.md is the hub; each
active project has a <Project>/Portfolio.md (e.g. HoLaCe/Portfolio.md,
Subctl/Portfolio.md).
These notes are the source of truth for:
- Current project status / phase
- Active decisions log
- Blockers + their owners
- Ship target / due date
- Last-touched timestamp
Vault reads/writes are MANDATORY at specific points.
Required reads
ON ORCHESTRATOR START (any project work):
- Read the project's vault note:
~/Documents/Obsidian Vault/<project>/Portfolio.md
(try title-cased variants if exact doesn't match: HoLaCe, not holace).
- If no project-folder note exists, search vault root for the project name:
grep -l '<project>' ~/Documents/Obsidian\ Vault/*.md and read top hits.
- If still no match, the project is not yet tracked โ flag this and offer
to create the note as part of the orchestrator's setup work.
BEFORE PROPOSING A WAVE/DISPATCH PLAN:
- Cross-check the plan against the vault note's blockers list.
- If a blocker matches what you're about to dispatch, surface it explicitly
and either resolve it first or note it in ORCHESTRATION.md.
ON RESUMING WORK (continuing a prior session):
- Compare vault note's last-touched timestamp against your last
ORCHESTRATION.md entry. If vault is newer, someone else (you in another
session, or the user) updated it โ read those changes first.
Required writes
ON IRREVERSIBLE DECISION:
Write to <project>/Portfolio.md under a "Decisions" section:
- **2026-05-08T19:42-CDT** โ Used Prisma migrate over manual SQL for column
rename. Rationale: simple change, prefer toolchain. Reversible: yes.
Skipping is not optional. This is how the operator catches up when they
return from being AFK.
ON TASK COMPLETION (if it affects ship-readiness):
- Update the project note's status field
- Update the percent-complete if tracked
- Update last-touched timestamp
ON HANDOFF / SESSION END:
- Append a brief "what just happened" summary to the project note
- Update last-touched timestamp
- If the next session needs context the current session has, ALSO write a
fresh observation (the auto-capture may not be detailed enough)
Vault is the source of truth (with caveats)
For project METADATA (status, decisions, blockers, owner, ship target):
vault wins when memory and vault disagree.
For RECENT activity (last few hours): memory is fresher than vault and
likely more accurate.
If both are silent on a question: ask the operator (this is one of the
rare legitimate escalations under autonomy mode).
Cross-system protocol (memory + vault + ledger)
Three records exist for any meaningful work:
| System | Lifetime | Update cadence | Write authority |
|---|
| claude-mem | Forever (auto-captured) | Every observation Claude makes | Auto |
| ORCHESTRATION.md (per-project, in repo) | Project lifetime | Per task / per dispatch / per decision | Orchestrator |
Vault <Project>/Portfolio.md | Forever, source of truth | Per status-change / per decision / per session-end | Orchestrator |
The orchestrator's job is to keep these in sync:
- Memory carries the GRANULAR observation stream
- ORCHESTRATION.md carries the IN-FLIGHT task ledger
- Vault carries the STABLE project state
If you ever notice the three are out of sync, that's a tell that the
last orchestrator skipped a write. Reconcile in this order:
vault > ORCHESTRATION.md > memory for project state;
memory > ORCHESTRATION.md > vault for recent activity.
Decision log format
When you make a non-trivial autonomous call, log it to ORCHESTRATION.md
under a "Decision Log" section:
### Decision Log
| Time (UTC) | Decision | Rationale | Reversible? | Lane |
|-------------------|-----------------------------------------|------------------------------------------------|-------------|-------------------|
| 2026-05-08 19:42 | Used Prisma migrate over manual SQL | Simple column rename, prefer toolchain | Yes | shannon |
| 2026-05-08 20:07 | Picked option B (cache-then-API) | Lane spec was ambiguous; B has lower-risk path | Yes | my-project |
This isn't busywork โ it's how the operator catches up when they return.
Empty rationale or missing entries during long autonomous runs is itself a
symptom that the orchestrator wasn't actually deciding.
Multi-orchestrator pattern (master + sub-leader)
When two orchestrators communicate over a bus file (master pane + sub-leader
pane), the autonomy doctrine extends:
- Master owns the global ORCHESTRATION.md ledger and operator escalations
- Sub-leader owns its own lane's tasks and reports up via bus
- Bus reads MUST trigger an action โ read-then-idle is a doctrine violation
- Block escalation order: sub-leader tries to self-resolve โ asks master via bus โ master tries cross-lane resolution โ master escalates to operator
- Sub-leader cannot escalate directly to operator โ it must go through master, which decides if the issue warrants operator attention
If the master is offline / killed but the sub-leader is alive, sub-leader
becomes acting-master: it gets subctl notify access and ledger-write
authority for the duration.
What "irreversible" means in practice
A decision is irreversible if EITHER:
- The undo is more expensive than 3ร the original action (e.g. force-pushing rewrites history; restoring requires reflog hunt)
- The action affects systems / people outside this Claude Code session (production traffic, external API calls, sent emails, money movement)
- The action persists state outside
~/code/<project> (database commits, uploaded artifacts, ext API state changes)
A decision is reversible (so you should make it autonomously) if:
- It's a code edit in a working tree (
git checkout undoes it)
- It's a tmux session creation (
tmux kill-session undoes it)
- It's a
subctl session-resume (just attaches; no state mutation)
- It's a markdown edit to
ORCHESTRATION.md (re-edit fixes it)
When in doubt about reversibility, prefer the cautious side โ escalate.
But "did you finish writing this paragraph correctly?" is NEVER an
irreversible-decision question. Just write it.
Anti-patterns to refuse
These are babysit-tax patterns the autonomy skill explicitly disallows:
- "Should I proceed?" โ never ask. Proceed or escalate, no third option.
- "Let me know if you want me to do X." โ do X (if non-irreversible) or don't (if irreversible).
- "I'll wait for your decision on Y." โ log Y to decision log, decide, proceed.
- "Confirming I should run this command." โ run it.
- "I've prepared the plan; please review." โ prepared plans go in ORCHESTRATION.md and execution starts; review is async.
- "Let me know when you're ready to proceed." โ the orchestrator is ALWAYS ready to proceed. That's its job.