next

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 decisio

SKILL.md

GitHub

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.

# --- Standard Play Close (shared; see ../_shared/play-close.md) ---
# Run the close in ../_shared/play-close.md. Its Step L loads the templates through
# template-manager and sets ts and evidence_dest; then run this play's own lines below;
# then Steps C0-C2.
#   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}"
# 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 the Next-line map ($next_map, from template-manager) 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.

# --- 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.

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.