Deliver

SkillAI & models

Take a plan all the way to a ready-to-merge pull request — review the plan (scaled to risk), implement it test-first, code-review and fix, run the CI gate, open the PR, and watch it green. Use after you have an approved plan (from plan mode, or the Plan agent); pass `issue <n>` to deliver a specific GitHub issue you name, or `next` to take the top startable issue off the project board's Ready column — either way it re-verifies, claims and plans the issue first. Invoking it with a plan already in hand is itself plan approval — it then runs autonomously to a single hard stop: ready-to-merge.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Deliver skill

What this skill tells your AI

The instructions your AI receives, as published by adamayoung/tmdb in .claude/skills/deliver/SKILL.md and read by ahel’s review.

Drive the current plan through the whole feature pipeline to a PR that is green and ready to merge. This skill is an orchestrator — it sequences the existing skills and adds the safety gates; the expertise lives in the pieces it invokes. It runs autonomously from invocation (which is itself plan approval) to a single hard stop — ready-to-merge — auto-scaling its machinery to the change's risk, and writing a short retrospective that rides the delivery's own PR. Every run happens in its own git worktree (Phase 1; torn down on merge, Phase 12) so the user's main checkout stays free. The plan is created first in plan mode (or with the Plan agent; there is no /plan skill) — /deliver picks up from there. A selection run supplies its own plan: /deliver next takes the top startable issue off the project board's Ready column and /deliver issue <n> takes the one you name, then drafts a plan for it (Phase 0; references/next-mode.md).

you approve the plan ─▶ /deliver ─────▶ entry gate (ACs?) ─▶ worktree ─▶ [review-plan] ─▶
   (or: /deliver next | issue <n> ─▶ select ─▶ re-verify ─▶ claim ─▶ draft ─▶ approve ─┘)
  implement ─▶ code-review + fix ─▶ security-review + fix ─▶
  rubric check (ACs met?) ─▶ capture ─▶ retro (pre-PR) ─▶ /pr reviewed ─▶ /watch-pr ─▶
  GATE: ready-to-merge ─▶ wrap-up (wiki + recurring-pattern scan)
  ▲ the only hard stop
  … then, when the PR actually merges (maybe a later session): teardown (Phase 12)

Detail on demand: procedures, traps, incident history and design rationale live in references/ — read the named file when its phase arrives, not up front.

Agent Behaviour Contract

