# Roadmap Fleet

> Roadmap Fleet

- Skill: `intense-visions/roadmap-fleet` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add intense-visions/roadmap-fleet`
- Raw SKILL.md: https://api.skillmd.com/api/skills/intense-visions/roadmap-fleet/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: Intense-Visions (https://skillmd.com/u/intense-visions)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/intense-visions/roadmap-fleet

---

# Roadmap Fleet

> Autonomous batch-build orchestrator — score a batch of backlog candidates, confirm it with the human in one up-front round, fan out worktree-isolated subagents that each run the **real** per-item pipeline (brainstorming then autopilot), independently verify every result by artifact and all-OS CI, and hand back a set of merge-ready PRs for one bulk review. The fleet never auto-merges and never trusts a subagent's self-report.

Building a backlog through the harness pipeline one item at a time is an attention slog: every roadmap item or external issue must be hand-driven through brainstorming then autopilot, with a human present at each clarifying question, spec sign-off, and autopilot decision. For dozens of items the human's attention — not the machinery — is the bottleneck. `roadmap-fleet` inverts the model: it takes a **batch**, runs the real per-item pipeline autonomously and in isolation for each candidate, verifies the result, and returns **merge-ready PRs to review in bulk** — moving the human from "drive every item" to "confirm the batch once, review the PRs once." It is the **build** stage of the `-fleet` family conveyor: intake → decide → **build (roadmap-fleet)** → land.

## When to Use

- A batch of independent backlog candidates (open issues and/or unblocked roadmap items) needs autonomous build plus one bulk PR review
- Clearing accumulated backlog pressure where per-item interactive driving does not scale
- Turning a triaged, roughly-independent work queue into a set of verified, merge-ready PRs in a single session
- When the items are genuinely parallelizable — each produces its own PR and does not depend on another item's output
- NOT for a single item — invoke `harness-brainstorming` then `harness-autopilot` directly; a fleet's overhead only pays off across a batch
- NOT for landing / merging PRs — that is `pr-fleet`; `roadmap-fleet` stops at merge-ready and never merges
- NOT for convergence on one target — iterating a single spec/PR to done is a **pipeline** (it loops on one thing), not a fleet (which fans out across many independent items into many PRs)
- NOT when items are tightly coupled (each depends on the previous one's merge) — sequence them through autopilot instead; fan-out assumes independence

## Flags

| Flag              | Effect                                                                                                                |
| ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| `--concurrency`   | Cap concurrent build subagents (default 2, max recommended 3 — the machine-storm limit)                               |
| `--report-only`   | Enumerate, score, and present the ranked batch; do not dispatch, verify, or report PRs                                |
| `--dry-run`       | Run SELECT and CONFIRM only; stop before fan-out                                                                      |
| `--lease-seconds` | Override the cross-run claim-lease TTL (default 720s); see §Cross-run claim lease in `docs/reference/fleet-family.md` |
| `--no-claim`      | Disable the cross-run claim lease entirely — fall back to open-PR-cross-check-only coordination                       |

## Process

### Iron Law

**A PR is "merge-ready" only after independent artifact + all-OS-CI verification. The fleet never auto-merges, and never accepts a subagent's self-report as proof its pipeline ran.**

A subagent that reports "done — pipeline ran, CI green" has told you what it believes, not what is true. The only evidence that the real per-item pipeline ran is the artifact it necessarily leaves behind (a plan directory plus a committed pipeline-provenance file) and the CI signal on the pushed branch. If either is missing, the item did not run the pipeline as required and is rejected or retried — regardless of how confident the report reads. And landing the batch is the human's call: the fleet stops at a set of verified, reviewable PRs.

```
Phase 1: SELECT --> Phase 2: CONFIRM --> Phase 3: DISPATCH
                                                    |
                                                    v
                     Phase 5: REPORT <-- Phase 4: VERIFY
