build-story
Skill2 starsChanged 12 days agoMITView on GitHub
Build one backlog story end to end with independent checks — done-contract, acceptance tests written before any code, implementation, cold review and adversarial attack proportioned to the story's risk (trivial, light or full, chosen by you from its dimensions and touches, never asked of the user), verification in the running app, then merge. Use when the user says "build the next story", "implement AUTH-003", "next", "continue the backlog", "construí la siguiente historia", "implementá AUTH-003", "seguí con el backlog", or picks a ready story from /keelokit. With a count or several ids of one wave, runs those stories in parallel worktrees.
In this repository18 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .claude/CLAUDE.mdCLAUDE.md
- template/CLAUDE.mdCLAUDE.md
- check-bugbashSkill
- check-healthSkill
- check-securitySkill
- coordinateSkill
- harness-upgradeSkill
- keelokitSkill
- plan-backlogSkill
- plan-intakeSkill
- project-adoptSkill
- project-dashboardSkill
- project-newSkill
- project-reportSkill
- run-localSkill
- ship-releaseSkill
- ship-setupSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 2 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
Read the story's front matter (dimensions, touches, invariants) and the diff you expect, then pick the lightest tier whose condition holds.
- Very specific: line 39
Re-evaluate after the builder, escalate only: If doctor --scope fails, or the diff reaches auth, data, a shared contract, a critical area, …
- Very specific: line 57
Wait on a background run once (until on its log or exit status).
- Distinctive: line 95
Write the story's done-contract as a checklist and show it in one block, then continue:
- Very specific: line 102
every promise the story's text makes to the user (COPY-1), with the behaviour that keeps it.
- Very specific: line 129
Every BLOCKING or BROKEN item: the verifier reproduces it as a failing test first (mode A), and adds its row to docs/escapes.md with the …
- Distinctive: line 147
Commit with the trailer that closes the story, as the message's last line:
- Very specific: line 153
If the result differs from the story, append ## Addendum — <date> to the story file.
- Very specific: line 167
After each story lands, refresh the dashboard (/keelokit:project-dashboard).
≈ “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
Build — the builder never grades its own work
How work is done and what "done" means is in .keelokit/harness/execution-protocol.md; this skill
is the procedure. Roles are separate agents with fresh context:
| Role | Agent | Model |
| Orchestrator (you) | this session | Sonnet; Opus while designing something hard to undo in full tier |
| Verifier — writes acceptance and invariant tests, declares done | agents/verifier.md | Sonnet; Opus in full tier |
| Builder — writes the code | a general agent you spawn | Sonnet |
| Reviewer — reads the diff cold | agents/reviewer.md | Sonnet; Opus in full tier |
| Breaker — tries to break the branch (full tier only) | agents/breaker.md | Opus |
The agent files default to Sonnet; for the full tier pass model: "opus" when you delegate to the
verifier, reviewer and breaker. Searches, logs, status and screenshots go to Haiku. The table by
role and tier is in .keelokit/harness/agent-brief.md (Models). Which roles run depends on the tier (step 0).
0. Choose the tier — you decide, the user is never asked
Read the story's front matter (dimensions, touches, invariants) and the diff you expect,
then pick the lightest tier whose condition holds. Say it in one line: tier and the reason. The
user can force a tier with --trivial, --light or --full; without a flag it is your call.
| Tier | Pick it when ALL hold | What runs |
| trivial | dimensions ⊆ {docs, copy, config, dx, ui}; touches has no logic (text, docs, styles, config, locale files); no critical area; the text promises nothing (no time, amount, "we'll notify you", "you can undo", "free": COPY-1) | The builder writes the scenario tests the doctor's TRACE-1 asks for, and runs pnpm verify. You run doctor --scope, read the diff yourself and, for a screen, look at it once. No verifier A, no reviewer, no breaker, no verifier B |
| light | at most two dimensions, none of data, auth, security, contract, nfr, integrity; no critical area; no money, quota, permission, notice or data-deletion path | Verifier A writes the tests first; the builder runs them; ONE reviewer; verifier B walks the result. No breaker |
| full | anything else | Every step below |
Rules for the choice:
- When in doubt, go up one tier. Missing an escape costs more than a reviewer's tokens.
integrity, a critical area, money, reservations, quotas, credits, refunds, notices, permissions or an assistant are always full (doctor enforces the declaration).- Re-evaluate after the builder, escalate only. If
doctor --scopefails, or the diff reachesauth,data, a shared contract, a critical area, or a new endpoint or write path the tier didn't expect, rerun from the missing steps at the higher tier. Never lower a tier after a finding. - A trivial story whose diff turns out to carry a promise or logic becomes light.
Spend less, same checks (every tier)
- One agent per role per story. A later round continues the same agent (
SendMessage) instead of launching one that rereads everything; the verifier reproduces ALL the round's findings in one pass, not one agent per finding. - Each Agent's description starts
<ID> · <role>(AUTH-003 · reviewer), so a list of agents reads by story. - Agents get paths, not pasted files: the story, the contract, the base sha. Reports are at
most 10 lines with
file:lineand commit hashes; the full detail stays in the commit or file. - Roles read only what the story needs: the
dimensions.mdrows of its declared dimensions, theinvariants.mdclasses of its invariants. Not the whole catalogue. - NON-BLOCKING findings are batched into one commit at the end, never a round of their own.
- Wait on a background run once (
untilon its log or exit status); don't poll.
1. Pick
python3 .keelokit/bin/doctor.py --brief → first ready story, or the ones the user named. For N
stories: only from the same wave (doctor guarantees their touches and critical areas don't
overlap). A count N takes the first ready story and the next ready ones of its wave; several ids
(/keelokit:build-story AUTH-002 AUTH-003, what the dashboard's "Build wave N" button sends)
take exactly those, and one that isn't ready or is in another wave is left out with the reason
said. One worktree each (git worktree add ../<repo>-<ID> -b <id-lower>), steps 2–7 per
story in parallel. Give each worktree its own ports:
E2E_PORT=41<n>0 E2E_MOBILE_PORT=81<n>0 E2E_API_PORT=31<n>0 (n = 1..N).
For parallel sessions (one per story, possibly on several terminals) the shared brief is
.keelokit/harness/agent-brief.md; /keelokit:coordinate runs the rounds. Stories that add a
migration go one per wave (MIG-1). Names follow the brief: a session you start gets the title
python3 .keelokit/bin/status.py title <ID> prints (<project> · wave <n> · <ID>), this session
renames itself with its story's title when its tool can, and the branch stays the id in lowercase.
How many at once comes from [run] in .keelokit/state.toml: build = "serial" → one;
build = "parallel" → up to parallel ready stories of the wave. A count the user gives now
wins for this run only. Never ask again when [run] is set; if it isn't, ask once, in plain words
— one at a time (slower, follow every step, Claude usage spread out) or N in parallel (faster,
more Claude usage at once, several results to review together; safe because a wave's stories
never touch the same files) — recommend one at a time, and record the answer in [run].
mode = "auto" in [run]: after a story lands, pick the next ready ones and go on, wave after
wave, until nothing is ready. Stop only for what needs a person: a product rule the story doesn't
define or a new invariant (steps 2), a third failed review round (step 5), and anything the
execution protocol reserves for the human. mode = "step": report after each story (or each
batch) and wait for the user.
A story that brings something new into the project — its first migration, a new app, a deploy
config, personal data, payments — updates traits in .keelokit/profile.toml in the same change;
the doctor warns when the code shows a trait the profile lacks.
2. Contract
Write the story's done-contract as a checklist and show it in one block, then continue:
- each scenario
<ID>.S<n>; - each invariant the story lists (
invariants), with its class and the test that class calls for, from${CLAUDE_PLUGIN_ROOT}/references/invariants.md; - for each declared dimension, its lines from
${CLAUDE_PLUGIN_ROOT}/references/dimensions.md; - dimensions the
touchesimply but the story forgot (a screen →ux,ui,i18n,a11y; a critical area →integrity): add them to the story's front matter now; - every promise the story's text makes to the user (COPY-1), with the behaviour that keeps it.
Anything the story leaves undefined that changes behaviour → a gap in
docs/context/gaps.mdand a question to the user. Don't guess product rules. An invariant the story needs butdomain.mddoesn't have is a product rule too: propose it to the user, don't write it alone.
3. Acceptance tests first — verifier, mode A
Delegate to verifier (mode A). Its tests fail for the right reason before any code exists,
cover every scenario and every invariant with the kind of test its class calls for, and are
committed first on the story branch as test(<ID>): acceptance tests.
4. Implement — builder
Spawn a fresh agent (Sonnet) with the story, the contract, the failing tests and AGENTS.md:
make the tests pass without editing them (a wrong test → stop and say why; only the verifier
changes them, in a test(<ID>): … commit); fix causes where all callers route through; stay
within touches; keep critical rules in pure functions the API wraps in a transaction;
pnpm verify green. For an integrity story, pnpm mutation too: read its survivors and add
the tests that kill them (MUT-1).
5. Review and attack — before landing
git fetch && git rebase origin/main, then record the base:git rev-parse origin/main.python3 .keelokit/bin/doctor.py --scope <ID>must pass: no files outsidetouches, no undeclared critical area, no acceptance test edited by the builder.- In parallel:
reviewer(always), andbreakerin mode A (full mode). Each gets the story, the contract and the recorded base. - Every BLOCKING or BROKEN item: the verifier reproduces it as a failing test first (mode A),
and adds its row to
docs/escapes.mdwith the check that now catches its class (ESC-1). Then back to step 4. Two rounds at most; a third means the story itself is wrong: stop and tell the user.
6. Verify — verifier, mode B
Delegate to verifier (mode B). NOT DONE → the same loop as step 5.4: failing test, escape row,
builder.
7. Land
git fetch. Iforigin/mainmoved past the base recorded in step 5, other work landed in between:git rebase origin/main, thenbreakerin mode B (old base → new base × this story) and, if it touched the same journeys, a verifier mode B re-walk of them. Findings go through the step 5.4 loop.pnpm verify --preflightfirst if the full run is long, thenpnpm verify(the pre-push hook runs it with the seal, which skips the repeat only for this exact, unchanged commit).- Commit with the trailer that closes the story, as the message's last line:
feat(auth): sign up with email Story: AUTH-003 - If the result differs from the story, append
## Addendum — <date>to the story file. - Push and merge per the project's flow; production deploys stay with the human. The story is
landed only when
git log origin/mainshows its commit: report that hash, never "done" alone. With[landing] policy = "convoy"in.keelokit/state.toml, push the branch only, never main: the agent brief's convoy landing. Verify the branch with a plainpnpm verify(step 2: the scope of--since origin/main, but sealed, so the branch push doesn't repeat it); report the branch, the full hash, the tier (trivial/light/full) and the verify result. A test that fails intermittently while you land is a race: find the cause (FLAKY-1), never a longer timeout, a retry or a skip. python3 .keelokit/bin/doctor.pypasses: TRACE-1 now checks this story's scenarios and INV-1 its invariants.
Report
After each story lands, refresh the dashboard (/keelokit:project-dashboard).
Per story: mode (full/light), contract, tests added (ids), invariants proven and how, review and
attack rounds (findings, what reproduced), escapes logged with their new checks, mutation score
if integrity, verification evidence (screenshot paths for screens), addendum if any, and the
next ready story.
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.

