pan-lane · diff

git:20261101.4758883 to git:20261102.507d152

15 added, 4 removed. Audit A to A.

---
name: pan-lane
description: "pan lane start|list|wait|report|stop|reap — launch gauntlet lanes (builder, critic, verifier, play, orchestrator conversations) from any harness, wait on their reports, and reap them. Lanes nest under the conversation that launched them."
triggers:
- pan lane
- launch a lane
- gauntlet lane
allowed-tools:
- Bash
- Read
---
# Gauntlet Lanes
## Overview
`pan lane start` launches a **lane**: an ordinary Overdeck conversation with its own working
directory, any harness, model and effort, and four launch-time facts on its row (parent, run key,
lane key, role). It nests under the conversation that launched it on the Command Deck and the Agents
page. The command reads `$OVERDECK_CONVERSATION`, so any conversation can launch lanes, whatever its
harness. Reports go through the worker report store; waiting reuses `pan worker wait` semantics.
Full reference: `reference/lanes.mdx` in the Overdeck docs.
## When to use
- Fan out gauntlet builders and critics (the `pan-gauntlet-loop` skill) when your harness has no
Agent tool, the lane needs a model the Agent tool cannot run, the lane must outlive your context or
one turn, or the lane needs its own branch.
- Anything issue-linked inside the managed pipeline is a worker (`pan worker run`), not a lane.
- Continuing a lane's own work in a fresh conversation is `pan lane start --reuse`, not `pan handoff`.
## Commands
```bash
# builders (run key from a root conversation; an orchestrator lane's launches inherit its run)
pan lane start --run hotel --key 663 --role builder --brief briefs/663.md --model claude-sonnet-5
pan lane start --run hotel --key 663 --role builder --reuse --brief briefs/663-resume.md
pan lane start --run hotel --key 663 --role builder --replace --brief briefs/663.md
# critics: a fresh lane per iteration, launched by a root conversation; --for names the builder
pan lane start --run hotel --role critic --for 663 --brief briefs/663-critic.md --model claude-opus-5-5
# (no --at: the door checks the critic out at the builder's newest done head)
# the critic ends with one verdict:
# pan lane report --file r.md --verdict NOT_YET --verdict-file gauntlet/notes/critique-663-iter1.json
pan lane show --run hotel --key 663 # i1 built → critic c1: NOT_YET (7 defects) → …
# cold play-tester: an empty directory, no Overdeck context, no CLAUDE.md
pan lane start --run hotel --key cold-1 --role play --brief briefs/play.md
# watch
pan lane list --run hotel
pan lane wait --run hotel --timeout 540 # next report of any lane in the run
pan lane wait --run hotel --after <cursor> --timeout 540
pan lane wait conv-<name> --timeout 540 # one lane
# inside a lane, at the end of its brief
pan lane report --file result.md
pan lane report --file ruling.md --status blocked # first line: RULING, SPEND, ONE-WAY or BLOCKED
# steer, stop, clean up
pan tell conv-<name> "<steer>"
pan lane stop conv-<name>
pan lane reap conv-<name> # removes the worktree, archives the conversation
pan lane reap conv-<name> --park # saves uncommitted work to a verified patch first
pan lane reap conv-<name> --keep # leaves the conversation listed
```
With no `--model`, the role's model comes from `projects.<key>.gauntlet.roles.<role>.model`; with
none there, the launch is refused. `--effort` takes `low`, `medium` or `high`.
- `--machine <label|auto>` (with `--needs <tags>` for auto) picks where the lane runs: Auto placement
- by load, or a machine label. When it picks this machine the lane launches as usual; another machine
- is refused with `Lanes on other machines arrive with PAN-4638 (chosen: <label>)` until PAN-4638 runs
- lanes there. With nothing that fits, the command prints `No machine fits: …` and exits 1.
+ `--machine <label|environment-id|auto>` (with `--needs <tags>` for auto) runs the lane on a linked
+ machine: a desktop, a laptop or a linked Fly machine. Auto places it by load; this machine's own
+ label launches here as usual. With nothing that fits, the command prints `No machine fits: …` and
+ exits 1. A remote lane prints `Lane <run>/<key> <role> i<n>: <name> on <label> in <cwd>`.
+
+ - The run's rules (parent, run, iteration, one live lane per run/key/role, `--replace`) span every
+ machine. Orchestrator lanes stay on this machine. `--reuse` continues on the newest lane's machine,
+ so it takes no `--machine`.
+ - A critic on another machine judges a commit that is on `origin`: the builder must push first.
+ - A Fly machine runs Claude Code and Codex lanes only.
+ - `pan lane list` and `show` show remote lanes with the conversation name in `ID` and the machine in
+ `MACHINE` (`(offline)` while it cannot be reached). `wait`, `stop` and `reap` work on them from
+ here; an unreachable machine delays a report and never fails the wait.
+ - Steer a remote lane with `pan tell @<label>/<name> "<steer>"`; `pan tell conv-<name>` reaches only
+ lanes on this machine.
## Rules the door enforces
- One working directory per lane, under the project's lanes root (never `/tmp`, never the primary
checkout). A second live lane with the same run, key and role is refused unless `--replace`.
- Only a root conversation launches `orchestrator` and `critic` lanes. An orchestrator lane launches
builders, verifiers and play lanes in its run. Builder, critic and verifier lanes launch nothing.
- Iteration n ≥ 2 of a builder gets a new branch `<run>/<key>-i<n>` cut from the previous
iteration's branch; a branch that reported done is frozen.
- A builder reports `done` only from a clean, pushed tree (`--allow-unpushed` waives the push).
- A critic needs `--for <builder key>`; a critic or verifier files exactly one verdict
(`--verdict`, with `--verdict-file` naming its JSON). `pan tell` refuses a critic or verifier lane
that already filed its done report: launch a fresh one instead.
- A critic's brief names no builder; the door links the builder row and tells the critic only the
commit it judges.
- `pan lane reap` never kills a process and never discards work: it refuses while a process runs in
the lane directory, and refuses a dirty tree unless `--park`.
## How to wait from each harness
- **Claude Code:** run `pan lane wait …` with the Bash tool's `run_in_background: true`. The
foreground limit is 10 minutes; a background command notifies you when it exits, and its stdout is
the report.
- **Codex and other harnesses:** wait in a loop until the exit code is not 3. A timed-out wait loses
nothing: the next one still returns the report.
Exit codes for `wait` and `report`: 0 done, 4 blocked or failed, 2 exited or idle without a report,
3 timeout (still running), 1 error. A run wait's status line ends with the next command and its
cursor; pass that cursor with `--after` so you never read a report twice.
## Close-out
Reap each lane when its work is merged or abandoned; reap builders before the orchestrator lane that
launched them. At run end, `pan lane list --run <key>` shows every lane `archived` or `stopped`.
Archived lanes stay in the list, so the run's ledger (iterations, reports, cost) stays complete.