```

| Phase       | Purpose                                                               | Exit Condition                                                           |
| ----------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| 1. SELECT   | Enumerate + cross-check + score candidates                            | Ranked `Candidate[]` with cross-check verdicts and detected forks        |
| 2. CONFIRM  | One up-front human round: approve/trim, answer forks, set concurrency | Human-approved batch with answered forks and agreed concurrency          |
| 3. DISPATCH | Worktree-isolated subagents run the real per-item pipeline            | Every confirmed item returned a branch, parked, or failed (all recorded) |
| 4. VERIFY   | Independent artifact + all-OS-CI confirmation, never self-report      | Each returned item marked verified / rejected / retry                    |
| 5. REPORT   | One-row-per-item batch summary; close resolved issues; never merge    | Report delivered; resolved issues closed with resolving-PR citations     |

### Phase 1: SELECT — Enumerate, Cross-Check, Score

1. **Enumerate candidates from both sources.** Open external issues via `gh` (`gh issue list --state open`) and unblocked roadmap items via `manage_roadmap` (planned/unblocked shards only — never items already `in-progress` under another owner). Missing `gh` auth or a missing roadmap degrades to whichever source is available; record which source was unavailable rather than aborting. Additionally fetch items carrying the `fleet:claimed` label and their claim comments — this piggybacks the same enumeration (no extra `gh pr list`) and feeds the cross-run claim-lease drop in the next step (see the **§Cross-run claim lease** section of `docs/reference/fleet-family.md`).

2. **Cross-check each candidate against merged and open PRs.** For every candidate, search merged PRs (`gh pr list --state merged --search`) and open PRs for one that already resolves it. A candidate whose work already merged is **already-resolved** — mark it for closure, not rebuild. A candidate with an open PR in flight is **in-progress elsewhere** — drop it from the batch. A candidate carrying a **live claim lease written by another run** is **claimed-elsewhere** — drop it as a soft reservation; a **stale** lease is ignored and the item stays claimable. Staleness and the lease record are defined once in the **§Cross-run claim lease** section of `docs/reference/fleet-family.md` — do not restate it here. If `gh` auth is absent, skip the claim-label scan and **degrade to the open-PR cross-check only** (log the degradation; never abort).

3. **Score and order via `roadmap-pilot` impact scoring.** Do not rank ad-hoc. Reuse `harness-roadmap-pilot`'s impact scoring so selection is principled and reproducible; order the batch highest-impact first.

4. **Detect decision forks up front.** For each candidate, scan its issue/spec text for genuine ambiguity that a builder would otherwise have to guess (e.g. "store as UTC or local?", "extend the existing table or add a new one?"). These _known_ forks are surfaced in CONFIRM. Do not attempt to answer them here.

5. **Classify each candidate's route (item-type routing).** Attach the pipeline route the item's
   **type** needs, per the canonical rubric in `docs/reference/fleet-family.md` (§Item-type routing,
   ADR 0103). Apply the precedence — **metadata first, rubric fallback, first match wins**:
   1. **Explicit metadata** — a GH issue label (`bug`/`defect` → `bug`; `feature`/`enhancement` →
      `feature`) or the roadmap shard's kind/type field.
   2. **Spec presence** — the item already links an approved spec (roadmap `spec:` non-null or a
      `proposal.md`) → `spec-ready`.
   3. **Rubric fallback** — apply `harness-router`'s scope rubric by judgment over the item text:
      diagnostic signals (broken, slow, failing, regression, error, crash) → `bug`; construction
      signals (build, add, design, new) → `feature`; genuine ambiguity → `feature` (the safe
      default). Record which rule fired as `routeSignal`. Do not guess a `bug` route on ambiguity —
      brainstorming can still decide an item needs no design, but debugging cannot invent one.

6. **Build the `Candidate` record** for each survivor:

   ```
   Candidate {
     source,            // "issue" | "roadmap-shard"
     id,                // issue ref or shard id
     title,
     score,             // roadmap-pilot impact score
     crossCheck,        // "novel" | "already-resolved" | "in-progress-elsewhere" | "claimed-elsewhere"
     resolvingPr,       // set when crossCheck = already-resolved
     alreadyResolved,   // boolean, flags for closure not rebuild
     forks,             // detected known decision forks (may be empty)
     route,             // "bug" | "spec-ready" | "feature" (item-type routing, §fleet-family)
     routeSignal,       // which precedence rule fired: "label" | "spec-present" | "rubric"
   }
   ```

### Phase 2: CONFIRM — The Single Up-Front Human Gate `[checkpoint:human-verify]`

1. **Present the ranked batch in one round.** This is the **only guaranteed human touchpoint before PR review** — everything downstream runs autonomously. Present, together, in a single surface:
   - The ranked candidates (highest-impact first) with scores.
   - Each item's **routing decision** — `bug` → `harness-debugging`, `spec-ready` → `harness-autopilot`, or `feature` → `harness-brainstorming`→`harness-autopilot` (with the `routeSignal` that chose it) — presented as an **overridable** decision. The human may re-route any item before fan-out; a corrected route is recorded like any answered fork and fed into that item's DISPATCH brief. This is the single point at which a misclassification is caught before it wastes a lane.
   - Already-resolved items **flagged for closure** with their resolving PR — the human confirms closing, the fleet never rebuilds them.
   - Every detected known decision fork as a **multiple-choice question** with a recommended default.
   - The **proposed concurrency** (default 2, capped at ~3).

2. **The human approves or trims once, and answers the forks.** Batch approval, fork answering, and stale-issue triage all happen in this same gate — front-loading the genuinely-ambiguous items is what keeps wrong-guess rework low. Answered forks are recorded and fed into each item's DISPATCH brief.

3. **From here it is autonomous.** After this gate the fleet does not pause per-item. The only thing that re-surfaces to the human before REPORT is an _unforeseen_ fork that parks a single item (see DISPATCH) — and even that does not block the batch. Under `--dry-run` the skill stops at the end of this phase.

### Phase 3: DISPATCH — Worktree Fan-Out With a Concurrency Governor

1. **One worktree-isolated subagent per confirmed item, briefed to run the item's _routed_ pipeline.** Each subagent runs the **real** per-item pipeline its confirmed `route` selects (§Item-type routing in `docs/reference/fleet-family.md`), never a hardcoded chain:
   - `route = bug` → `harness-debugging` (investigate → fix → a reproducing test that fails before the fix and passes after).
   - `route = spec-ready` → `harness-autopilot` directly against the linked spec (brainstorming is skipped — the design is already settled).
   - `route = feature` → `harness-brainstorming` then `harness-autopilot` in autonomous mode.

   It does not hand-implement, and it does not skip the pipeline — the artifacts the routed pipeline leaves behind are what VERIFY checks for. Feed the item's answered forks **and its confirmed route** from CONFIRM into the brief so the builder never re-asks a settled question and never second-guesses the route.

2. **Cap concurrency at the governor (default 2, max ~3).** This is the machine-storm limit: beyond roughly three concurrent build agents the compound load produces flaky failures that are indistinguishable from real ones. Never exceed the confirmed concurrency to "go faster" — a stormed batch is slower once you account for re-runs.

3. **Park unforeseen forks; never guess mid-flight.** A subagent runs autonomously on recommended-option defaults for anything routine. But if an item hits a genuinely **unforeseen** decision fork — one that was not surfaced in CONFIRM and that materially changes the outcome — that item **parks and reports** the fork instead of guessing. Parking is per-item: the other items in the batch continue uninterrupted. The parked fork appears in REPORT for the human.

4. **Record an "assumptions made" note per item.** Each subagent records the recommended-option defaults it took so the eventual PR carries an assumptions note — batch review is only trustworthy when the reviewer can see what was assumed.

5. **Write a committed pipeline-provenance file.** Each lane **MUST** write `docs/changes/<slug>/provenance.json` and commit it onto its branch. This is the verifiable proof the real pipeline ran — it replaces the session state that `.harness/.gitignore` excludes from every branch by construction (and so never survives into a PR). The file records at minimum: the item's **issue number(s)**, the confirmed **route** (`bug` / `spec-ready` / `feature`), the **pipeline stages run** — which reflect the route (`[debugging]` for a bug; `[autopilot, …]` for spec-ready; `[brainstorming, autopilot, …]` for a feature) — and the **assumptions** taken (the recommended-option defaults from item 4). A feature or spec-ready lane also records the **plan-artifact path** under `docs/changes/<slug>/plans/`; a bug lane records the **reproducing-test path** instead (a debugging run leaves no `plans/` directory). VERIFY checks for this committed file and the route-appropriate artifact; a branch without them did not run the pipeline.

   After committing it, each lane **MUST** also run:

   ```
   harness waypoint record-provenance docs/changes/<slug>/provenance.json
   ```

   This is the sanctioned seam that turns the written artifact into an `sdlc.*` event on the project's ledger (ADR-0120, ADR-0124 — which names this command provenance's first consumer). Writing the file without recording it means the fleet's own evidence never reaches Waypoint, so lanes never advance from fleet activity and wave forecasts stay cold-start. The command is a **guaranteed no-op** (exit 0, explanatory note) in any repo with no `waypoint.sink` configured, so lanes call it unconditionally and non-adopters see no change.

6. **Reference the issue with the correct closing keyword.** Each lane decides — and states in its PR body — how its PR references the issue it was dispatched for. This is a real decision with a default, not an incidental phrasing:
   - A PR that **fully resolves** its issue uses `Closes #<N>`, so the merge-triggered reconciler closes the issue and marks the roadmap row done.
   - A PR that lands only **one slice** of a multi-finding issue uses `Refs #<N>` (which triggers no auto-close) and **flags the issue for manual reconciliation** in REPORT, naming the row that still needs attention.

   Defaulting to `Refs` on a fully-resolving PR silently strands the roadmap row `planned`/`in-progress` forever, because `Refs` fires no closing behavior; defaulting to `Closes` on a partial slice closes an issue that still has open findings. The lane picks deliberately and records which keyword it used (and why, if partial) in its assumptions note and provenance file.

