Imported from mckissinger/keel (
skills/implement-feature/SKILL.md). Install upstream withnpx skills add mckissinger/keel --skill implement-feature. Copyright stays with the author.
Implement Feature
Build a feature's milestones end-to-end. This skill is connective tissue: it sequences implement-milestone and verify-milestone in dependency order and enforces the GitHub process, but re-implements neither and — by default — stops at the user's merge (agents never merge on their own initiative). The one standing exception is a repo the human has armed for committed auto-merge (or an active keel:auto mode): there the run continues through landing into a prepared review-feature (see Where the run ends).
First: ask the cadence
Feature milestones relate in one of three ways, and the choice changes everything downstream — so always ask, defaulting to interleaved:
- Interleaved (default) — build M1 → user merges M1 → M2 builds off updated
main. No stack ever forms. - Stacked — build all milestones in dependency order, open stacked PRs, user merges bottom-up; concentrates the cascade risk
land-featurehandles. - By wave — independent milestones concurrently off
main, the dependent chain stacked; review, then the next wave.
Read the milestone specs for parallelizable markings (§4 of the rules) and keep any stack as shallow as the genuine dependency chain requires — prefer independent milestones off main.
The one exception a real dependency forces is a diamond milestone (multi-parent) — depends on all its siblings and carries an "after all land" whole-repo check. Not a single-parent stacked PR, so build + verify it on a conflict-free integration branch (a merge of its parents), base its PR there, keep it last. The rebase-onto-main-and-re-pin finish is land-feature's.
The orchestration
At orchestration start, read the feature spec's Lifecycle section (specs/features/<feature>.md) with the milestone specs — it enumerates this feature's gates and their state sources, for the handoff to report. A spec with no Lifecycle section has that absence surfaced in the handoff, never silently skipped; land-feature's reconciliation backfills it.
For each milestone, in dependency order (bottom-up for a stack):
- Build — dispatch
implement-milestoneon its own branch: off a freshly fetchedorigin/mainif independent (never localmain— the stale-base scar in that skill's step 2), off the parent if it genuinely stacks, off the diamond's integration branch if multi-parent. The build subagent always runsclaude-opus-5; route only its effort by the milestone'sRouting:tag (§4):mechanical→highridesimplement-milestone's frontmatter (nothing to set);reasoning-heavy→xhighvia a mechanism that actually carries an effort arg — the Agent/Task dispatch exposesmodelbut noeffortarg, soxhighrides a Workflowagent()dispatch or a session set toxhigh; where neither is available, dispatch at the frontmatter default and record the routing gap as a run-note once for the run, not per dispatch (${CLAUDE_PLUGIN_ROOT}/references/model-routing.md, the harness reality check). - Verify in a fresh context — dispatch verification as a subagent with its own context window. Prompt it from the spec's done-conditions + the checkout, never from the builder's claims. Every dispatch here follows the report contract, and every CI/merge watch the settle-only rule (
${CLAUDE_PLUGIN_ROOT}/references/dispatch-and-monitoring.md— name the report sections in the prompt; a placeholder/truncated report gets one protocol resume, then counts as not run; watch for all-settled or first-failure, and emptyghoutput is a failed read, never success). Dispatch theverifierathighfor every milestone — its frontmatter is the dispatch; the never-weaker invariant is carried by capability decorrelation (Fable 5 athighexceeds the Opus-5 builder at any routed effort —${CLAUDE_PLUGIN_ROOT}/references/model-routing.md, the verifier-strength invariant; the reason isdecisions/2026-07-01-model-capability-ledger.md, and the effort-escalation form reactivates whenever the verifier's model does not strictly exceed the build model). The fresh-context verifier's proof run is the full committed suite — its dispatch forbids a spec/milestone filter, never scoped to this milestone's own tests (${CLAUDE_PLUGIN_ROOT}/references/milestones-and-verification.md§9.1).[auto]conditions → verifier subagents run in parallel (worktrees).[runtime]conditions → run serially — the runtime-proof needs sole access to the shared local services — unless the profile carries a proven Q13 isolation contract (specs/stack-profile.md), in which case each subagent claims its own instance and[runtime]milestones verify in parallel.
- Pin bottom-up — on a clean verdict, the orchestrator writes the
verified:pin (the verifier subagent is read-only) and runs the mechanical postcondition checks (HEAD^== verified SHA, working tree clean). For a stack, write pins in stack order via clean rebases onto the plan-only pin commits. - Open the PR — base
mainfor an independent milestone, the parent branch for a stacked one. Quote the done-conditions + verification evidence in the body.
Keep the orchestrator's retained state thin (a ledger: slug → branch → PR → verdict → SHA); build and verify detail lives in the subagents.
Two hard boundaries
- Verification is independent. The orchestrator dispatches verification but does not judge it; build and remediation are different subagents from verification.
- Stops at merge — by default. With no committed auto-merge marker and no active mode,
implement-featureends at all milestones built, verified, pinned, PRs open with correct bases, stack minimal and bottom-up — and the user merges, exactly as written. The merge-time choreography island-feature's, under the user's per-merge approval. The one standing exception — a repo armed for committed auto-merge, or an active mode — is the next section; there the run continues through landing, but even then it stops at a preparedreview-feature, never passing it.
Where the run ends — three authorization branches, totally ordered
Which of three end-states the run reaches is decided in one fixed order — the first that applies wins, and they are mutually exclusive:
- Active
keel:automode → the autonomy branch. - Else a valid committed auto-merge marker (
.claude/keel-auto-merge.json,scope: "project", present on the default branch, armed bykeel:arm-auto-merge) → the run-through branch. - Else → the "stops at merge" default above (the user merges).
This order matches the guards' precedence mode > committed (the per-session attended marker is not an implement-feature concern — that marker governs an interactive per-merge flow, not this orchestration). No branch claims an unobservable outcome — each reports what gh and the checks actually returned, never "merged without a prompt" (a queued --auto is reported as queued behind the required checks, not as merged).
The run-through branch (reached by a committed marker)
The run continues through landing instead of stopping at open PRs. It drives the land-feature choreography itself — a bare, un-chained gh pr merge <pr> --auto on each pinned, gate-passing PR (the merge-guard.sh committed-project row emits allow; the build-session guard-branch-rules.sh row does not emit allow — it exit 0 defers to merge-guard.sh) — then runs the post-wave consolidated check on main, and then prepares review-feature. This mirrors the autonomy branch's landing step, but is reached by the committed marker, not a mode — and the run states which authorization it is acting under. The merge mechanics themselves (bottom-up, retarget-before-delete, close+reopen, re-pin, consolidated check, reconciliation) are land-feature's and unchanged; only who fires the merge command differs from the default. The run may carry this landing phase via the babysit-prs workflow (a doctrine dispatch — the same mechanics and the same committed-marker authorization, run as a background loop).
The autonomy branch (reached by an active mode)
Under an active keel:auto mode (per decisions/2026-07-05-autonomy-modes-v2.md + decisions/2026-07-genesis-envelope.md), two gates change: the cadence ask becomes a ledgered default (per keel:auto's ledger contract under specs/runs/<run-id>/), and "stops at merge" becomes enable gh pr merge --auto on each pinned, gate-passing PR — per the land-feature choreography — and proceed. Everything else (fresh-context verification, pin discipline, the branch guard) is unchanged.
Both continuing branches PREPARE review-feature — neither passes it
The run prepares the human's review and ends there; it never renders a verdict on it.
- UI feature: render the surfaces and stage the review inputs (the activation driver, screenshots, and the workbench composition to diff against, per
review-feature's pass), then halt at the human aesthetic/completeness judgment — reporting the feature built-verified-merged, review prepared, not done. - No-UI feature:
review-featureis skipped (as its own skill states), and the run reports the feature done at the consolidated check.
Either way the taste gate, the feature-spec sign-off, and the never-auto list are untouched — the run does not pass, waive, or pre-judge any of them.
Stop-points vs notify-and-continue
The run asks mid-flight only at true stop-points; everything else is recorded and the run proceeds.
- A stop-point halts the run attended — surfaced with the five-line gate block (
references/gate-presentation.md), and the run ends on it, never silently deferred. The stop-point set is exactly the un-pre-authorizable set the framework already names: live/paid/irreversible spend, a missing credential, a red substrate (routed to the profile's Q12 remedy, never absorbed), a required/security-reviewfinding, averify-milestoneblockedverdict (or adiscrepancya remediation pass does not clear — a singlediscrepancyis normal build iteration, not a stop-point), amerge-guarddeny, a genuine scope change, and — under an active mode — the consult contract's two attended halts: anuncertainconsult disposition and the cap-exceeded would-be consult (both per the consult contract inskills/auto/SKILL.md— anuncertainconsult never resolves to a silent default). This set is the written rule — not a per-run judgment. (The verdict tokens areverify-milestone's own —clean/discrepancy/blocked— there is nofailverdict;blockedis the state that cannot self-resolve.) - Under an active mode, a mid-build judgment question is neither of the two by itself — a build subagent that surfaces one (the spec underdetermines a choice among viable alternatives) hands it to the orchestrator, which routes it per the consult contract in
skills/auto/SKILL.md(cited here, never restated): the consult's disposition then decides —answeredproceeds as a ledgered default, whileuncertainandreframed-as-authorizationare stop-points per the set above and the contract's own semantics. - Everything else is notify-and-continue: recorded as a run-note (in-transcript, and appended to the run's ledger when one exists under
specs/runs/<run-id>/), and the run proceeds to the next independent milestone. All run-notes are surfaced together in the final handoff, so nothing recorded is lost. - No new notification infrastructure is invented. The mechanism is run-notes plus the existing five-line halt; keel has no push channel today, and the required-checks floor means a missed notification never lands unreviewed code. If the harness exposes a push affordance the run may additionally use it, but nothing in the flow depends on one.
Output
The handoff depends on which authorization branch the run took, and always reports each lifecycle gate's derived state — the pins and PRs this run produced, and the gates still open — plus every run-note gathered along the way, surfaced together:
- Default (no marker, no mode): a feature whose milestones are all built, independently verified, and pinned, PRs open and correctly based — handed to the user for merge (
land-feature), thenreview-feature. Gates still open: the user's merges,land-feature's reconciliation + consolidated check,review-feature. - Run-through (committed marker) or autonomy (mode): the milestones are additionally landed (each via a gate-passing
--auto) and the consolidated check has run onmain; the run ends at a preparedreview-feature. For a UI feature the handoff reports it built-verified-merged, review prepared, not done, with the review inputs staged; for a no-UI feature it reports the feature done at the consolidated check. The taste gate, the feature-spec sign-off, and the never-auto list remain the human's — the run never rendered a verdict on them.