Agile Review Sprint

Table of Contents

When to use this skill

When asked to review sprint health — mid-sprint to catch drift or at close to record a final verdict. The output is a * Health Review section written into sprint.org so it is version-controlled and available in future sessions without re-running the analysis.

This skill is intentionally System 2: it does not merely summarise what is already in the status tables. It challenges assumptions, flags gaps, and produces a critical assessment. Resist every instinct to be optimistic or reassuring — the value is in the questions it forces.

How to use this skill

Step 1 — Activate System 2

Before gathering any data, read the sprint goals slowly and ask:

  • Are these goals still the right goals? Could circumstances have shifted them?
  • What would a failing sprint look like from the outside?
  • What am I likely to overlook if I rush this?

Write down any pre-existing concerns before collecting evidence. This prevents anchoring on the positive signals first.

Step 2 — Gather data

Sprint document

Read the full sprint.org: mission, goals list, * Status table (sprint start date is the Start field of the first STARTED story, or infer from #+created: on sprint.org), and the * Stories table.

Story and task files

Read every story.org and task_*.org under the sprint directory. For each story note: State, how many tasks it has, how many are DONE vs BACKLOG/STARTED, and whether the story title/description maps to a sprint goal.

find doc/agile/versions/v0/sprint_<N> -name "story.org" -o -name "task_*.org" | sort

Git commit load

git log --oneline --since=<sprint-start-date> | wc -l
git log --oneline --since=<sprint-start-date> | head -20

Use the sprint start date from sprint.org. Compute commits/day and project the total at sprint close (typically 7 days from start).

PR velocity

$(git rev-parse --show-toplevel)/projects/ores.compass/compass.sh fleet -f json 2>/dev/null

Also run:

gh pr list --state merged --search "merged:>=<sprint-start-date>" --limit 100
gh pr list --state merged --search "merged:>=<sprint-start-date>" --limit 100 | wc -l

Identify: PRs merged per day, open PRs (from compass fleet), any branch that has been open more than one day without a merged PR (WIP accumulation).

Step 3 — Analyse (System 2 questions for each dimension)

For each dimension below, answer the mandatory questions before writing the verdict. The questions are the analysis — the written section is the output.

Goal alignment

For each sprint goal:

  • Which stories directly serve this goal? (Match by title/description — do not rely on tags alone.)
  • Are there stories with no clear mapping to any goal? If so, why are they in the sprint?
  • Is any goal uncovered — no story addresses it at all?

Challenge: could any "covered" mapping be wishful? A story that tangentially touches a goal is not a substitute for one that directly advances it.

Sprint load

Targets: ≤ 1000 commits, ≤ 7 days.

  • Commits so far, elapsed days, commits/day average.
  • Projected total at close (commits/day × remaining days).
  • Verdict: ≤ 1000 = GREEN; 1000–1300 = AMBER; over 1300 = RED. A sprint that is slightly over target is amber, not automatically red — these are soft thresholds.

Challenge: is the commit rate sustainable? Are bursts hiding idle periods? Is the per-day average masking a sprint that started fast and has stalled?

PR velocity

Target: 100–120 PRs merged for a 7-day sprint.

  • PRs merged per day since sprint start.
  • Total PRs merged so far this sprint, against the 100–120 target.
  • PRs currently open (from fleet).
  • Any PR open longer than one day without review activity (WIP accumulation signal).
  • Verdict: ≥ 1 PR/day, total within 100–120, and no long-open WIP = GREEN; slower merge rate, total up to ~150, or 1 long-open PR = AMBER; stalled PRs, total over ~150, or no merges in 2+ days = RED.

Challenge: are PRs being merged quickly or piling up? Is WIP spreading across too many branches?

Story and task balance

  • Stories without any tasks (not decomposed — work is opaque).
  • Stories STARTED the longest without closing (calculate days open for each STARTED story).
  • Ratio of DONE to BACKLOG+STARTED across all stories.
  • Verdict: all stories decomposed, ratio ≥ 0.5 = GREEN; some undecomposed or ratio 0.3–0.5 = AMBER; major undecomposed stories or ratio < 0.3 = RED.

Challenge: a STARTED story with no tasks is a black box — progress cannot be tracked. Is that acceptable for its size?

  • Sprawling stories: split, don't carry

    Watch for a specific shape distinct from plain undecomposed work: a STARTED story that has accumulated a large number of tasks (roughly 10+, often from scope creep or a donor story merged in mid-sprint) where most tasks are DONE but the story itself is not finished at sprint end. Carrying the whole story forward as "still STARTED" into the next sprint is bookkeeping debt — the DONE work is real and should be recorded as delivered, not left implicitly incomplete pending the last few tasks.

    Recommended handling, applied per story (not as a blanket rule for every STARTED story — see the test below):

    • If the DONE tasks already satisfy the story's own Acceptance criteria and the remaining tasks are forward-looking extensions not required by that acceptance: close the story DONE now, narrowing its Acceptance/description to what actually shipped, and split the remaining tasks into a new, more focused story (product backlog if genuinely not yet started; a next-sprint story if one is already in flight) covering only that remainder.
    • If the remaining tasks instead are the story's own unmet Acceptance criteria (the core deliverable hasn't shipped, only supporting/infrastructure tasks have) — do NOT close it. Closing would misrepresent the story as finished. Leave it STARTED and carry it forward honestly instead.
    • A partial variant applies when only some remaining tasks are genuine extras: split just those out, leaving the story STARTED with a smaller, acceptance-focused task list.

    The test to apply before splitting: read the story's own * Acceptance section and check each remaining BACKLOG task against it. "Done tasks happen to be most of the list" is not sufficient on its own — the finished tasks must actually satisfy what the story promised.

    Use compass task move <task> --story <new-story-slug-or-uuid> to relocate tasks without losing their UUID or history; the closed story's Now field should reference the new story so the split is traceable both ways.

