Recommend what to do next on the product — read the product model (the spine `_spine.yaml` plus each slice''s lens docs), build the list of every runnable or blocked action with a deterministic decision tree, order it to finish one slice before the others advance, and show ONE next-best-action plus the ordered list (≤11 entries). Reading and ordering are scripts; the play only presents. Order: repair first, then every step of the focus slice (the lowest roadmap-order slice with work left — fe...
$npx -y skills add kapilvirenahuja/garura --skill next --agent claude-code
Installs into .claude/skills of the current project.
Are you the author of Next?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kapilvirenahuja-next)
---
name: next
position: none
description: 'Recommend what to do next on the product — read the product model (the spine `_spine.yaml` plus each slice''s lens docs), build the list of every runnable or blocked action with a deterministic decision tree, order it to finish one slice before the others advance, and show ONE next-best-action plus the ordered list (≤11 entries). Reading and ordering are scripts; the play only presents. Order: repair first, then every step of the focus slice (the lowest roadmap-order slice with work left — feature track, technical track, /measure, /grill, its epics), then strategy, then other slices'' steps as parallel lanes (shown, never hidden), then learning and refresh. The model is the single source: no backlog, sprint plan, or work queue exists or is consulted. Recommend ONLY: the play never modifies the model, never creates work items, never launches a play. Read-only and position none: runnable anytime, on any branch, even mid-pipeline. Use when the user asks "what next", "what should I work on", "where are we", or wants the model''s work ordered.'
user-invokable: true
---
# next
Read the product model, build the list of everything that could happen next —
strategy (vision, understand, shape, roadmap), realization (the seven lens docs across
the functional and non-functional tracks, then /measure), grilling, execution
(implement, validate, launch), learning (learn), and strategy refresh once everything
is delivered — put it in the finish-the-slice-first order, and show it: one
**next-best-action** plus the ordered list, every entry carrying the exact command and a
plain-language line on why.
The recommendation is advice, never action. The play writes nothing to the model,
opens nothing, launches nothing. Its only durable products are the recommendation it
presents and — when evidence recording is on — the evidence record; every transient
working file is deleted once the recommendation has been presented (C10).
## Compiled From
This play was compiled from the next ICE (`reference/ice.md`) by play-creator and
recompiled by play-editor (#466 Batch D, Level 3 rollout per ADR 025; #533 spine read;
#533 simplification). Intent defines constraints (C1–C6, C8–C14) and failure conditions
(F1–F3, F5–F11); the expectation defines success scenarios (S1, S4–S8), a Done means
(D1–D2, baked to `stop-condition.yaml`), and one recovery entry per failure condition.
To modify this play, update `reference/ice.md` and recompile with play-editor.
Do NOT edit this file manually — it is a compiled artifact.
## Role
You are the orchestrator. Three things happen, in order: a script reads the model, a
script builds and orders the list, and you present it. Every mechanical part is a
bundled script — the model scan, the decision tree and the ordering — never re-reasoned
prose. Your one piece of judgment is wording the presentation; you never reorder, add,
or drop an entry. At close you delete the working folder yourself — the play leaves no
scratch behind; the evidence record is never deleted.
**Forbidden:** writing anything under the product model; creating issues, branches, or
work items; launching another play from this one; deriving or ordering candidates by
reasoning instead of `scripts/derive_candidates.py`; consulting any backlog or project
store (none exists — the model is the only source).
**Agent boundaries:** none. This play dispatches no agents and no skills — there is no
judgment step a script cannot own, and no git/issue machinery (read-only, position none).
## Pre-flight
| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Resolve config (`.garura/core/config.yaml`) via `scripts/preflight.py` | — | Hard halt |
| Product model present under `<product_base>/product-os/` | — | **Not a failure** — feeds the tree's cold-start branch |
```
python3 scripts/preflight.py --play next --config .garura/core/config.yaml
```
`preflight.py` returns the config facts (`product_base`, `stm_base`,
`evidence_record`). The working dir is `<working> = ${product_base}_status/next/` (a
play-lifecycle folder; the model tree itself is never written). /next has no branch or
issue resolution (position none): it runs on whatever branch it finds, including main,
and leaves it untouched.
Record the session identity stamp's start marker (#463 — soft-fail, never a halt). The
marker lives in the working folder and is removed by the self-clean; its durable copy is
the evidence record:
```
python3 scripts/session_stamp.py --phase start \
--marker "<working>/session-stamp-next.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
```
**Resume check:** /next is cheap and advisory — a re-run is always a fresh run. If
`<working>/` holds artifacts from a prior run, overwrite them; never resume a stale
recommendation against a model that may have moved.
## Task DAG
Create ALL tasks immediately after resolving config — before any other work.
```
[T1] Scan the model blockedBy: []
[T2] Build and order the list blockedBy: [T1]
[T3] Scenario Validation (quick) blockedBy: [T2]
[T4] Present recommendations blockedBy: [T3]
[T5] Close blockedBy: [T4]
[T6] Self-clean (delete working dir) blockedBy: [T5]
```
Mark each task in-progress before its step and completed right after its eval passes.
No runtime reordering.
## Workflow
### Phase: Preparation
**Step 1 — Scan the model** · Owner: play · Depends on: pre-flight
Snapshot the model's state, read-only. The scan reads the model the way the
model-writing plays write it (C13, ADR 026): the spine `_spine.yaml` is the index of
record for the profile, domains, capability detail, slices (status / order / effort /
depends_on) and epics; lens presence is the seven `lens/<type>.md` docs per slice; a
slice record is read only for its name and functionalities, never for its status. A tree
with files but no spine is recorded as `spine_exists: false` — never read from legacy
per-node files:
```
python3 scripts/scan_model.py --product-base <product_base> \
--out <working>/model-state.json
```
A missing model is a valid snapshot (`model_exists: false` — the /vision branch), never
an error.
**SE-1 (C1/C2/C13, F3):** `model-state.json` exists and was read from `<product_base>`
only (C1); the scan and every later script write only their `--out` file under
`<working>` and the play has no model-write step and launches nothing, so nothing under
`product-os/` changes (F3/C2); the snapshot's profile, slices and epics come from the
spine (C13).
**Step 2 — Build and order the list** · Owner: play · Depends on: Step 1
Run the decision tree and the ordering as one pure function of the snapshot. The tree
spans strategy → both realize tracks of `standards/rules/pipeline-next.md` (the
functional track ux → agentic → marketing and the non-functional track arch → quality →
run, each offering its first missing lens doc) → /measure once both are done (it stamps
the slice realized, so a planned slice with all seven docs is a /measure repair) → grill
→ execute → learning → refresh. Track order is pipeline-next's recommendation, not a
readiness gate. The ordering then finishes a slice first: repair anywhere → every step
of the focus slice (the lowest roadmap-order slice with work left) → strategy → other
slices' steps by roadmap order, flagged parallel → learning → refresh:
```
python3 scripts/derive_candidates.py --state <working>/model-state.json \
--out <working>/candidates.json
```
**SE-2 (F1, F2, F6 / C6, C8, C9):** `candidates.json` exists carrying the ordered
`candidates` and the `inconsistencies` report (present even when empty — F2's detection
always runs); every candidate cites the gates that admit it, matching its target play's
own readiness rule (F1/F6); other-slice steps cite the roadmap order that permits them
(C6); the tree's branches span the full loop (C9); the file records a `derivation_hash`
so the same model state is shown to give the same ordered list (C8).
**SE-3 (F11 / C5, C14):** checkable from `candidates.json` alone — every repair
candidate ranks above every non-repair candidate (C5); every step of `focus_slice` ranks
above every strategy step, every other slice's step, and every learning or refresh step
(C14); every other slice's step carries `parallel_lane: true`. On a GAP apply REC11.
**SE-4 (F5 / C3, C4):** `entries` holds at most 11 candidates in rank order, each with a
`command` and a plain-language `why` sentence (C3/C4); `cut_for_cap` names every
candidate id past the cap — nothing is silently dropped (F5).
**SE-5 (F8/C11):** for every slice with a `delivered` epic that declares a user-facing
surface (`web_dashboard`/`server_api`/`cli`) **and is not `surface_verified`**, the
inconsistency report carries a `surface-debt` entry for that slice, a
`repair/{slice}/surface` candidate is present in the `repair` lane, and EVERY live
execute epic of that slice is `blocked` naming the surface debt — no runnable execute
candidate survives for a slice in surface debt. A delivered user-facing epic that **is**
`surface_verified` raises no debt. On a GAP, apply REC8 and re-run derivation.
### Phase: Scenario Validation
**Step 3 — Scenario evals (quick)** · Owner: play · Depends on: Step 2
One call, well under a second — the regression file builds small spine-shaped models in
a temp folder and checks the read, the tree and the order. It carries the independent
reader (`scripts/check_model_agreement.py`, which does not import the scanner), so a
wrong read cannot confirm itself. It runs before the list is shown, so a failure halts
the run before anything is presented:
```
python3 scripts/test_derive_candidates.py
```
**SE-7 (F1, F6, F10, F11 / C13):** the file exits 0 — the read cases prove the spine
and lens-doc read against the independent reader (F10/C13), the tree cases prove each
branch offers the action its target gate admits (F1/F6), and the order cases prove a
slice is finished first (F11). On a failing read case apply REC10; on a failing order
case apply REC11 — either way halt before Step 4.
- **SCE-1 (S1 — builder, product mid-delivery):** `case_realized_missing_lens_s1` —
with a realized-but-lens-missing slice and a ready epic behind it, rank 1 is the
repair (the missing lens play) and the blocked epic names the missing lens.
- **SCE-4 (S4 — founder, fresh start):** `case_cold_start` — with no product model,
the only and first command is `/vision`.
- **SCE-5 (S5 — product owner, everything delivered):** `case_all_delivered_learn_s5`
— with the slice realized and every epic delivered, the list holds `/learn`.
- **SCE-6 (S6 — team running parallel agents):** `case_focus_slice_first` and
`case_griffin_like_s7` — slice 2's step appears, flagged parallel, ranked below every
slice-1 step, its gates citing roadmap order 2.
- **SCE-7 (S7 — product owner, roadmap merged):** `case_griffin_like_s7` — profile set,
four planned slices at order 1–4, the functional-track docs on the order-2 slice: no
strategy action, the order-2 slice's action is `/arch`, and the independent reader
agrees with the snapshot.
- **SCE-8 (S8 — builder finishing a slice):** `case_ready_epic_outranks_next_slice` —
slice 1 realized with a ready epic and slice 2 planned: rank 1 is slice 1's
`/implement`, and slice 2's `/ux` ranks below it.
### Phase: Present
**Step 4 — Present recommendations** · Owner: play · Depends on: Step 3
Write `<working>/recommendations.md` from `candidates.json` `entries` and output it to
the user **inline**: the next-best-action (rank 1) as the lead, then the list in rank
order with one plain-language line each (built from `why`), the slice being finished
named once, parallel lanes marked as such, a short repair section when
`inconsistencies` is not empty, and a count of `cut_for_cap` when it is not empty. The
operator (or each parallel agent) picks an entry and runs its command themselves.
**SE-6 (C2, C3, C8):** `recommendations.md` exists; its entries appear in the same rank
order as `entries`, every command in it is a command from `entries`, and none is added
or dropped (C8); every entry has its plain-language line (C3); nothing was launched (C2).
### Phase: Evidence & Close
**Step 5 — Close** · Owner: play · Depends on: Step 4
Run the Standard Play Close. /next is a **product-scoped** play (no issue) — use the
product-scoped evidence base and slug. Evidence recording is play-only and config-gated
per the D1 evidence rule (`standards/rules/evidence-recording.md`).
This phase ends with **Step 6 — Self-clean** (after the close): once the evidence record
and delivery report are written, the working folder is deleted as the terminal action.
**SE-8 (C10/F7):** after Step 6, `${working}` no longer exists on disk while the
evidence folder (when evidence recording is on) is intact. On a GAP (working files
remain), apply REC7 and re-run Step 6.
**SE-9 (F9/C12):** the close is stop-condition gated — `check_stop_condition.py` over the
baked `stop-condition.yaml` (D1 the ordered candidate set exists; D2 the presented
report exists) reads **held** before the run closes COMPLETED; anything else closes
HALTED with the unmet clauses named. The gate runs at Step 5, BEFORE Step 6's self-clean
removes the working folder. This play has no checkpoint, so there are no gates to class
under `gate-config.md`.
```bash
# --- Standard Play Close (canonical; see standards/rules/play-close.md) ---
# Path tokens resolved at pre-flight (resolve here if not already):
# ltm_project_target = yq '.ltm.project-target' .garura/core/config.yaml
# evidence_base, slug:
# project-scoped play : evidence_base="${stm_base}${issue}/evidence/next/" ; slug="#${issue}"
# product-scoped play : evidence_base="${product_base}_evidence/next/" ; slug="${product_slug}"
evidence_template=$(cat "${ltm_project_target}standards/templates/evidence-file.md")
delivery_template=$(cat "${ltm_project_target}standards/templates/delivery-report.md")
ts=$(date -u +%Y%m%d-%H%M%S)
evidence_dest="${evidence_base}${ts}.md"
mkdir -p "$(dirname "$evidence_dest")"
# Session identity stamp (#463) — close phase; start phase ran at pre-flight
session_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "<working>/session-stamp-next.json")
# Stop-condition gate (#464) — Step C0: this play carries a baked manifest, so the
# gate is LIVE. Evaluate the Done means here — BEFORE Step 6's self-clean deletes
# the working folder — as the close's authoritative input.
python3 scripts/check_stop_condition.py \
--manifest "<play-dir>/stop-condition.yaml" \
--base "<working>/" \
--out "<working>/stop-condition-next.yaml"
sc_exit=$? # 0 held · 1 unmet · 2 error
```
`/next` is product-scoped: `evidence_base="${product_base}_evidence/next/"` and
`slug="${product_slug}"` (the product, e.g. `token-burn-dash`).
**Step C0 — bind the verdict.** `sc_exit == 0` (held) permits `status: COMPLETED`.
Anything else closes `HALTED` with `exit_reason: stop_condition_unmet` and the
evidence's Stop Condition section names every unmet clause. An unevaluable verdict
is never a pass.
**Step C1 — Write evidence file.** Gated by the resolved `evidence.record` flag
(global + per-play `evidence.plays.next`; first match wins, absent ⇒ record).
When false, skip the write and record `evidence skipped (record=false)` in the
report's pointer line. Otherwise fill the `evidence-file.md` slots (play `next`,
run_id `next-${ts}`, product_slug, started_at/completed_at, status per C0,
exit_reason; artifacts produced: the model-state snapshot, the ordered candidate set,
the presented report, the stop-condition verdict; step and scenario eval results
SE-1…SE-9 / SCE-1, SCE-4…SCE-8; checkpoint decisions: none — this play has no gates;
the session identity stamp fields from $session_stamp (#463): session_id, ledger_file,
ledger_start_offset, ledger_end_offset (null when unresolved — never blocks the close);
and stop_condition per C0 with the Stop Condition section filled) and write to
`$evidence_dest`. Do NOT hand-author the body.
**Step C2 — Render delivery report.** Also render the **Next** line: resolve this play in `standards/rules/pipeline-next.md` and emit `**Next:** /<command> — <why>. Or run /next to see all recommended actions.` (only /next pointer, or omit, when the mapped command is null), per `play-close.md`. Fill the `delivery-report.md` slots and
output the report: `## next Delivered — ${product_slug}`, the Run Summary table,
the Pipeline Steps table from the task DAG, the Artifacts Produced table (the
next-best-action, the ordered entries, the focus slice, the inconsistency count),
Next Steps (the next-best-action's command — the whole point), and a pointer to
`$evidence_dest`. Always emitted; never gated.
```bash
# --- end Standard Play Close ---
```
**Step 6 — Self-clean** · Owner: play · Depends on: Step 5 (declared above; SE-8)
The terminal action. Delete ONLY the working folder so the run leaves no scratch behind;
never touch the evidence folder (`${product_base}_evidence/next/`), the durable record.
```bash
rm -rf "${working}" # working = ${product_base}_status/next/
```
## Scenario Validation
| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — product mid-delivery, broken gate | builder | SCE-1 |
| S4 — fresh start | founder | SCE-4 |
| S5 — everything delivered | product owner | SCE-5 |
| S6 — parallel lanes below the focus slice | team running parallel agents | SCE-6 |
| S7 — roadmap merged, read from the spine | product owner | SCE-7 |
| S8 — finish the slice first | builder | SCE-8 |
## Recovery
| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | a recommended command would halt at its own gate | record the divergence between the tree's rule and the target play's gate, fix the tree, and add a regression case | human |
| F2 | downstream work halts on an inconsistency the run reported nothing about | record the missed inconsistency class, extend the consistency scan, add a regression case | human |
| F3 | anything in the model changed, or a play was launched, during the run | halt immediately and surface exactly what changed — nothing is auto-reverted | human |
| F5 | more than 11 entries, or an entry with no explanation | re-run the ordering script, which caps the list and templates every explanation | autonomous |
| F6 | the readiness gates admit an action the list lacks | re-run derivation; if the action is still missing, the derivation rules are incomplete — record the gap and add a regression case | autonomous |
| F7 | working files remain after the run completes | delete the working folder; the already-presented recommendation is the only product | autonomous |
| F8 | a slice has surface debt (a delivered epic with unmet required user-facing surface) and /next would recommend its next execute epic | surface the debt as a blocking inconsistency, recommend the surface-repair action for that slice in the next-best-action slot, and withhold every further execute epic of that slice until the debt clears | autonomous |
| F9 | the close would report COMPLETED without the Done means held | evaluate the stop condition and surface the unmet clauses; re-run the producing step (derivation or presentation) to restore the missing artifact, or close HALTED with the verdict recorded | autonomous |
| F10 | the regression test file fails a read or agreement case | halt before presenting — nothing built on the wrong read is shown; surface the failing cases so the scanner is fixed | human |
| F11 | an ordering case fails, or a presented list ranks another slice's step above the focus slice's | halt before presenting, surface the mis-ordered entries, and fix the ordering script | human |
## Pause and Resume
Steps run top to bottom. /next does not resume — a recommendation is only as good as
the model state it was derived from, so any interruption means a fresh run: re-scan,
re-derive. Prior artifacts in `<working>/` are overwritten. There is no status marker.
## Compilation Metadata
| Field | Value |
|-------|-------|
| fingerprint | sha256:47abfbc27a373eaf59eb4512875b19476d42b2f3196cb7f050e14c1a8d2603d0 (of `reference/ice.md`) |
| compiled_by | play-editor (#533 simplification + slice-first order; #533 spine read; #466 Batch D, Level 3 rollout per ADR 025); prior: play-creator |
| pipeline_position | none |
| structural_constraints | C1 (scan + derivation read only the model tree — by construction of `scan_model.py`/`derive_candidates.py`); C9 (the tree's branches span strategy → both realize tracks + /measure → repair → grill → execute → learning → refresh — `derive_candidates.py`); C11 (surface debt detected mechanically from the spine epics index's `surface_type` + `surface_verified`); C13 (the spine is the index of record in `scan_model.py`, proven by the independent reader inside `test_derive_candidates.py`); C14 (the order is `order_candidates()` in `derive_candidates.py`) |
| workflow_structure | readiness-only (analysis, no generation; no checkpoint — the output is advice; nothing to class under gate-config.md) |
| stop_condition | stop-condition.yaml (D1–D2), gate live at Step C0 — evaluated BEFORE the Step 6 self-clean |
| domain_agents | 0 |
| utility_agents | 0 |
| skills_used | none |
| scripts | 7 (preflight.py, scan_model.py, derive_candidates.py, test_derive_candidates.py, check_model_agreement.py — called only by the test file, check_stop_condition.py, session_stamp.py) |
| step_evals | 9 (SE-1…SE-9; every failure condition covered: F1→SE-2+SE-7, F2→SE-2, F3→SE-1, F5→SE-4, F6→SE-2+SE-7, F7→SE-8, F8→SE-5, F9→SE-9, F10→SE-7, F11→SE-3+SE-7) |
| scenario_evals | 6 (SCE-1, SCE-4…SCE-8) |
| recovery_entries | 10 (one per failure condition; 5 autonomous / 5 human) |
## Recompile note (#533)
Two intent changes under #533, both via `reference/ice.md` → recompile.
**Spine read.** /next still read the pre-ADR-026 model layout (profile.yaml, per-slice
record status, `lens/<type>.yaml`, six lenses, top-level `ice:` files, `epics/*.yaml`)
and recommended finished work. `scan_model.py` now reads the spine and
`lens/<type>.md`; `derive_candidates.py` walks both realize tracks from
`standards/rules/pipeline-next.md`, recommends /measure when both are done, repairs an
unstamped slice with /measure (was /run), reports `model-has-no-spine` and
`slice-not-indexed`, and uses the spine domain id for /shape.
**Simplification + slice-first order** (user direction, 2026-09-11). /next is now read →
build and order → show. Removed: operator fit (the git-history capture, the
work-intelligence map check, `classify_work.py`, the former fit constraint, failure,
two scenarios and recovery), the ranking agent dispatch (`product-os-keeper` →
`rank-recommendations`), the runtime re-scan / re-derive / output enforcer
(`check_output.py`) and the runtime agreement step. The independent agreement reader
(`check_model_agreement.py`) now runs only inside the quick regression file, which is
the play's scenario validation and runs before presenting. Added C14 (finish the slice
first), F11 + REC11, S8; S6 now places other slices' steps below the focus slice.
`derive_candidates.py` orders the list (`order_candidates()`), stamps `rank`, `focus`,
`parallel_lane` and a templated `why`, and emits `entries` (cap 11), `cut_for_cap` and
`focus_slice`. Done means rebaked to D1 (`candidates.json`) and D2
(`recommendations.md`). Constraint, failure and scenario ids kept stable, so the declared
sets have gaps where removed items were. Fingerprint recomputed over the edited ICE.