Agile Refine Backlog
Table of Contents
- When to use this skill
- How to use this skill — standard mode
- Deep refinement mode
- Step 1 — Inventory all three buckets
- Step 2 — Read every capture and story folder
- Step 3 — Verify each one against the live codebase
- Step 4 — Merge duplicates
- Step 5 — Score bucket fit against the current sprint's mission
- Step 6 — Regenerate indexes and run the sprint audit
- Step 7 — Scaffold (or continue) the deep-refinement story and its report task
- Step 8 — Write the full report into the task's
* Result - Step 9 — Commit
- Recipes
- Reference
When to use this skill
When the user asks to tidy, groom, or review the product backlog — not to plan a specific sprint (use sprint-planner for that) but to keep the backlog healthy: pruning stale captures, clarifying vague ones, moving items between next and deferred, or filing new ideas as they come up.
Two modes:
- Standard (default) — the lightweight sweep in "How to use this skill" below: scan next/deferred, clarify, cull, re-prioritise. Good for a quick tidy between sprints.
- Deep (explicit trigger: user says "deep", "thorough", "full audit",
or similar) — see "Deep refinement mode" further down. A slower,
System-2 audit of every capture in all three buckets (inbox
included), each one checked against the live codebase rather than
taken on its own word, duplicates merged, and every bucket
reassigned by scoring against the current sprint's mission. Ends
with a written report, structured like agile-review-sprint's health
reviews: a persistent story, one numbered task per run, the full
report in that task's
* Result, with an org-roamid:link to every file the run touched and one line on what happened to it. Expensive — expect to read every capture in the backlog — so only run it when the user actually asks for the deep variant.
How to use this skill — standard mode
List both buckets to get a full picture before changing anything:
./projects/ores.compass/compass.sh list --type capture --sort path | grep next ./projects/ores.compass/compass.sh list --type capture --sort path | grep deferred
Note the total count — next should stay manageable (≤ 20 is a useful heuristic). A crowded next bucket signals drift; a sparse one may mean work is being under-captured.
- Read each capture in the target bucket. For each one assess:
- Validity — is the idea still relevant? If the work was done in
a past sprint or the need has gone away, move the file to
discarded/(git mv,:ID:unchanged) and add a bolded reason line under the "in the discarded bucket" intro explaining what resolved it and linking the doc that did (see an existing file underdiscarded/for the exact convention). Captures have no#+todostate field — the bucket/folder is the state. - Clarity — is the
#+titleand#+descriptionspecific enough that someone could act on it without back-channel context? If not, sharpen both in place. - Bucket fit — does this item belong in
next/(candidate for the next version) ordeferred/(longer-horizon)? Move by renaming the file path; the:ID:stays unchanged so existing links keep working. - Duplicates — if two captures describe the same idea, merge
them: keep the richer one, fold in every fact the other has that
the survivor doesn't (check paragraph by paragraph — do not
assume "richer" means "complete"), move the absorbed one to
discarded/with a "Duplicate, merged into" reason line, and repoint anyid:links that pointed at the absorbed capture to the survivor (grep -rl "<absorbed-id>" doc/to find them all).
- Validity — is the idea still relevant? If the work was done in
a past sprint or the need has gone away, move the file to
File new captures as they surface during the review. Use the
agile-product-ownerskill's codegen step to scaffold each one:projects/ores.compass/compass.sh capture --note "<idea text>"Re-prioritise by moving files between
next/anddeferred/:git mv doc/agile/product_backlog/next/<slug>.org \ doc/agile/product_backlog/deferred/<slug>.orgCommit the full sweep in one atomic commit per bucket (or one combined commit if the changes are small):
git add doc/agile/product_backlog/ git commit -m "[agile] Backlog refinement — next bucket housekeeping"
Deep refinement mode
Triggered explicitly — the user asks for a deep backlog refinement,
a thorough audit, or similar. Unlike standard mode, deep mode covers
all three buckets (inbox, next, deferred), verifies each
capture against the live codebase rather than trusting its own text,
and produces a written, linkable report. Model this on
agile-review-sprint's health-review pattern: a persistent story, one
numbered task per run, the full narrative in that task's * Result.
This is slow by design — reading every capture and checking a
meaningful fraction against the codebase is the point; do not shortcut
it to make the run faster.
Step 1 — Inventory all three buckets
find doc/agile/product_backlog/inbox doc/agile/product_backlog/next doc/agile/product_backlog/deferred \ -maxdepth 1 \( -name "*.org" -o -type d \) | sort
Note the total count per bucket up front — it anchors the report's "before" picture and lets the summary state a concrete before/after delta.
Step 2 — Read every capture and story folder
For each entry (a lone .org file, or a folder with story.org plus
task files), read it in full — title, description, What/Why,
References, See also. Group entries that look related by shared
keywords/tags/entity names before deciding anything, so duplicates
(Step 4) are caught by grouping, not by memory across a long session.
Step 3 — Verify each one against the live codebase
Do not take a capture's premise on faith — this is what makes the mode "deep." For each entry:
- If it claims something is missing (a field, a function, a
mechanism),
grep=/=findfor it. If it already exists, the capture is resolved — move todiscarded/with a reason note citing the file/PR that closed it (see the standard-mode Validity bullet for the exact convention). - If it references another story/task by
id:link, check that target's current state — a capture can be silently resolved by work done under a different title. - If it's a story folder with tasks, check each task's State against reality the same way; a task marked BACKLOG that the codebase shows is actually done is a paperwork bug to fix, not just a note.
This step is the majority of the time a deep run takes. Budget for it.
Step 4 — Merge duplicates
Where Step 2's grouping surfaces two or more captures describing the
same idea: keep the richer one (most complete References/Why/context),
merge in every fact unique to the others (check paragraph by
paragraph), move the others to discarded/ with a "Duplicate, merged
into" reason line pointing at the survivor, and repoint every inbound
id: link found via grep -rl "<absorbed-id>" doc/ at the survivor's
:ID:. Verify no content was lost before deleting/moving anything —
diff the merged survivor against each absorbed capture's original
text if there's any doubt.
Step 5 — Score bucket fit against the current sprint's mission
Read the current sprint's sprint.org mission and goals. For every
capture that survives Steps 3–4, ask: does this fit the next
version's likely near-term direction (the current sprint's mission is
the best available signal for that), or is it genuinely longer-horizon
(→ deferred)? Move files between buckets accordingly (git mv,
:ID: unchanged). A capture with no clear relationship to any
foreseeable near-term direction and no standalone urgency is a
candidate for next; only demote to deferred for items that are
clearly not next-in-line, not merely "not this sprint's theme" — next
should hold real candidates for the next planning session, not only
things thematically matching whatever sprint happens to be open right
now.
inbox is not a valid resting bucket for this step. Every capture
that survives Steps 3–4 and started in inbox must end this step
filed into next or deferred — inbox should be empty of
pre-existing items once Step 5 completes for a run that covers it
(new captures filed during the run itself are the only legitimate
exception). Don't leave an item "for later triage" in inbox as a
third option; that's exactly the drift this step exists to clear.
Step 6 — Regenerate indexes and run the sprint audit
python3 projects/ores.codegen/scripts/regenerate_backlog_indexes.py ./compass.sh sprint audit
discarded.org is not regenerated by the script (a known gap) — if
this run discarded anything, that index will be stale; note it in the
report rather than silently leaving it inconsistent.
Step 7 — Scaffold (or continue) the deep-refinement story and its report task
7a — The story (once, ever)
Scaffold the deep-refinement story into the current sprint. Find the
current sprint's sprint.org (or run compass where) and scaffold:
./compass.sh add story \ --parent-dir doc/agile/versions/v0/<current_sprint> \ --parent-id <current_sprint_uuid> \ --parent-title "Sprint XX" \ --slug backlog_deep_refinement \ --title "Backlog deep refinement" \ --description "Recurring deep audits of the product backlog: every capture in inbox/next/deferred verified against the codebase, duplicates merged, buckets re-scored against the current sprint's mission."
Wire the story into the sprint's * Stories table. Like every sprint
story, it closes when its work is done — each run is a numbered task
under it.
7b — The report task (every run)
Count existing task_deep_refinement_*.org files under that story
and increment. Scaffold:
./compass.sh add task \ --parent-dir doc/agile/versions/v0/<current_sprint>/backlog_deep_refinement \ --slug deep_refinement_<number> \ --title "Deep refinement <number> — <date>" \ --description "Deep backlog refinement run <number>: inbox/next/deferred audit."
Step 8 — Write the full report into the task's * Result
Every file touched this run gets one row, linked by id: (org-roam
link, not a path — paths move). "Touched" means read and acted on;
a capture that was read, verified still valid, and left exactly where
it was does not need a row (note the total count instead), but
anything moved, merged, discarded, or edited does.
* Result ** Run on <date> *** Before / after | Bucket | Before | After | Notes | |----------+--------+-------+-------| | inbox | <n> | <n> | | | next | <n> | <n> | | | deferred | <n> | <n> | | *** Captures discarded (resolved) | Capture | Resolved by | |---------+-------------| | [[id:UUID][Title]] | [[id:UUID][What closed it]] — one line why | *** Duplicates merged | Kept | Absorbed | Notes | |------+----------+-------| | [[id:UUID][Title]] | [[id:UUID][Title]] | what was folded in; links repointed | *** Bucket moves | Capture | From | To | Why | |---------+------+----+-----| | [[id:UUID][Title]] | inbox | next | fits sprint N's mission: <one line> | *** Clarity fixes | Capture | What changed | |---------+--------------| | [[id:UUID][Title]] | title/description sharpened: <one line> | *** Paperwork bugs found [Any task/story State that didn't match reality — same class of finding as this session's sprint-22 mislabeled-ABANDONED stories. Link each one and note the fix.] *** Summary [One paragraph: total captures reviewed, net bucket-size deltas, biggest single finding, and one recommendation for what the next deep run should watch for.]
Mark the task State: DONE and Now: Complete. once written.
Step 9 — Commit
One atomic commit for the whole run (docs move together with the report that explains them):
git add doc/agile/product_backlog/ doc/agile/versions/
git commit -m "[agile] Deep backlog refinement <number>"
Recipes
- How do I refine the backlog? — the human-readable checklist for this skill's procedure.
- How do I create a new doc? — codegen invocations for new captures.
Reference
- Product backlog — the next/deferred structure and its invariants.
- Capture — the document type contract.
- Document types — full frontmatter contract for all types.
Agile product owner— atomic operations (file, promote, scaffold) this skill orchestrates.- Sprint planner — use instead when the goal is to select stories for a specific sprint.
- Agile review sprint — the health-review pattern deep refinement mode is modelled on (persistent parent + numbered report tasks).