backlog-refinement
Refine coarse-grained PBIs into implementation-ready items
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Refine coarse-grained PBIs into implementation-ready items
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Whole-repo, multi-agent audit that IS the Sprint-end cross-review ceremony (product-wide integrity): 4 axes — spec-conformance, logic/defect hunt, redundancy, and product-security — over the ACCUMULATED codebase at HEAD, not the Sprint diff. Findings are swept to zero per defect class — one class = one PBI covering every occurrence, documentation drift batched into a single DOCS PBI — and non-blocking: Critical/High become draft PBIs for the NEXT Sprint, Medium/Low at PO discretion. At Integration-Sprint entry a thin re-check confirms the latest audit is fresh and no open Critical/High audit PBIs remain before testing proceeds.
Sprint-end product-wide integrity gate. The five per-aspect reviews (requirement conformance, functional quality, security, maintainability, docs consistency) now run PER-PBI inside the pipeline before a PBI reaches awaiting_cross_review. Sprint-end cross-review is the whole-repo codebase-audit ONLY: static analysis + 4 audit axes (spec-conformance, logic-defect, redundancy, product-security) over the accumulated codebase at HEAD. The audit is non-blocking — Critical/High findings become draft PBIs for the next Sprint; it never reverts a PBI.
Handles PBI pipeline escalation notifications from Developer. Reads escalation context, applies response matrix (retry / split / hold / human), and routes to user when human intervention is needed.
SM-side merge orchestration for a single PBI. Triggered when the Developer notifies `[<pbi-id>] PBI_READY_TO_MERGE`. Drives `.scrum/scripts/merge-pbi.sh` and handles the failure / retry cycle through SendMessage to the assigned Developer.
PBI development pipeline — orchestrates design, impl+UT, PBI review, and UT-run stages with sub-agent fan-out, file-based handoff, and deterministic termination gates (Anthropic + Ralph + GAN-derived). Used by Developer per assigned PBI. Replaces former design + implementation skills.
PO acceptance verification — launches and operates the app to verify acceptance criteria by command execution. Used in Sprint Review (demo mode) and Integration Sprint (UAT mode) when .scrum/config.json po_mode is "agent".
| name | backlog-refinement |
| description | Refine coarse-grained PBIs into implementation-ready items |
| disable-model-invocation | false |
backlog.json → items with status: draftrequirements.mddocs/requirements-benchmark.md — prior-art / similar-case findings
with per-item dispositions produced by Requirement Definition (reuse
first before any refinement-time web search; may be absent on a
pre-brief / resumed project)backlog.json → items[].status: refined, acceptance_criteria (non-empty), ux_change, demo_plan (non-empty for kind=code), design_doc_paths, priority (non-negative integer)description (and the doc it will
shape is named in design_doc_paths), with no PO-only spec question
about it left open (see Steps 3.a2 / 3.a3).scrum/po/decisions.json (agent mode) — any spec_clarification
ruling emitted during refinement, logged via append-po-decision.shThe PO-clarification points below (Step 3.a3, and any PO-only spec
question surfaced during 3.a2 research) resolve to the PO seat per
.scrum/config.json.po_mode and ../../rules/scrum-context.md § PO seat
resolution:
human (default) → the SM asks the user in the main session and
waits for a natural-language reply.agent → the SM routes
[<pbi-id>] PO_DECISION_REQUEST kind=spec_clarification options=[...] recommendation=<...> to the product-owner teammate and proceeds on
the returned PO_DECISION (logged via append-po-decision.sh, with
the dec_id echoed). Never block on human input: a genuinely
human-only unknown is appended to .scrum/po/attention.md and the
PBI stays draft.Read backlog.json
Count refined PBIs. If ≥12→skip (WIP cap reached)
Each draft PBI (up to WIP cap 12 total refined): a. Break into implementation-ready items as vertical slices: each item is one user experience or one capability extension, cut end-to-end through every layer it needs (UI + API + persistence together). NEVER split a single user experience into component items ("frontend PBI / API PBI / DB PBI") — component splits let per-layer work drift apart; in a target project they produced large late-stage inconsistencies and dead branches between components, discovered only at integration testing.
Walking skeleton first (per feature epic). When a draft PBI
is a large feature addition/overhaul that refines into multiple
items, the FIRST item of the group is a walking skeleton: the
minimal user experience that already runs end-to-end through the
whole system, exercisable locally. Later items of the group flesh
it out one experience unit at a time; give each of them
depends_on_pbi_ids naming the skeleton (step 3.e) and give the
skeleton the lowest priority number of the group (step 3.f) so
sprint-planning's dependency rule (FR-008) lands it in an earlier
Sprint.
a1. Vertical-slice inspection checklist (mandatory, per item).
A split you cannot confidently settle is a PO decision, not a
guess: raise [<pbi-id>] PO_DECISION_REQUEST kind=pbi_split options=[...] with the proposed vertical recut as the
recommendation (same decision shape as sprint-planning Step 5;
human mode: ask the user per § PO seat resolution).
a2. Approach & prior-art clarity gate (mandatory, before AC).
The goal of refinement is to hand the Developer a PBI whose
solution approach/method is settled — not one where the
designer must guess the method or reverse-engineer intent. Before
writing AC, decide per item whether the approach is determinable
from requirements.md + docs/requirements-benchmark.md:
docs/requirements-benchmark.md first. It already
holds prior-art dispositions (adopt/adapt/reject) from
Requirement Definition. Do NOT re-search what it already
answers.If a gap remains that a targeted search can close (prior-art or
tech-direction not settled at Requirement Definition),
delegate a bounded web search to an Opus sub-agent (mirrors
the Requirement Definition benchmark pattern). Record the resolved
direction into the PBI description, and name the doc it will
shape in design_doc_paths (step 3d):
Agent({
subagent_type: "general-purpose",
model: "opus",
description: "Refinement approach/prior-art research",
prompt: <<<EOF
Given one PBI (title, description, draft AC) plus excerpts of
requirements.md and requirements-benchmark.md, close the
*approach/method* gap for this PBI.
Rules:
1. Reuse requirements-benchmark.md first; only search for what
it does NOT already answer.
2. Run >=3 distinct WebSearch queries on prior art / similar
solutions / the accepted method for this feature, then
WebFetch the most relevant sources. Ground every claim in a
source read this session — never from memory.
3. Return the settled approach, the sources, the design docs
it should shape, and any residual question that ONLY the PO
can answer (business rule / scope boundary / ordering /
threshold / acceptance semantics).
Scope boundary — do NOT duplicate the Design stage. Detailed
per-library API selection and the S-070 technology specs are
the pbi-designer's mandatory library web search at Design
time. Here, settle *direction/method* only; do not pre-empt
library-level choices.
Output JSON:
{
"approach": "<settled method, 1-3 sentences>",
"sources": ["<url>", ...],
"shapes_docs": ["docs/design/specs/....md", ...],
"po_questions": ["<spec question only the PO can answer>", ...]
}
If WebSearch is unavailable or fails at the harness level (not
a "no results" content outcome), return
{"harness_incident": "websearch_unavailable"}
and do NOT fabricate an approach from memory.
EOF
})
SM main loop reads the JSON: fold approach into the PBI
description, merge shapes_docs into design_doc_paths, and
carry every po_questions entry into step 3.a3. On
harness_incident treat it as a harness incident, not a
fallback (mirrors requirement-definition step 5): surface per
the PO seat (human → tell the user and wait; agent → append to
.scrum/po/attention.md) and do not fabricate an approach.
Boundary restated: this step settles approach/method
direction only. Per-library API selection + S-070 specs stay
with the Design stage — do not duplicate them here.
a3. PO clarification for residual spec ambiguity (do not pass
ambiguity downstream). After research, resolve now — not by
deferring to the Developer/designer — any remaining unknown that
is PO-only: a business rule, scope boundary, ordering /
threshold, or acceptance semantics. Apply the escalate-vs-guess
filter in ../../rules/scrum-context.md § When you don't know:
description / AC before refining.Never guess PO intent. An item is not eligible for refined
while a PO-only question about it is open (human mode: unanswered;
agent mode: no matching PO_DECISION / parked in attention.md).
b. Fill acceptance_criteria (Definition of Ready). Every string MUST
be independently verifiable — either:
Reject vague adjectives without a measurable condition: "robust", "intuitive", "fast", "user-friendly", "error handling is robust", "good performance". Rewrite as a concrete check, or split into multiple criteria that each name an observable check.
AC array order is significant. The 1-based index of each
string is the AC's id used by downstream artifacts: the design
doc's Acceptance Criteria Mapping section and the UT
ac-coverage-r{n}.json map both reference it by index. Do not
reorder a PBI's acceptance_criteria after refinement without
a Change Process update — downstream references go stale.
Opus override for AC verifiability + scenario coverage
(mandatory). AC quality failures recurred 5 times across 3
target projects. Each failure traces to AC that pass the surface
check above (Given/When/Then or measurable assertion) but miss
one of: (i) scenario coverage (normal / failure / edge), (ii)
mandatory grep-zero on deleted config variables, (iii) parity
with a reference implementation when one exists. The SM main
loop runs on Sonnet; pinning these rules in skill text has not
been sufficient. Delegate the per-AC verifiability + coverage
audit to an Opus-backed sub-agent via the Agent tool, on each
PBI's draft AC list, before setting status: refined:
Agent({
subagent_type: "general-purpose",
model: "opus",
description: "AC verifiability + kind audit",
prompt: <<<EOF
Audit the acceptance_criteria of one PBI before refinement,
AND classify it as kind=code or kind=docs.
Inputs:
- PBI id, title, description, ux_change
- demo_plan (string; null when not yet set)
- Draft acceptance_criteria (string array)
- catalog_targets (string array; may be empty)
- PBI type signal: derive from description keywords
(impl / refactor / config-removal / order-engine /
schema-version / docs-only / audit-follow-up)
Checks per AC string:
1. Verifiability: Given/When/Then form OR observable
input/action -> observable outcome. Reject vague
adjectives without a measurable condition.
2. Scenario coverage across the AC array as a whole:
(a) normal-path AC present
(b) failure-mode AC present (when impl PBI)
(c) edge-case AC present (concurrency / null / boundary)
3. Type-specific mandatory clauses:
- config-removal PBI -> "grep <removed-symbol> returns
zero across docs/ and CLAUDE.md" must appear
- SCHEMA_VERSION bump PBI -> "requirements.md and the
schema doc reflect the new version" must appear
- order-engine PBI -> "price parity with backtest
reference implementation" must appear
- audit-follow-up PBI -> UT scenarios named explicitly
per AC
4. AC ordering: normal-path first, failure / edge after.
Kind classification (3-axis OR rule, lean toward `code` on
ambiguity — false-negative `code` is harmless, false-positive
`docs` skips UT/coverage gates and lets code slip through):
- Axis A — description markers: "doc-only", "docs-consistency",
"documentation only", "[docs]", "[doc]" anywhere in title or
description.
- Axis B — AC content: every AC describes a doc-shaped change
(a passage exists / a cross-reference is correct /
frontmatter / revision_history / spec text). NO AC names a
runtime behaviour, API contract, UI interaction, or DB
mutation.
- Axis C — catalog_targets non-empty AND all elements end in
`.md`.
Decision: kind = "docs" iff (A AND B), OR (B AND C). All other
cases → kind = "code". (Axis A alone is a marker but not
sufficient — title text can lie. Axis C alone happens when a
code PBI also updates a spec — still code.)
Extra Check 5 — grep-shaped AC anti-pattern (applies when
kind == "docs"):
- Reject any AC whose verifiable claim is reducible to
"grep <pattern> in <file> returns N lines" / "<file>
contains <substring>" / "occurrence count == N" without a
semantic read of the content.
- Replace with: "<file> §X states <semantic claim>, verified
by reviewer reading the passage". The Integrity stage's
requirement-conformance reviewer reads passages; grep is
not a substitute for comprehension.
- Rationale: target-project pbi-054 had 6 grep-shaped AC and
the UT author wrapped each grep in a test function. The
tests passed without anyone (human or model) reading the
doc. Never again.
Extra Check 6 — demo_plan locality (applies when
kind == "code"):
- Flag a demo_plan that is null/empty, requires a cloud
deployment ("deploy to ...", a cloud provider name as the
only way to observe behavior), or reduces to "read the
code" / "inspect the diff". A valid plan names a local
start command and an observable check; cloud-only
dependencies name their local substitute (stub / fake /
local container).
Output: JSON
{
"verdict": "pass" | "needs_revision",
"kind": "code" | "docs",
"kind_rationale": "axes A=<true|false> B=<...> C=<...>; decision=...",
"per_ac": [
{ "index": 1, "text": "...", "issues": ["..."],
"rewrite_suggestion": "..." | null }
],
"missing_acs": [ "<concrete AC to add>" ],
"demo_plan_issue": "<why the plan is not locally executable>" | null
}
EOF
})
SM main loop reads the JSON. If verdict == "needs_revision",
apply rewrite_suggestion for flagged AC and append every
missing_acs entry before persisting; a non-null
demo_plan_issue means the demo_plan is not locally executable —
rewrite it per step 3.c2. Do not advance status to
refined until the next audit returns verdict: pass. If an AC
cannot be made verifiable without a PO-only decision (e.g. an
undecided acceptance threshold), route that question through step
3.a3 rather than inventing a value.
Persist kind on every PBI (code or docs — never leave the
field unset, the default is for legacy data only):
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" kind <code|docs>
Persist the audited AC list via the wrapper:
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" \
acceptance_criteria '["AC 1 ...","AC 2 ..."]'
The wrapper validates JSON-array-of-strings; status remains
draft until step 4 below.
c. Set ux_change (user-facing changes) via wrapper:
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" ux_change <true|false>
c2. Set demo_plan (mandatory for kind=code — machine-gated: the
status wrapper refuses refined while it is empty):
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" demo_plan \
"<start command; URL/CLI steps; what to observe>"
Decide NOW how this PBI will be shown running locally at Sprint Review:
tests/stubs/, an in-memory fake, or a local container. Stub
philosophy is canonical in
../integration-tests/references/stub-construction.md (stub
only non-locally-reproducible interfaces; never an if TEST
branch in product code).ux_change=false → the plan names the observable local check
(CLI invocation / curl / data assertion), not a UI tour.kind=docs → exempt (the doc is the demo); leave it null."Deploy to to see it" and "read the code" are NOT demo plans. If no local demonstration path exists, the item is not refinement-ready — route the scope question through step 3.a3. d. Set design_doc_paths (docs needing creation/update) via wrapper:
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" \
design_doc_paths '["docs/design/specs/feature-x.md","docs/design/specs/feature-y.md"]'
e. (Optional) Set description / depends_on_pbi_ids via wrapper:
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" description "..."
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" \
depends_on_pbi_ids '["pbi-001","pbi-002"]'
f. Assign priority (non-negative integer, lower = higher priority, 1 = highest) via wrapper:
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" priority <integer>
Integer only. String labels ("high"/"medium"/"low") violate the
schema and break the dashboard PBI Board. The wrapper rejects non-integers.
All field writes above MUST go through
.scrum/scripts/set-backlog-item-field.sh. The PreToolUse guard
blocks raw edits to .scrum/backlog.json; status is the only field
with its own wrapper (update-backlog-status.sh).
Flip status→"refined" via wrapper:
.scrum/scripts/update-backlog-status.sh "$PBI_ID" refined
Superseded drafts → cancelled. If refinement absorbed a draft
PBI into another PBI, replaced it with child PBIs (its scope is
fully covered by items carrying parent_pbi_id), or the PO ruled
it no longer needed, do not leave it lingering as draft (and
never park it as blocked — that status is hold-and-resume only):
.scrum/scripts/set-backlog-item-field.sh "$PBI_ID" \
description "Superseded by <pbi-ids / reason>. <original description>"
.scrum/scripts/update-backlog-status.sh "$PBI_ID" cancelled
cancelled is terminal; record the superseding pbi-ids in the
description first so the audit trail survives.
Report: count refined, total refined WIP, count cancelled (superseded)
Ref: FR-003
code or docs)depends_on_pbi_idskind=code PBI has a non-empty demo_plan naming a
fully local demonstration (Step 3.c2; update-backlog-status.sh
enforces this at →refined)acceptance_criteria[i] is independently verifiable per Step 3b
(Given/When/Then or measurable assertion; no bare vague adjective)description (Step 3.a2) — the designer is not left to guess the
method; approach/prior-art gaps were closed by reusing
requirements-benchmark.md, by delegated web research, or by a PO
spec_clarification decisionPO_DECISION is
logged, or the question is parked in .scrum/po/attention.md and the
PBI remains draft