7. **Push-path caveat.** A worktree created under a `.claude/`-nested path breaks the local pre-push `check-docs` gate (it self-excludes and scans zero files). Subagents push via the GitHub API or from a non-`.claude` throwaway worktree. **Never `--no-verify`** — bypassing the gate defeats the verification the fleet depends on.

**Worker handoff — return the canonical `FleetHandoffRecord`.** When a worker finishes its item it hands the orchestrator exactly one `FleetHandoffRecord` (from `@harness-engineering/types`) — the ONE bounded envelope every `-fleet` member emits, so `fleet-command` parses any fleet's worker output uniformly instead of special-casing an ad hoc per-worker report shape. The record carries `status` (`done | parked | blocked | failed`), `fleet`, `item`, a one-line `summary`, an `evidence[]` of verifiable pointers (branch, PR, artifact path, CI check — exactly the references VERIFY re-checks), `next_steps[]`, and, for any non-`done` status, a `blocker`. The orchestrator validates it with `validateFleetHandoffRecord`; a malformed or unknown-keyed record is rejected, never silently misread. See the canonical handoff record in `docs/reference/fleet-family.md`.

**Claim the item before building — cross-run claim lease (CLAIM → HEARTBEAT → RELEASE).** On entering DISPATCH for an item, the orchestrator takes the item's cross-run claim so a concurrent run on another clone auto-partitions around it: add the `fleet:claimed` label and post the claim comment, then **re-read** — if a competing live claim appeared since SELECT, **yield this item** (soft reservation) and continue the batch. While the worker builds, the orchestrator **heartbeats** the claim (edits the comment every `HEARTBEAT_SECONDS`) so a live-but-slow item is not mistaken for a dead one. On PR-open it **releases** the label — the open PR is now the durable claim (VERIFY's existing open-PR handling backstops it). A parked or failed item with no PR also releases the label so it is not stranded. Under `--no-claim` this whole step is skipped. The record format, TTL/staleness semantics, and the reclaim tiebreak are stated once in the **§Cross-run claim lease** section of `docs/reference/fleet-family.md` — this member references them, it does not restate them.

