agentleFS
leekleek/agent-skills/skills/implement-spec/SKILL.md

implement-spec

Skill5 starsChanged 10 days agoMITView on GitHub

Build a whole spec fast: parallel implementer subagents work the ticket frontier, each in its own worktree, merging onto one integration branch; then one review, one verification pass, and one PR or a stack of PRs.

107 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use implement-spec-with-codex, close-spec and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • dzhngSkill

    implement-spec-with-codex

    Run [implement-spec](../implement-spec/SKILL.md) with Codex doing the implementation passes while you orchestrate, integrate, and review. Use when the user asks to implement a spec with Codex, or to run implement-spec with Codex as the implementer.

    Also in 4 projects that use this

  • dzhngSkill

    close-spec

    When a spec under specs/<feature>/ is done shipping (a write-spec build, or any planned task that produced a spec), archive it to specs/done/ and rewrite it from a build-plan into a durable rationale — the why, the principles, the invariants — pointing back to the real code for the how. Use when implementation has landed and the plan no longer matches what shipped, or the user says a feature/spec is finished. Pairs with [write-spec](../write-spec/SKILL.md) (the plan this closes) and [review](../review/SKILL.md) (run before closing).

    Also in 4 projects that use this

  • wolverin0Skill

    audit-decisions

    Standardize remediation decisions, baseline-policy entries, and legal-review banners for accepted, deferred, or policy-blocked audit findings.

    Also in 4 projects that use this

  • saffron-healthSkill

    get-pr-reviews

    Get nicely formatted output of the last review comments on a PR. Used internally by other skills.

    Also in 3 projects that use this

  • saffron-healthSkill

    push-everything

    Stage ALL changes in the repository (not just session changes), commit, and push. Use when you need to commit all pending changes.

    Also in 3 projects that use this

  • transitive-bullshitSkill

    compare-screenshots

    Compare screenshots against the intended design, distinguishing approved references from historical baselines. Use for iterative implementation matching, before/after visual review, objective image telemetry, or checking a lone capture for flat, empty, or badly framed content.

    Also in 4 projects that use this

  • +5 more from dzhng

The file

We split this skill into the rules it gives an agent

