oliverspec-apply
Skill0 starsChanged 3 months agoMITView on GitHub
Implement an OliverSpec Linear project end-to-end — work all tickets in one go, aggressively launching sub-agents in parallel, and open one GitHub stacked PR per ticket. Use when the user wants to apply, implement, /oliverspec apply, or oliverspec-apply for a Linear-proposed project.
- Commits and pushes
In this repository9 other files it gives its agents.
- babysitSkill
- dashboard-uiSkill
- factorySkill
- lab-notebookSkill
- oliverspec-babysitSkill
- oliverspec-exploreSkill
- oliverspec-proposeSkill
- oliverspec-scopeSkill
- oliverspec-shipSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
23 rules. About 0 are common, 12 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈12
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 29
If ambiguous, list_projects / ask which project.
- Distinctive: line 53
Read Linear MCP tool schemas before calling tools
- Very specific: line 57
If there are no tickets, stop and tell the user to run oliverspec-scope (after oliverspec-propose if PRD/TRD are also missing)
- Very specific: line 75
When a ticket has multiple children, the first child continues the chain.
- Distinctive: line 96
Before launching a wave: create one worktree per ticket in the wave (see below) and pass its absolute path in the Task prompt
- Distinctive: line 99
Do not pause for merge/review between waves.
- Very specific: line 112
Put $WORKTREES outside the repository, e.g.
- Distinctive: line 133
If two tickets in the same wave will hard-conflict on the same files, prefer separate agents staggered/sequenced for those two only.
- Very specific: line 156
Do not use gh stack submit to create these PRs.
- Very specific: line 157
If a parent branch moved after its children were cut: gh stack rebase --upstack from the moved branch, then gh stack push.
- Very specific: line 171
Branch naming: use the Linear ticket’s git branch name exactly (returned by get_issue).
- Distinctive: line 205
Do not implement production behavior first.
- Very specific: line 216
Phase 1 — tests + stubs: write comprehensive failing tests for the ACs, then stubs/fakes/types so typecheck passes while tests remain red.
- Distinctive: line 218
Run the relevant automated tests and typecheck.
- Very specific: line 219
Commit with plain git (git add -A && git commit -m "...").
- Distinctive: line 232
Create the ticket’s worktree and branch, and pass the absolute path + branch + base in the Task prompt
- Distinctive: line 249
No stopping after the first ticket
- Distinctive: line 251
Always prefer launching the next batch of ready tickets as parallel Task calls in one turn
- Distinctive: line 292
Keep changes scoped to each ticket's acceptance criteria
- Distinctive: line 293
Never push to main/master.
- Distinctive: line 294
Don't create new Linear tickets during apply unless the user asks
- Very specific: line 295
If the project has no PRD/TRD, stop and tell the user to run oliverspec-propose
- Very specific: line 296
If the project has PRD/TRD but no tickets, stop and tell the user to run oliverspec-scope
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Implement an entire OliverSpec project from Linear in one session.
There is no apply gate: do not wait for PR review or merge between tickets. Drive the whole project to "PRs opened" in one go, aggressively launch sub-agents in parallel, and publish one stacked PR per ticket.
Parallelism is mandatory, not optional. Do not implement tickets yourself serially. Do not start one sub-agent, wait for it to finish, then start the next when others could run concurrently. In a single turn, fire multiple Task tool calls together — one per ready ticket — and keep the pipeline saturated.
PRs are stacked with GitHub stacked pull requests (gh stack) — not Graphite (gt), and not independent PRs against trunk (unless a ticket truly has no parent). Dependent tickets become upper layers stacked on their Linear blockedBy parents.
Input
- Linear project name (or infer from conversation)
- Optional: subset of ticket IDs (default = all unfinished tickets in the project)
If ambiguous, list_projects / ask which project. Announce: Applying OliverSpec project: <name>.
Steps
0. Preflight (fail fast, once, at the start)
gh --version # need 2.90.0 or later
gh auth status
gh extension install github/gh-stack # no-op if already installed
gh stack view --short 2>/dev/null # exit 9 = stacks not enabled for this repo
git worktree listgholder than 2.90.0 → tell the user to upgrade (brew upgrade gh) before continuing- Exit code 9 from any
gh stackcommand means stacked PRs are not enabled for the repo. Fall back to chained plain PRs (gh pr create --base <parent-branch>), keep every other rule in this skill, and say clearly in the final summary that the stack objects were not created - Exit code 8 means the stack is locked by another process — you have concurrent
gh stackcalls, which this skill forbids (see step 2)
Optional but useful: gh skill install github/gh-stack to give agents the official command reference.
1. Load the project plan from Linear
- Read Linear MCP tool schemas before calling tools
- Resolve the project (
list_projects/get_project) - Load the PRD and TRD (
list_documents+get_document) — treat them as source of truth for intent/design - Load tickets (
list_issueswithproject); for dependency edges useget_issuewithincludeRelations: true - If there are no tickets, stop and tell the user to run
oliverspec-scope(afteroliverspec-proposeif PRD/TRD are also missing) - Build the dependency graph from Linear’s native
blockedBy/blocksrelations only — ignore dependency prose in descriptions if it conflicts; if relations are missing but the docs/graph imply them, stop and tell the user to re-runoliverspec-scopeto wire relations - Set the Linear project status to In Progress (
save_projectwithid= the project andstate: "In Progress", or the team's equivalent started state if the name differs) if it isn't already — this happens once, up front, regardless of per-ticket states
Show a short plan:
- Ticket order / parallel waves
- Chain decomposition (which tickets share a stack — see step 2)
- Which tickets get which sub-agents
- Branch names (from each Linear issue’s git branch name)
Then start immediately — do not wait for per-ticket approval unless the user asked to confirm first.
2. Map the dependency graph onto GitHub stacks
A gh stack is a strictly linear chain: each branch targets the branch below it, and gh stack add only appends to the top. A Linear dependency graph is a DAG. Decompose it into chains before you dispatch anything:
- Walk the DAG in topological order. A chain is a maximal path where each ticket’s base is the ticket immediately before it
- When a ticket has multiple children, the first child continues the chain; each additional child starts a new stack rooted at that parent’s branch (
gh stack init --base <parent-linear-branch> …). A stack can target any branch, not just trunk - A ticket with multiple
blockedByparents cannot sit under both. Pick the parent on the longest chain as its base, and note the other dependency in the PR body under## Linear - Tickets with no
blockedBystart chains rooted at trunk
Record the chain table in the plan — it is what step 4 assembles.
Waves are still the unit of parallelism. Chains are only about stack topology. Two tickets in the same wave that land in different chains are still implemented concurrently.
3. Execution model (aggressive parallel sub-agents)
Goal: finish the whole project in one apply run by maximizing concurrent sub-agents.
Mapping rules:
- 1 ticket → 1 sub-agent by default. Do not assign a whole wave (or multiple tickets) to a single sub-agent — that usually defeats the point of sub-agents
- 1 ticket → 1 git worktree — every ticket sub-agent must work in its own worktree, never the parent’s checkout. Parallel agents sharing one working tree overwrite each other’s HEAD and dirty state
- 1 wave → N sub-agents in parallel where N = number of ready tickets in that wave. A wave is a dependency batching boundary, not a unit of work for one agent
- Multiple waves over the session are expected. A wave may legitimately contain only one ticket when the graph has a single unlock — that is fine; still give that ticket its own agent and worktree, then fan out the next wave in parallel once it lands
- Collapsing several tickets into one agent is highly discouraged, not banned — only do it when parallelism is clearly wasteful or harmful (e.g. unavoidable same-file thrash with no clean split), and say why
- Partition tickets into waves by dependencies (wave 1 = no blockers, wave 2 = blocked only by wave 1, etc.)
- Before launching a wave: for each ticket in the wave, mark it In Progress in Linear (
save_issuewithstate: "In Progress"— or the team’s equivalent started state fromlist_issue_statusesif the name differs). Do this as soon as you pick the ticket up, before/as you dispatch its sub-agent — not after the PR exists - Before launching a wave: create one worktree per ticket in the wave (see below) and pass its absolute path in the Task prompt
- For every wave: launch one Task sub-agent per ticket, all in the same message when N > 1 — true parallelism via multiple concurrent
Taskcalls. Usesubagent_type: generalPurpose(orshellfor narrow git ops) - Independent chains in the same wave all run concurrently (separate agents, separate worktrees)
- Do not pause for merge/review between waves. As soon as a wave’s agents return, tear down its worktrees, assemble the stacks (step 4), and immediately launch the next wave
- Parent agent coordinates only: Linear state, worktree lifecycle, the parallel Task batch per wave, all
gh stackcommands, rebases, conflict resolution, PR linking — parent does not implement ticket bodies by default
Worktrees (required for parallel apply):
# Parent, once per ticket, before dispatch. Base = trunk, or the parent ticket's branch.
git worktree add "$WORKTREES/<ISSUE-ID>" -b <linear-branch-name> <base-ref>
# Parent, after the agent returns (before any gh stack command touches that branch)
git worktree remove "$WORKTREES/<ISSUE-ID>"- Put
$WORKTREESoutside the repository, e.g. a sibling../.oliverspec-worktrees/. Worktrees nested inside the checkout make the parent’s globs and greps see every file twice - The parent creates the branch with
-b, so the agent must not create it again. The agent’s worktree is already on the right branch - Each agent’s cwd must be its worktree. Never
cdback to the parent checkout to edit application files - On agent failure, still remove the worktree; keep the branch for inspection
Concurrency rule — this is the one that breaks builds if you get it wrong:
gh stack init,add,rebase,sync,push,modify, and the navigation commands all check out branches, and git refuses to check out a branch that is already checked out in another worktree. They also take a stack-wide lock (exit code 8).Sub-agents never run
gh stack. They use plaingitplusgh pr createon their own branch only. The parent runs everygh stackcommand from the main checkout, serially, with the wave’s worktrees already removed.
Discouraged (avoid unless justified):
- One sub-agent owning multiple tickets / an entire wave when those tickets could be separate agents
- Implementing ticket bodies yourself instead of dispatching agents
- Running same-wave ticket agents strictly sequentially “to be safe” when they could run in parallel
- Waiting for one PR’s CI/review before launching the rest of a ready wave
- Two agents editing the same worktree / checkout
- Any
gh stackcall from inside a sub-agent
Not an anti-pattern: a wave with N=1 because the dependency graph only unlocked one ticket — run that one agent, then parallelize the following wave hard.
If two tickets in the same wave will hard-conflict on the same files, prefer separate agents staggered/sequenced for those two only; keep every other ready ticket’s agent running in parallel. Merging those two into one agent is a last resort — call it out.
4. Assemble the stack (parent only, after each wave)
Once a wave’s agents have returned and their worktrees are removed:
# Adopt the chain's branches into a local stack, bottom to top.
# Existing branches are adopted; --base roots the stack at trunk or at a parent ticket's branch.
gh stack init --base <trunk-or-parent-branch> <branch-1> <branch-2> <branch-3>
# Link the already-created PRs into a stack on GitHub, bottom to top.
# Accepts PR numbers, PR URLs, or branch names; fixes any base branch that
# does not match the chain; additive, so later waves can extend the stack.
gh stack link <pr-1> <pr-2> <pr-3>
# Extend an existing stack later without re-listing its PRs:
gh stack link <stack-number> <pr-4> <pr-5>
gh stack view --json # verify topologygh stack linkneeds no local tracking and checks out nothing, so it is the safe assembly primitive.gh stack initis what gives you local tracking for latergh stack rebase/gh stack sync- Do not use
gh stack submitto create these PRs. In non-interactive mode it auto-generates titles and opens drafts, which loses the required PR body. Agents create the PRs; the parent links them - If a parent branch moved after its children were cut:
gh stack rebase --upstackfrom the moved branch, thengh stack push. On conflict, resolve,git add,gh stack rebase --continue;gh stack rebase --abortrestores every branch
5. Per-ticket sub-agent contract
Each ticket agent receives a self-contained prompt including:
- Issue id + title + full description (scope + acceptance criteria)
- Relevant PRD + TRD excerpts
- Repo constraints / pointers to touch points discovered by the parent
- Worktree path (absolute) where all git and file operations must happen — required; never the parent checkout
- Branch name (the Linear issue’s git branch name from
get_issue) — already created and checked out in that worktree - Base branch for the PR: trunk for chain roots, otherwise the parent ticket’s Linear branch
- Required outputs: PR URL + number, branch name, base branch, worktree path, files changed, AC checklist result, test summary (what was added/updated; commands run)
Branch naming: use the Linear ticket’s git branch name exactly (returned by get_issue). Never invent oliverspec/... or other custom branch names.
Worktrees: one isolated worktree per ticket agent — no shared working directories across parallel agents.
No gh stack in agents: plain git + gh pr create only.
TDD required (red → stubs typecheck → green): land comprehensive failing tests first, keep the tree type-checking via stubs/fakes/interfaces, then implement until tests pass. Token smoke tests are not enough.
PR title: <ISSUE-ID>: <ticket title>
PR body must include:
## Summary
- ...
## Linear
- Fixes <ISSUE-ID> (or Links <ISSUE-ID>)
- Project: <project name>
- PRD: <url>
- TRD: <url>
- Also depends on: <ISSUE-ID> (only when the ticket has a second blockedBy parent outside this chain)
## Stack
- Base: <base branch>
## Acceptance Criteria
- [x] / [ ] copied from the ticket (including TDD / comprehensive test ACs)
## Test plan
- [ ] Phase 1: comprehensive failing tests + typecheck-clean stubs/fakes
- [ ] Phase 2: real implementation until tests pass (work backwards from the tests)
- [ ] Coverage for this ticket’s scope (happy path, edges, failures)
- [ ] <commands run, e.g. pnpm --filter … test / type-check>TDD sequence (required per ticket)
Do not implement production behavior first. Work in this order:
- Tests first (red) — write comprehensive automated tests that encode the acceptance criteria and TRD behavior (happy path, edges, failures). Tests should fail for the right reason (missing/incorrect behavior), not because of compile/type errors
- Stubs so typecheck passes — add the minimum interfaces, types, fakes, or stub implementations so
type-check/tscis clean while tests still fail. Stubs must not pretend to satisfy the behavioral ACs - Implement backwards (green) — replace stubs with real code until the suite passes. Prefer driving design from the tests; don’t expand scope beyond the ticket
- Verify — run the ticket’s test + typecheck commands; fix until both are green
Agent responsibilities:
cdto the assigned worktree. Confirm withgit statusthat you are on the assigned branch. Every command below runs with cwd = that worktree- Confirm the issue is In Progress (if the parent hasn’t already:
save_issueid+state: "In Progress"), thenget_issuefor full context - Phase 1 — tests + stubs: write comprehensive failing tests for the ACs, then stubs/fakes/types so typecheck passes while tests remain red. Commit this phase when practical
- Phase 2 — implement backwards: replace stubs with real implementation until all new/updated tests pass and ACs are met (or clearly blocked)
- Run the relevant automated tests and typecheck; both must pass before opening the PR
- Commit with plain git (
git add -A && git commit -m "..."). Prefer history that shows phase 1 then phase 2 - Push and open the PR against the assigned base:
git push -u origin <linear-branch-name> gh pr create --base <base-branch> --head <linear-branch-name> \ --title "<ISSUE-ID>: <title>" --body "<body from the template above>" - Return PR URL + number, base branch, worktree path, test summary (phase 1/2), and residual risks. Do not run
gh stack,gh pr merge, or touch any other ticket’s branch
Parent responsibilities:
On pickup (when dispatching an agent for a ticket):
- Mark the issue In Progress via
save_issue(state: "In Progress"or team equivalent) - Create the ticket’s worktree and branch, and pass the absolute path + branch + base in the Task prompt
After each agent returns:
git worktree removefor that ticket- Attach PR to the Linear issue (
save_issuelinks: [{ url, title }]) - Move issue to an appropriate next state (e.g. In Review) if statuses allow
- Record progress in the session summary
After each wave (all worktrees for the wave removed):
gh stack init/gh stack linkfor the affected chains (step 4)gh stack rebase+gh stack pushif a lower layer movedgh stack view --jsonto confirm topology before launching the next wave
6. Keep going until the project is done
Loop until every in-scope ticket has a PR (or a hard blocker):
- No stopping after the first ticket
- No "should I continue?" between waves unless blocked
- Always prefer launching the next batch of ready tickets as parallel Task calls in one turn
- On agent failure: retry once with a tighter prompt in parallel with other work, then escalate that ticket in the final report while continuing others
7. Final summary
## OliverSpec Apply Complete
**Project:** <name> (<url>)
**PRD:** <url>
**TRD:** <url>
| Ticket | Title | PR | Stack | Base | Status |
|--------|-------|----|-------|------|--------|
| LEM-123 | ... | url | #<stack-number> | main | opened / blocked |
### Blockers
- ...
### Suggested next steps
- Run `oliverspec-babysit` to clear PR comments + CI across the stack
- Then run `oliverspec-ship` to merge the stack and move the project to Completed
- Re-run apply for any blocked tickets after resolving blockersGuardrails
- Linear is the plan — don't invent tickets; implement what's in the project
- One PR per ticket — no bundling multiple tickets into one PR
- GitHub stacks, not Graphite — assemble with
gh stack init/gh stack link; nevergt. Dependent PRs target their parent's branch, never trunk - Only the parent runs
gh stack— serially, from the main checkout, with the wave's worktrees removed. Sub-agents use plaingit+gh pr create - Stacks are linear — decompose the Linear DAG into chains first; fan out extra children as new stacks rooted at the parent's branch with
--base - Branch names from Linear — always use the issue's git branch name from
get_issue; the parent creates the branch with the worktree - One worktree per sub-agent, outside the repo — parallel ticket agents never share a checkout
- No apply gate — don't wait for review/merge to continue the project
- Move the project to In Progress at the start of apply (
save_projectstate), once — separate from per-ticket state - Mark In Progress on pickup — set Linear ticket state when work starts (before/as the sub-agent is dispatched), not only when the PR is opened
- TDD required — (1) comprehensive failing tests, (2) stubs/fakes so typecheck passes while tests stay red, (3) implement backwards until green. No production-first shortcuts
- Parallel sub-agents by default — parent only coordinates; prefer 1 ticket = 1 sub-agent; each wave fans out N agents in one turn when N > 1; collapsing multiple tickets into one agent is highly discouraged (justify if you do). A single-ticket wave from real dependencies is fine
- Keep changes scoped to each ticket's acceptance criteria
- Never push to
main/master; always feature branches + stacked PRs - Don't create new Linear tickets during apply unless the user asks
- If the project has no PRD/TRD, stop and tell the user to run
oliverspec-propose - If the project has PRD/TRD but no tickets, stop and tell the user to run
oliverspec-scope
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
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.

