Skip to content
Back to skills

Dispatch Spawn

ASecurity

The one spawn path for `/dispatch` — `scripts/spawn-confined.sh <harness>` forks the worker's worktree, wraps it in a kernel-level jail, and runs the harness headless inside it. Every harness takes this path; there is no in-session arm and no unconfined fallback. The worker cannot commit — it hands back an uncommitted working tree and the orchestrator imports it. Reached from the `/dispatch` router; do not invoke directly.

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 19, 2026
developmentrustgit

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add davidlee/doctrine --skill dispatch-spawn --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dispatch Spawn?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dispatch Spawn
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/davidlee-dispatch-spawn/badge)](https://www.skillsdirectory.com/skills/davidlee-dispatch-spawn)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dispatch-spawn
description: The one spawn path for `/dispatch` — `scripts/spawn-confined.sh <harness>` forks the worker's worktree, wraps it in a kernel-level jail, and runs the harness headless inside it. Every harness takes this path; there is no in-session arm and no unconfined fallback. The worker cannot commit — it hands back an uncommitted working tree and the orchestrator imports it. Reached from the `/dispatch` router; do not invoke directly.
---

# Dispatch — spawn a confined worker

One spawn shape, for every harness. The drive cadence lives in the
[`/dispatch` router](../dispatch/SKILL.md); this skill is the spawn call plus the
landing mechanics.

See `lib:reference/dispatch-mechanics.md` § The worker returns a working tree,
not a commit.

## Spawn

```sh
scripts/spawn-confined.sh <harness> <B> <BRANCH> <DIR> <PROMPT_FILE> [BACKSTOP_SECS]
```

`<harness>` is `pi` or `claude`. The script does the whole pre-spawn sequence
itself — you do not fork separately:

1. **Capability probe.** Linux asserts `bwrap` is present and refuses
   `bwrap-unavailable` *before* minting a fork; macOS gets its named refusal from
   `doctrine worktree jail-prefix`, which fails closed and writes no prefix.
   **There is no unconfined fallback** — an unresolvable jail aborts the spawn
   rather than degrading (an empty prefix is caught by its own guard).
2. **Fork.** `doctrine worktree fork --base <B> --branch <BRANCH> --dir <DIR>
   --worker`, orchestrator-classed, run from the project root before any
   confinement. The fork is deliberately **unbound** — no `--slice`/`--phase`
   (see *The funnel*, below).
3. **Confine + exec.** `timeout <BACKSTOP> <jail prefix> <harness exec>`,
   delivering `<PROMPT_FILE>` to the worker (stdin for `claude`; one compact RPC
   line for `pi`) and capturing the transcript. The jail rw-binds the fork dir
   and the harness config dir, ro-binds the rest, and sets `DOCTRINE_WORKER=1`
   inside the namespace.
4. **Hand back.** `claude -p` exits when the turn ends — process exit *is* the
   completion signal. `pi --mode rpc` never self-exits, so that profile alone
   holds stdin open with a fifo and polls for its typed settle event. That
   asymmetry is the only harness difference beyond the config dir and the exec
   line.

See `lib:reference/dispatch-mechanics.md` § Workers can silently discard their
own work for the prompt-fencing rules (clean checkout, forbidden verbs,
edit-not-discard for a red proof).

Never trust the worker's self-reported success. The tree is the ground truth.

## Landing

The delta is an uncommitted working tree that **persists** after the process
exits — nothing auto-reaps it.

1. **Import.** `doctrine worktree import --base <B> --from-worktree <DIR>
   --slice <N>` — gathers the tracked + untracked delta, runs the
   `classify_import` scope belt and the reject-and-halt prove gate per
   `lib:reference/dispatch-mechanics.md` — a red delta halts staged, never
   auto-fixed (land-or-reject, never rewrite). Any refusal is
   report-and-halt — never import around it.
2. **Commit ONE** on the coordination branch — the orchestrator's own act, and
   the reason import is non-committing.
3. **Record the boundary.** `doctrine slice record-delta <N> PHASE-NN --commit
   <S>`, with `S` **pinned at the code commit**, never read from `HEAD` at record
   time. Knowledge commits trail the code commit, so `HEAD` may have moved;
   `--commit` records exactly `S`'s own patch, which excludes trailing knowledge
   and any refresh-base merge by construction. This write is **not skippable** —
   `dispatch sync --prepare-review`'s completeness gate halts if a completed
   phase has no registry row.
4. **Verify and conclude.** Run the phase's verification on the coordination
   tree (the worker's own report is advisory), then flip the sheet:
   `doctrine slice phase --status completed <N> PHASE-NN`.
5. **Reap** the spent fork: `doctrine worktree gc --fork <BRANCH>` — the
   unfunnelled-fork case its patch-id oracle is narrowed to, and idempotent.
   Never `git worktree remove --force` an unimported tree: that deletes the sole
   copy of the delta. `--dry-run` prints the verdict and destroys nothing.

## The funnel: a bound fork's machinery, not this path's

See `lib:reference/dispatch-mechanics.md` § The funnel record, and when it is
the driver — this path forks unbound, so no row lands and `next` sits at
`spawn`.

## Red Flags

**Never:** instruct or expect a worker to commit (its `.git` is read-only —
there is no self-commit path); spawn outside the script (a hand-rolled exec is
an unconfined worker); omit the backstop timeout; `eval` the prompt; use a
heredoc for the pi profile's RPC stdin (EOF kills it); import around a scope or
prove-gate refusal (a refusal is a defect or a halt, never a detour); auto-fix a
red delta into the import; force-remove a fork before its delta has landed;
trust the worker's own green/failure labels; treat a `spawn` prescription from
`dispatch next` as a stuck funnel.

**Always:** halt on a non-zero spawn (fail-closed is the whole posture — a
confinement that cannot be established means no worker); pass a pre-distilled,
self-contained prompt; import with `--slice` so the scope belt has selectors to
check; pin `S` at the code commit before recording the boundary; return to the
router for the drive cadence.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.