8 rules. 0 are common, 4 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 100 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Verify identifiers before using them: route names, config keys, enum values, package APIs.

    line 21
  2. Very specific:

    Read the spec: its Build Contract section first, then what the tickets name.

    line 33
  3. Distinctive:

    Before the first dispatch, ask these in one structured-question call (harness-tools.

    line 45
  4. Very specific:

    When several tickets need the same exploration (an unfamiliar module, a package's docs), run one read-only exploration subagent first that …

    line 65
  5. Distinctive:

    Before reporting, merge the current integration tip into the branch and rerun the focused tests.

    line 79
  6. Very specific:

    Keep each implementer's report in $notes/<NN>.md: it feeds dependents' briefs and the ticket's Resolution.

    line 90
  7. Very specific:

    After each merge, update the ticket board, and post one progress line so the user never has to ask for status: <NN> merged (<k> of <M>).

    line 92
  8. Distinctive:

    When the user stops the run, follow Stopping mid-run.

    line 120

“Common” is measured: kept by at least 6 in 10 of the 100 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Implement Spec

Build every ticket of one spec in this session by orchestrating, not building: implementer subagents do the code, each in its own worktree; you own the tracker, the integration branch, the merges, and the final gates. The goal is the whole spec on one integration branch, every ticket closed, delivered as the user chose: one PR, a stack of PRs (one per ticket), or a pushed branch.

The tickets are not a list of steps. They are a task graph: blocked-by edges mean there is always a frontier of tickets ready to grab, and every ticket on it can be built at once.

Reach for the neighbours instead when they fit better: /implement <spec> all builds the same tickets one after another in this session, with no subagents (and is the fallback when the harness has none: say so and stop); autopilot drives the tickets through fresh top-level sessions while you are away.

Talk to subagents in context pointers: paths to the spec, the ticket, blocker resolutions, notes, commits. Never paste what a pointer already reaches. Ask them for sparse reports. To follow up with a named subagent (an implementer or fixer), use SendMessage to its name in Claude Code, or the follow-up move in harness-tools elsewhere; where neither exists, brief a fresh one with its worktree path, its ticket or findings, and the new input.

Guardrails

  • Never reset, roll back, drop, or truncate a database this run did not create, or run another destructive data operation on one, without explicit approval. Schema changes go in new migrations.
  • Verify identifiers before using them: route names, config keys, enum values, package APIs.

Stack references. Identify the stack from its manifests. If a matching file exists below, read it before step 1 and pass its pointer into every implementer brief: it names that stack's destructive commands, worktree setup, test-config files, and formatter.

  • Laravel (laravel/framework in composer.json): references/laravel.md

Ticket board. Report each ticket's status per ticket-board.md, with kind: "spec": ready and blocked (note: the blockers) from step 1, skipped for tickets left out, running at dispatch, fixing when a failure goes back to its implementer, merged (note: the merge SHA), released (note: why), and closed in step 7, or awaiting-deploy (note: the after-deploy steps, in a few words) for a delivery ticket left at ready-for-human. From step 5 on, also send the stage at each change (review and verify round 1, fix pass 1, review and verify round 2, fix pass 2, fix pass 3 when step 5's extra round runs, final checks, deliver) and each finding's status, so the pane never goes quiet after the last merge.

Process

1. Load the task graph

Read the spec: its Build Contract section first, then what the tickets name. Read every ticket's frontmatter once (status, blocked-by, deploy-gate, claimed-by).

No tickets/ yet? Cut them yourself with to-tickets' rules: its step 3 for the slicing, its step 4 for the open decisions, its step 5 and Ticket template to publish and commit. Vertical slices with honest blocked-by edges are what make the frontier wide; a chain of tickets each blocked by the last builds no faster than /implement all.

Open the ticket board now, before anything else in this step: load mcp__leek-skills__ticket_board with ToolSearch if it is deferred, and send every in-scope ticket with its title as ready or blocked, and the left-out ones as skipped.

Leave out closed tickets and tickets claimed by someone else (name them in the report). Never dispatch the delivery ticket (delivery: true) to an implementer: you work it in steps 6–7. A deploy-gate: true ticket bounds the run: build up to and including it, then stop at step 7 with a PR.

Run scripts/spec-run-state.sh <slug> once from the main checkout (read-only, JSON). Its branch is the name this run uses wherever this skill says <slug>: an earlier run's finished branch moves this one to the next free <slug>-<n>. When mode is resume, or a deploy gate has dependents in scope, read references/resume-and-gates.md now and follow it in steps 1–3.

Sweep for open decisions first. Run one read-only subagent over the spec, every in-scope ticket, and the spec's decisions/ and research/ (a domain-expert agent type when the harness offers one for the spec's domain). Its brief: list every choice the build will have to make that these documents do not settle, each with the tickets it touches, the line that leaves it open, and a recommended answer. Settled choices (including those to-tickets' sweep already wrote to decisions/) and pure implementation detail are not open decisions. Most questions a run would otherwise raise mid-build come from here, and asking them now keeps the frontier moving. Skip the sweep when the script's decision_sweep_done is true (a committed Build decisions ticket from to-tickets, and no later commit touched the spec or a ticket): that sweep already covered these documents.

Before the first dispatch, ask these in one structured-question call (harness-tools; a second call when they pass four; otherwise one message in chat), and nothing else:

  • Open decisions from the sweep, recommended answer first, in as many further structured-question calls as they need (at most 4 questions each). Step 2 commits the answers to the integration branch; pass that pointer in every implementer and review brief so a reviewer never reopens a settled choice.
  • Worktree: build the integration branch in a worktree at .claude/worktrees/<slug> (recommended: this checkout stays as it is), or switch this checkout to <slug>. Skip it when the tree is dirty (the worktree is the only option; say so) or the request already says. Each implementer gets its own worktree either way: that is what lets them build in parallel.
  • Delivery: implement's delivery question for a whole spec: one PR, stacked PRs, or the branch with no PR.
  • Deploy gate, when dependents wait behind one (per the reference).
  • Local <default>, when the script's local_default_scratch_only is true: implement's Local <default> question, answered in step 2 once it has carried the spec over.
  • Resume, on a resumed run with claims of its own (per the reference).
  • Cleanup: at the end, remove what step 8 would otherwise ask about (a refused or released ticket's worktree and database, and the verify setup) without asking (recommended), or list them for a choice then. A worktree holding uncommitted work beyond agent notes is always listed, and a branch with unmerged commits always stays.

Finish when every in-scope ticket and its edges are known, the ticket board lists them (where the tool exists), the open decisions are answered, the worktree, delivery and cleanup choices are made, and the first frontier is listed.

2. Create the integration branch

Make a notes directory outside every worktree: the script's notes (<git-common-dir>/implement-spec/<slug>).

On a resume, set up the integration checkout and base_sha per the reference. Otherwise follow implement's PR delivery: before step 1: branch <slug> from fresh origin/<default>, in .claude/worktrees/<slug> when step 1's worktree answer (or a dirty tree) says so, with the spec's .scratch/<slug>/ carried over. Record base_sha, and write it to $notes/base_sha. Either way, this checkout is the integration checkout.

When step 1 answered open decisions, write them in the integration checkout as one closed decision ticket in .scratch/<slug>/decisions/, in the format to-tickets' Publish step gives its Build decisions ticket, and commit it (docs(scratch): <slug> build decisions, unless the repo ignores .scratch) before base_sha is recorded (between that reference's steps 3 and 5), so every ticket worktree carries the answers and no ticket's PR shows them.

When several tickets need the same exploration (an unfamiliar module, a package's docs), run one read-only exploration subagent first that writes its findings to $notes as Markdown, so implementers build instead of explore.

3. Dispatch the frontier

For each frontier ticket, up to the concurrency limit (default 4: each one runs a test suite). A ticket whose ## Files share a path with a running ticket's waits until that one merges, so the two never conflict; dispatch the next frontier ticket instead.

  1. Claim it in the integration checkout per the tracker's Claim operation, with claimed-by: implement-spec-<slug>-<run id>. Only you write .scratch/; claims stay uncommitted until step 7.
  2. Worktree. git worktree add -b <slug>--<NN> <main checkout>/.claude/worktrees/<slug>--<NN> <integration tip> (the main checkout's .claude/worktrees/, never one inside the integration worktree), then make it runnable (install dependencies, copy local env config) the way the project's docs say, or as the stack reference says. When you write the setup into the implementer's brief, point at that recipe rather than restating a shorter one: a hand-written list that skips a step (for Laravel, the herd.yml workspaces.copy files) fails the implementer's first artisan call. When the tests need a real database, give it its own (<app db>_spec_<slug>_<NN>, never a name the main checkout's env or test config uses) and register it the moment you create it: bash <this-skill-dir>/../laravel-herd-worktrees/scripts/scratch-db.sh register <pgsql|mysql> <database> <worktree path> (Scratch database registry).
  3. Implementer subagent, in the background where the harness allows (Claude Code: subagents run in the background by default and wake you on completion; pass run_in_background: true where the Agent tool offers it; give each a name of <slug>--<NN> so you can address it later; other harnesses: dispatch in the background per harness-tools, keeping each returned id against <slug>--<NN>). Its brief gives pointers (worktree path, ticket path, the spec's Build Contract, the decisions answered in step 1, direct blockers' reports from step 4, the notes directory) and these rules:
    • Work only in that worktree (enter it with EnterWorktree({path}) where available, otherwise use absolute paths into it). Confirm git merge-base --is-ancestor <integration tip> HEAD before starting.
    • Choose seams with the tdd skill's Seams: where tests go rules and state them; then call the Skill tool with tdd and build the ticket test-first. Focused tests and configured static analysis end green.
    • Run tests in the foreground and wait for the result. Never send a test run to the background and go idle on it: an idle implementer may not wake when the run ends. A run too long for the tool's timeout is too broad; run fewer files.
    • Format touched paths with the repo's configured formatter, commit by explicit path. Never touch .scratch/, never push, never write another branch.
    • Before reporting, merge the current integration tip into the branch and rerun the focused tests.
    • Report in at most ten lines: commit SHAs, touched paths, seams (name any public seam a dependent ticket should reuse), the focused test command and result, deviations from the ticket, any decision built on an assumed answer, and anything blocking.

Then end the turn and let completion notifications wake you; never poll. An idle notification with no report and no new commit is a stall, not progress: follow up with that implementer at once to finish or say what blocks it. One that repeats a report you already acted on needs nothing: end the turn without a reply.

A hung tool call sends no notification at all. So whenever the run waits on a single implementer (the others have reported, or nothing else is ready), arm one 20-minute wake-up the harness offers (Claude Code: a Monitor whose command exits once that worktree has gone 20 minutes with no file change; otherwise check that worktree's last file change whenever anything wakes you). Woken with no new commit, message it to report what it is waiting on, and stop the hung call when it cannot.

4. Merge as each implementer lands

With Stacked PRs, review the ticket on its branch first, per implement's Stacked PRs step 1: its PR must hold every commit it will ever get. Then, in the integration checkout: git merge --no-ff --no-commit <slug>--<NN>. On a conflict, call the Skill tool with resolving-merge-conflicts. Rerun that ticket's focused tests on the merged tree, then commit the merge; on a failure, git merge --abort, so <slug> only ever holds green merges. With Stacked PRs, push and open the ticket's PR right after its merge commit, per implement's Stacked PRs. A failure goes back to the same implementer with the output (follow up with it), so it keeps its worktree and ticket context; a ticket that reports itself blocked is released (the tracker's Release), and its dependents stay out of this run.

Keep each implementer's report in $notes/<NN>.md: it feeds dependents' briefs and the ticket's Resolution. A merged ticket counts as done for its dependents' blocked-by, so recompute the frontier and dispatch what it unblocked (step 3).

After each merge, update the ticket board, and post one progress line so the user never has to ask for status: <NN> merged (<k> of <M>); running: <NNs>; next: <NNs>, with · PR #<n> after merged in a stack. Skip the line when the board's pane shows the run.

A question never stops the run. A decision the sweep missed (one that only shows once code exists) is built on its recommended answer when that answer is reversible: the implementer or fixer records it as an assumption in its report, and you ask it at the next merge, so a different answer becomes a follow-up fix, not a wait. When the choice is not reversible (a schema shape a later ticket builds on, a data migration), release that ticket and its dependents, keep building the rest of the frontier, and ask the open questions together at the next merge, or in the final report when nothing else is running. Stop and wait only when every remaining ticket is blocked on an answer.

Finish when every in-scope ticket but the delivery ticket is merged or released, and no implementer is running.

5. Review and verify once, over the whole branch

Start both at the integration tip, at once: call the Skill tool with code-review against base_sha on the integration branch, scoped to every path the run touched, and dispatch one verifier subagent (dispatch and wait per harness-tools) that calls the Skill tool with verify (otherwise follows the verify skill) and checks every ticket's acceptance criteria in one pass, reporting each failure and its screenshots' paths. A harness with no sub-agents runs verify inline once the review returns. Verification needs no review fix to start, and its failures join the same fix batch instead of a second cycle. With Stacked PRs, every ticket's commits were already reviewed on all three axes before their merge, so pass code-review only the Correctness and Spec axes, its Correctness brief aimed at what crosses tickets (shared seams, ordering, one ticket's change breaking another's path) and at each ticket's review-fix commits, which got no re-review of their own. Its fix batch also takes every ticket's BLOCKING and MAJOR Left open: findings.

Fix both sets of findings as one batch, grouped into fixers per Parallel fix batch steps 1–4 (its merged-tree test run included; the re-review below is its pre-push review, and nothing is pushed): each fixer in a detached worktree <main checkout>/.claude/worktrees/<slug>--fix-<k> off the integration tip, named <slug>--fix-<k> (its database, when it needs one, <app db>_spec_<slug>_fix<k>), merged back into the integration checkout. A batch below that file's threshold goes to a single fixer, <slug>--fix, working in the integration checkout. Later rounds follow up with each fixer, and a fixer merges the integration tip into its worktree before a later round, so it builds on every earlier fix. Fixers work through tdd and commit each finding on its own, with a subject that says what it fixed. Mark the findings fixing at the handoff, and fixed (note: the SHA) for each one whose commit git log shows whenever you wake. When you tell the user about findings, name each by what is wrong and where, never by a made-up code (C2, S1) the user has no key for; once the fixes are merged, re-run code-review as a re-review, passing the previous round's findings and head, and re-run verify only on the criteria that failed or whose code the fixes touched. A finding that needs the user's decision never holds the round: send every other finding now, ask that one in parallel, and pass the answer on as a follow-up. Two rounds is the budget. When the second still has BLOCKING or MAJOR findings, fix those in one more round without asking, its re-review covering only them; name whatever is left in the final report and the PR, with the commit each round reviewed (if the user asks to ship them in a follow-up PR, open one follow-up PR for all remaining findings, never one PR per finding, after step 7, based on the integration branch while that PR is open (in a stack, on the closing PR's <slug>-stack-fixes, since the remote <slug> holds no ticket until triage lands them); once it has merged, retarget per Follow-up on a delivered PR). Finish when review and verification report nothing actionable, or when the rounds are spent; a verification failure an external dependency blocks is named, and its tickets stay open.

6. Final checks

Run implement's step 6 once over the whole range. Skip the full-suite question when the repo's rules or the user's saved preferences already settle it (CI runs the suite, or "do not run the full suite unless asked"); otherwise ask once. A declined full suite is never replaced by a broad sweep of many test files: each ticket's focused tests stand as the evidence. A failure the run caused goes to step 5's fixers. Then, when the spec has a delivery ticket, run its pass 1 per DELIVERY-TICKET.md: the full suite and step 5's verify pass count toward its Before merge list, and a coverage gap goes to step 5's fixers like a product failure. Finish when the checks passed and pass 1 is done, or name the exact external blocker and leave those tickets open.

7. Close and deliver

For each verified ticket: append ## Resolution (what was built, deviations, verification evidence, its implementation commits, seams for successors, from $notes/<NN>.md) and set status: closed; re-read to confirm. The delivery ticket closes, or goes to ready-for-human with its after-deploy steps copied into the PR body, per its file. Commit the tracker separately (docs(scratch): <slug> resolutions), never folded into code. Then follow PR delivery: after step 8 for the chosen shape: push, open the PR (or, for a stack, whose ticket PRs opened as each ticket merged and whose integration PR opened in step 2, open the closing PR and fill in the integration PR's body per its Stacked PRs step 4), and read review threads once, except on a stack.

8. Clean up

Run cleanup from the integration checkout, so git branch -d checks each ticket branch against <slug>. For each ticket merged into the integration branch, clean up only the environment this run created, in order: carry any change under its .claude/agent-memory/ into the main checkout's copy (reviewer notes are append-only: add the lines the main copy lacks), then restore the tracked notes (git checkout -- .claude/agent-memory, when any are tracked) and delete the untracked ones you carried (git status --porcelain --untracked-files=all -- .claude/agent-memory lists them); then run bash <this-skill-dir>/../laravel-herd-worktrees/scripts/remove-worktree.sh <worktree> --branch <slug>--<NN> (laravel-herd-worktrees' Remove a served worktree: clean check, no --force, git branch -d only). Drop each database its databases lists (<app db>_spec_<slug>_<NN> and its _test_<N> copies), unregistering each only after its drop succeeded. A refused removal keeps that ticket's branch, databases, and registry lines together; a refused git branch -d keeps the branch (its -D hint is not a go-ahead); a failed drop keeps its registry line. Name each refusal in the report. A fixer worktree <slug>--fix-<k> whose commits are merged goes the same way, with no --branch. List each successful removal.

What is left that you created (a refused environment, the environment of an unmerged or released ticket, and the verify setup: the Herd workspace, database or worktree verify made for the run, when it made any) follows step 1's cleanup answer. When it was to remove them, remove each by the same ordered cleanup: a worktree that holds uncommitted work beyond agent notes is listed instead, and a branch git branch -d refuses stays and is named in the report. Otherwise ask once about them per What is left in Remove a served worktree, one option per ticket's retained environment. Keeping a worktree keeps its associated resources. Keep the integration worktree: it holds the PR branch (leave it with ExitWorktree({action: "keep"}) if you entered it). Anything kept is repository-cleanup's job later.

Stopping mid-run

When the user stops the run, follow Stopping mid-run.

When you're done

Print the end-of-session block using the frame in wayfinder/references/pipeline-end-block.md:

---
Pipeline: decide → spec → tickets → **build**   (4 of 4)
Done: <tickets closed of total, integration branch, PR, verification state>
Next:
  • <condition> → /<skill> <ref>
  • A PR is open and review bots are still running → /resolve-review-comments <PR> once they post
  • A stack of PRs is open → /triage-github-pr <every PR, bottom-up> to land it bottom-up with merge commits
  • Stopped at a deploy gate → deploy the PR, then /implement-spec <spec> for the dependents
  • The delivery ticket is at ready-for-human → merge and deploy, then /implement <delivery ticket> for its after-deploy steps; list them
  • Tickets released or left open → /implement <ticket> for each, or /implement-spec <spec> again
  • The build exposed a decision nobody made → /grill-me on it, then re-run /to-spec
  • The run went sideways → /retro this before clearing

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.