Sprint planning
A sprint starts by selecting and ordering a batch. You can say it in plain language - “plan the next sprint”, “break it down but don’t write code”, “deliver all the open bugs” - and it maps to the explicit form.
/sdlc-studio sprint --bugs Open --goal done # deliver the open bugs/sdlc-studio sprint --crs Proposed --goal design # just the backlog, no code/sdlc-studio sprint --epic EP0007 --goal done # deliver an epic/sdlc-studio sprint --bugs Open --crs Proposed # one mixed backlog-clear tranche/sdlc-studio sprint --bugs Open --autonomous # unattended, guardrails onThe goal ladder
Section titled “The goal ladder”The goal is a stop-point, and the rungs are cumulative. Ask for a lower rung when you want a checkpoint; ask for done to take it all the way.
--goal |
Stops when | You get |
|---|---|---|
triage |
the plan is approved | the ordered worklist, and the readiness of the batch |
plan |
a sprint-sized batch is selected, sequenced and estimated | a committed sprint plan |
design |
every unit is decomposed to Ready stories with criteria and points | a reviewable, estimated backlog |
done |
every unit is implemented, verified, conformant and reviewed | the delivered increment |
The Sprint Goal
Section titled “The Sprint Goal”Separately from the rung, a run can carry a Sprint Goal: one sentence of product outcome that unifies the batch. Not a pipeline stage - an outcome.
/sdlc-studio sprint --bugs Open --sprint-goal "the release blocker list is empty and each fix has a regression test"It is prompted for when absent and never invented. Before the run opens, the seats review it: is it achievable by this batch, what does done mean for it, and does it read as one increment? The verdict has an effect rather than being decoration - a seat that judges the goal unachievable, or not one increment, refuses the plan.
At the close it is judged: goal-verdict --verdict achieved|partial|missed. A run whose plan set no goal is judged as a batch, honestly. The tooling will not invent alignment after the fact.
The breakdown gate
Section titled “The breakdown gate”sprint plan refuses a batch whose units are not groomed. Every unit must declare two things:
| Field | Why it is compulsory |
|---|---|
Affects: |
the files the unit will touch. Without it nothing can size the unit, and nothing can see that two units touch the same file - so the planner reports them as safely parallel when they will collide |
Points: |
the job size on the modified Fibonacci scale (1, 2, 3, 5, 8, 13, 20). Not urgency, not a guess at hours. It is relative: is this bigger than the last 3 you delivered? |
Ungroomed, it exits non-zero and prints no plan at all. This is deliberate - a plan over unsized units cannot be sized or safely parallelised, and it looks authoritative anyway. The refusal names each unit, what it lacks and the fix.
breakdown: 20 unit(s), 15 ungroomed, 0 above 8 points, 4 shared-file cluster(s) (mode=enforce) ungroomed - `sprint plan` refuses a batch holding any of these: BG0488 lacks: Acceptance Criteria (none at all) BG0513 lacks: Acceptance Criteria (restates the summary, so nothing states what passing is) ... opt out ONLY as a recorded decision. an absent config BLOCKS.Take the same census read-only, before you commit to anything:
sprint.py breakdown --stories Ready --bugs OpenAbove 8 points, refused
Section titled “Above 8 points, refused”A unit above the split threshold is refused and must be split, not estimated. This is not ceremony bolted on; it is the rule that makes the cost model work.
A story point behaves as a stable unit of cost from 2 through 8 - measured across delivered units it lands between roughly 22,000 and 27,000 tokens per point, essentially flat. Above that it breaks: 13-pointers came in 1.9x cheaper per point, systematically over-estimated, and every estimator returned them with low confidence and the unprompted words “should be split”.
So above 8 the estimate is not worth having, and the honest answer is to decompose - which is a triage decision, not an estimation one. A 7 is refused too: that is the false precision the scale exists to prevent.
Decomposing also makes the estimate better, not just the tracking. Four large requests sized in one shot came in at 0.56x their forecast with a 2.3x spread. Decomposed first, their summed points against the same unchanged rate predicted the batch to 1.00x.
Ordering
Section titled “Ordering”/sdlc-studio sprint <batch> --order priority # default/sdlc-studio sprint <batch> --order wsjf # cost of delay over size/sdlc-studio sprint <batch> --order manualWSJF is cost of delay divided by job size, with both on the same modified Fibonacci scale. It is seat-scored - sprint planning is a value, size and risk judgement rather than a bare priority sort - and the components are recorded in the plan artefact, so the ordering can be argued with later.
Dependency waves and shared-file clusters
Section titled “Dependency waves and shared-file clusters”For priority and wsjf, the plan emits waves alongside the flat order: wave 1 is everything with no in-batch dependency, wave n+1 is everything whose dependencies sit in earlier waves. Units inside one wave are independent, and therefore parallelisable.
The planner also derives clusters from the Affects it already parses. A declared dependency is a claim; a shared file is a fact. Units touching the same file are one cluster and are not independent parallel work, whatever the declarations say. Without this the planner once reported two units as safely parallel while both were rewriting the same module.
Capacity and appetite
Section titled “Capacity and appetite”Three ceilings, set in .config.yaml:
capacity: tokens: 500000 # forecast ceiling for the batch minutes: 240 # wall-clock ceiling for the run units: 8 # unit-count ceilingThe appetite is the circuit breaker built from those. It is resolved once at plan time and stamped on the run, so the ceiling the plan sized the batch against is the ceiling that stops the run. It is never auto-extended. Zero on an axis means unbounded.
Raise it in flight and that is a recorded decision, so the close still reports the overage rather than showing a run that neatly fitted:
sprint.py appetite resize --units 16 --reason "an epic joined the batch"The forecast has two terms
Section titled “The forecast has two terms”forecast = fixed + sum(Points) x tokens-per-pointThe fixed term prices what a point cannot: the ceremony, the review rounds and the close. Both terms are measured from the project’s own whole-sprint actuals rather than written down as constants - re-measured every time a plan is built, and the plan always says whether it is quoting your evidence or the shipped seed.
Below five units of your own evidence the seed stands and says so. A rate re-fitted to one or two units is fitting noise, and this project has twice had to delete a rate that hardened into an article of faith.
Where to next
Section titled “Where to next”- Delivery - what happens once you approve the plan.
- Review and close - the batch boundary and the close chain.
- Configuration - every key named on this page.
- Evidence - the measurements behind the 8-point threshold and the two-term forecast.