### Phase 4: VERIFY — Independent Confirmation, Never Self-Report

1. **Never accept a subagent's self-report as verification.** "The pipeline ran and CI is green" is a claim to be checked, not a result. For each returned branch, the orchestrator independently confirms the evidence itself.

2. **Require the pipeline artifact — matched to the item's route.** Confirm the committed
   pipeline-provenance file exists **and** the artifact the route implies, both **committed on the
   branch** (so they survive into the PR). The provenance file replaces the old session-state check:
   session state lives under `.harness/sessions/`, which `.harness/.gitignore` excludes from every
   branch by construction, so it is absent from every PR and can never be verified — the committed
   provenance file is the artifact that actually survives to where the orchestrator can check it.
   - Always: a committed `provenance.json` under `docs/changes/<slug>/` recording the issue
     number(s), the confirmed **route**, the pipeline stages run, and the assumptions taken.
   - `route = feature` or `spec-ready` — a plan artifact under `docs/changes/<slug>/plans/` (the
     trace of a real autopilot run); the `stages` include `autopilot` (and `brainstorming` for a
     feature).
   - `route = bug` — a committed **reproducing test** (fails before the fix, passes after) and
     `stages=[debugging]`; there is **no** `plans/` directory for a debugging run, so its absence is
     not a defect. Do not reject a debug-routed item for lacking a plan artifact.

   An item **missing its committed provenance file, or missing the artifact its route requires, did
   not run the real pipeline** — regardless of what the subagent reported. Reject it (or retry
   once); it is never marked merge-ready.

