dos-promote
dos-promote identifies every unit stuck in the pre-dispatch gate and routes each to its typed unblock action. It enumerates all declared units from workspace plans, gates each against pickability constraints, and surfaces held units with their HoldReason (DRAFT_CLASS, OPERATOR_GATED, SOAK_OPEN, DEPENDENCY_UNMET, UNPARSEABLE) and the corresponding action needed to unblock them. Use this when units are invisible to the picker and you need to systematically diagnose why each one is held and what to do about it.
git clone --depth 1 https://github.com/anthony-chaudhary/dos-kernel /tmp/dos-promote && cp -r /tmp/dos-promote/src/dos/skills/dos-promote ~/.claude/skills/dos-promoteSKILL.md
# dos-promote — surface every held unit + its unblock action > **Make the invisible pickable.** The picker silently drops a unit it cannot > offer; `/dos-promote` does the inverse — it runs the **pre-dispatch gate** > (`dos pickable`) over every declared unit, and for each one that is HELD it > surfaces the unit, its *typed* hold reason, and the derived unblock action. The > hold reason → action routing is data, not a guess: a `DRAFT_CLASS` hold wants a > promotion, a `SOAK_OPEN` hold wants the clock, an `OPERATOR_GATED` hold wants a > decision. This is the operator-facing half of the shipped `pickable` primitive. The shape: **enumerate the units → gate each → route each hold to its action → auto-enact only the safe mechanical reclassify → surface the rest.** The gate and the enumeration are kernel verbs (`dos pickable`, `dos enumerate`); the reason→action routing is derivable from the `HoldReason` itself. ## Inputs - `--scope <lane>` (optional) — limit to one lane from the active `[lanes]`. Omitted = every declared unit the workspace can see. ## Step 0 — Discover the layout ```bash dos doctor --workspace . --json ``` Read `paths.plans_glob` (where the plan docs live), `lanes` (the taxonomy), and `lifecycle.classes` (the declared class set — which class is the workspace's "draft" / "active"). **Use these; never hardcode a plan path or a class name.** ## Step 1 — Enumerate the declared units For each plan doc under `paths.plans_glob`, enumerate the units it declares: ```bash dos enumerate <plan-doc> --json ``` Read `units` (the universe), `remaining` (the not-yet-shipped), and `drift` — a `drift[kind=unparseable]` is itself a held-by-UNPARSEABLE signal (the picker-invisibility cure: a typed refusal, never a silent drop). Collect the remaining units across all plans as the candidate set. ## Step 2 — Gate each candidate (the pre-dispatch verdict) For each remaining unit, run the pre-dispatch gate over the unit's host-gathered state (its plan class, soak index, live claims): ```bash dos pickable <UNIT> --state '<json>' --json ``` Branch on the exit code (the verdict IS the code — distinct per hold): - `0` **OFFERABLE** → a worker could pick it up now; NOT surfaced (it is not stuck). - `10` **DRAFT_CLASS** → the plan is draft-class; the unblock is a **promotion**. - `11` **OPERATOR_GATED** → blocked on a decision; raise it. - `12` **SOAK_OPEN** → a soak deadline; **wait** (never promote — time un-gates it). - `13` **DEPENDENCY_UNMET** → ship the prerequisite first. - `24` **UNPARSEABLE** → inspect/fix the deriver or the doc; the unit is invisible. - `20`–`23` **IN_FLIGHT / SOFT_CLAIMED / STALE_CLAIM / COOLDOWN** → a live/transient hold that clears on its own; surface as info, no action. ## Step 3 — Route each hold to its unblock action (data, not a guess) The action is derived from the typed `HoldReason`, not re-discovered per unit: | Hold | Unblock action | |---|---| | `DRAFT_CLASS` | promote the plan draft→active (the workspace's `lifecycle` default→next class) | | `OPERATOR_GATED` | raise an operator decision (`dos decisions add`) | | `SOAK_OPEN` | wait for the soak to close — surface the deadline, do NOT promote | | `DEPENDENCY_UNMET` | ship the named prerequisite first | | `UNPARSEABLE` | inspect the deriver / backfill the doc's phase grammar | A host may declare a richer reason→action map in `dos.toml`; absent one, this default routing (documented on the `HoldReason` enum) is used. ## Step 4 — Auto-enact ONLY the safe mechanical reclassify The single auto-applied action is the **DRAFT→active promotion** of a plan whose draft phases are demonstrably wanted — a mechanical plan-meta `classification:` edit + ONE commit, gated. Read the trunk + ship grammar from `dos doctor --json`'s `stamp`; **do not hardcode a commit prefix.** Everything else — a decision, a soak wait, a dependency, an unparseable doc — is surfaced for a human, never auto-applied (those are real judgment calls). ## Step 5 — Surface the rest ```bash dos decisions add # one row per held unit that needs a human ``` ## What this skill deliberately does NOT do (no silent gap) - **No auto-decision / auto-dependency-ship.** Only the mechanical reclassify is auto; an OPERATOR_GATED / DEPENDENCY_UNMET hold is a human's call. - **No soak fast-forward.** A SOAK_OPEN hold is surfaced with its deadline; the loop NEVER promotes past a soak (time is the only thing that un-gates it). - **No host class taxonomy.** The draft/active classes come from `lifecycle.classes`; a 2-class repo and a job-shaped repo both run this skill. ## Anti-patterns - ❌ Promoting a SOAK_OPEN unit — a soak is un-gated by the clock, not a promotion; promoting it re-introduces the very drain-trap the typed hold prevents. - ❌ Auto-resolving an OPERATOR_GATED hold — that decision is the operator's. - ❌ Hardcoding "DRAFT"/"ACTIVE" — read the class set from `dos doctor --json`'s `lifecycle.classes`.
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).
Run /dos-dispatch on a recurring cadence, alternating with /dos-replan when the backlog drains — the dispatch→replan→dispatch cycle. The continue/stop/next-mode decision is the kernel's typed loop decision, not inline prose: each iteration is classified (`dos gate`) into a verdict and the loop's counters (drained-twice, the unclear/dirty-zero breakers, the iteration cap) drive the next step. Several loops on disjoint lanes run concurrently, each taking its own lane lease via `dos arbitrate`. Driven entirely by `dos` verbs + the workspace's `dos.toml`. The DOS reference loop workflow (SKP Axis 5).
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`.