dos-dispatch-loop
The dos-dispatch-loop runs repeated `/dos-dispatch` cycles on a single lane, switching to `/dos-replan` when the backlog drains, and stopping via kernel-decided conditions rather than heuristic prose. Stop verdicts include iteration caps, genuine exhaustion (drained-twice), systematic subprocess failure, rate limits, held invariants that re-dispatch cannot resolve, cooldown conflicts, and ratchet failure where shipping count stalls despite reported progress. Multiple loops run concurrently on disjoint lanes, each holding its own lane lease via `dos arbitrate`, entirely driven by `/dos` verbs and workspace `dos.toml` configuration as the reference workflow for unattended plan-and-ship cycles.
git clone --depth 1 https://github.com/anthony-chaudhary/dos-kernel /tmp/dos-dispatch-loop && cp -r /tmp/dos-dispatch-loop/src/dos/skills/dos-dispatch-loop ~/.claude/skills/dos-dispatch-loopSKILL.md
# dos-dispatch-loop — the generic dispatch⇄replan cadence > **The unattended plan-and-ship loop.** It runs `/dos-dispatch` repeatedly and > falls to `/dos-replan` when a lane drains, stopping on a typed, kernel-decided > condition (not a prose guess). The stop/continue logic is the kernel's > `loop_decide.decide` — the loop carries counters, the kernel decides. Several > loops on disjoint lanes run in parallel, each holding its own lane lease. The stop conditions are the kernel's, in one place: 1. **iteration cap** — reached `max_iterations` (default 10). 2. **drained-twice** — a DRAIN after a *productive* `/dos-replan` that itself followed a DRAIN (the lane is genuinely exhausted). 3. **consecutive-unclear** — the dispatch subprocess is failing systematically. 4. **rate-limited** — a usage window is exhausted (don't burn launches). 5. **launch-failed** — a subprocess never started. 6. **pick-held-invariant** — the next unit is held ONLY by a reason a re-dispatch cannot change (draft-class / operator-gated / soak-open / dependency-unmet); re-dispatching it would re-block identically, so honest-STOP + surface the hold. 7. **pick-cooldown** — the next unit was attempted-and-didn't-move inside its cooldown window AND nothing fresher is offerable; re-dispatching it would re-storm a known drain (the ~5%-shipping re-pick loop the bare loop hit). 8. **not-ratcheting** — the OUTER RATCHET (docs/351): the loop has run too many iterations in a row with no *witnessed net gain* — the reconcile-VERIFIED ship-count (Step 3) is not rising, even though each iteration reported SHIPPED. The loop is running but not improving (the "spinning, narrating progress while net-shipping nothing real" failure that worsens the longer the loop runs). The verdict is the kernel's `improve` ESCALATE, read VERBATIM — not the loop's self-report. Hand the judgment back to a human. Conditions 6–7 are the docs/207 anti-churn rungs (the loop stops re-picking work it cannot move); condition 8 is the docs/351 ratchet (the loop stops when it is moving but not *improving* — RSI made first-class here, the same `improve` keep-gate the `/dos-self-improve` loop uses, now gating each dispatch iteration's net gain). ## Inputs - `--lane <name>` (optional) — focus the whole loop on one lane (fixed for the run; a bare loop auto-picks a free lane at Step 0). - `--gate hard|soft|drive` (default `hard`) — the verdict policy. `hard` routes a non-LIVE verdict through `/dos-replan`; `soft`/`drive` stop on a true DRAIN; `drive` self-heals a STALE-STAMP inline. - `--max-iterations <N>` (default 10). ## Step 0 — Pre-flight: take the lane, read the taxonomy ```bash dos doctor --workspace . --json dos arbitrate --workspace . --lane <LANE> --kind cluster --leases '<SIBLING_LEASES>' ``` The arbiter ADMITs a free lane (or auto-picks one); a REFUSE means a sibling loop already holds an overlapping lane — pick a free one from `free_clusters` or exit. Initialise the loop counters (iteration=1, the breakers at 0). ## Step 1 — Pick-selection: skip held + cooled units (the anti-churn gate) Before a `dispatch` iteration offers a unit, screen the candidate unit set so the loop never re-storms work it cannot move (the docs/207 §6 throughline). For each candidate, in order: ```bash dos pickable <UNIT> --state '<host-gathered state>' # OFFERABLE=0; HELD=per-reason code dos cooldown <UNIT> # CLEAR=0; RECENTLY_ATTEMPTED=3 ``` - A `pickable` exit of **0** (OFFERABLE) **and** a `cooldown` exit of **0** (CLEAR) → this unit is dispatchable; offer it and proceed to the iteration. - A `pickable` HELD by a re-dispatch-CURABLE reason (IN_FLIGHT / SOFT_CLAIMED / STALE_CLAIM / UNPARSEABLE) or a `cooldown` of **3** (RECENTLY_ATTEMPTED) → **skip this unit, try the next candidate** (the skip-to-next is pick-selection's job). - A `pickable` HELD by a re-dispatch-INVARIANT reason (DRAFT_CLASS=10 / OPERATOR_GATED=11 / SOAK_OPEN=12 / DEPENDENCY_UNMET=13) → carry that verdict into Step 2; the kernel will honest-STOP on it (don't re-dispatch a unit a re-dispatch cannot un-gate). When EVERY remaining candidate is skipped (all cooled / curably-held), carry the last `cooldown` RECENTLY_ATTEMPTED (or the invariant `pickable` hold) into Step 2 as the loop's pre-dispatch evidence — the kernel turns "nothing fresh is offerable" into the `pick-cooldown` / `pick-held-invariant` honest-STOP. **Do not re-dispatch the cooled/held unit yourself** — that is the re-pick storm this gate prevents. ## Step 1b — Run one iteration For a `dispatch` iteration, invoke `/dos-dispatch --lane <LANE>` (it snapshots, gates, and ships). For a `replan` iteration, invoke `/dos-replan`. Capture the iteration's outcome: - a **dispatch** iteration that reached the gate carries a typed verdict — get it from `dos gate` over the packet's dispositions sidecar (LIVE/DRAIN/STALE-STAMP/ BLOCKED/RACE). - a **replan** iteration carries a productivity signal (did it refill/garden?). ## Step 2 — Decide continue / replan / stop (the kernel decides) This is the load-bearing step: **the decision is a kernel mechanism, not prose.** Feed the iteration outcome + the carried counters to the loop decider. In code a host calls `dos.loop_decide.decide(state, outcome)`; the screenplay's job is to construct the typed `IterationOutcome` and read the returned `LoopDecision`: - `action: "continue"` → run the next iteration in `next_mode` (`dispatch` or `replan`); if `reconcile` is set (a soft/drive STALE-STAMP), run an inline stamp-reconcile pass first. Carry `next_state` forward (the updated counters). - `action: "stop"` → the loop ends; report `stop_reason` (one of the five above) and `surface` (whether it needs operator attention). - `action: "retry-same-iter"` → a transient overload; sleep `backoff_seconds` and re-run the SAME iteration. The drained-twice rule is the kernel's: a DRAIN counts toward an early stop ONLY af
Adjudicate a GitHub issue's "this is resolved" claim from witnesses the claimant didn't author — then close it carrying the evidence, or refuse with the typed gap. Use when an issue looks already-solved, after landing a fix that should have closed one, or to sweep open issues for silently-resolved ones.
Pick the next most important open GitHub issue this agent can actually complete, make its done-condition true, land it with witnesses (suite + parity + commit-audit), and priority-tag every issue touched along the way. Use when asked to "work the backlog", "complete the next most important issue", or to fix a specific issue number end-to-end.
Cut a versioned release of the DOS kernel — bump the version, draft release notes, commit, tag, push to master, and create a GitHub release. The tag push triggers the gated PyPI publish pipeline (publish.yml); the skill surfaces the run and its approval gate.
Promote an already-shipped rolling release (vX.Y.Z) of the DOS kernel to a named stable channel — gated on a green kernel suite + a green third-party CI run on the candidate + a clean truth syscall + a soak window. Writes an evidence file and adds a stable/<codename> git tag on the same commit. Does NOT bump versions or build new artifacts.
One automatic plan-class lifecycle tick. Reads the DECLARED class set + transition list from the workspace `[lifecycle]` table (not a hardcoded taxonomy), evaluates each trigger, spawns a read-only JUDGE-rung adjudicator (the `dos.judges` seam — advisory, fail-to-abstain) to approve/defer each candidate transition, applies the gated transitions as plan-meta edits + one commit per cycle, and logs to the run archive. Failsafes (per-cycle cap, per-plan cooldown, a veto class) are `[lifecycle]` data; the judge content is a host `dos.judges` driver. Every path/class comes from `dos doctor --json`. Use to garden a plan portfolio's lifecycle automatically, judge-gated. The DOS lifecycle gardener (SKP Axis 5, docs/207 Phase 5c).
End-to-end plan-and-ship for one lane — snapshot the portfolio with /dos-next-up, take a lane lease via `dos arbitrate` so parallel dispatches don't collide, gate the empty case via `dos gate`, ship the packet, and archive the run under the configured run dir. Driven entirely by `dos` verbs + the workspace's `dos.toml`; names no host path, lane, or commit convention. Use when you want to plan and ship the next batch on one lane in a single command, with concurrency safety. The DOS reference dispatch workflow (SKP Axis 5).
Ground a "keep working until the goal is met" stop condition in a witness the agent did not author, instead of letting the agent self-certify "done". A harness goal/Stop-hook condition is normally checked by the model re-reading its OWN work — consistency, not grounding. This skill turns the operator's goal into checkable EFFECT claims and wires `dos hook stop` so the Stop is refused until git ancestry (a shipped phase) or an effect read-back corroborates the claimed effect. Driven by `dos` verbs and the workspace's own `dos.toml` — no host-specific paths, lanes, or commit conventions. Use when you want a self-stopping agent (or a `/loop` worker) to be unable to declare a goal complete on its own say-so. The single-agent self-stop analogue of `dos-witness-claim`.
Snapshot a repo's phased-plan portfolio and produce a parallel-agent dispatch packet, driven entirely by `dos` verbs and the workspace's own `dos.toml` — no host-specific paths, lanes, or commit conventions. Walks the configured plans glob, audits each candidate pick against `dos verify` for its true shipped/unshipped status, renders a self-contained packet to the configured output dir, and reports a typed gate verdict via `dos gate`. Use when you want a "where are we / what's next / who-does-what" snapshot of any repo that has a few plan docs and real commits. This is the DOS reference workflow (SKP Axis 5); a host may use it, fork it, or ignore it.