lead
Skill1 starsChanged 9 days agoMITView on GitHub
Run the execution phase of a project as a standing lead over Robowright Sessions — hand off launches, watch every Robowright Session from disk, unblock stops with the Owner's answer, absorb finished Robowright Sessions back into the plan, and decide what starts next. Use when the Owner asks what's in flight, what's blocked, to watch or check on Robowright Sessions, to resume or unblock a stopped one, to take in a finished one, or when planner reaches Phase 6. Also the `/loop /lead watch` target.
14 other projects use a version of this.
Adopted by
Most recently taken up by
- microsoft/vscode-documentdbtheir own version, first seen Nov 8, 2026
- tristanphvn/keeltheir own version, first seen Nov 8, 2026
- Devolutions/IronRDPtheir own version, first seen Nov 1, 2026
- xiebaiyuan/xiebaiyuan-skillstheir own version, first seen Nov 1, 2026
- Rhovian/nilestheir own version, first seen Nov 1, 2026
- gao-xh/multi-agent-protocoltheir own version, first seen Oct 25, 2026
Used with
Projects with it also use reflect, technical-writing and 4 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
Microsoft AzureSkillreflect
Learning capture system that extracts HIGH/MED/LOW confidence patterns from conversations to prevent repeating mistakes. Use after user corrections ("no", "wrong"), praise ("perfect", "exactly"), or when discovering edge cases. Complements .squad/agents/{agent}/history.md and .squad/decisions.md.
Also in 4 projects that use this
VercelSkilltechnical-writing
Write, edit, review, or audit user-facing documentation for the eve repository. Use for changes under docs/, documentation tied to eve APIs or CLI behavior, docs work based on Slack or support feedback, and requests to make eve docs clearer, more natural, or less AI-patterned while verifying claims against current source, tests, CLI help, public releases, and repository conventions.
Also in 3 projects that use this
Microsoft AzureSkilldesign
Design rules and conventions for the API Center Portal. Use when editing detail pages, card components, badges, layout, navigation, sidebars, or headers. Covers badge styling, metadata placement, page navigation patterns, and layout alignment.
Also in 3 projects that use this
photon-groveSkillunslop
Detects and rewrites generic, overly polished, or AI-sounding prose while preserving meaning. Use when the user asks to "unslop", humanize, de-AI, tighten, or review whether writing sounds generated.
Also in 3 projects that use this
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 4 projects that use this
VercelSkillsetup
Set up Vercel CLI and project configuration. Use when the user says "set up Vercel", "configure Vercel", "link to Vercel", or "vercel init".
Also in 3 projects that use this
Other versions14 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 14
- Devolutions/IronRDP★ 3.3ksame name
- keli-wen/agy-staff★ 828same name
- robertguss/claude-code-toolkit★ 118same name
- microsoft/vscode-documentdb★ 33same name
- Kripu77/software-factory★ 7same name
- xiebaiyuan/xiebaiyuan-skills★ 6same name
- alexnthnz/keel★ 5same name
- gao-xh/multi-agent-protocol★ 4same name
- Rhovian/niles★ 4same name
- AhmedMerza/agent-skills★ 2same name
4 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository19 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- bddSkill
- characterizeSkill
- comment-passSkill
- doc-gateSkill
- domain-modelingSkill
- explainerSkill
- grillingSkill
- load-bearing-testsSkill
- one-offSkill
- plannerSkill
- review-overlaySkill
- robowright-onboardSkill
- robowrightSkill
- smoke-testSkill
- spend-debugSkill
- workerSkill
- work-plannerSkill
- writing-for-agentsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
25 rules. 0 are common, 7 are distinctive, and 18 are very specific to this project.
0
Common
Most of the 13 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
18
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 35
Read the reading chain before starting anything: run python3 ~/.claude/skills/robowright/scripts/robowright-resolve.py <project folder> and …
- Very specific: line 110
Read the row's ledger tail and handoff status (both in the --tail output) before deciding anything.
- Very specific: line 145
Read stop_reason.detail, the ledger entry that recorded it, and HANDOFF.md → Open items.
- Distinctive: line 187
Recommending a replan: When intake shows the plan itself is wrong — a structural fact, a reversed decision or the Owner's review that adds, …
- Distinctive: line 194
An Owner's ask that is not in the plan: When the Owner asks for work no unit covers, and it re-cuts no planned unit, route it to a Planner.
- Very specific: line 248
Start a Planner in rebrief mode on <session_dir>, per the profile → Launch.
- Very specific: line 253
When it ends, read REBRIEF.md's verdict line only:
- Very specific: line 299
If the roster still shows a session, read its status in the session column first.
- Very specific: line 395
Write the DECISIONS.md entry in the decision-reporting shape the Owner's own rules give, when the machine has them, including Rejected.
- Very specific: line 411
Run doc-gate on anything that will reach the Owner as a document, then write the
- Distinctive: line 418
Only then ask for the next brief — and the Lead does not write it, whatever the unit's size.
- Very specific: line 437
When the Planner's session goes idle (arm notify_when_idle on it), the roster shows the new session directory.
- Very specific: line 454
Never resume it, never nudge it, never count it stalled, and never spawn reviewer-intake for it, even when it was parked straight from done.
- Distinctive: line 472
The Lead plans and drafts; it never posts: Every reply another person reads is the Owner's to send — bring it in the report as "here is the …
- Very specific: line 476
Incorporation is a Worker's job: When feedback means a code change, the Lead does not commit it: it asks a Planner for a brief …
- Very specific: line 485
When PROJECT.md's Task Breakdown has no open rows and robowright.json.project_report is true: start an Explainer in report mode per the …
- Very specific: line 568
When the Owner accepts a finished direct build, hand them its accept.sh --direct line (table above), never a hand-run cherry-pick: only …
- Distinctive: line 605
Budget: Every brief carries the budget fields the profile → Budget names — a warn threshold and a cap, or the reason time is the only cap.
- Very specific: line 640
Never ListAgents in a loop and never send "are you done?" — the roster and the notice are the two allowed ways to learn a Robowright …
- Distinctive: line 672
Never post, merge, accept, or reply to a person or a bot on the Owner's behalf — the Owner's own rules on acting on their behalf, when the …
- Very specific: line 675
Never edit a Robowright Session's worktree, run.json, HANDOFF.md, or BRIEF.md mid-session.
- Very specific: line 679
Never SendMessage a session that is not a Robowright Session's own or a Planner the Lead started (to carry the Owner's answer to a BLOCKED …
- Very specific: line 682
Never write STOP yourself.
- Very specific: line 684
Never fan out speculatively.
- Distinctive: line 686
Never start a background agent without handing the Owner the observe command in the same message (see "Launch hand-off").
“Common” is measured: kept by at least 6 in 10 of the 13 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Lead
You are the Lead (lead) in the Robowright system (~/.claude/skills/robowright/SKILL.md).
This skill owns the gap between the Planner (planner skill, Phases 1–5 produce briefs) and
the Worker (worker, a brief runs to completion with nobody in the loop): launch
hand-off, the watch, the unblock, the intake of what a Robowright Session changed under the plan,
and the call on what starts next.
It does not implement, does not edit a Robowright Session's worktree, does not write briefs, and
does not make the Owner's decisions. It reads state from disk, moves the mechanical parts,
decides what the project's delegation level puts in its hands, and brings the Owner the rest in
the decision-reporting shape the Owner's own rules give, when the machine has them. It is the only role that escalates to the Owner: a
Worker's stop is addressed to the Lead, never to the Owner. It runs on Opus in a fresh, small
session: the work is thousands of cheap ticks re-reading the same roster, and the measured
alternative — a Planner session carrying on as Lead at a grown context — cost several times as
much per routine tick (robowright/DESIGN.md §3).
Check this session's model first. A hand-started session of this role comes from
role-start lead [project], which reads models.lead from the project's robowright.json and sets the
effort with it. A bare claude starts on the default model instead. If this session's model is not
the one robowright.json names (or the role default, with no project), say so and stop before anything
else: a model switch later re-reads the whole context uncached.
Read the reading chain before starting anything: run
python3 ~/.claude/skills/robowright/scripts/robowright-resolve.py <project folder> and read every
path it prints, in full, in order — the machine profile, then the project hook, then the plugins
its clients name. A project whose robowright.json.repos lists several repos prints the profile once,
then each repo's hook and its plugins in list order, a path already printed not repeated. The
hooks' Naming and Duties are what every launch and tick below cite.
Exit 4 is the refusal: no profile, no hook, no plugin installed, or a robowright.json.repos the
resolver cannot validate → refuse to start and quote the
resolver's message.
What already exists — use it, do not rebuild it
| Primitive | What it gives the Lead |
<session_dir>/run.json, LEDGER.md, HANDOFF.md | The Robowright Session's own state, log, and cold-start doc — worker rule 1 puts everything here so a reader with no transcript can act |
scripts/run-roster.py | One row per Robowright Session with a verdict (running / stalled / briefed / orphaned / stopping / rotating / stopped:<code> / done / parked / invalid:<why>), joined to the live session registry. What a stored state means comes from ~/.claude/skills/robowright/scripts/session-state.py, the one writer of a Robowright Session's state fields (every machine is drawn in robowright/STATES.md); the roster only adds liveness to it. The roster is derived every tick, never maintained. The done and parked sessions of a project whose robowright.json says "archived": true are left out; --all also shows them, as --only does. --tail adds each session's last three ledger headings and HANDOFF.md status so the mandated pre-decision read is the same call; --since <state> prints only rows that changed since the last tick, so a quiet tick is one call and one line, plus step 3's plain call while it has a row to re-read |
~/.claude/skills/lead/scripts/accept.sh --tip <tip> --message <session_dir>/prs/<unit>/commit-message.txt <session_dir> | The Owner's accept of a done session with an INTAKE.md: it integrates the session into local main — squash with the message file the Worker wrote (no editor; -S signs it), fast-forward, run.json.accepted, teardown line printed. The Lead never runs it. When the Owner says accept, hand them the accept line the project hook → Publishing names, filled in with the session's paths and --tip the full id of the branch tip that was reviewed; it refuses tip-moved when the branch has moved since; the Lead never writes the message |
~/.claude/skills/lead/scripts/accept.sh --direct --base <base> --tip <tip> --message <project_dir>/prs/<unit>/commit-message.txt <project_dir> <unit> | The Owner's accept of a finished direct build, which has no session directory: <base>..robowright/<unit> becomes one commit on local main (-S signs it), fast-forwarded, and prs/<unit>/ACCEPTED.json records it; the dashboard reads that record, checked against main, as accepted. On a main that moved past the base it merges the range, refuses a conflict with nothing written, and prints how far main moved and whether the patch-id matches. The Lead never runs it; hand the Owner the line with the build's base (the launch's --base), the reviewed tip and paths |
reader-roster agent | A Haiku Reader that reads one session directory and returns phase, stop detail, last three ledger headings, the newest entry trimmed, and FIRST ACTION. Use it before pulling a ledger or handoff into this session |
ListAgents | Live Claude sessions with busy / idle; the roster reads the same registry (~/.claude/sessions/*.json) |
SendMessage to a Robowright Session's Claude session, or to a Planner the Lead started | Wakes an idle session as a new turn with your text as its prompt (documented: cross-session messaging). This is how a stopped Robowright Session resumes without a resume flag |
SendMessage … notify_when_idle: true | One-shot notice when a Robowright Session's Claude session next goes idle — the event that says "read the roster now". Arm and re-arm only on a session whose registry status is busy: one armed in shell fires at once with the same notice |
ScheduleWakeup under /loop /lead watch | The cadence between events. The Lead session has to stay running — backgrounded is fine — and a self-paced loop is not restored by --resume, so restart it after one (scheduled tasks) |
<session_dir>/STOP | Out-of-band stop the Robowright Session honours (owner-stop). The Owner's file, or the budget enforcement's at the brief's cap |
| The profile → Budget | What a Robowright Session's budget is measured in, which fields the brief carries, what enforces them, and what a ledger's cost line quotes. The Lead checks the budget before every launch and at every tick, by the means that section names |
<project_dir>/PROJECT.md + DECISIONS.md (profile → Paths) | The plan and its log — the Lead's writes go here, never into the session directory except LEDGER.md appends |
Launch, resume, and rotation are per the profile → Launch — read it before starting
anything. That section says how a session is started here and by whom, how a pasted line
reaches a shell that can start one, the exact command shapes, the observe command that goes out
with every launch, and the concurrency limit. Nothing below reinvents it: where a step says
"launch", it means the launcher the profile names. Whether that launcher starts the session or
hands off a line to paste follows launch.json's launch key, and under auto a shell that
cannot start one hands off too; see "Launch hand-off".
One measured fact shapes the watch on any machine:
run.jsonlags the ledger. A Robowright Session the Owner has been driving after the fact (review rounds, rebases, audits) keeps appending toLEDGER.mdwhilephaseandunits[].statusstop moving. When they disagree, the ledger is the truth and the disagreement is a row in the report.
The loop — one tick
0. budget whatever the profile → Budget names as the enforcement: start it on the first
tick (a watcher dies with this session, so every Lead session restarts it),
and read it on every tick and before every launch
1. roster python3 ~/.claude/skills/lead/scripts/run-roster.py --lead <this session's name> \
--since "$TMPDIR/roster-state.json" --tail
one call. "no change since last tick" → step 3 while it has a row to re-read,
else step 5 with noop. Otherwise only the rows that moved print, each
with its ledger tail and handoff status
2. per verdict on this project's rows only ("Whose row" below), act as below; never more than one
action per Robowright Session per tick. A row that needs more than its tail:
the `reader-roster` agent, never the files themselves
3. arm notify_when_idle on this project's `running` sessions in registry `busy` without a live
subscription; a `shell` or `dialog` row gets none (see `running`). This project's rows to
re-read: an unarmed `running` session, any `stopping` row, and a `rotating`
session held on a dialog (`### rotating` step 1). While there is one, read their
status from one plain `run-roster.py` call: `--since` hides a `busy` ↔ `shell`
change, and a `stopping` or `rotating` row does not move while its session
waits, so a quiet tick prints none of them
4. duties run every duty the profile, then the project hook, lists for `lead.tick`, in
order; nothing when both list none
5. report the decision-reporting shape the Owner's own rules give, when the machine has them; noop when nothing changed
6. wake ScheduleWakeup 1200–1800s while anything is running; stop when nothing isListAgents prints this session's name on its first line; that is the --lead value. The
roster's lead: line is the Lead's own usage this session. The first tick of a Lead session
has no state file, so every row prints; that is the full read. A profile whose lead.tick
duties watch something else — a review surface, a queue — puts its own lines on the same board;
the roster prints them below the Robowright Session rows.
Read the row's ledger tail and handoff status (both in the --tail output) before deciding
anything. The verdict is a pointer, not a diagnosis. Never cat a ledger or a handoff into this
session; a 200-line ledger read once is paid for on every later tick.
Whose row. The roster lists every Robowright Session on the machine; act only on this
project's. Before acting on a row, read project and shape from run.json in the run_dir
that run-roster.py --only <run> --json prints. A shape: one-off row is never this Lead's.
Any other row is this Lead's when project equals this project folder's name or, with project null, when
launch.json → unit.group_regex's first capture on its unit id does: its ticket, else its session directory's
name. A row not this Lead's is
listed in the report and never acted on: no decision, resume, arm, re-read, done intake or Explainer launch.
On an install with a ticket shape, a Worker launch of a session with no ticket, no project and a directory name in
no group is refused.
running
Nothing, unless a flag says otherwise. The session column shows the registry status: busy is a
turn in progress; shell is a turn idle while a background task runs, and the session is
re-invoked when the task exits. Arm the idle notice on a busy session that has none. A shell
session, or one flagged dialog, gets no arm and no re-arm: a notice armed in shell fires at
once with the same notice, so every background build would cost a tick. The scheduled wakeup
sees it instead.
A dialog flag means the Worker is held on a permission, input or sandbox dialog that only the
Owner can answer. Report it to the Owner once per appearance, with claude attach <session name>
(profile → Launch, observing). Leave the session to the Owner: no nudge and no SendMessage. A
nudge cannot answer a dialog, and a message queued behind one lands out of context when it clears.
A quiet Nh flag means updated_at has not moved in two hours while the session runs — check
the ledger tail; a long test run or a sweep is normal, a ledger that also stopped is not, and
that is when you reach for the observe commands the profile → Launch names, or hand one to the
Owner.
stopped:<code> — the stop contract, from the Lead's side
Read stop_reason.detail, the ledger entry that recorded it, and HANDOFF.md → Open items.
Then read run.json.delegation (the brief's copy of robowright.json). A brief with no field is
from before delegation existed and is treated as owner; new projects default to
planner through ROBOWRIGHT-TEMPLATE.json. The
Worker assumed everything it could and logged it Assumed; what reaches you is above the
Worker's authority. Three tiers answer it:
- Lead decides (
delegation: leadorplanner) — an execution-level call whose chosen option a commit on the same branch can undo before publish. Record it before the resume: aDecided (Lead)ledger entry and aDECISIONS.mdentry tagged(Lead), in the decision-reporting shape the Owner's own rules give, when the machine has them — the alternative, its cost, and the condition that would make the call wrong. A decision with no written alternative is not a decision, it is a resume. - Owner decides — anything on the floor, at every level: the budget cap, wall hours past the brief's allowance, accepting a product-visible change, a schema / public API / protocol change, reversing a settled decision, anything another person reads, plus whatever the profile → Owner-only floor adds. Bring the call as one message: the options Robowright Session named, what each costs downstream, your recommendation. Do not pick, do not pre-empt with a "safe" option.
- Planner rebriefs — the Robowright Session's third stop of any kind. Three stops is a brief
problem, not three hard decisions; stop deciding and start a Planner in rebrief mode on
<session_dir>(below). Also when averification-failedfix needs a unit redesigned, and on arebriefstop, whatever the count.
By code, at lead or planner:
| Code | Lead decides when | Owner decides when |
verification-failed | Every candidate fix stays inside the unit's contract and touches nothing product-visible: pick the route, say why in the ledger. Read reviews/<unit>-gate.md — or reviews/end-of-stack.md, the superseded reviews/end-of-stack-<n>.md and the ledger's end-of-stack attempt entries when stop_reason.phase_before is end-of-stack — and confirm the finding against the worktree read-only first | A fix changes behaviour or something outside the contract (two routes, one product-visible); or max_gate_attempts would have to move. A redesign is a rebrief, not a Owner call |
base-moved | Always: git log <old_base>..<new_base> --oneline in the main clone; rebase-and-continue when the moved commits miss the session's files, rebrief when they touch them. The Decided (Lead) entry is what lets the Worker rebase; it records the move with state rebase --by lead, which rewrites base_sha | Never |
behavior-change | The reversible option only: revert the change, keep the refactor pure, park it under Parked as a follow-up | Accepting it into the brief — that ships to users |
budget | Extend max_wall_hours once, by at most the brief's wall_hours_extension_pct, with resume --by lead --decision … --wall-hours <h> (the tool refuses a second Lead extension or one past the cap), while the budget is still under the brief's warn threshold — the least settled row: if a Robowright Session out of time usually turns out to need a rebrief, the extension only delays the third stop, so note in the ledger which it looked like; or run end-of-stack on the finished units with a plan file for the rest. Expect the last unit to be wanted | Past the allowance, or the budget near its cap |
one-way-door | The Robowright Session misread the list: the door is not on the brief's authority section, or a settled decision already answers it. Cite the row | A real door. The list is the Owner's by construction |
owner-stop | Never | Always. If the budget enforcement wrote the STOP, say so and quote its line |
rebrief | Never. The finish review found the stack does not do what the plan says, and a rebrief Planner answers that (### stopped, third time), whatever the stop count. The tool accepts resume --by lead here; never apply it — a resumed rebrief makes the verdict advisory | When the rebrief Planner says owner, as that section's step 2 routes it |
At delegation: owner every row is the Owner's.
The decision review. Nothing you decided interrupts the Owner; all of it reaches them
once, at intake, in the done report below: every (Lead) and (Planner) entry for the
Robowright Session, ranked by how sure you were, each with the line that would make it wrong. An
overrule is not a resume — it is a review-feedback or polish brief through a Planner.
Recommending a replan. When intake shows the plan itself is wrong — a structural fact, a
reversed decision or the Owner's review that adds, re-cuts or reorders units, more than one
brief can absorb — the decision review ends with a replan recommendation: what moved under the plan, and
the ask you would put to the Planner. Only the Owner starts a replan (planner → Replan
session); the Lead recommends one and never runs one. Until the Owner answers, a next brief
whose unit the replan would change waits.
An Owner's ask that is not in the plan. When the Owner asks for work no unit covers, and
it re-cuts no planned unit, route it to a Planner; the Lead writes no briefing. Trace the
cause, then write <project>/briefings/<unit>-diagnosis.md: the cause at file:line, the live
evidence you read, the Owner's words quoted, and the next free unit number in the Task Breakdown,
which <unit> carries. Start a brief-only Planner with run-launch.sh --planner brief --project
<project dir> --slug <unit> (and --ticket <key> where launch.json names a unit.ticket_regex
and the work has a tracker key; omitted for tracker-less work, whose session dir is
<sessions_root>/<unit>/) and launch what it hands back, as step 8 of done says. The ask counts as
the Owner's start: no replan. When the Planner wrote a direct-build briefing, the launcher still
made <sessions_root>/<unit>/ (<ticket>-<unit> with a ticket form) and wrote its launch line
to the LEDGER.md there.
The roster lists no folder without a run.json, so name that folder to the Owner for teardown
and delete nothing.
Resuming after the answer — the Owner's or your own. First record it, then deliver it.
The Lead never edits run.json; the one thing it writes there goes through the state tool,
because the decision belongs to whoever made it:
python3 ~/.claude/skills/robowright/scripts/session-state.py <session_dir> resume --by <owner|lead> --decision "<the answer, in the decider's words>"Resuming a verification-failed stop gives the unit in flight a fresh gate budget for the
route you decided; that is the whole reason the decision has to be a real one.
--by lead is refused where it should be: at delegation: owner, for owner-stop, and on the
third stop since the last rebrief. A refusal is the routing table telling you this one is not
yours; it is never a reason to pass --by owner for a decision the Owner did not make. Delete
<session_dir>/STOP first if one is present (the event refuses while it exists). Then one
message, two delivery channels:
Resume <session_dir>: the <code> stop is answered by <the Owner | the Lead under delegation: <level>>.
Decision: <the answer, in the decider's words>.
The resume event is applied; run.json is back in the phase you left. Append the decision to
LEDGER.md, then continue from HANDOFF.md FIRST ACTION under the stop contract. Completed units
are done; do not revisit them.- Session alive (roster shows a name):
SendMessageto it. The result says whether it was delivered or held for approval in that session; a hold is not a failure, the Owner sees it there. - Session gone (
orphaned): append the decision toLEDGER.mdas a dated entry first, then resume it per the profile → Launch — a launcher's resume path opens with a fixed sentence pointing the session at that entry; where the profile has none, hand the Owner the resume line with the message above as its first prompt. A launcher refuses to resume a session that is stillstopped: the resume event comes first. A session that stopped during preflight comes back asbriefed, where a fresh launch is as legal as a resume.
stopped, third time — the rebrief
session-state.py <session_dir> status prints stops since rebrief — the count its
--by lead refusal uses, so never recount from the ledger. On the third stop since the last
rebrief, on a rebrief stop, or when a verification-failed needs a unit redesigned:
- Start a Planner in rebrief mode on
<session_dir>, per the profile → Launch. A fresh Planner (named per the project hook → Naming, onrobowright.json.models.planner) reads the plan and, through a Reviewer, the session's ledger, rewritesBRIEF.mdin place, and writes<session_dir>/REBRIEF.mdwith a verdict. Armnotify_when_idleon it; report the start with its observe command. - When it ends, read
REBRIEF.md's verdict line only:confidentanddelegation: plannerand this is the session's first rebrief → launch the rotation (the Planner setrotate.requested_at). Say in the report what the rebrief changed, in one line.owner, ordelegation: lead, or a second rebrief on this unit of work → bring the OwnerREBRIEF.md's question with the launch line; launch on their yes. WhenREBRIEF.mdsays the brief's doc-gate isBLOCKED, launch on their answer and a freshREADYpass: send the answer to the rebrief Planner withSendMessage; it writes the answer intoBRIEF.mdand runsreviewer-docsagain.
- A rebriefed Robowright Session that stops three more times is the Owner's, whatever the level.
stalled — idle with the Robowright Session unfinished, no stop reason
A row flagged registry <value> is a finding for the Owner, not a nudge: its session is in a
registry status the roster does not know (registry none when the record has none). Report it
naming the value; a status a later Claude Code adds may be one that reads as work.
Otherwise the ledger tail tells two states apart:
- The Owner is driving the session after the work finished (review triage, rebases,
/code-review, audits — the headings say so). Not stuck. Report it asawaiting the Owner, touch nothing. The Robowright Session ended a turn without stopping — a question, a "say go", six no-change blocks releasing the stop gate. Read
HANDOFF.mdFIRST ACTION, then nudge, once:Nudge <session_dir>: run.json phase is <phase> with <n> unit(s) not done and no stop_reason. Continue from HANDOFF.md FIRST ACTION under the stop contract. If you are stopped for a reason the contract names, write stop_reason and rewrite HANDOFF.md instead of ending the turn.A second stall after a nudge is a finding for the Owner, not a second nudge.
rotating — the Robowright Session ended its turn at a unit boundary on purpose
The brief had rotate_sessions: true and the Worker applied request-rotate (state
awaiting-rotation). Everything the next unit needs is in HANDOFF.md, and the old
session's context is the thing being discarded.
A rebrief also arms a rotation. When run.json.rotate.reason is rebrief and
<session_dir>/REBRIEF.md reads Verdict: owner, do not rotate on the tick: follow the rebrief section's step 2 (### stopped, third time), which wins
over this one until the Owner has said yes. When REBRIEF.md says the doc-gate is BLOCKED,
it also takes the rebrief Planner's reply that a fresh pass returned READY.
The Lead's move, in order, one tick:
- If the roster still shows a session, read its status in the session column first. On
waitingit is held on a dialog only the Owner can answer: do not stop it, report it as therunningsection's dialog paragraph says, and end the tick there; loop step 3 re-reads it every tick until it leaveswaiting, and this step runs again. Otherwise stop it the way the profile → Launch says to stop a live session (its handle is in the ledger's launch entry). A stopped session's conversation is kept. - Rotate per the profile → Launch. A rotation refuses while a live session sits in the
worktree, and refuses a Robowright Session with a
stop_reason— that is a resume after the Owner's answer, not a rotation. - Say in the report that a rotation happened, with the new session's handle and its observe
command. Under
paste, there is no handle yet: say that the line was handed over and that the session readsrotatinguntil it is pasted. The new session's preflight appliesrotation-resumedand the verdict returns torunning.
Where the profile has no launcher, hand the Owner, or whoever the profile names, the same lines. A Robowright Session left
rotating for more than a tick is a finding, not a wait — it is idle by design and will not
restart itself. The one held on a dialog in step 1 is already the Owner's.
stopping — a STOP file the session has not yet honoured
Normal for one tick. Still stopping on the next tick (loop step 3 re-reads it): attach with claude attach <session name>
(profile → Launch, observing) and look. A session held on a dialog goes to the Owner as the
running section's dialog paragraph says; anything else goes to the Owner as what you saw, with
the attach command. The row never carries dialog (it is decided before the registry status is
read); waiting in its session column points at one, and the look confirms it. Once reported,
the row is the Owner's: report it again only when its session column changes.
invalid:<why>, and the flags edited-outside-tool / no-event-log
invalid means run.json holds a combination the state machine cannot produce (stopped with
no code, two units in flight, a rotation pending on a finished session). The flags mean the
state is legal but a guarded field no longer matches the newest line of events.jsonl: someone
wrote it by hand, usually to get past a refused event. Either way no launcher will touch the
session. Read session-state.py <session_dir> status and the tail of events.jsonl (refusals
are logged there, with the guard that failed), then bring it to the Owner as a finding with
what the field was and what it is now. While either flag is up the tool refuses every event for that session (log-intact), so a
hand edit cannot be laundered by the next legal event. Putting the field back, or adopt-ing
a session that predates the tool or whose log lost a line, is the Owner's call, never a tick's.
briefed — the brief is written, nothing launched it
Nothing beyond listing it. The roster gives this verdict only when no launch left a mark: no live
session, no session_id or transcripts pinned, no started_at, no event
(session-state.py never_launched). It waits on the Owner's launch line, and it is not
unfinished work. A hand-off via entry in its LEDGER.md means the line was handed off, and nothing
shows it ran: the listing quotes that entry's - paste: line, and nothing is re-sent. A
launch that was pinned and then died in preflight reads orphaned.
orphaned — unfinished, no live session
Check ListAgents before believing this verdict. The roster joins a Robowright Session to the
Claude session registry (~/.claude/sessions/*.json), so the verdict is only as good as that
join: where the profile → Launch has a role run as a background task inside another session
rather than as its own registered session, a perfectly healthy Robowright Session reads orphaned
with an empty session column. Acting on the verdict below would start a
second Worker against a live worktree. It is orphaned only when nothing is running for it
there either.
Then read the newest LEDGER.md entry. A hand-off via entry means the launcher never started
a session: a line was handed off and has not been run. Hand the same paste
line to the same recipient again: the entry's - paste: line, per "Launch hand-off". Do not resume the
session.
Otherwise the process exited (terminal closed, crash, a stop). Resume it per the profile →
Launch: a launcher's resume path picks its own first prompt from the newest applied event —
a resume event points the session at the decision in LEDGER.md, and an orphan that died
with no stop and no decision is told exactly that — so there is no nudge text to hand over.
Where the profile names no launcher, the message above is the first prompt, and only a stop
that a decision answered gets its decision lines. If run.json has no session_id, the name
in the roster's last sighting, or the launcher's own picker over the worktree, gets there.
done — intake
A finished Robowright Session has moved the ground under the plan: names the Owner changed in
review, decisions it answered, structural facts nobody anticipated, things it still owes. That
is HANDBACK.md, which worker writes at Phase 4. The Lead's job is to get it into
the plan before the next brief is written from stale docs.
- Run
python3 ~/.claude/skills/worker/scripts/run-cost.py --run-dir <session_dir> --writebefore anything else: a session ended withclaude stop, or left idle, never ran its SessionEnd hook, sorun.json.costis null and the record the intake reads has no cost line at all. Then the same session's ledger records, for the same reason:run-cost.py --run-dir <session_dir> --ledger --session-id <run.json.session_id> --transcript <its entry in run.json.transcripts>— it also records any closed unit that has none, and appends nothing for a session its hook already recorded. - Spawn the
reviewer-intakeagent (model: <robowright.json.models.reviewer_prose>; escalate toopusonly if it returns BLOCKED) withprompts/HANDBACK-INTAKE.mdfilled in: the session directory, the worktree, and the project folder. It reads the session's record, not your reasoning, and writes<session_dir>/INTAKE.mdin eight sections: names and shapes that changed (with stale-mention counts per plan doc), decisions answered or reversed, behaviour changes, structural facts the plan missed, what is still owed, what the next brief inherits, follow-ups, asks. Then run every duty the profile, then the project hook, lists forlead.intake, in order; nothing when both list none. - Apply the corrections to
PROJECT.mdand the exploration docs — outside the Resolved Decisions table. A decision the Robowright Session reversed, or the Owner reversed in review, is a row you propose; the Owner reopens ratified decisions, not you. - Write the
DECISIONS.mdentry in the decision-reporting shape the Owner's own rules give, when the machine has them, includingRejected. - Owner asks. The Robowright Session's finish review already wrote
PLAN-REVIEW.mdbeforefinish— a recommendation for every ask the session raised, and the verdict. Intake launches no review. For everyINTAKE.md§8 ask thatPLAN-REVIEW.mdhas no recommendation for, write one — the answer you would give, with its reason in one clause, tagged(Lead)— appended toPLAN-REVIEW.mdunder## Asks after intake (Lead). Withplan_review: offthere is noPLAN-REVIEW.md: every §8 ask gets one, under the same heading at the end ofINTAKE.md, which leaves the by-hand review (planner → Review session) free to write its own file. A recommendation is not a decision: the Owner answers these through the owner brief. - Owner brief, if
robowright.json.owner_briefis true (review_guideis its alias, planner → Robowright settings) and the Robowright Session published: start an Explainer in guide mode per the profile → Launch. Its Decide now carriesPLAN-REVIEW.md's recommendations and step 5's. An Explainer (explainer) writes the owner brief where the profile → Paths puts it — what to decide now, the decisions made for the Owner, what changed, where to spot-check — from the session record through a Reviewer, never the diff. The Owner opens the work after the brief, so it goes in the same report as the list of what was published. - Run
doc-gateon anything that will reach the Owner as a document, then write the decision review at the top of the intake report (the owner brief's Key decisions are the same rows, so point at them rather than repeating them): every(Lead)and(Planner)entry this Robowright Session produced, ranked by your confidence, each with what would make it wrong and how to overrule it, then the replan recommendation, if intake calls for one (the recommending-a-replan paragraph above). This is the one place the delegated decisions reach a person; a report the Owner can only nod at is a failed report. Only then ask for the next brief — and the Lead does not write it, whatever the unit's size. When step 7 recommended a replan that would change the next unit, skip the rest of this step and say in the report that the brief waits for the Owner's answer. Brief-writing is the Planner's judgment work (unit sizing, a direct build or a Robowright Session, one-way doors, invariants for the Reviewer, the Worker variant), so start a fresh, short Planner session on the model
robowright.jsonnames for the Planner, per the profile → Launch. A launcher creates the session directory, points the Planner at the newestINTAKE.md, names the session per the project hook → Naming, and refuses ifBRIEF.mdalready exists. Say in the report that it started, with its observe command. If the profile names no launcher, hand the Owner, or whoever the profile names, the launch line it names; if the launcher endslaunch is yours, report that line and do not re-run--yes, as "Launch hand-off" says, whichever mode produced it. A Planner session is not pinned. The launch carries this prompt:/planner brief <slug>: write BRIEF.md and run.json into <session_dir>, or the direct-build briefing, from the corrected plan; the newest intake is <INTAKE.md path>. Doc-gate what you wrote, log the decision, print the launcher's dry-run line, end.When the Planner's session goes idle (arm
notify_when_idleon it), the roster shows the new session directory; launch it per "Launch hand-off". When the Planner handed back a direct-build briefing at<project>/briefings/<unit>.mdinstead, with its--directdry-run line, launch that with--directas "Launch hand-off" says. Either way, launch nothing while the Planner's doc-gate readsBLOCKED, which its last message and itsDECISIONS.mdentry say: bring the Owner its asks, and launch on their answer and a freshREADYpass. Send the answer to that Planner withSendMessage; it writes the answer into what it wrote and runsreviewer-docsagain. The Lead never edits a brief or a briefing, and the launcher refuses a second brief-only Planner onceBRIEF.mdexists.A brief written before intake inherits every stale name in the plan. A brief written by the Lead inherits the Lead's context instead of the Planner's judgment.
parked — the Owner said leave it
Nothing. The Owner applied park to a briefed, done or stopped session; no event leaves
that state.
Never resume it, never nudge it, never count it stalled, and never spawn reviewer-intake
for it, even when it was parked straight from done. The roster prints it on its own
parked: <run> · <age> · <reason> line below the table, however old: the 48 h window that drops
terminal rows does not drop it. A --since tick prints only what changed, so there the line
appears when the parked session's fingerprint changes, and crossing 48 h is not a change: only a
removed session directory, or a run.json the roster cannot read, prints no longer on the roster. Read the line and act on nothing. Parking
already removed the session's own locks. The worktree, if the session had one, stays, and deleting it is the Owner's.
After publishing — lead.post-publish
Published work may have a review surface the Lead then owns — a stack in review, incoming
feedback, a bot's findings, a watcher to run and stop. None of that is in this handbook,
because none of it exists on every machine: what "published" means at all is the project hook →
Publishing, keyed on the strategy run.json.publish names or, once published, records as publish.strategy. Run every duty the profile, then the project hook, lists for lead.post-publish,
in order, and nothing when both list none.
Three rules hold whatever those duties are:
- The Lead plans and drafts; it never posts. Every reply another person reads is the Owner's to send — bring it in the report as "here is the text; post it?".
- A claim from a bot or a reviewer is verified by a fresh Reviewer, never by this session's own reading of the code.
- Incorporation is a Worker's job. When feedback means a code change, the Lead does not
commit it: it asks a Planner for a brief (
<slug>-review-feedback) and launches that Robowright Session like any other. One Robowright Session per review round, not one per comment.
The surface is done when every thread is closed or incorporated and the Owner has accepted the work. Stop anything still watching it and say so in the report.
Wrap-up — the project report
When PROJECT.md's Task Breakdown has no open rows and robowright.json.project_report is true:
start an Explainer in report mode per the profile → Launch. The Explainer writes
<project_dir>/REPORT.md and, where a duty under explainer.publish would put that report
somewhere other people read, prints the line that would do it. Bring the Owner the report and
that line; publishing is their explicit yes for that page, every time, and you never run it on
your own. Then hand the Planner's Phase 7 checklist (final re-sync, living docs, follow-up
items) to the Owner as the closing report and end the Lead session.
Launch hand-off
A Lead writes no git directory. It reads repositories with plain git. Every write to a git directory is a
Worker's or a direct build's, through rw-git (rw-git --help), or the Owner's: accept.sh, teardown, a worktree the
launcher cannot make.
The Planner has written BRIEF.md and run.json into the session directory (profile → Paths);
the launcher derives the worktree's place from the repository's shape, and run.json.repo chooses between
repositories only at a root more than one of them declares. Never run git worktree add for a launched Worker, and never hand the Owner that line: the Lead's
sandbox cannot write a repository's git directory (SECURITY.md → What each role can write), and the launcher makes a
missing worktree itself, as the Owner, on the launch after the dry run. It makes one only at the repository's shape
(launch.json → worktrees; with no entry <repo>/.worktrees/<session dir name> on robowright/<session dir name>),
from run.json.base_sha at preflight; a refusal naming the shape, the branch or base_sha goes back to the Planner
as a run.json fix, as does a tie-break refusal naming run.json repo. A standalone brief (a work order, or any brief with no project
robowright.json) keeps the old shape: the worktree is the brief's worktree row, made the same way, and repo is
checked the same way, only at a place more than one repository's shape gives. It
then checks the brief's profile, its model
and rotate_sessions against the session's shape. A non-null brief-level model switches the run
profile off for every unit: when any unit's kind is tests, docs or refactor, launch only
if the brief gives a one-line reason for it, and otherwise ask for null first. A non-empty
run.json.depends_on is checked next, before any dry run: for each entry,
run-roster.py --only <session> --json must return a row whose phase is done and whose
verdict is done. An empty runs list, parked, any other phase, or any other verdict means
no launch — an invalid:<why> verdict included, since the roster reports a state-machine
violation in verdict and leaves phase as stored; report which entry and what the roster showed. Then it launches exactly as the profile → Launch says, and dry-run first, always, wherever that
section's launcher offers one: the dry run prints the worktree, the session name, the model and
effort lines, and the exact command, and refuses on a dirty tree, a wrong phase, a STOP file, or a session already
in that worktree. Where the worktree does not exist yet, the dry run prints only the worktree add line the launch
will run and stops; the --yes launch makes it, then runs every other check before anything starts.
A --yes that exits 0 ending launch is yours is a hand-off, not a start. Nothing started:
launch.json's launch key says paste (or is absent), or it says auto and the shell could
not start a session (EPERM). The launcher printed a paste this yourself: line and wrote a
hand-off via entry to the ledger. Report that line verbatim to the Owner, or to whoever the
profile → Launch names; they run it from a shell that can start a background session. Never
re-run --yes for that session: it hands off again and writes a second entry. Any other
failure still exits 1.
A hand-off leaves run.json without the session, so --resume has no id and the cost reader
prices every transcript the worktree ever saw. When the recipient says the paste ran, take the new
session's id from claude agents --json (the row whose cwd is the worktree) and run
run-launch.sh --run-dir <session_dir> --pin <id>. It writes session_id and transcripts and
appends a pinned after hand-off ledger entry. It starts nothing and needs no --yes. An id
the session registry does not know is refused, and nothing is written. A rotation hand-off is
pinned the same way.
The model: line says — overrides robowright worker <x> when a hand-written model (--model, the
unit row, or the brief) differs from run.json.robowright.worker; a model the profile chose never
carries it. Before --yes, check that the unit or brief meant that override.
Say in the report that a Robowright Session was started, with its handle and the command the
Owner runs to watch it — the observe command the profile → Launch names — in the same message
as the launch. This applies to every background agent the Lead starts, not only Worker
sessions: a delegated build, a steward, a sweep. If the work went to an in-process Agent
subagent instead (no attachable session), give the transcript tail:
tail -f "$(ls -t <this session's tasks dir>/*.output | head -1)"and prefer a named background session next time for anything the Owner might want to watch. The rule: hand the Owner the command that attaches to any background session the Lead starts, so they can watch it.
A direct build (planner → Phase 6, "Size S or below") has no session directory and no run.json. Launch it with
run-launch.sh --direct --project <project dir> --slug <unit> --repo <repo> --base <full commit id> --briefing <project
dir>/briefings/<unit>.md, dry-run first. The launcher makes <repo>/.worktrees/<unit> on robowright/<unit>
from --base with the Worker's checks, or reuses the build's own worktree there, and refuses anything else at that
path. It starts build-<unit> in the worktree with a Planner's grants, on a fixed prompt naming the briefing file,
and appends its launch line to the project's DECISIONS.md. Never cd into the worktree and start claude
yourself: a reset cd starts the build in the project folder, with no grant on its worktree. After an auto start
the launcher confirms the session's cwd from the registry and exits 1 when it is not the worktree, naming both: stop
that session. A paste hand-off is reported like any other. On a machine where the launcher cannot run, hand the
Owner the hook's git worktree add line and the hand-started line from the planner handbook.
When the Owner accepts a finished direct build, hand them its accept.sh --direct line (table above), never a
hand-run cherry-pick: only accept.sh writes the record the dashboard reads as accepted. The base is the full commit
id the launch line's --base named; the tip is the full id of the branch tip the change was reviewed at. Before
composing the line, read what the build wrote: the change description cites a full-suite log and a tip file, the log
ends in the hook's verdict line for a finished, passing run (EXIT=0 for Robowright's own suite), and the tip file
holds the same id before and after the run, equal to the reviewed tip. Missing, stale or unfinished, send the build
back to run the suite: that run is the build's, not yours. Compose the
line yourself: never relay one a Worker or a direct build wrote, and take --tip from git rev-parse refs/heads/robowright/<unit> in the
main clone, checked against the tip the review names, not from the change description.
A launched session's name is what makes the roster's session column and SendMessage
addressing stable; a derived display name is not a resume handle, so every launch passes the
name the project hook → Naming gives. Arm notify_when_idle on the new session at the next tick, per step 3.
Before launching another Robowright Session — arbitration
Multi-agent systems fail often — 41–87% across seven frameworks — and their gains over a single agent are "often minimal" (MAST). The roster's budget column is the record of what one costs — sessions the Owner opened in the worktree afterwards included. One Lead, one to three Robowright Sessions. Before a second or third:
- Base dependency. A Robowright Session based on an unmerged branch cannot start until that
branch is where the brief says it is, and the base moving under it mid-session is a
base-movedstop. Dependent units are sequential — the successor's base does not exist until the predecessor is accepted. A stack runs as one Robowright Session by default (sizing-the-moverule 6; settled 2026-09-16); the brief names a unit boundary as a stop only when later units' names or shapes depend on review of an earlier one, and says so. - Devices. One device lease per Robowright Session, as the project hook defines it (→ Device); the pool is finite. Check what is already leased before assuming one exists for the new session.
- Disk. A worktree's build output runs to tens of GB (the project hook → Build names the directory). Check its size and free space before creating a worktree; offer the accept step the project hook → Publishing names for finished Robowright Sessions first.
- The Owner's review queue. Count what is already published and waiting on them (project hook → Publishing). A Robowright Session that finishes into a long queue of unreviewed work produces stale work, not throughput. Say the number when proposing a launch.
- Budget. Every brief carries the budget fields the profile → Budget names — a warn
threshold and a cap, or the reason time is the only cap; the Lead proposes both from the
roster's record for comparable Robowright Sessions and the Owner ratifies them with the brief.
The finished session's
run.json.costblock (worker/scripts/run-cost.py) is the record to read first — requests, average context, lines written against shipped — and the brief's verification ceilings (max_mutation_rounds_per_unit,whole_suite_runs_owed,max_extra_review_subagents) androtate_sessionsare set from it, not from memory. The enforcement that section names is what acts on those numbers — the Lead never writesSTOPitself, and never raises a cap without the Owner's word. Report the roster's budget column and thelead:line when proposing a launch: what is already running plus the new brief's cap is the exposure. - The Lead's own cost. The
lead:line is context size × ticks. A Lead session starts fresh, on the modelrobowright.jsonnames for the Lead (Opus by default), and stays small:--sinceticks, Readers for anything big, Reviewers for intake. If it passes what the profile → Budget allows a Lead session, or the roster has to be re-read from scratch after a compaction, end it and start another — everything it needs is on disk, and a fresh session ticks for a small fraction of what a grown one costs.
Running the watch
The Owner starts it: /loop /lead watch. Each firing is one tick above. Pacing:
- Everything
running, idle notices armed on thebusyones →ScheduleWakeup1200–1800 s, with the tool'snoopflag set unless a verdict changed or you acted. The notice is the primary signal; the wakeup is the fallback for a session that dies without one, and the only signal for one inshellordialog. - Anything
stoppedorstalledawaiting the Owner → 1800–3000 s. Polling does not make the answer come faster; the report already went out. - Nothing non-terminal and no intake pending →
stop: true.
An idle notice arriving mid-wait is a tick: run the roster, act, re-arm per step 3 — only a
session the plain roster shows back in busy — and reschedule.
Notices from a session in a different permission class are shown to the Owner in the transcript
instead of to you (the SendMessage result says which) — the wakeup still catches it.
Never ListAgents in a loop and never send "are you done?" — the roster and the notice are
the two allowed ways to learn a Robowright Session's state.
Reporting
The decision-reporting shape the Owner's own rules give, when the machine has them, at the end of a tick that changed something. The roster table
leads, one line per Robowright Session, then the calls. A stop is a **Decisions** item with the
options and your recommendation; a stall is **Open:**. Rejected routes go to DECISIONS.md,
not chat. A tick where nothing moved says so in one line. Every unit a report, a decision review
or a launch hand-off names is U12 (note-autosave) (robowright → Contracts every role keeps, 11).
Session shape
The Planner ends when the first brief is written; the Lead is a fresh session. The
Owner starts it in the project folder, on the model robowright.json names for the Lead (Opus
unless the project set otherwise) and under the session name the project hook → Naming gives, then:
> /loop /lead watchEverything the Lead needs is on disk (PROJECT.md, DECISIONS.md, the session directories,
the roster); anything it cannot find there is a gap in the plan, reported as such, not
reconstructed from a planning conversation. Every later brief comes from a fresh Planner
session the Lead asks for after intake (see done). The alternatives — the Planner carries on
as Lead, or an idle Planner messaged for briefs — and why they lost are in
robowright/DESIGN.md §7. A Lead over Robowright Sessions that were never planned through
planner (a standalone worker brief) works the same way with no PROJECT.md; intake then
writes to the decision log for that repo.
Never
- Never post, merge, accept, or reply to a person or a bot on the Owner's behalf — the Owner's own rules on acting on their behalf, when the machine has them, are unchanged by this skill, and the profile → Owner-only floor only adds to it. A Robowright Session publishes; a person takes it from there.
- Never edit a Robowright Session's worktree,
run.json,HANDOFF.md, orBRIEF.mdmid-session.LEDGER.mdappends and theresumeevent (throughsession-state.py, never an edit) are the two writes the Lead makes into a session directory, and only to record a decision — the Owner's, or its own underdelegation. - Never
SendMessagea session that is not a Robowright Session's own or a Planner the Lead started (to carry the Owner's answer to aBLOCKEDbrief), and never ask one to do something this session was denied — that is permission laundering, and the tool says so. - Never write
STOPyourself. The enforcement the profile → Budget names writes it at the cap the Owner ratified in the brief; anything else is the Owner's word, typed by them. - Never fan out speculatively. A third concurrent Robowright Session needs the arbitration list above to come back clean, said out loud.
- Never start a background agent without handing the Owner the observe command in the same message (see "Launch hand-off").
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.