3. **Check the PR body's issue reference.** Confirm the PR body carries the closing keyword that matches the item's scope (the DISPATCH contract): a fully-resolving item uses `Closes #<N>`; a partial-slice item uses `Refs #<N>` and is flagged for manual reconciliation. A **fully-resolving item whose PR body carries no closing keyword** will strand its roadmap row on merge — flag it for correction before the batch is handed over. This is cheaply detectable from the PR body at verify time.

4. **Require all-OS CI green.** Confirm the pushed branch's CI is green on **all target operating systems** plus the project's required checks (`gh pr checks` / `gh run list`). Green on one OS is not green. A subset-red branch is not merge-ready — it is reported as failed, and the batch continues. **Base freshness (spine clause):** all-OS green is trusted as `verified` only when it ran against **current `main`** — the branch is up to date with `main`, or branch protection enforces strict / up-to-date-before-merge. Green gathered against a base that `main` has since moved past is **stale**: downgrade the item to **`degraded`**, not verified, and report the stale tested base SHA vs current `main`. See `docs/reference/fleet-family.md` § _Base freshness_ (`classifyBaseFreshness`).

5. **Classify each returned item** as `verified` (the route-appropriate artifact from item 2 + committed provenance file present, correct closing keyword, and all-OS CI green), `rejected` (missing the route's artifact/provenance or definitively red), or `retry` (transient, retried at most once). No item reaches REPORT as merge-ready without passing both the artifact and the CI check.

### Phase 5: REPORT — Batch Summary, Resolved-Issue Closure, Never Merge

1. **Emit a one-row-per-item batch summary** for bulk human review:

   | Item | Verdict | PR  | Assumptions made | Parked forks |
   | ---- | ------- | --- | ---------------- | ------------ |

   Every verified item's row carries its PR link, the **assumptions-made note** from DISPATCH, and any parked unforeseen fork. Rejected/failed items are listed with the reason.

2. **Close already-resolved issues accurately.** For each item flagged already-resolved in SELECT and confirmed in CONFIRM, close the issue with a comment **citing the resolving PR** — never a bare close, and never a rebuild.

3. **Never merge.** The fleet delivers verified, reviewable PRs; the human (optionally via `pr-fleet`) lands the batch. Auto-merging a feature PR is out of scope by design.

4. **Degrade gracefully.** A missing roadmap, missing `gh` auth, or a single item's failed pipeline results in that item (or source) being **reported** while the rest of the batch proceeds. One bad item never sinks the batch.

## Harness Integration

- **`harness skill run roadmap-fleet`** — Run the full five-phase batch pipeline.
- **`harness-roadmap-pilot`** — Composed in SELECT for principled impact scoring and ordering of the batch.
- **`manage_roadmap`** — Enumerate unblocked roadmap shards (SELECT) and reconcile status after the batch.
- **`gh`** — Enumerate open issues, cross-check merged/open PRs (SELECT), read `gh pr checks` (VERIFY), and close already-resolved issues with resolving-PR citations (REPORT).
- **`run_skill` / `harness skill run`** — Each build subagent invokes the **routed** real pipeline for its one item (DISPATCH): `harness-debugging` for a `bug`, `harness-autopilot` for a `spec-ready` item, or `harness-brainstorming` then `harness-autopilot` for a `feature`.
- **`harness-debugging`** — The per-item pipeline for `bug`-routed items (see §Item-type routing / ADR 0103): investigate → fix → a reproducing test that fails before and passes after. A bug is diagnosed by the skill built for it rather than forced through the design-first path.
- **`harness-autopilot`'s code-review phase** — The per-item quality gate inside each subagent's pipeline; the fleet does not re-implement review.
- **`harness skill validate roadmap-fleet`** — The authoring-time gate for this skill's own structure and schema.
- **`docs/reference/fleet-family.md`** — The shared `-fleet` spine this skill builds on (the five-phase skeleton, the **§Item-type routing** rubric this skill applies, the concurrency governor, the artifact + all-OS-CI verification discipline, the worktree fan-out, and the never-silent-merge invariant), stated once for the family.
- **§Cross-run claim lease (`docs/reference/fleet-family.md`) + `@harness-engineering/core` (`fleet/claims`)** — The canonical cross-run coordination mechanism this member consumes in SELECT (drop live-leased items) and DISPATCH (CLAIM → HEARTBEAT → RELEASE); the pure `buildClaimBody`/`parseClaimComment`/`isLeaseLive` primitives and `classifyClaim`/`selectUnclaimed` helpers live in core, all `gh` I/O in this skill layer.

## Success Criteria

- Given a confirmed batch of N candidates, the fleet produces **up to N** PRs, each with the route-appropriate verified artifact (plan artifact for feature/spec-ready, reproducing test for bug), a committed provenance file, a scope-correct closing keyword, and green CI across all target operating systems plus the project's required checks.
- **Every item is routed by type** (§Item-type routing / ADR 0103): a `bug`-labeled or diagnostic item runs `harness-debugging`, a spec-carrying item runs `harness-autopilot` directly, and a new-feature/ambiguous item runs `harness-brainstorming`→`harness-autopilot`. The route is shown and is human-overridable in CONFIRM.
- There is **exactly one** up-front human decision round; no per-item interactive pauses except a genuinely-new fork parked to its own item.
- **Every emitted PR carries an "assumptions made" note.**
- Already-resolved candidates are **closed with resolving-PR citations, not rebuilt**.
- The skill **never auto-merges** a feature PR.
- It **degrades gracefully**: a missing roadmap, missing `gh` auth, or a single item's failed pipeline is reported while the batch continues.
- Concurrency never exceeds the confirmed governor (default 2, max ~3).
- No item is marked merge-ready on a subagent self-report — every verdict is backed by independently-checked artifact + CI evidence.

## Gates

- **No "merge-ready" without a verified plan artifact and committed provenance file.** An item lacking either `docs/changes/<slug>/plans/` or a committed `docs/changes/<slug>/provenance.json` did not run the real pipeline (the provenance file — not the gitignored session state, which never reaches a branch — is the artifact that survives into the PR). It is rejected or retried — never reported as merge-ready, no matter what the subagent claimed.
- **No fully-resolving PR without a closing keyword.** A PR that fully resolves its issue but whose body carries no `Closes #<N>` will strand its roadmap row on merge; a partial-slice PR must use `Refs #<N>` and be flagged for manual reconciliation. A mismatch between scope and keyword is a gate finding — correct it before handover.
- **No "merge-ready" without all-OS CI green.** Green on a subset of operating systems (or with enforce/harness checks red) is not merge-ready. Report it failed; do not ship it.
- **Never auto-merge.** The fleet stops at reviewable PRs. Merging a feature PR from inside the fleet = gate violation; the human lands the batch.
- **Never exceed the concurrency governor.** More than ~3 concurrent build agents is the machine-storm zone; do not raise the cap to "go faster."
- **A self-report is never verification.** Accepting "pipeline ran, CI green" without independently checking the artifact and CI = gate violation. Re-verify independently.
- **Never `--no-verify`.** No subagent bypasses the pre-push gates; a `.claude/`-nested worktree pushes via the GitHub API or a non-nested worktree instead.

## Escalation

- **Missing roadmap (`manage_roadmap` returns nothing):** proceed with issues-only enumeration; record the missing roadmap in REPORT rather than aborting the batch.
- **Missing `gh` auth:** proceed with roadmap-only enumeration (cross-check against PRs is degraded); note the gap in REPORT. If both sources are unavailable, stop and report — there is nothing to build.
- **A subagent returns a branch with no plan artifact:** do not accept its self-report. Reject or retry once; if it still produces no artifact, report the item as "did not run the pipeline" and move on — the batch continues.
- **An item parks on an unforeseen fork:** surface the fork (with the item's context and the recommended default) in REPORT for the human; do not guess and continue. The parked item is the only one affected.
- **CI red on a subset of OS:** report the item failed with the failing OS/check named; never mark it merge-ready. Do not average a mixed CI result into "mostly green".
- **The batch appears coupled (one item's branch depends on another's merge):** stop fanning out those items; the coupling means they are a pipeline, not a fleet. Escalate to the human to sequence them through autopilot.

## Rationalizations to Reject

| Rationalization                                                                   | Reality                                                                                                                                                                                                          |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| "The subagent reported its pipeline ran and CI is green, so it did"               | A self-report is a claim, not evidence. Independently confirm the `docs/changes/<slug>/plans/` artifact and the committed `docs/changes/<slug>/provenance.json` exist and CI is green — or the item did not run. |
| "CI is green on Linux, ship it"                                                   | Green on one OS is not green. Merge-ready requires all target operating systems plus the project's required checks. A subset-red branch is reported failed, not shipped.                                         |
| "This item's fork is small — I'll just guess and keep the batch moving"           | Unforeseen forks **park and report**; they are never silently guessed mid-flight. Guessing buries an unstated assumption in a PR the reviewer cannot see.                                                        |
| "I'll hand-implement this one item — it's faster than driving the whole pipeline" | Dogfood the real per-item skills. A hand-built item leaves no plan artifact, fails VERIFY, and breaks the guarantee that every PR ran the audited pipeline.                                                      |
| "The batch is verified and ready — I'll merge them to save the human a step"      | Never auto-merge. The fleet stops at reviewable PRs; the human (or `pr-fleet`) lands the batch. Auto-merging removes the one review the whole model is built around.                                             |
| "One item's pipeline failed, so the run is a bust — abort the batch"              | Degrade gracefully. Report the failed item and keep the verified ones; one bad item never sinks the batch.                                                                                                       |
| "This candidate looks new to me, no need to check merged PRs"                     | Cross-check every candidate against merged/open PRs. An already-resolved item rebuilt from scratch is duplicate work and a conflicting PR; resolved items get closed, not rebuilt.                               |
| "Bumping concurrency to six will finish the batch sooner"                         | Beyond ~3 concurrent build agents is the machine-storm zone — compound load produces flaky failures that cost more in re-runs than the extra parallelism saves.                                                  |

## Red Flags

| Flag                                                                    | Corrective Action                                                                                              |
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| "I'll mark it verified based on the subagent's summary"                 | STOP. Independently check the artifact and CI. A summary is not a verification.                                |
| "I'll answer this new fork with the obvious choice and continue"        | STOP. Unforeseen forks park and report. Record it for the human; do not guess it into a PR.                    |
| "The pre-push gate is failing in this worktree — I'll `--no-verify`"    | STOP. Never bypass. Push via the GitHub API or a non-`.claude` worktree; the gate is part of the verification. |
| "All verified — let me merge and close the loop"                        | STOP. The fleet never merges. Deliver the PRs for review; landing is the human's step.                         |
| "I'll rebuild this item; it's easier than confirming whether it merged" | STOP. Cross-check first. Rebuilding an already-resolved item creates a conflicting duplicate PR.               |

## Examples

### Example: A six-candidate backlog batch

```
$ harness skill run roadmap-fleet --concurrency 2

Phase 1: SELECT
  Enumerated: 4 open issues (gh) + 3 unblocked roadmap shards (manage_roadmap).
  Cross-check vs merged/open PRs:
    - "cache invalidation on tag write"  -> already-resolved (merged PR: link) -> flag for closure
    - "retry policy for webhook sender"  -> in-progress-elsewhere (open PR) -> dropped
  Scored 5 survivors via roadmap-pilot impact scoring; ordered highest-first.
  Detected forks: 2
    - "token store": UTC vs local expiry timestamps?
    - "audit log": extend existing table vs new table?

Phase 2: CONFIRM  [checkpoint:human-verify]
  Ranked batch (5) presented. Already-resolved item flagged for closure.
  Human answers forks: token store -> UTC; audit log -> new table.
  Human trims 1 low-value item -> batch = 4. Concurrency confirmed: 2.

Phase 3: DISPATCH (governor = 2)
  4 worktree-isolated subagents, 2 at a time, each running real
  brainstorming -> autopilot for its one item; answered forks fed into briefs.
  Item "rate-limit headers" hits an UNFORESEEN fork (per-route vs global limit)
    -> parks and reports; the other 3 continue.

Phase 4: VERIFY (independent — no self-report)
  item A: plan artifact + provenance.json present, Closes #N in body, CI green all 3 OS + enforce + harness -> verified
  item B: plan artifact + provenance.json present, Closes #N in body, CI green all 3 OS -> verified
  item C: NO plan artifact / no provenance.json on the branch (self-reported "done") -> REJECTED (hand-built, not piped)
  item D: parked in DISPATCH -> not verified (fork awaits human)

Phase 5: REPORT
  | Item              | Verdict   | PR    | Assumptions made           | Parked forks            |
  | ----------------- | --------- | ----- | -------------------------- | ----------------------- |
  | token store       | verified  | link  | UTC expiry (from confirm)  | —                       |
  | audit log         | verified  | link  | new table (from confirm)   | —                       |
  | webhook signing   | rejected  | —     | —                          | — (no plan artifact)    |
  | rate-limit headers| parked    | —     | —                          | per-route vs global?    |
  Closed 1 already-resolved issue with a comment citing the resolving PR.
  Never merged. 2 PRs handed to the human for bulk review.
```

### Example: Rejecting a hand-built item

A subagent returns a branch and reports "done — implemented the fix, tests pass, CI green." VERIFY looks for `docs/changes/<slug>/plans/` and finds nothing: there is no plan artifact and no committed `provenance.json`. The item was hand-implemented, short-cutting the real pipeline. Per the Iron Law it is **rejected** (retried once, still no artifact → reported as "did not run the pipeline"), never marked merge-ready. The batch's other verified items proceed to REPORT unaffected.

## Test Scenarios

### Scenario 1: Gate — a self-report accepted as verification

VERIFY receives a subagent claiming "pipeline ran, CI green" but the branch has no `docs/changes/<slug>/plans/` artifact and no committed `provenance.json`. Expected: the "no merge-ready without a verified plan artifact and committed provenance file" Gate halts marking it merge-ready; the item is rejected/retried, not reported as a PR. Accepting the self-report is the failure this scenario guards against.

### Scenario 4: Closing-keyword contract — a fully-resolving PR briefed with `Refs`

A lane fully resolves its single-finding issue but its PR body reads `Refs #N`. Expected: VERIFY's PR-body check flags the scope/keyword mismatch — a fully-resolving PR must use `Closes #N` or the merge-triggered reconciler leaves the roadmap row `planned`/`in-progress` forever. The lane corrects the body to `Closes #N` before handover. A partial-slice PR of a multi-finding issue is the mirror case: it correctly keeps `Refs #N` and is flagged for manual reconciliation. Defaulting the keyword by accident — the failure that stranded rows #1208/#1128/#1129/#603 — is what this scenario guards against.

### Scenario 2: Rationalization — hand-implementing one item

An operator reasons "I'll just hand-implement this small item, it's faster than the pipeline." Expected: rejected by the "dogfood the real per-item skills" rationalization — the hand-built item leaves no plan artifact and fails VERIFY. The correct action is to dispatch the real brainstorming→autopilot pipeline for it like every other item.

### Scenario 3: Park-unforeseen — a new fork mid-flight

A build subagent hits a genuinely new decision fork not surfaced in CONFIRM (per-route vs global rate limit). Expected: the item **parks and reports** the fork rather than guessing; the parked fork appears in REPORT for the human; the other in-flight items continue uninterrupted. Silently guessing the fork is the failure this scenario guards against.