Focus signal

  • Count of simultaneously STARTED stories (stories where State = STARTED and no End date).
  • Are STARTED stories from unrelated themes (cross-cutting concern)? Compare #+filetags: across in-flight stories.
  • Verdict: 1–3 STARTED stories with coherent themes = GREEN; 4–5 or mixed themes = AMBER; 6+ or wildly divergent themes = RED.

Challenge: focus is sacrificed incrementally. Each "just one more" story in flight compounds context-switching cost. Is the current count deliberate or accidental?

Overall verdict

Write one paragraph (3–5 sentences) that synthesises all five dimensions. State the overall RAG (a sprint is RED if any single critical dimension is RED; AMBER if two or more are AMBER). Name the most important concern and the one thing that, if fixed, would most improve sprint health.

Step 4 — Create a health review task and write the full review into it

The full review content lives in a dedicated task, not in sprint.org directly. sprint.org holds only a compact summary table — one row per review run.

4a — Scaffold the task

Determine the review number (count existing task_health_review_*.org files in the sprint directory and increment). Then run:

./projects/ores.compass/compass.sh add task \
  --parent-dir doc/agile/versions/v0/sprint_<N>/sprint_health_review \
  --slug health_review_<number> \
  --title "Health review <number> — sprint <N> <mid-sprint|close> analysis" \
  --description "System 2 health review <number> of sprint <N>."

Set #+branch: to the current working branch and wire the new task into the story's * Tasks list.

4b — Write the full review into the task's * Result

Write the complete analysis under * Result in the new task file, using this structure:

* Result

** Review on <date> (day <N> of 7)

*** Goal alignment

[narrative + table: Goal | Coverage | Stories (DONE/STARTED/BACKLOG) | Verdict]

*** Sprint load

[narrative + table: Metric | Value | Target | Status]

*** PR velocity

[narrative + table: Metric | Value | Notes]

*** Story and task balance

[narrative + table: Story | State | Tasks | Age | Notes]

*** Focus signal

[narrative + table: Metric | Value | Verdict]

*** Velocity

[narrative + table: Metric | Value | Notes]

*** Overall verdict

[RAG table: Dimension | Verdict]

[one paragraph summary]

Mark the task State: DONE and Now: Complete. once written.

4c — Add a summary row to sprint.org

Find the * Health Review section in sprint.org. It contains a summary table. Add one row for this review:

* Health Review

| # | Date       | Day   | Overall | Task                          |
|---+------------+-------+---------+-------------------------------|
| 1 | 2026-05-25 | day 4 | AMBER   | [[id:UUID][Health review 1 — sprint N analysis]] |
| 2 | <date>     | day N | <RAG>   | [[id:UUID][Health review 2 — sprint N analysis]] |

Use the task's :ID: property for the org-roam link. Do not replace the existing rows — append only.

Step 5 — Update agile paperwork

Update the sprint-health-review story's State and Now fields if all tasks are now DONE. Wire the new task into the story's * Tasks list if not already done in Step 4a.

Sprint template note

New sprints scaffolded with compass add sprint include an empty * Health Review placeholder with the summary table header:

* Health Review

| # | Date | Day | Overall | Task |
|---+------+-----+---------+------|

(Run =sprint-reviewer= to populate this table.)

This placeholder is present from day one. Each run of this skill adds one row; the full analysis lives in the task linked from that row.

Emacs 29.3 (Org mode 9.6.15)