- name
- drive-epic
- description
- Model-agnostic orchestrator playbook for driving ONE epic/track lane end-to-end over the fleet-comms message plane. Invoke this when you are launched as an epic/track driver (Grok, Sonnet-5, Gemini/AGY, Kimi, Claude, or Cursor) via a start-<model>-driver.sh --epic launch and told to "drive this epic". Teaches the METHOD — topology → route → dispatch → settle → cross-family review → merge → handoff — and defers all live roster/routing DATA to /api/rules and model_catalog.yaml. Not for main-orchestrator cold-start (that has its own hook) and not for writing a single module (use $track-completion).
- effort
- xhigh
# Drive an epic lane
You were launched to **drive one epic/track lane** (`SESSION_EPIC` is set). You are
**NOT** the main orchestrator. This skill is the portable playbook every non-Claude
driver — and Claude when driving a track — follows so orchestration behaves the same
regardless of which model is in the seat.
**Golden rule of this skill: it teaches the *method*, never the *roster*.** Who is in
which lane, which model fits which task, and the current width (CodexBar pace/reserve +
disk headroom, not a fixed cap) are **live data** that change; always read them fresh from
the served rules and catalog, never from memory:
- `GET http://127.0.0.1:8765/api/rules` — model-assignment (routing SSOT), review-seat
economics, cross-family pairing. Served first; supports `If-None-Match`.
- `scripts/config/model_catalog.yaml` — machine-enforced quality floors + ordered peer
tiers per task-risk.
- `docs/best-practices/agent-activity-matrix.md` §2/§2b — roster + no-idle capacity routing.
**Driver role (not a clerk).** You own the lane's judgment: what is wrong, what is
next, which model×harness should do it, whether the artifact actually worked, and
what residual remains. Dispatch exists so the fleet does the volume; it is not a
substitute for thinking. Always use established best practice
(`docs/best-practices/` and the live prior art for the domain); find and fix the
root cause before treating a symptom. You decide in-scope calls. You are not a
designated advisor (Fable/Sol) and not the CF of record for work you drove — you
*do* read the review and the diff before you merge. Spend other seats to keep
this context on the hard turn, not to avoid a decision you can already make.
Unused paid quota is waste (§2c); manufactured work is a defect. Judgment is not
implementation — seat no-solo rules still bind.
If any claim you are about to make (a lane name, a cap, a word/stress/morphology fact,
a gate status, a count) is not in fresh tool output, **STOP and run the tool** — every
verifiable claim is tool-backed (deterministic-over-hallucination).
**Work-board orientation surface:** `GET http://127.0.0.1:8765/api/work/v1/projection`
returns the merged work board — issues, PRs, dispatch tasks, and reviews — with each item
carrying a rule-derived `health` (`ON_TRACK` / `AT_RISK` / `OFF_TRACK` / `UNKNOWN` — authority
missing/stale, pairs with the `INSPECT_UNKNOWN` safe action; see `HEALTH_RANK` in
`scripts/work/attention.py`), an `attention_rank`, and a `safe_next_action`. Query it at orient
and again when picking the next unblocked action (§2); it is a queue INPUT alongside your
stream/GH/issue sources, never a replacement for them.
**Stream next-queue:** `GET http://127.0.0.1:8765/api/work/v1/next?stream=<your-stream>`
returns a compact, stream-scoped actionable pick list (default `limit` 7). Consult it at orient
and next-action time alongside the projection — also a queue INPUT, never a replacement. Cold
(absent) cache → `503` `building` + `retry_after_s` (does not trigger a build); unknown
`stream` → `400` with `valid_streams`.
---
## The loop (run it every cycle)
### 0. Orient
```bash
curl -sS --max-time 2 "http://127.0.0.1:8765/api/orient?lean=true" || true
curl -sS --max-time 2 "http://127.0.0.1:8765/api/work/v1/projection" || true # best-effort: local server, degraded/absent sources are normal
curl -sS --max-time 2 "http://127.0.0.1:8765/api/work/v1/next?stream=<your-stream>" || true # stream-scoped pick list (#6880)
.venv/bin/python -m scripts.fleet_comms plane-status # message-plane mode/parity
```
Know your `SESSION_EPIC`, your stream, and your handoff slot (the launcher already
claimed the stream lease — do **not** open or resume it yourself). Establish your
session-health signal **by seat**: **grok / gemini / kimi** have a canary lane —
`.venv/bin/python -m scripts.session_canary.{grok,gemini,kimi}_lane mint --epic <epic>`;
**Claude / Sonnet** have **no** canary lane and use the native SessionStart / PostCompact
hook chain + thread-handoff instead (do not call a non-existent `<model>_lane`).
### 0a. Required live-driver inbox drain — cycle start
At the start of **every** cycle, inspect this driver's legacy inbox. The live loop —
not a detached `process-*` / `ask-*` worker — must read and apply every message marked
`unread` or `read-but-not-live-consumed`, then record that consumption explicitly:
```bash
.venv/bin/python -m scripts.ai_agent_bridge inbox --for "$SESSION_HANDOFF_AGENT"
.venv/bin/python -m scripts.ai_agent_bridge ack --consumed-by-live-driver <message-id> [<message-id> ...]
```
Never use a plain `ack` for messages this live loop has consumed: plain acknowledgement
also records one-shot/headless processing and is not delivery proof for the live driver.
### 0b. Optional Monitor inbox-watcher wakeup — cold start only
At cold-start, **if your harness has a Monitor-equivalent**, invoke it once with that
harness's `persistent`/timeout option, pointed at this one shell command:
```bash
scripts/ai_agent_bridge/inbox_watch.sh "$SESSION_HANDOFF_AGENT"
```
This is a **wakeup signal only**: each stdout line says that an unconsumed legacy
message exists, with its id, sender, request id, and a bounded preview. It never reads
the full body into your context and never marks a message consumed. You still must run
the existing required `0a` / `4a` / `5a` / `8a` inbox-drain steps to read, apply, and
explicitly live-consume everything the signal points at; those steps remain the
universal fallback for every seat, watcher or not.
Direct confirmation exists only for **Claude Code, Gemini/AGY, and Grok CLI**. For any
other harness, ask the running agent directly whether it has an equivalent before using
one; do not infer it from documentation or `--help`. Stop a running watcher cleanly
with `scripts/ai_agent_bridge/inbox_watch.sh --stop "$SESSION_HANDOFF_AGENT"`; if a
crashed process leaves a stale pidfile, the operating system releases its advisory lock
and the next watcher replaces the recorded pid safely.
### 0c. Hramatka epic — dual-repo queue (epic #4542 only)
If `SESSION_EPIC` is Hramatka (public #4542), the priority/ownership queue is
private BOARD `learn-ukrainian-infra-private#349`, not the public epic body. Cold-start
read order: **private #349 → private open PRs → public PRs linked from #4542 only.**
Public #4542 is charter + bare pointer — never generate or mirror a public checklist
from the private board (leak + dual-write). GitHub issue/PR state in either repo
remains the factual SSOT for open/closed; #349 is the priority queue, not a duplicate
status feed. Operator-only host mutation (private #360, #212) is **ESCALATE**, not
solo action, on missing GO. If #349 and any other queue view disagree, **#349 wins** —
correct the other view the same session. Full contract:
`docs/runbooks/hramatka-driver-queue.md`.
Before a new dispatch, scope, or PR, run `scripts.fleet.hramatka_scope_gate`
as specified in that runbook; only `ALLOW` permits the new action.
### 1. Read topology + metrics (don't hold state — query it)
```bash
.venv/bin/python -m scripts.fleet_comms metrics # efficiency metrics (no content)
.venv/bin/python -m scripts.fleet_comms backlog # pending/dispatched delivery
.venv/bin/python -m scripts.fleet_comms dead-letters # stuck deliveries
```
Fleet-comms externalizes topology + usage so you decide against fresh state, not a
stale in-context snapshot. For per-lane budget health before dispatch:
`.venv/bin/python -m scripts.fleet.capacity_pick` then
`scripts/delegate.py dispatch --check-budget` (or `LU_DISPATCH_CHECK_BUDGET=1`)
(+ `/api/state/routing-budget` for subscription lanes).
### 2. Pick the next unblocked action
Source of next work: your epic's stream tail / handoff, open GH issues for the epic, the
build/review queue, the Work API projection's ranked attention list (§0), and
`GET /api/work/v1/next?stream=<your-stream>` — cross-check against them before committing to
an action. **Step 0 of any dispatch:** `gh pr list --state all
--search "<issue-nr>"` by issue reference (an open issue ≠ unfixed; a sibling PR may already
carry it). If nothing genuinely fits a free lane, log it and leave it idle — never
manufacture busywork (quality > utilization).
### 2-epic. Epic issue ownership cycle (binding — operator 2026-08-28)
You are an **epic orchestrator**, not a clerk waiting on one PR. Every cycle must advance
the epic's open issue set:
1. **Inventory** — open GitHub issues for this epic/stream (plus Work API `/next` +
grok-bot QA issues per §2b). Quote the count.
2. **Disposition each item** — for every open issue, exactly one of:
- **in_flight** (named PR/task id + head),
- **dispatch now** (ROUTING_CARD + `capacity_pick` / `/api/state/routing-budget` +
`--check-budget`),
- **named hold** with one §2c code (`dependency_blocked | authoring_wip_cap |
review_wip_cap | ci_capacity | worktree_wip_cap | disk_capacity |
integration_wip_cap | human_decision | no_ready_work`).
3. **Silence is a defect** — an open epic issue with no disposition is a driver failure.
4. **Closeout** — after merge: close the issue (or prove residual), then follow §7a order
(P0 reaper first, then branch deletion). Merge alone is not done.
**Anti-passive (all seats, Cursor especially):** while CF or CI runs on unit N, you
**must** either dispatch the next ready epic child or emit a §2c disposition code in the
same turn. Ending a turn with only "waiting on review/CI" and no fill/disposition is
forbidden. Overnight/session gaps do not excuse an unfinished CLEAN/MERGEABLE PR —
re-read checks and finish merge/hygiene on the next live turn.
### 2a. NO FABRICATED DONE (binding all epic drivers)
- Never invent acceptance thresholds the operator, issue, or epic goal did not set.
- Never declare a goal done while measured residual remains in the same mandate unless
tools prove it impossible or the operator accepted it on the issue.
- Never end with "when you want" or an "optional next" for in-scope residual — dispatch it.
- Never relabel unfinished work as an intentional skip without issue text or tool proof.
- Before "done" or handback, quote the tool residual count; `residual > 0` requires a
next dispatch in the same session.
### 2b. Grok-bot QA findings — queue input, not a fleet seat
Grok Bot (`app/cursor`) is an **external QA observer** — it reads CI/site signals and files
labeled GitHub issues; drivers consume those issues through the normal loop above like any
other open issue. It is **never** a dispatch target: no `--agent grok-bot`, no `ask-grok-bot`,
no fleet-comms seat. If Grok Bot ever authors a PR, same-family Grok must not CF it — route to
an outside-family reviewer per §6. Full contract: `docs/runbooks/grok-bot-qa-observer.md`.
### 2c. No idle lanes — subscription min-max (binding, all driver seats)
Idle paid lanes are direct financial loss (operator 2026-08-17). This generalizes the
Grok-seat fleet-first *utilization* rule to **every** driver seat.
**Definitions.** *Free lane* — healthy, budget-eligible seat with no live assignment.
*Ready item* — queued work that is valuable, unblocked, and has an integration path.
*Compatible / independent* — the item fits the free lane and does not collide with
in-flight units (paths, review identity, or a hard dependency). *Settle event* — any
dispatch/review/CI terminal or decision point. *Grace period* — the short fill window
after a settle event before a hold is allowed. *Epic done* — operator goal met with
tool-backed residual 0, or operator-accepted residual on the issue.
**Precedence (strict):** correctness/quality → safety/resource bounds →
dependency/critical-path → utilization. Later items never override earlier ones.
1. **Waits are dispatch windows.** After any dispatch or review ask, **before** holding,
fill every free lane with a compatible ready item (unblocked work, banked follow-ups,
or prep the next program child whose dependency allows it). Idle free lane + ready
item = utilization failure.
2. **Authorized idle is not a utilization failure.** A settle-hold must name one code:
`dependency_blocked | authoring_wip_cap | review_wip_cap | ci_capacity |
worktree_wip_cap | disk_capacity | integration_wip_cap | human_decision |
no_ready_work`. Silence is not a disposition.
3. **Pipeline with a depth limit.** While CF/CI runs on unit N, author N+1 only up to
the WIP/resource cap. Unit N **regains priority** the moment review feedback returns.
Never serialize implement → review → delta with idle gaps.
4. **Ready-work forecast.** An unfinished epic needs a current ready-work forecast. An
empty ready queue requires an explicit disposition, not silence. File banked
follow-ups as GitHub issues when identified. Empty stream `/next` is a driver defect
unless the epic is done or a disposition applies.
5. **Anti-gaming.** No placeholder agents, artificial task splitting, premature PRs, or
speculative work without an integration path. §2 still binds: never manufacture
busywork (quality > utilization). Disk wins every conflict (#M-14 — `df` + `du` of
`.worktrees` before fan-out; reap first).
Mechanical reminder + disposition telemetry (#6976/#6998). At every
dispatch/review settle, evaluate eligible ready items and first-class admission
WIP limits (authoring / review / CI / worktrees / disk / integration) plus
queue readiness. The reminder fires only when something is eligible; then
dispatch or pass a structured code. Unknown codes are rejected. Do not add a
raw idle-time threshold. Guardrail-authorized idle is not a failure.
`driver_breadth_report --enforce` fails the breadth floor (unless NOTE-waived)
and MISSING/DISHONEST idle dispositions — never opportunity-seconds.
```bash
.venv/bin/python -m scripts.orchestration.dispatch_settle task --task-id <id> \
--idle-snapshot-json <snap.json> [--dispatched | --disposition <code>]
.venv/bin/python -m scripts.fleet.idle_settle evaluate \
--snapshot-json <snap.json> --kind dispatch --task-id <id> \
[--dispatched | --disposition <code>]
.venv/bin/python -m scripts.fleet.idle_settle report
.venv/bin/python -m scripts.fleet.idle_settle admission --snapshot-json <snap.json>
.venv/bin/python -m scripts.fleet.driver_breadth_report --initiator grok --since-hours 24 --enforce
```
### 3. Route by model × harness fit
Decide the lane from `/api/rules` + `model_catalog.yaml`, **never** from the provider
name. Respect the live caps (in-flight ceilings), the language-lane restriction
(UK authoring / linguistic / content review route only to the sanctioned language lanes
per the served rules), folk carve-outs (cross-family only), and the judge-seat rules.
On limit: note the substitution and reroute per the fallback table — never block on one lane.
**Live capacity (binding every implement / CF settle):** before picking a seat, read
fresh tool output from **both**:
```bash
curl -sS --max-time 3 "http://127.0.0.1:8765/api/state/routing-budget"
.venv/bin/python -m scripts.fleet.capacity_pick
```
Prefer cooler / higher-headroom seats from that data. Do **not** habit-route to a hot or
in-flight-saturated lane when a cooler eligible seat exists. CodexBar is an **input to
the API**, not a separate driver app workflow — if both surfaces are empty/stale, probe
and record that in the ROUTING_CARD (`NOTE: routing_budget_empty`), then use `/api/rules`
fallback tables. Never invent burn % from memory.
### 3-routing. Mandatory ROUTING_CARD_V1 + breadth (operator GO 2026-08-06)
**Binding full text:** `agents_extensions/shared/rules/fleet-driver-routing.md` (served at
`/api/rules` after model-assignment).
Before **every** implement `delegate.py dispatch`:
1. Emit a **ROUTING_CARD_V1** (handoff / issue / `batch_state/` receipt) with:
`tier` (authority|practical|heap) · `model_x_harness` · `why_this_tier` ·
`advisor_packet` (required if tier=heap) · `owned_paths` · `acceptance_cmd` ·
≥2 `alternatives_considered` · `parallel_free_seats` · quoted
`routing_budget_primary` + `capacity_pick_order` (tool evidence).
2. **No card = no dispatch.** Skipping the card is a process defect; do not launch the
worker and "write the card later."
3. **Default bounded work:** Fable or Sol **brief** → heap/practical **worker(s)** —
not a Sonnet/Terra fixation solo. Heap without advisor packet is a process defect.
4. **Fable path:** native `claude-fable-5-1` or Cursor pin to Fable; do not spend Fable on
lockfiles / pointer / smoke jobs.
5. After ≥3 implement dispatches this session, require ≥2 agents **and** ≥2 tiers **or** a
written `NOTE: fleet_breadth` with tool-backed blockers.
6. Before handoff, run and attach:
```bash
.venv/bin/python -m scripts.fleet.driver_breadth_report --initiator "$SESSION_HANDOFF_AGENT" --since-hours 24
GitHub에서 보기