| name | vision |
| position | start |
| description | Turn a business goal into the seed of the product model — a detailed domain grounding doc, directional capability grounding docs, the spine entries that wire them, and a directional product profile. The entry play of the strategic (shaping) pipeline in the ProductOS command model — the CXO conversation. Use when starting a new product area from a business goal, before /understand and /shape. Opens no delivery issue. |
| user-invocable | true |
vision
Turn a business goal into the seed of the product model: a detailed domain
grounding doc, directional capability grounding docs, the spine entries that
wire them (domain + capability nodes), and a directional product profile. /vision is
the CXO conversation — what you take to a CXO and get back: strategic, directional,
CXO altitude. The domain is named and detailed; each capability is named and given
directionality only. The deeper work — detailing the capabilities and introducing their
functionalities (/understand, the product-manager step), then breaking the model into
deliverable end-to-end verticals and epics (/shape, the product-owner step) — is not done
here.
Pipeline position: start. /vision OPENS the strategy pipeline (vision → understand → shape → roadmap): the D2 rule prepends start-change — resolve or create the strategy issue, cut the branch off fresh main, optional worktree, init STM — so every later strategy play runs on this already-started branch. No close sequence is injected here; the strategy change closes at /roadmap. It writes the persistent product model directly (additively), on the started branch. (#437)
Compiled From
This play was compiled from the vision ICE (reference/ice.md) by play-creator and
recompiled by play-editor (#466 Batch C, Level 3 rollout per ADR 025; #467 Batch B —
the checkpoint upgraded to a conditional learned gate, see
standards/rules/gate-config.md).
Intent defines constraints (C1–C8) and failure conditions (F1–F8); the expectation
defines success scenarios (S1–S4), a Done means (D1–D4, 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. You own the workflow and the step order. You delegate the
domain work — KB grounding and seed authoring — to the product-os-keeper agent via
JSON contracts over files on disk, and you run the mechanical checks (shape/spine
validation, grounding, the content-quality eval, the additive merge) through bundled
scripts and an isolated judge. You never write the grounding docs or the spine yourself,
and you never persist anything before the single checkpoint (C7) resolves — a typed
approval, a recorded config skip, or a recorded policy auto-pass.
Forbidden: hand-writing grounding docs or spine entries; writing to product_base
by any route other than scripts/apply_seed.py; persisting the seed before the Step 4
gate resolves; writing a functionality, a detailed capability, acceptance criteria, or a
set/locked profile (over-reach — F3).
Agent boundaries:
| Agent | Domain | Skill it invokes | Phases |
|---|
product-os-keeper | Ground the goal in the KB; draft the directional seed (spine entries + detailed domain doc + directional capability docs + directional profile) | search-kb, propose-kb-node, author-vision-seed | Grounding, Draft |
product-os-keeper is the single domain agent this play uses (1 of the ≤5
budget). No utility agents are needed — git/issue machinery is absent (position none).
The content-quality judge always runs as an isolated, clean-context sub-agent
(optionally on a configured different model) — never the orchestrator's own context.
Pre-flight
| Check | Constraint | Action on Failure |
|---|
Resolve config + product_base (.garura/core/config.yaml) | — | Hard halt |
Resolve grounding-eval.judge (optional model override) | C2 | Default: sub-agent on the session model |
| Business goal present (play argument, else interview the user for it) | — | Gather (interview), not a halt |
Resolve the pre-flight facts mechanically with the bundled resolver — do not derive
them by inference. /vision has no branch or issue (position none), so the orchestrator
passes neither --branch nor --porcelain-file:
python3 scripts/preflight.py --play vision --config .garura/core/config.yaml
It returns one JSON object of facts. /vision reads product_base (where the model is
written — the spine _spine.yaml and the grounding docs), stm_base (where drafts +
evidence live), the resolved grounding-eval.judge config (the optional judge model
override), and evidence_record (the D1 gate). If product_base is null, hard halt
— there is nowhere to seed the model. The business goal is a runtime input: take it from
the play argument; if absent, interview the user for one before Step 1.
<working> — the run's working folder for drafts and apply records — is
{stm_base}_shaping/vision/<product_slug>/; every <working>/... path below, and the
baked stop condition's clauses, resolve against it.
Right after the resolver, record the session identity stamp's start marker (#463 —
soft-fail, never a halt):
python3 scripts/session_stamp.py --phase start \
--marker "{stm_base}_shaping/vision/status/session-stamp-vision.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
Resume check: if {stm_base}_shaping/vision/status/<product_slug>.json exists,
resume — skip completed steps, reset any in-progress step to pending, continue from
the first incomplete.
Task DAG
Create ALL tasks immediately after resolving config — before any domain work.
The play owns this DAG; the agent must not edit its top-level tasks.
[T0] start-change (injected — start, head) blockedBy: []
[T1] Ground the goal blockedBy: [T0]
[T2] Draft the seed blockedBy: [T1]
[T3] Validate the draft blockedBy: [T2]
[T4] Checkpoint (approval) blockedBy: [T3]
[T5] Persist the seed blockedBy: [T4]
[T6] Validate the model blockedBy: [T5]
[T7] Scenario Validation blockedBy: [T6]
[T8] Close blockedBy: [T7]
Mark each task in-progress before its step and completed right after its eval passes.
No runtime reordering. On resume, skip completed and reset in-progress to pending.
Workflow
Phase: Start (injected — D2 position: start)
Step 0 — start-change · Owner: start-change (sub-play) · Depends on: pre-flight
Run the start-of-pipeline member as a sub-play, dispatched with parent_run_id so it
emits only its own C1 evidence and this play's close absorbs it. It resolves or creates
the strategy-pipeline issue, cuts the branch off fresh main, sets up a worktree iff config calls for
it, and initializes the STM workspace. Every later strategy play (/understand, /shape, /roadmap) runs on this already-started branch; /roadmap closes it.
{
"play": "start-change",
"parent_run_id": "<this run id>",
"inputs": { "title": "<the business goal, e.g. 'vision: <goal>'>" },
"outputs": { "result": "{stm_base}_vision/start/start-change.json" }
}
start-change owns its own evals (issue anchored, branch off latest main, worktree per
config, STM initialized); they are not re-checked here.
Phase: Grounding
Step 1 — Ground the goal · Owner: product-os-keeper · Depends on: pre-flight
The agent does two things, in order: (1) route the goal to its domain with
search-kb, then (2) read that domain's full shelf through the KB router
(python3 $KB shelf <domain>) to enumerate the candidate capability set the
domain offers — breadth, not a single placement. For any capability or whole domain the
KB does not cover, it raises a propose-kb-node proposal. It writes the grounding
(domain + the candidate-capability set, each with its KB shelf reference) and any
proposals to disk:
{
"task": "route the goal to its domain, then enumerate the candidate capability set from that domain's shelf; propose KB nodes for gaps",
"inputs": { "goal": "<the business goal>" },
"outputs": { "grounding": "<working>/grounding.yaml",
"proposals_dir": "<working>/proposals/" }
}
It returns the same contract with the output paths confirmed on disk — never the
routing data inline. The grounding must carry one or more candidate capabilities
(a domain seed is rarely a single capability). A net-new domain routes through
propose-kb-node's own review; record that proposal as evidence and proceed — do not
block the seed on a KB-write approval (the single human gate is Step 4).
Phase: Draft
Step 2 — Draft the seed · Owner: product-os-keeper · Depends on: Step 1
The agent invokes author-vision-seed to draft the directional seed into a draft folder
under STM — a draft _spine.yaml (domain + capability nodes, status: proposed,
capabilities detail: directional, each with a one_line + doc pointer, plus the
directional profile block), a detailed domain.md (Theme template), a
directional capability.md per capability (capability template, directional stage),
all at CXO altitude — plus a seed-manifest.yaml:
{
"task": "draft the directional vision seed from the goal + grounding — detailed domain doc, directional capability docs, spine entries, directional profile",
"inputs": { "goal": "<the business goal>",
"grounding": "<working>/grounding.yaml",
"proposals_dir": "<working>/proposals/",
"product_base": "<product_base>" },
"outputs": { "draft_dir": "<working>/draft/",
"manifest": "<working>/draft/seed-manifest.yaml" }
}
The skill reads product_base read-only (to draft only absent nodes) and writes
the draft tree only — never the live model.
Step 3 — Validate the draft · Owner: play · Depends on: Step 2
Run the two guards over the draft before showing it to the human — shape first (cheap,
deterministic), then content quality (the judge).
python3 scripts/lint_grounding.py --root <working>/draft/product-os \
--spine <working>/draft/product-os/_spine.yaml
python3 scripts/grounding_check.py --manifest <working>/draft/seed-manifest.yaml \
--proposals-dir <working>/proposals
Then run the content-quality eval over the grounding docs as a concurrent read-only
fan-out (standards/rules/concurrent-fanout.md): dispatch one isolated, clean-context
judge sub-agent PER doc, ALL IN ONE CONCURRENT BATCH — each handed the judge prompt
(standards/rules/grounding-eval.md), its doc, and the kind's per-section guidance (it
sees neither the brief nor the author's reasoning), on the model from
grounding-eval.judge.model (default the session model). The three safety conditions
hold: each judge only READS its own doc, writes only its own verdict JSON, and no judge
depends on another. Join — wait for every verdict to return before gating any. Then
gate every returned verdict (order-stable, so the outcome is identical to a serial run):
python3 scripts/grounding_gate.py --verdict <verdict.json>
SE-1 (F1/C1): lint_grounding.py exits 0 — every drafted grounding doc conforms to
its template (domain → Theme; capability → directional stage), every spine entry
conforms to the spine schema, and the spine and docs are consistent (each entry points at
an existing doc of the matching kind/stage).
SE-2 (F2/C2): the content-quality eval gate (grounding_gate.py) passes for EVERY
grounding doc — each section self-explains at CXO altitude and the doc clears the
stranger test. A label-only or thin doc fails.
SE-3 (F3/C3): no over-reach — the draft spine has no functionalities entry, no
capability doc is in the detailed stage, no acceptance criteria appear, and the profile
is not set/locked (lint_grounding.py stage check + spine scan).
SE-4 (C4): directional state — every capability entry is status: proposed and
detail: directional; the profile is state: directional.
SE-5 (F4/C5): grounding_check.py exits 0 — every capability in the manifest
carries a KB shelf match or an existing KB-node proposal; none is ungrounded.
On any GAP, apply the matching recovery (REC1–REC4) and re-run before the checkpoint —
for a content-eval fail (SE-2), REC2 rewrites the doc to the judge's cited fixes and
re-judges until the gate passes.
Phase: Checkpoint (conditional gate, C7)
Step 4 — Human review (class: standard, conditional) · Owner: play · Depends on: Step 3
This checkpoint is a conditional gate (#467) per standards/rules/gate-config.md —
/vision is one of the eleven conditional document plays. Resolve it first match wins:
pinned (n/a here) → gates.plays.vision → the learned policy → gates.classes.standard
→ gates.default (absent ⇒ on). For the policy lookup, classify the draft-vs-live
change shape first:
python3 scripts/classify_change.py --play vision --draft <working>/draft \
--live <product_base> --out <working>/shape.json
Look the shape key up in the config-resolved policy (gates.conditional.policy):
auto-pass iff the shape is in the policy's auto: block AND not in never_auto:
AND Step 3 stands with no blocking finding (a lint_grounding.py gap or a
grounding_gate.py content-eval fail). On auto-pass, do NOT wait: record
gate auto-passed by learned policy (shape: <shape-key>, policy v<version>) as a
Checkpoint Decisions row, include the draft's diff summary in the run record, append
the crossing's live-eval ledger line, and proceed to Step 5:
python3 scripts/gate_eval.py append --ledger <gates.conditional.ledger> --play vision \
--issue <strategy issue> --shape <shape-key> --predicted auto --human auto_pass \
--policy-version <policy version> --ts <run ts>
Anything else resolves the gate on (an explicit gates.plays.vision: off instead
records gate skipped by config (<resolution path>) as a Checkpoint Decisions row and
proceeds). When on, present the proposed seed inline — the domain (its intent, the
bet, its guiding rules, the directional capabilities), each capability's directional
intent, and the directional profile (shape + rough NFR levels) — render the approval
prompt (standards/templates/approval-prompt.md) and wait for the typed response.
Approve → continue to persist; cancel → halt with nothing written to the model. Then
append the crossing's live-eval ledger line with the human's real action:
python3 scripts/gate_eval.py append --ledger <gates.conditional.ledger> --play vision \
--issue <strategy issue> --shape <shape-key> --predicted gate \
--human <approved_clean|approved_edited|rejected> --ts <run ts>
<strategy issue> is the strategy-pipeline issue Step 0 resolved.
<gates.conditional.ledger> / <gates.conditional.policy> resolve from config
gates.conditional (defaults .garura/core/gate-evals.jsonl /
.garura/core/gate-policy.yaml); <policy version> is the policy file's version:
field. <run ts> is the run's own UTC timestamp, derived the same way the close
derives ts (date -u), passed by the orchestrator.
SE-7 (F6/C7): the seed is persisted only after this gate resolves — a typed
approval, a recorded config skip, or a recorded policy auto-pass; Step 5 is the sole
writer to product_base and depends on this step; no product-model file exists before
Step 5 runs.
SE-9 (F8): every crossing of this gate appended exactly one live-eval ledger line
(shape, predicted gate|auto, the human's real action or auto_pass), and an
auto-pass fired only for a shape the policy lists in auto: (and not in never_auto:)
with no blocking finding standing.
Phase: Apply
Step 5 — Persist the seed · Owner: play · Depends on: Step 4
On approval, persist the draft additively. apply_seed.py merges the spine by entry id
(adds only absent nodes + the profile if none exists, never modifies an existing entry)
and copies grounding docs skip-if-exists. It emits an {applied, written, skipped}
manifest (applied: true is the stop-condition gate's apply record, D4) — captured to
disk so Step 6 can validate exactly what this run wrote:
python3 scripts/apply_seed.py --draft <working>/draft --product-base <product_base> \
> <working>/apply-manifest.json
SE-6 (F5/C6): the apply manifest's written list contains no entry or doc that
already existed (those appear only in skipped) — the merge-by-id + skip-if-exists
writer makes overwriting an existing spine entry or grounding doc structurally impossible.
Step 6 — Validate the model · Owner: play · Depends on: Step 5
Re-validate only what this run wrote — the live spine plus the grounding docs whose
doc: paths appear in the apply manifest's written list. The live model may already
hold matured nodes (a detail: detailed capability, functionality nodes, a set
profile from a prior /understand or /shape on another domain) that /vision never touched
and must not be judged by directional rules — so the post-apply check is scoped to the
written set:
python3 scripts/lint_grounding.py --root <product_base>/product-os \
--spine <product_base>/product-os/_spine.yaml
SE-1 (F1/C1): the spine and the docs this run persisted conform to their schema/
templates and stay consistent.
SE-3 (F3/C3): none of the docs this run wrote is a functionality or a detailed
capability; the profile it wrote is not set/locked.
SE-4 (C4): the capabilities this run wrote are proposed + detail: directional; a
profile it wrote is directional.
Phase: Scenario Validation
Step 7 — Scenario evals · Owner: play · Depends on: Step 6
- SCE-1 (S1 — CXO / product strategist): the seed this run persisted — a domain entry
with a detailed
domain.md, at least one proposed + directional capability with a
directional capability.md, and a directional profile — clears both guards
(lint_grounding.py clean; grounding_gate.py passes for every grounding doc) and is
present in the live spine.
- SCE-2 (S2 — architect): every persisted capability traces to a KB shelf or a
recorded proposal in the seed manifest (
grounding_check.py is clean).
- SCE-3 (S3 — product owner, non-destructive re-run): on a re-run over an existing
domain, the apply manifest's
skipped list holds every pre-existing spine entry and
doc and written holds only newly-added capabilities — existing content is untouched.
- SCE-4 (S4 — reviewer): the Step 4 checkpoint showed the domain, the directional
capabilities, and the directional profile inline, and no product-model file was
written before that gate resolved — or, on the auto-pass path (a policy-listed
shape), the gate resolved with no wait and the recorded auto-pass, the appended
ledger line, and the diff summary stand in the approval's place.
Phase: Evidence & Close
Step 8 — Close · Owner: play · Depends on: Step 7
Run the Standard Play Close. /vision 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).
SE-8 (F7/C8): the close is stop-condition gated — check_stop_condition.py over
the baked stop-condition.yaml (D1 the grounding record exists; D2 the drafted spine
entries record exists; D3 the seed manifest exists; D4 the apply record reads
applied: true) reads held before the run closes COMPLETED; anything else closes
HALTED with the unmet clauses named.
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_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "${stm_base}_shaping/vision/status/session-stamp-vision.json")
python3 scripts/check_stop_condition.py \
--manifest "<play-dir>/stop-condition.yaml" \
--base "<working>/" \
--out "${stm_base}_shaping/vision/status/stop-condition-vision.yaml"
sc_exit=$?
python3 scripts/distill_gate_policy.py --ledger "<gates.conditional.ledger>" --policy "<gates.conditional.policy>" --streak <gates.conditional.streak> --project "<project name from config>" || true
/vision is product-scoped: evidence_base="${product_base}_evidence/vision/" and
slug="${product_slug}" (the seeded domain's slug, e.g. order-management).
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.vision; 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 vision, run_id vision-${ts},
product_slug, started_at/completed_at, status per C0, exit_reason; artifacts produced:
grounding.yaml, seed-manifest.yaml, the persisted spine + grounding-doc paths, the
apply manifest, the stop-condition verdict; the content-eval verdicts; step and scenario
eval results SE-1…SE-9 / SCE-1…SCE-4; checkpoint decision from Step 4 (or the
gate skipped by config / gate auto-passed by learned policy row when the gate
resolved without a wait) plus the gate ledger line(s) appended this run; 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: ## vision Delivered — ${product_slug}, the Run Summary table, the Pipeline
Steps table from the task DAG, the Artifacts Produced table (the seeded domain doc,
directional capability docs, spine entries, and profile), Next Steps (run /understand to
detail the capabilities and introduce their functionalities, and firm the profile), and a
pointer to $evidence_dest. Always emitted; never gated.
Scenario Validation
| Scenario | Persona | Eval |
|---|
| S1 — end to end | CXO / product strategist | SCE-1 |
| S2 — grounding audit | architect | SCE-2 |
| S3 — non-destructive re-run | product owner | SCE-3 |
| S4 — the checkpoint | reviewer | SCE-4 |
Recovery
| For | Trigger | Direction | Handoff |
|---|
| F1 | a grounding doc fails its template/shape, or a spine entry fails the schema or spine↔doc consistency | re-emit the failing doc or spine entry to conform and restore consistency before the play completes | autonomous |
| F2 | a grounding doc fails the content-quality eval | rewrite the failing doc to the judge's cited fixes — raise each flagged section to a self-explaining, CXO-altitude statement — and re-judge until the gate passes | autonomous |
| F3 | a functionality, a detailed capability, acceptance criteria, a set/locked profile, or a detail: detailed capability appears | strip the over-reach — drop the functionality, demote the capability to directional, remove the acceptance criteria, reset the profile to directional | autonomous |
| F4 | a capability has neither a KB shelf match nor a KB-node proposal | search the KB to ground it, or record a propose-kb-node proposal; never leave it ungrounded | autonomous |
| F5 | the content of an existing spine entry or grounding doc changed during the run | restore the prior content and re-apply only the additive seed for absent entries, after a human confirms the restore | human |
| F6 | a product-model file was written before the checkpoint was approved | revert the premature write and re-present the checkpoint; persist only after the human approves | human |
| F7 | the close would report COMPLETED without the Done means held | evaluate the stop condition and surface the unmet clauses; the run closes HALTED until state is fixed | autonomous |
| F8 | a conditional-gate crossing left no live-eval ledger line, or an auto-pass fired for a shape the policy does not list as auto (or that carried a blocking finding) | re-append the missing ledger line for the recorded crossing; when the auto-pass was unearned, re-run the gate as a live wait — render the approval prompt and wait for the typed response — before proceeding | autonomous |
Pause and Resume
Steps run top to bottom. On entry, resolve config, derive product_slug from the goal
or the in-progress draft, check the status marker, skip completed steps, reset any
in-progress step to pending, and continue. A fresh start with no marker runs everything
and creates the marker at Step 1.
Compilation Metadata
| Field | Value |
|---|
| fingerprint | sha256:6483756816ee32b576e91421fca45de97682fe7da702dbd0a9bc827a47d1d96d (of reference/ice.md) |
| compiled_by | play-editor (#467 Batch B); prior: play-editor (#466 Batch C); play-creator (edited via play-editor, #437; spine+grounding+eval model) |
| pipeline_position | start (start-change head; the strategy pipeline closes at /roadmap) |
| workflow_structure | A (single checkpoint — class: standard, conditional gate per gate-config.md #467; stop-condition gated close) |
| stop_condition | stop-condition.yaml (D1–D4), gate live at Step C0 |
| domain_agents | 1 (product-os-keeper) |
| utility_agents | 0 |
| skills_used | search-kb, propose-kb-node, author-vision-seed |
| scripts | 10 (preflight.py, lint_grounding.py, grounding_check.py, grounding_gate.py, apply_seed.py, classify_change.py, gate_eval.py, distill_gate_policy.py, check_stop_condition.py, session_stamp.py) |
| step_evals | 9 (SE-1…SE-9) |
| scenario_evals | 4 (SCE-1…SCE-4) |
| recovery_entries | 8 (one per failure condition; 6 autonomous / 2 human) |
Direct-edit deviation note (drop-codex-judge): the content-quality judge dispatch
was simplified from three modes (subagent / different-model / codex grader) to a single
isolated sub-agent (with an optional model override). This is an execution-mechanism
change only — it touches no constraint, failure, scenario, or eval, so the ICE
(reference/ice.md) and the fingerprint are unchanged. The run_codex_judge.py script
was removed. A future rebuild from the ICE need not restore the dropped modes.
Recompiled note (#467 Batch B): checkpoint upgraded to a conditional learned gate;
see gate-config.md.
Direct-edit deviation note (#468 Stage 5, concurrent fan-out): the Step 3
content-quality judge loop was changed from a serial per-doc loop to a concurrent
read-only fan-out — one isolated judge per doc dispatched in one batch, joined before
gating (standards/rules/concurrent-fanout.md). Execution-timing change only: each judge
stays isolated and read-only, writes only its own verdict, and the gate still runs over
every verdict, so coverage (SE-2) is unchanged. No constraint, failure, scenario, or eval
touched — the ICE (reference/ice.md) and fingerprint stand. play-creator emits the same
fan-out form so a rebuild converges.