$npx -y skills add Archive228/loopkit --skill sprint-contractNegotiate a pre-code contract between generator and evaluator personas that defines what "done" means before any code is written. Turns fuzzy specs into a testable target the evaluator can hold the generator to.
| 1 | # Sprint Contract |
| 2 | |
| 3 | The evaluator's leverage collapses when "done" is defined *after* the code exists. The generator ships something, the evaluator finds it plausible, the fuzzy spec silently reshapes to match what got built. Premature victory, dressed up. |
| 4 | |
| 5 | Fix the timing: write the contract *before* the generator writes a line of code. The evaluator's job for the sprint is then mechanical — hold the artifact against the contract, no re-negotiation mid-flight. |
| 6 | |
| 7 | Inspired by the planner/generator/evaluator split in Prithvi's March 2026 post on multi-agent harnesses. |
| 8 | |
| 9 | ## When to apply |
| 10 | |
| 11 | - You're about to start a chunk of work (one feature, one refactor, one bug fix) with an evaluator or reviewer persona in the loop. |
| 12 | - The planner output or upstream spec is ambiguous — you can imagine two reasonable implementations that both "satisfy" it. |
| 13 | - A session just rehydrated from `shift-notes` / a progress file and needs a concrete acceptance target before it picks up the keyboard. |
| 14 | |
| 15 | ## Procedure |
| 16 | |
| 17 | 1. **Name the one deliverable.** One feature, one sentence, user-observable. If you can't say it in a sentence, the sprint is too big — split it, contract the first slice. |
| 18 | 2. **Write the acceptance predicates.** 3-7 bullets, each one a check that either passes or fails. No "clean code", no "good UX" — write predicates a script or a browser click can decide. |
| 19 | 3. **Name the runtime path.** How is this exercised end-to-end? Which URL, which CLI invocation, which button click? The evaluator will drive this exact path — no substitutes. |
| 20 | 4. **List the out-of-scope items.** Two or three things the generator will be tempted to also fix. Written down = evaluator will reject them as scope creep, generator has an anchor when tempted. |
| 21 | 5. **Sign it in the shift notes.** Paste the contract into `claude-progress.txt` (or equivalent) under a `## Sprint contract` header, with the sprint start timestamp. Both personas reference this exact text for the rest of the sprint. |
| 22 | 6. **Then, and only then, write code.** |
| 23 | |
| 24 | ## Contract shape |
| 25 | |
| 26 | ``` |
| 27 | ## Sprint contract — <ISO timestamp> |
| 28 | |
| 29 | Deliverable: <one sentence, user-observable> |
| 30 | |
| 31 | Acceptance predicates: |
| 32 | - [ ] <predicate 1 — script-decidable> |
| 33 | - [ ] <predicate 2> |
| 34 | - [ ] <predicate 3> |
| 35 | |
| 36 | Runtime path: <exact URL / CLI / click sequence the evaluator will drive> |
| 37 | |
| 38 | Out of scope this sprint: |
| 39 | - <tempting adjacent fix> |
| 40 | - <tempting refactor> |
| 41 | ``` |
| 42 | |
| 43 | ## Anti-patterns |
| 44 | |
| 45 | - **Predicates that are prose, not checks.** "Handles errors gracefully" is not a predicate. "Returns 400 with `{error: "missing_field"}` when `name` is absent" is. |
| 46 | - **Renegotiating mid-sprint.** If the generator hits a wall, it does not edit the contract to route around it. It surfaces the wall, the *planner* revises scope, a new contract gets signed. Evaluator leniency comes from mid-flight edits — block them structurally. |
| 47 | - **Contract written by the generator alone.** The generator will write predicates its planned code happens to satisfy. Have the evaluator draft or at least sign off before code starts. |
| 48 | - **No runtime path.** Without it, the evaluator falls back to reading unit tests — see [[broken-window-check]] for how that fails. |
| 49 | - **Skipping the out-of-scope list.** This is the cheapest anti-drift device you have. Skip it and you'll ship a "small refactor" that broke two other features. |
| 50 | |
| 51 | ## Rehydration case |
| 52 | |
| 53 | Fresh session, no memory of the previous one. Read `shift-notes`, find the last signed contract with unchecked predicates. That is your target — no re-planning, no reinterpretation. Drive the runtime path, tick the predicates, ship. If the contract looks wrong on inspection, do not edit it; revert to the planner, get a new one signed. |
| 54 | |
| 55 | ## Cost |
| 56 | |
| 57 | Two to five minutes of prose before code. In return: the evaluator has something to be strict about, the generator has an anchor against scope drift, and the next session inherits a testable target instead of a vibe. |
| 58 | |
| 59 | ## Related |
| 60 | |
| 61 | - [[shift-notes]] — where the contract lives across sessions. |
| 62 | - [[broken-window-check]] — what the evaluator runs *against* the contract at session start. |
| 63 | - [[adversarial-verify]] — the end-of-sprint pass that decides whether every predicate actually holds. |
| 64 | |
| 65 | ## When NOT to apply |
| 66 | |
| 67 | Trivial edits (typo fix, one-line config change, dependency bump) — the contract overhead exceeds the work. Solo runs with no evaluator persona in the loop — write yourself a one-line acceptance note instead and move on. |