| description | Dispatch a background worker with role-templated prompt and auto-populated collision fences |
| mode | full |
| version | 1.1.0 |
| worker_template_version | v2 |
| level | intermediate |
| debug | false |
| category | orchestration |
| tags | ["dispatch","team","background","worker","orchestration","role"] |
| args | [{"name":"spec","description":"Inline YAML spec or path to YAML spec file (name/team/role/scope/targets required)","required":true},{"name":"--dry-run","description":"Print compiled prompt without spawning agent","required":false}] |
| inputs | [{"name":"spec","description":"YAML string or file path with dispatch spec"}] |
| outputs | [{"name":"worker_name","description":"Name of the dispatched worker"},{"name":"task_id","description":"ID of the created task"}] |
Dispatch Worker
Compile a worker dispatch spec through node_dispatch_worker and spawn a background agent.
Announce at start: "I'm using the dispatch-worker skill."
Autonomous execution: No human confirmation gate. --dry-run is the only preview mechanism.
Worker Behavior
Required for all dispatched workers — enforced by _COMMON_PREAMBLE in
omnimarket/src/omnimarket/nodes/node_dispatch_worker/handlers/handler_dispatch_worker.py.
- Ack after each deliverable. After every discrete deliverable (design doc written, test
run complete, PR opened, finding logged), send a one-line
SendMessage to {reports_to}.
Never batch acks across multiple deliverables.
- Stop after primary task. When the primary task is complete, send exactly:
"Primary task done — awaiting further instruction or shutdown." then stop.
Ambient-idle looping after task completion is forbidden.
Quick Start
# Inline YAML spec
/dispatch_worker "
name: pr-202-fix
team: daylight-0411
role: fixer
scope: Fix omnimarket#202 halt_conditions CodeRabbit findings
targets: [omnimarket#202, <TICKET>]
"
# From file
/dispatch_worker ~/docs/plans/workers/pr-202-fix.yaml
# Dry run (print compiled prompt, no spawn)
/dispatch_worker --dry-run "
name: vggp-designer
team: daylight-0411
role: designer
scope: Design VGGP inference pipeline
targets: [<TICKET>]
"
Valid Roles
| Role | Purpose | Default cap |
|---|
watcher | CI watch loop, no code changes | 90 min |
fixer | TDD-first fix + hostile_reviewer + PR | 90 min |
designer | Design doc + hostile_reviewer + plan | 120 min |
auditor | Read-only investigation + findings doc | 60 min |
synthesizer | Reconcile cross-domain design docs | 90 min |
sweep | Short-lived cron pulse, one metrics line | 10 min |
ops | Long-lived stateful admin worker | 480 min |
Spec Format
name: <worker-handle>
team: <team-name>
role: <role>
scope: "<goal description>"
targets: [<ticket>, <pr>, ...]
collision_fences: []
reports_to: team-lead
wall_clock_cap_min: 90
model: sonnet
replace: false
Dispatch record persistence ()
Immediately after the node compiles the worker prompt and before Agent() is
spawned, write a ModelDispatchRecord to
$ONEX_STATE_DIR/dispatches/<agent-id>.yaml so downstream hooks
(allowedTools audit, tool-call usage audit, consecutive-failure halt) can
reason about the dispatch:
from datetime import datetime, timezone
from omniclaude.hooks.lib.dispatch_record_writer import write_dispatch_record
from omniclaude.hooks.model_dispatch_record import ModelDispatchRecord
write_dispatch_record(
ModelDispatchRecord(
agent_id=spec["name"],
dispatched_at=datetime.now(timezone.utc),
dispatcher="onex:dispatch_worker",
ticket=spec["targets"][0],
allowed_tools=spec.get("allowedTools", []),
prompt_digest=prompt_digest,
parent_session_id=parent_session_id,
)
)
The PostToolUse post_tool_use_subagent_tool_log.sh hook appends a JSONL
line per subagent tool call to
$ONEX_STATE_DIR/dispatches/<agent-id>/tool-calls.jsonl when
ONEX_AGENT_ID is set in the subagent environment.
Worker Operating Rules (worker_template_version: v2)
The following 9 rules are injected verbatim into every worker prompt by prompt.md
before spawning. They are auto-injected — dispatchers MUST NOT hand-restate them.
## Operating Rules (auto-injected by dispatch_worker skill v2)
1. **No pre-existing excuse.** Pre-existing test failures block shipping regardless of
provenance. Fix them in the same PR or file a blocker — never push red tests.
2. **PR closing keyword.** The PR body MUST contain `Closes OMN-XXXX.` (exact closing-
keyword form, where XXXX is the primary ticket). Without it the receipt gate fails.
3. **Worktree-only development.** All code changes happen in a ticket worktree under
`$ONEX_WORKTREES_ROOT/<ticket>/<repo>/`. NEVER stage or commit inside the
canonical repo clone. The worktree guard hook enforces this.
4. **Full test suite before push.** Run `env -u PYTHONPATH uv run pytest tests/ -v` with
NO `-k` filter as the final pre-push check. The `env -u PYTHONPATH` prefix is required:
omniclaude hooks export PYTHONPATH into the parent environment, and that value shadows
the worktree's local `src/` layout, causing import failures. Always prefix `uv run`
and direct `python` invocations inside worktrees with `env -u PYTHONPATH`.
5. **Never bypass pre-commit hooks.** Never use `--no-verify`, `--no-gpg-sign`, or any
bypass flag. Pre-commit hooks enforce code quality and architectural constraints.
Fix the issue instead of bypassing the gate.
6. **Anchor-first ordering (<TICKET>).** Phase 0 is mandatory and must complete before
any long implementation leg: (a) verify or file the Linear ticket; (b) push a WIP
branch to origin (even if the branch is empty). Write a resume manifest to
`$ONEX_STATE_DIR/manifests/<ticket_id>/manifest.yaml` immediately after the WIP push
using `resume_manifest_writer.write_resume_manifest()` with
`phase=EnumResumeManifestPhase.PHASE_0_ANCHOR` and `wip_pushed_at` populated.
Update the manifest at every subsequent phase boundary (implement, local_review,
create_pr, done). On any auth or usage-limit error, call
`resume_manifest_writer.write_survivor_note(manifest, detail="<what was diagnosed>")`
before terminating so the defect retains identity even without a filed PR.
7. **Verifiable-handle reporting.** End with a ```json-report``` block; a merged/deploy
claim without its handle is BLOCKED at SubagentStop. (Full text in prompt.md.)
8. **OCC receipt pairing — tool-generate, never hand-author (<TICKET>, retro D-4).**
Runtime-path PRs pair with an OCC contract + receipt produced by
`uv run scripts/scaffold_occ_receipt.py <TICKET-ID> --pr-number <OCC-PR#> ...`,
which emits the full schema INCLUDING `contract_sha256`, defaults `--base dev`,
and self-reports the four OCC #2530 wedges. Each prohibition (no skip token,
target dev not main, never arm blind, cite Evidence-Source + Evidence-Ticket)
ships with its failure mode and alternative — "STOP and report back — any
bracketed skip-token hard-fails your PR." (Full text in prompt.md.)
9. **UI proof requires Playwright, not `curl` (D-6, <TICKET>).** For any DoD item that
touches UI behavior, the required proof is a Playwright interaction with the operator's
running surface: the live URL, a screenshot, and the network log of the actual request
the UI emitted. A `curl` of the canonical endpoint is NOT acceptable evidence for a UI
claim — it proves the backend answered, not that the operator's surface renders the data
or emits the request. Bridges the gap until the A-2 Receipt-Gate evidence-class check
(<TICKET>) is live.
See Also
node_dispatch_worker (omnimarket) — compiles the prompt template
- Design:
docs/design/dispatch-worker-skill-design.md
src/omniclaude/hooks/model_dispatch_record.py — dispatch record schema
src/omniclaude/hooks/lib/dispatch_record_writer.py — writer/reader
src/omniclaude/hooks/model_resume_manifest.py — resume manifest schema ()
src/omniclaude/hooks/lib/resume_manifest_writer.py — phase-boundary manifest writer ()