Pipeline routing rules and handoff conditions between specialist agents: gates, recovery, and the root-applied procedures. Load when coordinating feature delivery, checking pipeline state, or determining which agent to invoke next. The writer side of the log lives in handoff-append.
Installs into .claude/skills of the current project.
Are you the author of Handoff Routing?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/woditschka-handoff-routing)
---
name: handoff-routing
description: >-
Pipeline routing rules and handoff conditions between specialist agents:
gates, recovery, and the root-applied procedures. Load when coordinating
feature delivery, checking pipeline state, or determining which agent to
invoke next. The writer side of the log lives in handoff-append.
compatibility:
- claude-code
- github-copilot
- opencode
metadata:
version: "2.1"
author: team
---
## Agent Selection
| User Request | Agent | Shortcut Allowed |
|---|---|---|
| New feature or enhancement | product-requirements-expert, dispatched by `route` on the recorded `intake-decision` (`intake-ready`); the `intake` skill runs the discussion and records the exit | No — full pipeline required |
| Discuss or explore feature idea | root — the `intake` skill's discussion per `agentic-harness.md` § Conversations Stay in Root; the exit records an `intake-decision` | Yes — the recorded exit dispatches once |
| Requirement clarification | root — same intake discussion; product-requirements-expert records the PRD change | Yes — one recording dispatch after the conversation |
| Architecture question | root — the elicitation per § Conversations Stay in Root; system-design-expert records durable-memory changes | Yes — one recording dispatch after the conversation |
| Bug fix (known cause) | feature-implementer | Yes — skip PRD/design |
| Code review request | All reviewers in the roster | Yes — parallel invocation |
**Skip agents for:** git operations, answering questions, running one-off commands, summarizing an already-completed change. Formal review of a completed change routes to the reviewers in the roster per the table above.
## Handoff Conditions
All transitions are gated on the latest record per `(req_id, type)` in `.scratch/handoff.jsonl`; Gate 1 additionally reads the `docs/prd.md` scope-lock delta (`route-spec.md` § Gate 1). The Handoff Conditions table is executable: `python3 scripts/handoff.py route` evaluates it and prints one JSON decision. The table itself, the gates' field checks, and the recovery steps live in [`route-spec.md`](route-spec.md) — the normative spec `route` executes and `scripts/tests/test_handoff.py` pins rule by rule. No consumer re-derives it: root runs `route` after each dispatch returns and follows its decision.
Three decisions exist. `dispatch` names the next agent(s), the matched rule, and the prompt context. A failed gate is a `dispatch` of the upstream agent carrying the exact errors — the bounce, expressed as the re-dispatch it is. Root assembles each recovery dispatch's prompt from the section its rule maps to: `reviewer-stall-retry` from § Reviewer Stall Check; `build-retry` from `route-spec.md` § Build-Failure Recovery; `truncation-continue` from `route-spec.md` § Truncation Recovery, read on demand. Reviewer dispatches (`reviews-needed`, `reviewer-stall-retry`, `outstanding-dissent`) carry a paste-ready `prompt_note` in the decision context. Root appends it verbatim as the prompt's final sentence and composes no round context of its own — the root is a channel, not an author. `blocked` always halts for a human: a dirty log, a `conflicting` verdict, a stalled reviewer (`reviewer-stalled`) or planner (`planner-stalled`), a `human-consultation`, a consultation record naming no author or responder to resume (`consultation-invalid`), `review-non-convergence`, an invalid intake record (`intake-record-invalid` — the owner re-records it), feature-complete. `escalate` marks a state the table does not decide; the `pipeline-coordinator` is dispatched only on `escalate` and for untriaged fresh-intake classification. Route is fail-closed: it never repairs a log and never guesses past a failed check. A `process-findings` decision with `halt_after: true` carries an escalate finding — root halts after that dispatch per § Blocking.
An implementer dispatch names its tier. The ladder is active only on a slice whose `design-block` carries an `implementation_effort` rating; an unrated slice runs `feature-implementer` on every path, and an unrated re-triage reads as `involved`. On an active slice, `feature-implementer-routine` (identical body, pinned to the checklist tier) runs two paths: the initial implementation when the latest triage rates the work `routine`, and an all-autofix fix round. Everything else runs `feature-implementer`: an `involved`-rated initial, a mixed or escalate-carrying round, and every fresh recovery dispatch. A resume continues the session that paused. Retirement is permanent for the slice: a `build-failure` in a routine window, a mixed round after a routine initial, or any substantive dissent after a routine fix. An unattributable window retires it too. The decision's `tier_reason` context names the basis, and `python3 scripts/handoff.py tier` prints the same derivation on demand. Root dispatches whichever name the decision carries, exactly like any other dispatch.
The `escalate` arm is the closed set of rules `route` emits for judgment states. Ten rules exist: fresh intake (`no-active-slice`), `refactor-first` sibling ordering, an autofix-only findings round (`autofix-only-round`), and reviewer activity with no gating `build-pass` (`review-without-build-pass`). The rest are the degenerates: truncation with no recovery row (`truncation-undefined`), `truncation-before-design`, `no-substantive-record`, `failure-without-design`, `abort-unknown`, and any state matching no table row (`unroutable-state`). Both `refactor-first` log shapes escalate; `refactor-resume` then re-triages the original deterministically. A `no-active-slice` escalate on a pick the `next` skill already triaged is pre-resolved: root records the pick's `intake-decision` and follows `route`'s `intake-ready` dispatch, skipping the coordinator.
## Validation Gates
Each transition validates the inbound record(s) against a schema before dispatching the next specialist; malformed or missing records bounce back to the upstream agent without consuming a downstream dispatch. The gates are structural — required fields, types, patterns — and every check catches deterministically. Two checks read further, both still deterministic: Gate 2's `supersedes_record_at` pointer, and Gate 1's scope-lock. Scope-lock compares `docs/prd.md` against `HEAD` and verifies a cited human `consultation-response` (`route-spec.md` § Gate 1). `route` enforces them; the per-gate field checks are `route-spec.md` § Validation Gates. Content quality (are the acceptance criteria *good*?) is the consuming agent's judgement; other cross-record consistency is a consumer finding, not a gate check.
| Gate | Transition | Record | Schema |
|---|---|---|---|
| 0 | intake → product-requirements-expert | `intake-decision` | [`intake-decision.schema.json`](../../../schemas/scratch/intake-decision.schema.json) |
| 1 | product-requirements-expert → system-design-expert | `prd-entry` | [`prd-entry.schema.json`](../../../schemas/scratch/prd-entry.schema.json) |
| 2 | system-design-expert → implementer | `design-block` | [`design-block.schema.json`](../../../schemas/scratch/design-block.schema.json) |
| 2b | consultation roundtrip (either direction) | `consultation-request` / `consultation-response` | [`consultation-request.schema.json`](../../../schemas/scratch/consultation-request.schema.json), [`consultation-response.schema.json`](../../../schemas/scratch/consultation-response.schema.json) |
| 3 | implementer → reviewers | `build-pass` | [`build-pass.schema.json`](../../../schemas/scratch/build-pass.schema.json) |
| 5 | build-pass → reviewers (roster resolution) | `review-plan` | [`review-plan.schema.json`](../../../schemas/scratch/review-plan.schema.json) |
| 4 | reviewers → next step | `review-feedback`, one per pass-roster reviewer | [`review-feedback.schema.json`](../../../schemas/scratch/review-feedback.schema.json) |
Gate 0 differs in its failure mode: the record's author is the human, so an invalid `intake-decision` halts (`intake-record-invalid`) instead of bouncing to an agent. Gate 2b routes a `consultation-response` **back to the requesting specialist**, never forward (§ Mid-Implementation Consultation). A requirements answer that changed `docs/prd.md` is carried into the design doc by a second consultation before the build-pass; the append gate holds the build-pass until it is. Gate 5 resolves the pass roster from the `review-plan` the `build-pass` append emits at gate-pass. A `low`/`high` plan gates on its roster; a `gray` plan dispatches the `review-planner` to resolve it; a missing or invalid plan fails closed to the full battery (`route-spec.md` § Gate 5). Gate 4 then waits on that resolved roster — the four-reviewer floor plus declared extras is the default and the fail-closed fallback, defined in `review-workflow` § Review Phase. Feature-complete is `route`'s call, computed per `route-spec.md` § Gate 5 — never re-derived here. The `change-grader` is then dispatched (terminal, advisory; skipped when `layout.toml [harness] auto_grade = false`). On any `changes_requested` or `blocked`, findings split by artifact owner (the `review-workflow` skill's `reference.md` § Artifact Ownership) — except doc autofixes, which root applies per § Root-Applied Autofix on Doc Paths. An escalate-tagged finding halts per § Blocking. Review convergence is bounded: from round 3 dissent needs a `critical` finding or a `clarify`/`escalate`/`truncation` finding, and each non-convergence ceiling halts for the human (`route-spec.md` § Review Non-Convergence).
### Common Procedure
1. **Discover.** List `.scratch/` recursively to enumerate state files. Then read `.scratch/handoff.jsonl` only if it appears in the listing. Do not read directories as files.
2. **Gate.** If `handoff.jsonl` is missing or empty when a record is required, the gate fails — route back to the upstream agent.
3. **Filter.** Records by `req_id` and `type`. The **latest** record for each `(req_id, type)` is the active state.
4. **Check.** Required fields, types, and pattern constraints per the schema.
5. **Decide.** If every check passes: dispatch the next agent. If any check fails: bounce upstream — `route` emits a dispatch of the producing agent carrying the errors; the coordinator names the failed check in a `Blocked` recommendation.
## Blocking
If any gate fails, if a `design-block` record carries `verdict: "conflicting"`, or if a `review-feedback` record carries a `tag: "escalate"` finding, stop the pipeline and resolve before continuing. For an escalate finding, the halt follows the findings-processing dispatch that records the entry in `.scratch/escalations.md` (Gate 4). On an `approved` verdict no findings-processing runs — root appends the entry before halting. On a `review-non-convergence` halt no findings-processing runs either: root appends the entries for the `escalate_findings` its context counts, then puts the halt to the human. `route` enforces the escalate halt twice: `process-findings` carries `halt_after: true`, and `escalate-finding-halt` blocks re-review until a reviewer record follows the human's decision. The resume relays the human's decision in the human's own words; root never composes it.
## Build-Failure Recovery
A failed quality gate (build error, test failure, format/lint failure) ends the implementer dispatch with a `build-failure` record carrying the error output and retry count. Schema: [`schemas/scratch/build-failure.schema.json`](../../../schemas/scratch/build-failure.schema.json). `route` executes the recovery deterministically; `route-spec.md` § Build-Failure Recovery is the normative definition. The shape:
- An `abort_reason` short-circuits the retry counter: `wrong-shape-slice` → product-requirements-expert for re-split; `design-mismatch` (also a failed autofix audit on a design-doc record) → system-design-expert for re-triage; `prd-mismatch` (a failed autofix audit on a `prd-autofix` record) → product-requirements-expert for PRD reconciliation; `prerequisite-missing` → halt for the human. The record shape and trigger live in `tdd-workflow` § Wrong-Shape Slice Abort.
- Otherwise `retry < 3` re-dispatches the implementer with the error trail; `retry == 3` re-triages via system-design-expert, whose superseding `design-block` resets the counter. `build-failure` records count only after the latest `design-block`; `python3 scripts/handoff.py next-retry --req-id <id>` implements the rule.
## Truncation Recovery
A feature-implementer dispatch that ends without a `build-pass` or `build-failure` for the active `req_id` truncated before the quality gate. Truncation alone does **not** mean the slice is over-scoped: the Scoping Pre-Check re-scopes a multi-behavior slice *before* dispatch. A slice that reaches dispatch and then truncates is presumed correctly sized and simply long. **The default recovery is to continue the same slice** — up to 3 consecutive truncations, then re-triage via system-design-expert (non-convergence). Re-split is reserved for the Pre-Check's over-size branch and for non-convergence — and even there it is one outcome, not the first response. `route` executes the steps; `route-spec.md` § Truncation Recovery is the normative definition. It also defines the two partial-record paths (`build-failure` with `partial: true`; `review-feedback` carrying a `truncation` finding), which route through existing recovery instead.
### Dispatch Truncation Detection
Every dispatched project-defined agent except `pipeline-coordinator` and the terminal `change-grader` appends a `dispatch-start` record as its first tool call. Schema: [`schemas/scratch/dispatch-start.schema.json`](../../../schemas/scratch/dispatch-start.schema.json). Detection is deterministic, reads `.scratch/handoff.jsonl` alone, and is `route`'s code path. The rule text, the substantive-record closed enum, and the consultation carve-out live once in `route-spec.md` § Dispatch Truncation Detection, pinned to the `SUBSTANTIVE` constant. Built-in agents not defined under `.claude/agents/` (e.g. `general-purpose`, `Explore`) are out of scope for this contract; root carries the dispatch-discipline for those per `CLAUDE.md` § Tool-call budget.
## Mid-Implementation Consultation
The feature-implementer may need a focused answer from product-requirements-expert or system-design-expert during TDD cycles when the inner loop discovers a question the triage didn't anticipate. The implementer appends a `consultation-request` targeting the specialist; `route` dispatches that specialist in consultation mode (`consultation-dispatch`); the specialist appends a `consultation-response`; `route` returns control to the implementer (`consultation-return`).
Consultations are substeps, not handoffs. They preserve the implementer's active state — the pipeline advances only when the implementer's own next handoff (`build-pass` or `build-failure`) appears.
Consult when another agent owns the answer. When only the human can decide, target the human: a `consultation-request` with `target: "human"` halts the pipeline (`human-consultation`) while root runs the conversation. Root appends the `consultation-response` (`author: "human"`) and `route` resumes the requester — the elicitation pause of `agentic-harness.md` § Conversations Stay in Root. The response transcribes the human's reply, never an answer root composes; with no reply the halt stands. The halt is sticky: `route` holds `human-consultation` until the response lands, whatever else is appended. `.scratch/escalations.md` remains the surface for findings-driven escalations (§ Blocking) and external prerequisites. The test is who can unblock you.
## Consultation Ownership (Fresh Human Questions)
A question the human raises mid-run belongs to the expert owning its document surface. The boundaries are the same ones the Gate 4 finding split uses. Root's judgment is the table lookup; the discussion then runs in session under the owning contract (the intake pattern — no dispatch, no relay):
| Question surface | Owning contract root loads |
|---|---|
| Scope, behavior, acceptance, non-goals (`docs/prd.md` territory) | the product expert's — `prd-authoring` |
| Structure, trade-offs, patterns, integration (`docs/system-design.md`, `docs/adr/` territory) | the design expert's — `design-validation` |
| Ambiguous — the question spans both or names neither | the product expert's first; load both when the discussion turns structural |
The discussion is informational: nothing dispatches and nothing lands in the ledger while it is live. An outcome that changes recorded scope exits through the `intake` skill — a fresh `intake-decision`. A specialist's own question keeps its recorded channel (§ Mid-Implementation Consultation); this section covers only questions the human initiates.
## Review Feedback Actions
See the `review-workflow` skill for feedback tag definitions and the review process. The two root-applied procedures — the reviewer stall check and doc autofixes — live below, because root executes them while routing.
### Reviewer Stall Check (root)
`route` owns the detection and the ladder, deterministically: a reviewer with one silent `dispatch-start` since `build-pass` earns a single retry (`reviewer-stall-retry`); a second silent dispatch returns `reviewer-stalled` (blocked). Root's part is what a script cannot do. On `reviewer-stall-retry`, re-dispatch the named reviewer with this prompt, appending the decision's `prompt_note` verbatim as a final sentence: `"Your previous run returned without appending a review-feedback record to .scratch/handoff.jsonl. Run the review now. Your only deliverable is that record — see Output Protocol in review-workflow."` On `reviewer-stalled`, append an entry to `.scratch/escalations.md` naming the reviewer and stop — do not proceed to findings processing. Only root re-dispatches; specialists cannot.
### Root-Applied Autofix on Doc Paths
To keep the owning experts' quality bar tight while removing ceremony from mechanical fixes, root may apply `tag: "autofix"` findings on the owned doc paths directly — without redispatching the owner. Two path classes exist, each with its own audit record and auditing expert:
| Path class | Owner | Record | Owner's audit home |
|---|---|---|---|
| `docs/system-design.md`, `docs/adr/*.md` | system-design-expert | `design-doc-autofix` | `design-validation` § Autofix Audit |
| `docs/prd.md` | product-requirements-expert | `prd-autofix` | `prd-authoring` § Autofix Audit |
The quality bar lives in the `blocked` and `clarify` paths (with `clarify_target` naming the owner), which still route to the owning expert. The PRD path exists so a doc-only fix resolves in the current review round: without it, the owner's only substantive record is a `prd-entry`, which re-enters the pipeline at design triage.
The eligibility rules live in the `document-writing` skill's `autofix-protocol.md` — § Autofix on Design-Doc Paths and § Autofix on the PRD Path. Doc-reviewer is responsible for never tagging a finding as autofix on these paths unless every condition there holds (the `review-workflow` skill's `reference.md` § Root-Applied Autofix Eligibility). This section defines what root does once such a finding exists.
#### Apply Procedure
1. **Validate the finding statically.** Confirm: `tag == "autofix"`; `location` falls under an autofix-eligible doc path; `fix` field is present and is a literal replacement string (not a description). If any check fails, treat the finding as `blocked` and redispatch the owning expert instead.
2. **Apply verbatim.** Replace the finding's target text with the literal `fix` string. Read the file first to anchor the exact original text. Do not paraphrase or "improve" the fix — root acts as a typewriter for the doc-reviewer's verbatim proposal.
3. **Re-check the bounds after the edit.** Confirm the change stays within the autofix allowlist — the conditions in the matching `autofix-protocol.md` section, the same list `handoff.py audit-autofix` re-validates at gate time. If any check fails, revert the edit and redispatch the owning expert.
4. **Append the path class's record** to `.scratch/handoff.jsonl` carrying: the source finding (copied verbatim), the file path, the autofix category (`writing-standards` or `structural`), `old_content`, `new_content`, `lines_changed`, `chars_changed`. Schemas: [`schemas/scratch/design-doc-autofix.schema.json`](../../../schemas/scratch/design-doc-autofix.schema.json), [`schemas/scratch/prd-autofix.schema.json`](../../../schemas/scratch/prd-autofix.schema.json). Append per the `handoff-append` skill.
5. **Append-only discipline.** Preserve every prior line in `handoff.jsonl` verbatim.
#### Why The Record Matters
- **Gate-time re-validation.** `python3 scripts/handoff.py audit-autofix` (the `code-quality-gate` skill's autofix audit) mechanically re-checks every `design-doc-autofix` and `prd-autofix` record against the allowlist bounds, so a mis-applied autofix fails the quality gate before merge.
- **The owning expert audits on next dispatch.** The `design-validation` skill instructs the system-design-expert to judge all `design-doc-autofix` records since its last dispatch; the `prd-authoring` skill instructs the product-requirements-expert to judge all `prd-autofix` records since its last `prd-entry`. Each may reject any — the design side via an `autofix-rejected` finding on the next `design-block`, the PRD side via a corrective superseding `prd-entry`.
- **Direct-edit detection.** The same command fails if `docs/system-design.md` or `docs/adr/*` has uncommitted changes that no `design-doc-autofix`, `design-block`, or `consultation-response` record covers — catching any future bypass of the protocol. The scan is design-doc-scoped by decision: `docs/prd.md` has its own `prd-autofix` trail and stays outside it. A `prd-entry` carrying `scope_overrides` covers the non-goal ADR its Non-Goals change records, and `docs/adr/README.md` is covered whenever every other dirty ADR path is. `handoff.py append design-block` runs the same coverage check with the candidate block in the entry set and refuses a block that would leave a dirty design-doc path uncovered. An omitted path therefore surfaces at the expert's append, not at the implementer's gate.
#### What Root Does Not Do
- Root does NOT autofix on any path outside the two classes above — code-path findings route to the implementer regardless of tag.
- Root does NOT autofix any tag other than `autofix` (blocked/clarify/escalate route as defined elsewhere).
- Root does NOT batch autofixes across artifacts — one record per finding, one edit per finding.
## State Files
| File | Created By | Consumed By |
|---|---|---|
| `.scratch/handoff.jsonl` | product-requirements-expert, system-design-expert, feature-implementer, review-planner, the roster reviewers, change-grader, root (all append-only) | the router — `route` and, on `escalate`, the coordinator (validation gates); all consumer agents |
| `.scratch/tmp/` | every dispatched agent — the only sanctioned surface for an intermediate file, system `/tmp` barred | the writing agent alone; `new-feature` recreates it empty |
| `.scratch/implementation-plan.md` | feature-implementer | feature-implementer (self-tracking) |
| `.scratch/escalations.md` | feature-implementer (escalate-tag findings, mid-loop escalations); root on the router's `blocked` decision (prerequisite-missing aborts; reviewer stalls per § Reviewer Stall Check; escalate findings on an `approved` verdict per § Blocking) — never the coordinator itself | Human |
`.scratch/handoff.jsonl` is the append-only structured handoff log; one JSON object per line, each carrying a `type` discriminator. Record types:
| Record `type` | Producer | Purpose |
|---|---|---|
| `intake-decision` | `human` via root — the `intake` skill's exit, or headless preparation seeding from the task prompt | The owner's request and decisions, quoted verbatim; grounds the slice's `prd-entry`. Routes `intake-ready`: dispatch product-requirements-expert. |
| `prd-entry` | product-requirements-expert (system-design-expert: the refactor-first sibling entry) | Active feature scope for system-design-expert and implementer. |
| `design-block` | system-design-expert | Triage verdict and implementation guidance. |
| `consultation-request` | any specialist mid-work | Focused question to another specialist that does not advance the pipeline. |
| `consultation-response` | the consulted specialist, or `human` via root transcribing the human's reply on an elicitation pause | Focused answer; routes control back to the requester. |
| `review-feedback` | each reviewer agent in the roster | Per-reviewer verdict and findings. |
| `build-failure` | feature-implementer | Quality-gate failure with error context and retry counter. |
| `build-pass` | feature-implementer | Quality-gate success marker. |
| `review-plan` | `grading.py review-plan` (author `review-plan-engine`); `review-planner` for the gray zone | Names the reviewer roster and read scope for a review pass; fail-closed to the full battery when absent or invalid. |
| `design-doc-autofix` | root | Audit trail for root-applied autofixes on design-doc paths (see § Root-Applied Autofix on Doc Paths). |
| `prd-autofix` | root | Audit trail for root-applied autofixes on `docs/prd.md` (same section); keeps a doc-only PRD fix in the current review round. |
| `dispatch-start` | every project-defined agent except `pipeline-coordinator` and `change-grader` (as its first tool call) | Half of the dispatch-event contract; "no subsequent substantive record from same `(req_id, author)`" is the deterministic truncation signal. Not substantive — does not satisfy the implicit stop. |
| `grader-features` | change-grader (`grading.py extract`) | change-grader (the grading read). Deterministic structural row; advisory, terminal — does not route. |
| `grader-verdict` | change-grader | Advisory facets + rationale + `skim`/`scrutinize` verdict; surfaced to the session, recorded, never routed. Not substantive for truncation detection. |
## Log Access
The coordinator never writes records — it only reads them for routing decisions. All writes to `.scratch/handoff.jsonl` go through `scripts/handoff.py` per the `handoff-append` skill, which holds the writer contract, the full command table, and the exit codes. Reading the whole log for context is fine; decisions that gate routing use the query subcommands below.
| Operation | Command |
|---|---|
| Routing decision | `python3 scripts/handoff.py route [--req-id <id>]` |
| Latest record for a gate | `python3 scripts/handoff.py latest --type <type> [--req-id <id>]` |
| Next retry counter | `python3 scripts/handoff.py next-retry --req-id <id>` |
| Whole-file check | `python3 scripts/handoff.py validate` |
`route` exits 0 whenever a decision was computed — including `blocked` and `escalate`; the decision field carries the state. The human-inspection surface (`show`, and `view` via the `handoff-board` skill) is listed in `handoff-append` § Writer Commands.
## Human Checkpoints
Routing is deterministic: a passed gate names the next agent per the Handoff Conditions table, without waiting for approval. Human attention concentrates at four points — two advisory, two blocking:
1. **After PRD update** *(advisory)* — Review that the requirement captures intent. The pipeline proceeds; to intervene, halt and route back to product-requirements-expert to append a superseding `prd-entry`.
2. **After design notes** *(advisory)* — Review the architectural approach. Same intervention path, via system-design-expert.
3. **After escalations** *(blocking)* — The pipeline halts until the human decides each `[ESCALATE]` item. A `design-block` with `verdict: "conflicting"` halts the same way (Handoff Conditions table).
4. **After feature complete** *(blocking)* — The change-grader's verdict is advisory; only the human approves the merge.
## Coordinator Output Format
The coordinator handles what `route` cannot: untriaged fresh-intake classification and every `escalate` decision; a `next`-triaged pick dispatches `product-requirements-expert` directly. Its recommendation follows the same table; `route`'s JSON is the deterministic fast-path for the rows the table decides alone.
The pipeline coordinator responds with a structured recommendation:
```
## Pipeline State
[Current state based on .scratch/ files]
## Recommendation
**Action:** Invoke [agent-name]
**Prompt:** "[suggested prompt for the agent]"
**Shortcut:** Yes/No
**Reason:** [why this agent is next]
```
If blocked:
```
## Pipeline State
[Current state]
## Blocked
**Blocker:** [description]
**Resolution:** [what needs to happen]
```
## Coordinator Rules
These rules bind the coordinator when it is dispatched — fresh intake and `escalate` states. On the routine path `route` applies the same table.
1. Never skip pipeline stages for new features.
2. Shortcuts are allowed only per the agent selection table above.
3. If `.scratch/` contains stale state from a previous feature, recommend clearing it first.
4. Report all `design-block` records with `verdict: "conflicting"` and all `review-feedback` findings tagged `escalate`.
5. Recovery ladders are `route`'s, never yours: build-failure retries (`route-spec.md` § Build-Failure Recovery) and implementer truncation (§ Truncation Recovery) are decided deterministically. What reaches your escalate arm is their degenerate states — `abort-unknown`, `failure-without-design`, `truncation-before-design`, and a truncated agent with no recovery row. Decide those; never re-decide a ladder rung.
6. After `route` reports feature-complete (its Gate 5 call; `route-spec.md` § Gate 5), recommend dispatching the `change-grader` agent (terminal, advisory). With `layout.toml [harness] auto_grade = false`, skip that recommendation — `route` reports feature-complete directly. The grader assesses how much human attention the passing change deserves; its `skim`/`scrutinize` verdict is recorded and surfaced to the session, but it does **not** route and is **not** a merge or correctness gate. Do not consume its verdict for any routing decision.