| name | do |
| description | Orchestrate complex Unity tasks by planning and dispatching to specialized subagents in parallel. Use for any multi-step task that benefits from parallel execution. Enforces write-set collision checks and MCP instance pinning automatically. |
Task Orchestrator (with parallelism enforcement)
/do is the entry point for any non-trivial multi-agent task. It plans the work via the dispatch-planner agent, validates the resulting wave manifest against tools/do/check-writesets.py, injects MCP instance pins, and dispatches in waves with maximum parallelism.
The legacy advisory rules in .ai/knowledge/tooling/agent-guide.md (Pre-Read & Inject, write-set mapping, instance routing) are now enforced infrastructure when invoked via /do. Other dispatchers (/e2e, /physics, /improve-environment) still use the legacy manual pattern.
Argument grammar
/do <task> # normal path; gated by ~/.tmp/r8eox/enforcement.json
/do --rebind-dev-instance <hash> # one-shot: write ~/.tmp/r8eox/dev-instance.txt and exit
/do --no-enforce <task> # per-invocation bypass of write-set check (NOT pin injection)
/do --enforce-off # persistent: write enforcement.json with {enabled: false}
/do --enforce-on # persistent: write enforcement.json with {enabled: true}
/do --fanout-fragment <path> <task> # explicit handoff from /fanout shard
/do -- <task starting with double dash> # argparse end-of-options marker
--enforce-on, --enforce-off, and --no-enforce are rollout-and-recovery tools. Use --no-enforce only when the checker reports a false positive; each invocation logs a line to .tmp/do/<run_id>/enforcement-bypass.log. Default ship state is enabled: false (file missing); flip to true only after Verification §6–§12 pass on this machine.
Per-run directory layout
Every /do invocation generates a run id at startup:
run_id = <UTC timestamp YYYYMMDD-HHMMSS> + "-" + sha1(task_text)[:8]
# example: 20260411-210344-a3f29d1c
and allocates .tmp/do/<run_id>/ for ephemeral state:
.tmp/do/<run_id>/
├── task.txt # verbatim task text (session identity)
├── plan.json # canonical manifest produced by dispatch-planner
├── fanout-wave.json # optional copy of /fanout shard fragment
├── enforcement-bypass.log # appended by --no-enforce invocations
└── platform-primitives.snapshot.json # gate state at dispatch time (debugging)
Local-only files that persist across runs (per-machine, never tracked):
~/.tmp/r8eox/dev-instance.txt # operator binding for the dev editor hash
~/.tmp/r8eox/enforcement.json # rollout kill switch
~/.tmp/r8eox/platform-primitives.json # machine-readable platform-verification gate
Schema examples for the two JSON files are tracked at .claude/skills/do/enforcement.example.json and .claude/skills/do/platform-primitives.example.json. The runtime files are created via tools/do/local-state.py.
Canonical wave manifest schema
dispatch-planner is the SOLE producer of plan.json. Every /do task — trivial or complex — runs through it.
{
"schema_version": 1,
"task": "free-text description",
"waves": [
{
"id": 1,
"depends_on": [],
"agents": [
{
"index": 0,
"type": "unity-script-writer",
"read_only": false,
"edits": ["Assets/Scripts/Foo.cs"],
"creates": [],
"deletes": [],
"creates_dirs": [],
"deletes_dirs": [],
"reads": ["Assets/Scripts/Bar.cs"],
"extra_writes": [],
"mcp_capable": false,
"pin_target": "none",
"isolation": null,
"background": false
}
]
}
]
}
Field rules:
schema_version must be 1.
waves[].id strictly increasing from 1; duplicates and non-monotonic ids fail validation.
waves[].depends_on defaults to [] when omitted. Waves must EXPLICITLY list every prior wave they read from. Implicit "previous wave" chaining was removed because it leaked transitive dependencies.
agents[].read_only: true requires all five write arrays (edits, creates, deletes, creates_dirs, deletes_dirs) to be empty.
agents[].pin_target is "dev", "test", or "none". Every unity-e2e-tester MUST be "test" — the validator hard-fails otherwise.
agents[].isolation is null or "worktree". Worktree agents are exempt from intra-wave collision checks.
agents[].background: true and isolation: "worktree" are gated by ~/.tmp/r8eox/platform-primitives.json (see §15 manual checklist).
Companion-write expansion (the validator does this automatically)
The collision checker derives a normalized write_set per agent:
creates, deletes → auto-add <path>.meta and the parent folder's CLAUDE.md
creates_dirs, deletes_dirs → auto-add <parent>.meta (Unity NewFolder.meta), <dir>/CLAUDE.md (the new folder's own doc), and <parent>/CLAUDE.md (parent gains/loses a subfolder)
edits → does NOT auto-add anything. Two agents editing different files in the same folder do NOT collide on that folder's CLAUDE.md.
extra_writes is the escape hatch when an agent genuinely needs to touch a sibling file the rules don't capture.
This is what makes wider parallel waves safe.
Pre-dispatch pipeline
Every non-bypassed /do invocation runs:
- Allocate run id —
run_id = <timestamp>-<sha1(task)[:8]>. Create .tmp/do/<run_id>/. Write task.txt verbatim.
- Read MCP instances — call
ReadMcpResourceTool(server="UnityMCP", uri="mcpforunity://instances") and store the payload. Pipe through python3 tools/do/pick-dev-instance.py --home ~ < <payload> to get the dev editor hash. If the picker errors, surface the message and abort (most common: "no project_path in payload — run /do --rebind-dev-instance <hash>").
- Plan via dispatch-planner — dispatch
dispatch-planner (subagent_type) with the task plus the current platform-primitives snapshot. The planner returns ONLY a fenced ```json block. Pipe its stdout through python3 tools/do/extract-planner-json.py to validate and unwrap. Retry once with a stricter reminder if extraction fails; on second failure, surface the planner's raw response and abort.
- Merge fanout fragment (if
--fanout-fragment <path>) — read <path>, verify its task_hash matches sha1(task)[:8], copy into .tmp/do/<run_id>/fanout-wave.json, append to plan.json with id = max(existing) + 1. Mismatched task hash → hard error "fanout fragment is for a different task".
- Validate — run
python3 tools/do/check-writesets.py --run-dir .tmp/do/<run_id>. Block dispatch ONLY on non-zero exit code. With enforcement disabled (default), the checker always exits 0 and reports advisories on stderr — surface them but don't block.
- Inject pins — for each agent in the manifest:
pin_target: "dev" → prepend Pin to instance: R8EOX@<dev_hash> to the dispatched prompt.
pin_target: "test" → do nothing. The agent (typically unity-e2e-tester) handles its own pinning.
pin_target: "none" → do nothing.
- Dispatch — for each wave in order, send a single message containing one
Agent tool_use per agent in that wave (parallel within the wave). Pass isolation: "worktree" and run_in_background: true from the manifest fields verbatim. Wait for all agents in the wave before starting the next.
- Consolidate — after the final wave, run
git status, summarize commits, surface any reviewer findings.
Dev-vs-E2E instance discrimination
The picker (tools/do/pick-dev-instance.py) uses two strategies in order:
- Project-path rule (preferred): if any instance entry has
project_path, projectPath, path, or projectRoot, classify entries by absolute substring match: paths containing /.claude-worktrees/ are E2E editors; the remaining one is dev. Multiple non-worktree → ambiguous error. Zero non-worktree → no-dev error.
- Operator-binding fallback: only if NO entry has a path-like field. Read
~/.tmp/r8eox/dev-instance.txt (one line, the dev hash). If missing or stale → error "run /do --rebind-dev-instance <hash>".
/do --rebind-dev-instance <hash> writes ~/.tmp/r8eox/dev-instance.txt via tools/do/local-state.py write-dev-instance --hash <hash> and exits without dispatching.
Background & Worktree Isolation
Two Agent primitives are gated by the platform-primitives file (see §15 manual checklist):
| Primitive | Use when |
|---|
run_in_background: true | Agent runtime > 2 min AND result not required for next orchestrator step. Examples: unity-e2e-tester, physics-regression-detector, unity-profiler. |
isolation: "worktree" | Two agents have unavoidable write-set overlap but the work is logically independent. Worktree-isolated agents are exempt from the intra-wave collision check. |
Both are emitted by dispatch-planner ONLY after is_primitive_verified() returns True for the corresponding row in ~/.tmp/r8eox/platform-primitives.json. The validator independently rejects any manifest emitting a gated field while the gate is unverified — defense in depth, fail-closed.
/fanout handoff contract
For big read-mostly jobs (codebase audits, refactor sweeps), use /fanout shard first to deterministically split a glob into N read-only research agents:
/fanout shard --buckets 4 --glob "Assets/Scripts/**/*.cs" \
--task "audit for FindObjectOfType" \
--task-hash a3f29d1c \
--out /tmp/fanout-test.json \
--agent-type unity-researcher
Then hand the fragment to /do:
/do --fanout-fragment /tmp/fanout-test.json "audit for FindObjectOfType"
/do validates that the fragment's task_hash matches sha1(task)[:8], copies it into .tmp/do/<run_id>/fanout-wave.json, appends it as a new wave in plan.json, and runs check-writesets.py against the merged plan. Mismatched task hash → hard error.
/fanout context <task> (the other mode) emits a pre-loaded context block that the orchestrator pastes into N parallel agent prompts — eliminates the manual Pre-Read & Inject pattern when not sharding.
Agent prompt template
Every agent prompt MUST include:
- Reference to
.ai/knowledge/tooling/subagent-workflow.md (commit + save rules)
- The
Pin to instance: R8EOX@<hash> line (when pin_target: "dev")
- Pre-loaded shared context (root CLAUDE.md, folder rules, knowledge docs) — emit via
/fanout context or hand-injected
- Exact file paths the agent will create/modify, matching the manifest's
edits/creates/deletes/creates_dirs/deletes_dirs/extra_writes for that agent
- Documentation update reminder (companion CLAUDE.md changes already in the manifest)
Layout:
## Context (pre-loaded -- do NOT re-read these files)
### Project Conventions (from CLAUDE.md)
{namespace, code style, banned patterns, 450 line limit}
### Folder Rules (from local CLAUDE.md)
{folder-specific conventions}
### Reference (from .ai/knowledge/)
{relevant knowledge doc content}
Pin to instance: R8EOX@{hash} ← when pin_target == "dev"
## Your Task
{exact file paths to create/modify}
{exact content expectations}
{what to verify after completion}
## Documentation (after code work)
- Update CLAUDE.md Contents section for folders where you added/removed files
- Commit each file individually -- never `git add -A` or `git add .`
After each wave completes, the orchestrator MUST:
- Run
git log --oneline -<wave_agent_count> to verify commits happened
- Run
git status to check for orphaned .meta files — commit them if any agent missed them
- If an agent returned without per-file commits, treat it as a failed agent and re-dispatch
Required pre-merge gate
tools/do/run-tests.sh must pass before merging any change to the enforcement infrastructure:
bash tools/do/run-tests.sh
Wraps python3 -m unittest discover over tools/do/ and .claude/skills/fanout/scripts/. Pure stdlib — no pip install step.
Rules
- ALWAYS dispatch via the planner pipeline — do NOT plan manifests by hand in the main session
- Launch independent agents in PARALLEL using multiple Agent tool calls in a single message
- Wait for dependent waves to complete before launching the next
- If an agent reports errors, fix them before proceeding
- Each agent prompt must be SELF-CONTAINED — agents don't share the orchestrator's conversation
- Pre-read shared context once via
/fanout context and inject into every agent prompt
- Break tasks into the most granular pieces possible — maximize parallel agents
- Reference new classes/types that concurrent agents are creating so later agents know what to expect
Example dispatch
Task: "Add surface-type logging to WheelController and write an EditMode test"
dispatch-planner would emit a 2-wave manifest: wave 1 edits WheelController.cs, wave 2 (depends_on:[1]) creates WheelControllerSurfaceLoggingTests.cs. /do validates, pins, and dispatches:
Wave 1:
Agent: unity-script-writer
"Pin to instance: R8EOX@<hash>
## Context (pre-loaded) ...
## Your Task
Edit Assets/Scripts/Vehicle/WheelController.cs to add surface-type
debug logging when the wheel transitions surfaces. Read
Assets/Scripts/Vehicle/SurfaceProperties.cs for the current API."
Wave 2 (after wave 1 commits):
Agent: unity-tester
"Pin to instance: R8EOX@<hash>
## Context (pre-loaded) ...
## Your Task
Create Assets/Tests/EditMode/WheelControllerSurfaceLoggingTests.cs.
Verify the surface-type logging added in WheelController.cs (wave 1)."