Non-negotiable. Do these by default, without being reminded.

  1. Invoking /deliver is plan approval — run autonomously to the one gate (the diagram above), with no second "is the plan ok?" prompt. The only legitimate mid-run pauses: a blocker from /review-plan (Phase 2), a red gate you cannot triage (§4), or — on an attended selection run, under either policy — the one approval stop on a plan /deliver drafted for itself (Phase 0): invoking the skill approves the plan you brought, and a selection run brought none. Naming the issue yourself settles what to build, not how, so /deliver issue <n> gets that stop exactly as /deliver next does. In auto it is not a pause at all — the phase0n-selection panel rules instead.
  2. Delegate to the existing skills — don't reinvent them: /review-plan, /implement-plan, /review-changes, /security-review, /capture-knowledge, /pr, /watch-pr, /fix-integration-failures.
  3. Never work on main — always in a fresh worktree, entered before /review-plan or any file edit (CLAUDE.md forbids editing main).
  4. A red gate triages before it stops. In-diff failure → fix test-first and re-run. Pre-existing/unrelated (typically a flaky live integration test) → route to /fix-integration-failures and re-run — never hard-stop on someone else's flake. Only a genuine, in-diff, unfixable break stops the pipeline.
  5. Test-first all the way. Every review-loop fix follows canon-tdd — failing test first. No untested patches.
  6. Keep two records: a TaskCreate ledger and a run file. The ledger is the live view (one task per phase, statuses current, branch, PR number, weight); the run file is the durable one, because the ledger does not survive EnterWorktree, an MCP reconnect, or a plan-mode exit. Phase 0 writes it, Phase 1 records the reconcile into it, Phases 4/5/6 each stamp it on convergence (stamps.reviewedClean / securityClean / rubricGraded — that is what makes a resume able to skip a pass already done), and Phase 6 reads the rubric from it — so a skipped step fails loudly at a later phase instead of silently. Every phase that writes is named here, so if a phase you are in is absent, nothing writes on its behalf and you must not assume something else did. (Two non-phase writers exist and are documented where they apply: an async run writes the file before any ScheduleWakeup, and Phase 1's adopt path flips entry before re-locking — see references/.) Location and schema: references/worktree-lifecycle.md. Every run-file write after EnterWorktree goes through Scripts/deliver-runfile.py — the worktree guard refuses ad-hoc writes to .git/deliver/, sometimes silently — and the script verifies its own postcondition: exit 0 prints verified: …; anything else means the write did not land and is a hard stop for the phase making it. Never carry on assuming state you did not read back — the #493 delivery certified a plan revision to the juror panel that two silent refusals had kept off disk. A template→replicate delivery adds the Phase 4a — reference-unit review gate task, which blocks Phase 9. A multi-deliverable plan keeps one ledger sub-tree per deliverable.
  7. Jot knowledge candidates the moment a learning occurs (a lookup, a gotcha, a live-API surprise, a non-obvious decision) — one line each (<category>: <gist> [where]), in the ledger. Mirror the list into the run file (deliverables.<n>.knowledgeCandidates, via deliver-runfile.py) at Phase 7 entry at the latest — the ledger does not survive EnterWorktree, and the resume rule restores candidates from the file, so an unmirrored list is one a resumed run silently loses. Phase 7 curates them; reconstruction later loses the best material.
  8. Auto-start after plan-mode approval. ExitPlanMode approval IS the start signal — invoke /deliver immediately; pause first only if Phase 0's entry gate fires.

Invocation — /deliver [auto] [merge] [next | issue <n>]

The four keywords are recognised only as whole, standalone tokens in a leading run — parsing stops at the first token that is not one of them, and everything from there on is the named plan target Phase 0 resolves. So /deliver auto merge next is three keywords, and /deliver auto fix the merge handling plan is one keyword plus the target "fix the merge handling plan"not an auto-merge. A keyword found after the target has begun is part of the target; say so rather than acting on it — nobody notices an auto-merge they did not ask for until it has happened.

issue takes exactly one operand — the issue number, with an optional leading #. So /deliver auto issue 480 is two keywords plus an operand. (issue is a keyword with an operand, not a bare-number selector, so the leading-run rule never has to distinguish a selector from a plan target whose first word happens to be a number.)

Four contradictions — report and stop before any board write, worktree or edit, rather than silently picking one:

  • issue <n> with a named plan target
  • issue <n> together with next (two selection policies)
  • two issue operands
  • issue with no operand, or a non-numeric one

next and a named target contradict each other for the same reason. Either selector takes precedence over a plan already in the conversation, and says so before drafting.

Echo the parse before acting on it — one line, first thing, before any board write, worktree or edit:

parsed: auto=on · merge=off · select=issue#480 · target=(none)

select= renders as issue#<n> for an explicit pick, next for the top-of-run-list policy, or (none) when neither was requested. The echo exists because no grammar can disambiguate a target whose first token is a keyword (/deliver merge conflict handling plan) — a mis-parse must become visible in the second before it matters, not at the moment an unrequested squash-merge lands. Phase 0 writes the same parse to the run file at the same instant.

  • auto — unattended; every stop-and-ask becomes a juror panel (below).
  • merge — squash-merge once the PR is green, instead of stopping at the gate (Phase 10).
  • next — no plan needed: requests the top-of-run-list selection policy, which takes the top startable issue off the board's Ready column and drafts one (Phase 0; references/next-mode.md).
  • issue <n> — no plan needed: requests the explicit selection policy, which takes the issue you name and drafts one. Same path from there on — re-verify, claim, draft, and release the claim on any stop before the PR opens. Unlike next it may name an issue in Backlog: choosing it yourself is the triage judgement the Ready test otherwise stands in for.

Both selectors require the user-scoped GitHub Projects MCP — explicit still has to claim the issue — so both are unavailable on a GitHub Actions runner.

Auto mode & async invocation

/deliver auto replaces every stop-and-ask decision with an adversarial panel of three independent Opus jurors — a dead panel is never a proceed, and every panel convened leaves an audit line in the ledger. Decision points are marked Auto: below. Never delegated: a data-loss or breaking-change plan blocker is a hard stop even in auto, and in auto merge a breaking issue is never merged unattended: under next it is not selectable at all, and under issue <n> the merge opt-in is dropped so the PR waits at the gate (references/next-mode.md §5). /deliver can also be queued headless (the plan + ACs must travel in the trigger prompt — unless a selection policy supplies them, which only works where the Projects MCP is mounted). Panel procedure and queuing caveats: references/auto-and-async.md. In attended mode the Auto: branches do not apply — stop and ask, as written.

Delivery weight — auto-scale to risk

Judge from the plan; re-confirm from the diff after Phase 3; record in the ledger. Lite — small, mechanical, single-unit, no risky surface (no concurrency, networking/HTTPClient, or Decodable/CodingKeys changes; no new public API beyond a simple additive method; under a few hundred changed lines) ⇒ skip /review-plan's critics; /review-changes takes its single-reviewer path. Full — anything risky or large ⇒ the three-critic /review-plan and the fan-out + adversarial-verify /review-changes. When unsure, prefer full. The vocabulary is binary — a hybrid run (e.g. a pre-reviewed plan with the full review machinery) records as full with the skipped machinery noted, in the ledger and the retro; never invent a third tier.

One named override exists, and it is not a third tier. An auto selection run — under either policy — drafted its own plan with no human between the issue and the implementation, so it always runs /review-plan's critics whatever the weight (Phase 2). Record that as planReview: forced — auto-<policy> in the run file and the retro, leaving weight itself untouched; a lite run stays lite for Phases 4 and 5. explicit is covered too: naming the issue yourself puts a human between you and the issue, not between anyone and the plan, and it is the plan the critics read. An attended selection run is not covered: its Phase 0 approval stop is the same consent ExitPlanMode gives every other run, so it follows weight as normal.

Multi-deliverable plans — one run, several PRs

A plan that is a program of cohesive deliverables becomes one PR per deliverable. Decompose in Phase 0 with a dependency graph: dependent (consumes a type/API/helper/file another introduces or substantially changes) → sequence it (branch off its dependency, or wait for its merge); independent → own worktree + branch + PR; unsure → treat as dependent. Execution is serial implement, concurrent watch: one deliverable at a time through Phases 1→9, but once its PR is open, start its /watch-pr in the background and move to the next. The gate reports the batch; each worktree is torn down as its PR merges; a stuck PR never blocks the others. The full per-deliverable pipeline applies unchanged. (Genuinely parallel implementation = separate /deliver sessions.)

Context & isolation (by design)

  • The conductor stays lean (plan reference, ledger, gate, short per-phase summaries); heavy work is already isolated in Workflows/subagents — keep it that way.

  • Implement runs inline — on purpose (the TDD list stays visible). Do not convert it to a silent subagent.

  • The gate stays in the main agent; phases hand off via git / disk / the PR, not context.

  • Separate worktrees get separate .build dirs. No SCRATCH_PATH override is needed — that flag is only for multiple agents sharing one working directory.

  • One Swift process per worktree — at any instant, across every agent. Not "each agent runs its builds sequentially": one build in the whole worktree, full stop. The conductor owns it. Concretely:

    • Only the conductor and the tooling-runner it spawns may build. Reviewer, security and grader subagents must be told not to build — their prompts say so, and /review-changes and Phase 6 already carry that instruction.
    • Never run two analysis phases concurrently. Phase 4 and Phase 5 read the same commits and feel independent — but they serialise on disk, not on tokens. Finish one, then start the next.
    • Never spawn a tooling-runner in the background, and never two at once.

    Every target shares one scratch directory, and a build-docs run flips the SWIFTCI_DOCC manifest, which invalidates a concurrent build's plan rather than queueing behind it — the processes then redo each other's work in a cycle (knowledge/gotchas.mdDocs builds need their own scratch path).

Phase 0 — Preconditions

  • A plan must exist (named target → plan-mode plan → most recent in conversation). None → stop; ask for one in plan mode. Never invent one — except on the one sanctioned path: a selection run selects one instead. Under top-of-run-list (next) it takes the top startable issue off the board's Ready column; under explicit (issue <n>) it takes the issue you named, which may sit in Backlog. Either way it then re-verifies against origin/main, claims it, and drafts a plan with the Plan agent — and continues through the rest of this phase unchanged. Procedure, exclusions and the selection block: references/next-mode.md. Selection is part of Phase 0 rather than a phase of its own so the run file keeps one writer and the knowledge consult below still precedes the drafting that consumes it. Nothing startable, or no Projects MCP → stop before the worktree; never fall through to the "no plan" stop, which reads as an unrelated failure. Write the parsed invocation into the run file when you parse the keywords — before selection runs, not after. Record every keyword, not just this one ("mode": "auto merge next", or "mode": "auto explicit" for issue <n>next and explicit are the two selection-policy tokens, and every gate keys on that rather than on the literal word next), plus the raw argument string as invocation, plus conductorPid — this session's PID. Why the ordering and each field matter: references/worktree-lifecycle.mdRun state. Auto: the approval stop below becomes the phase0n-selection panel — proceed with this self-picked issue and self-drafted plan, vs stop.

  • A plan born from a review finding is a hypothesis — verify against the code (quick Explore) before planning or asking strategy questions.

  • State the goal in a sentence; judge the weight; open the ledger.

  • Pull wiki context best-effort (get_context on the goal); degrade silently if the wiki MCP is absent.

  • Consult the knowledge base — skim the entry headings of knowledge/gotchas.md and knowledge/tmdb-api-notes.md, read the entries (and any knowledge/decisions/ ADR) relevant to the goal's area, and record one consulted: <entries | none relevant> line in the run file (and the ledger for convenience). Captured knowledge only compounds if it is read at entry, and the line must live where it survives — the ledger alone is not enough, because Phase 1's EnterWorktree clears it. Phase 8 copies it into the retro, which is the committed, human-reviewed copy.

  • Identify the issue this delivers, and record it. Record issue: <number> on the deliverable in the run file (or issue: null when the work is genuinely untracked). Per-deliverable, not run-scoped: a multi-deliverable plan can close a different issue per PR, or none. Phase 1 moves it to In progress and Phase 10 to In review, so an unrecorded issue is one the board silently never reflects. A selection run has already made the In progress move itself, at the pick (Phase 1's move then finds it set and no-ops), and its claim carries an obligation: any stop before the PR opens releases it back to selection.claimedFrom — the column it was claimed from (references/next-mode.md §6).

  • Flag a reflexive delivery. If the plan touches any of the reflexive set.claude/skills/**, .claude/agents/**, .claude/workflows/**, .claude/docs/** or .github/CODE_REVIEW.md — this run is rewriting the machinery that runs it. Record reflexive: true in the run file. When in doubt about a path, resolve it as reflexive — a false positive costs one human merge; a false negative is the pipeline silently editing its own gates.

    This list is the reflexive set, and it is quoted in two other placesreferences/next-mode.md §5b, which refuses such an issue in merge mode, and references/worktree-lifecycle.md's run-file schema. Change all three or noneScripts/tests/test_deliver_selection_prose.py asserts they agree, because a prose cross-reference alone did not survive one delivery (the drift history lives with the schema).

    Then read references/reflexive.md now and hold its four consequences for the rest of the pipeline: no dogfooding before merge, verification pinned to the original text, the whole-footprint sweep (re-swept after every review-loop fix), and Phases 4/5 running even on a markdown diff.

  • Decompose a multi-deliverable plan (rules above); single-deliverable plans skip this.

  • Entry gate — a gradeable rubric required. Plans are expected as "As a <user-type> I want <feature> so that <reason>" + acceptance criteria. Extract the ACs verbatim as the delivery rubric (consumed in Phase 6) into the run file (and the ledger for convenience), and record rubricProvenance: supplied. Three cases, and only the last one stops:

    • ACs supplied → the above.
    • ACs absent but derivable — the plan has a definition of done in the wrong shape rather than none at all: a linked issue stating observable before/after behaviour, or an explicit canon-tdd test list. Derive the ACs into "Given X, when Y, then Z" form, record rubricProvenance: derived — <the source>, and say in the PR body that the rubric was derived. Bug fixes land here routinely; stopping to ask a question the plan already answers is ceremony, not rigour. A selection-run-drafted plan always lands here, under either policy: record derived — issue <number>, never suppliedsupplied means a human set the bar, and here the run that gets graded wrote its own rubric. Do not "simplify" it back.
    • Neither → stop and ask for them ("Given X, when Y, then Z") — don't enter the worktree. Auto: panel — proceed rubric-less (Phase 6 no-ops) vs stop; record that as rubric: none, which is present-and-empty, not a missing file.

    Reject a knowledge-shaped AC — it cannot pass. An AC whose evidence is a knowledge/ artifact ("an ADR records X", "a gotcha is captured") is guaranteed to fail its first grading, because Phase 7 writes that artifact after Phase 6 grades — deliberately, so capture observes the delivery's final state. Drop such an AC from the rubric when extracting it (the work still happens, enforced by Phase 7's own contract), say which ACs you dropped and why, and when deriving, don't write one in the first place.

    Derive to grade yourself honestly, not to pass: write the ACs from the source's own words before implementing, never after, and never soften one because the implementation went another way. Provenance makes a derived rubric auditable; Phase 6's independent grader is what stops a self-serving one.

  • Read the plan's content into context nowEnterWorktree switches CWD (clearing the plans cache), and a fresh worktree lacks uncommitted local files; the plan must travel in the conversation.

Phase 1 — Reconcile prior runs, then enter an isolated worktree

Procedures and traps: references/worktree-lifecycle.md.

  1. Reconcile before EnterWorktree (the run file already exists — Phase 0 wrote it; record the sweep into it, never mint a second one). Enumerate with git worktree list --porcelain (never ls .claude/worktrees/), scoped to <main-root>/.claude/worktrees/, and classify every one first-match-wins: live (lock PID alive — never touch) / report / reclaim (merged and Phase 12's two proofs) / resumable / settled. Report, never remove, anything that doesn't prove reclaimable, and verify a directory is gone before counting it reclaimed. Record reconciled: in the ledger, the reconciled block in the run file, and the retro (Phase 8) — never as swept:, which is Phase 7's knowledge sweep and will silently take the slot.

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
176
Forks
47
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
deliver
Source
github.com/adamayoung/tmdb