See every plan of the project at once, from the plan files alone — one card for each plan with its number and business intent, its direction (⏵, ⏵⏵, ⏵⏵⏵) on the line under, its Status, Branch and the plans it Waits on, then each of its epics with its Progress; the plan''s Status and Direction are what a person set in the plan file, never worked out; with --graph, each plan''s branch drawn against main with its commits ahead and behind, and the plans with no branch named as on main. Reads only...
Installs into .claude/skills of the current project.
Are you the author of List Plans?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/intent-driven-ai-list-plans)
---
name: list-plans
position: none
description: 'See every plan of the project at once, from the plan files alone — one card for each plan with its number and business intent, its direction (⏵, ⏵⏵, ⏵⏵⏵) on the line under, its Status, Branch and the plans it Waits on, then each of its epics with its Progress; the plan''s Status and Direction are what a person set in the plan file, never worked out; with --graph, each plan''s branch drawn against main with its commits ahead and behind, and the plans with no branch named as on main. Reads only the plan files (.garura/project/plans/) and, for the graph, git; never the tracker or the product model, and no model call makes the view: the plan tool prints it from the plan-view template, so the same files print the same way every time. Read only and position none: it writes no plan file, issue or branch, and runs on any branch. A plan file with a status, plan status or direction the template does not know stops the play with the file named. Use when someone asks "what plans are there", "where does every plan stand", "which plans are on a branch", or "how far is each plan from main".'
user-invocable: true
---
# list-plans
Print every plan of the project at once, from the plan files alone: one card per plan (the
default), or the graph of each plan's branch against main (`--graph`). The plan tool prints the view from the
plan-view template; a check proves it holds every plan once, in order, the same way twice, and
that nothing changed.
## Compiled From
This play was compiled from the list-plans ICE (`reference/ice.md`) by create-play (#719,
stories #729 and #806) and changed by edit-play (#983, #986). Intent defines constraints
(C1–C10) and failure conditions (F1–F8); the expectation defines success scenarios (S1–S6), 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 edit-play.
Do NOT edit this file manually — it is a compiled artifact.
## Role
You are the orchestrator. You own the workflow and the step order, and you do no domain work.
Every mechanical part — the mode, the view, the check — is a script (C5): the plan tool prints
the view, `check_list.py` proves it. You delegate one thing: loading the template, which is
`template-manager`'s job, because a play reads no memory (ADR 039).
**Forbidden:** reading the tracker, the product model or any source other than the plan files
and git's branches (C1/F3); writing a plan file, an issue or a branch (C2/F2); writing, editing
or re-wording any line of the view yourself — you present the plan tool's output as it is
(C4/F3); working out a plan's Status or Direction from its work, or showing any but the plan
file's (C10/F8); guessing a mode (C8); showing a list when the plan tool stopped (C6/F5).
**Agent boundaries:**
| Agent | Domain | Skills it invokes | Phases |
|-------|--------|-------------------|--------|
| `template-manager` | Load the plan-view template and the close templates into the run's working folder | — | Prepare |
`template-manager` is a **utility agent**, exempt from the domain-agent budget. This play uses
**zero domain agents**: there is nothing to decide.
## Pre-flight
| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Resolve config (`.garura/core/config.yaml`) via `scripts/preflight.py` | — | Hard halt |
| The mode resolves to `list` or `graph` via `scripts/resolve_args.py` | C8 | **Hard halt** — print its `error` line; never guess a mode |
| The plan tool is installed (`.garura/core/tools/plan/plan.py`) | C1 / C4 | Hard halt — without it there is no deterministic view |
| The plans folder (`plans.base-path`, default `.garura/project/plans/`) exists | C7 | Graceful — a missing folder is the same as an empty one: the view says there are no plans |
```
python3 scripts/preflight.py --play list-plans --config .garura/core/config.yaml \
--branch "$(git branch --show-current)"
python3 scripts/resolve_args.py --args="<the play's arguments>" --out <working>/mode.json
test -f .garura/core/tools/plan/plan.py || { echo "the plan tool is not installed — halt"; exit 1; }
```
The working folder is `<working> = ${stm_base}_plans/list-plans/` (the play has no issue of its
own). Create it fresh: a prior run's files are overwritten, never resumed. `<plans>` is
`plans.base-path` from config, else `.garura/project/plans/`.
Right after, record the session identity stamp's start marker (#463 — soft-fail, never a halt):
```
python3 scripts/session_stamp.py --phase start \
--marker "<working>/session-stamp-list-plans.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
```
## Task DAG
Create ALL tasks immediately after pre-flight — before any domain work.
```
[T1] Load the template blockedBy: []
[T2] Print the view blockedBy: [T1]
[T3] Check the view blockedBy: [T2]
[T4] Present the view blockedBy: [T3]
[T5] Scenario Validation blockedBy: [T4]
[T6] Close blockedBy: [T5]
[T7] Self-clean blockedBy: [T6]
```
Mark each task in-progress before its step and completed right after its eval passes. No runtime
reordering.
## Workflow
### Phase: Prepare
**Step 1 — Load the template** · Owner: `template-manager` · Depends on: pre-flight
Dispatch one JSON contract for the view's template and the close's templates — paths only:
{ "task": "load these templates into the run's working folder",
"inputs": { "issue": null,
"templates": ["standards/templates/plan-view.md",
"standards/templates/delivery-report.md",
"standards/rules/pipeline-next.md"] },
"outputs": { "out_dir": "<working>/context/templates/",
"manifest": "<working>/context/templates/manifest-close-list-plans.json" },
"task_id": "load-templates" }
`<template>` is `<working>/context/templates/standards/templates/plan-view.md`.
**SE-1 (C4/F3):** the manifest exists, names `plan-view.md` with a source tier and fingerprint,
and `<template>` holds a ```` ```yaml plan-view ```` block. A `template_missing` for
`plan-view.md` is a hard halt (REC3) — the play never prints a layout of its own.
### Phase: View
**Step 2 — Print the view** · Owner: play (script) · Depends on: Step 1
Record the plan files' hashes, then print the view twice with the plan tool — the second print
is the determinism proof (C5):
```
python3 scripts/check_list.py hash --plans-dir <plans> --out <working>/before.json
python3 .garura/core/tools/plan/plan.py <mode> --template <template> --plans-dir <plans> \
> <working>/view.txt 2> <working>/tool-error.txt; echo "{\"exit\": $?}" > <working>/tool-exit.json
python3 .garura/core/tools/plan/plan.py <mode> --template <template> --plans-dir <plans> \
> <working>/view2.txt 2>> <working>/tool-error.txt
```
`<mode>` is `list` or `graph`, from `mode.json`.
**SE-2 (C6/F5):** `tool-exit.json` reads 0. An exit of 2 is a hard halt: print
`tool-error.txt` (it names the plan file and the status, plan status or direction it does not
know) and show no list (REC5).
**Step 3 — Check the view** · Owner: play (script) · Depends on: Step 2
```
python3 scripts/check_list.py check --plans-dir <plans> --template <template> --mode <mode> \
--view <working>/view.txt --view2 <working>/view2.txt --before <working>/before.json \
--out <working>/check.json
```
**SE-3 (C3/C4/C5/C7, F1/F3/F4):** `check.json` reads `all_listed: true` (every plan once — F1;
an empty folder holds the template's no-plans line — C7), `in_order: true` (C3),
`template_used: true` (every plan line is the template's line — F3) and `same_twice: true`
(F4). On a GAP, apply REC1/REC3/REC4 and re-run Steps 2–3.
**SE-4 (C2/F2):** `check.json` reads `unchanged: true` — every plan file hashes the same as
before the tool ran — and no tracker or branch verb was run in this play (the play's only
commands are the ones written above). A changed hash is a hard halt (REC2).
**SE-7 (C10/F8):** in `list` mode, `check.json` reads `as_set: true`: under each card's
heading, the line holds the direction icon of the plan file's `direction` (and there is no
icon line when the file sets none), and the Status row reads the plan file's `status` —
nothing worked out from the work. On a GAP, apply REC8.
**SE-5 (C1/F6):** for `graph`, `check.json` reads `graph_numbers_match: true`: every
ahead/behind number equals git's own count (`git rev-list --left-right --count`). On a GAP,
apply REC6.
**Step 4 — Present the view** · Owner: play · Depends on: Step 3
Output `<working>/view.txt` to the person **as it is**, in a code block, with one plain line
before it: how many plans and which mode. Never re-word, sort, trim or add to a line of it (C4).
### Phase: Scenario Validation
**Step 5 — Scenario evals** · Owner: play · Depends on: Step 4
- **SCE-1 (S1 — developer, every plan at once):** in `list` mode, `check.json` reads
`all_listed: true` and `in_order: true`, and `plans_in_folder` equals the number of plan
files.
- **SCE-2 (S2 — lead, plans against main):** in `graph` mode, `check.json` reads
`graph_numbers_match: true` and `all_listed: true`.
- **SCE-3 (S3 — newcomer, no plans yet):** with no plan file, `view.txt` holds the template's
no-plans line and `check.json` reads `all_listed: true`.
- **SCE-4 (S4 — operator, an old plan file):** with a plan file whose status the template does
not know, `tool-exit.json` reads 2, `tool-error.txt` names the file, and no view was
presented.
- **SCE-5 (S5 — auditor, nothing changed and nothing drifted):** `check.json` reads
`same_twice: true`, `unchanged: true` and `template_used: true`.
- **SCE-6 (S6 — product owner, the direction as set):** in `list` mode, `check.json` reads
`as_set: true`.
### Phase: Evidence & Close
**Step 6 — Close** · Owner: play · Depends on: Step 5
Run the Standard Play Close. `/list-plans` has no issue of its own: its run's short-term folder
is `<working>`, and the close finds the templates Step 1 already loaded there.
**SE-6 (F7/C9):** the close is stop-condition gated — `check_stop_condition.py` over
`stop-condition.yaml` (D1 the view exists; D2 every plan is listed once, in order; D3 the same
files printed the same way twice; D4 no plan file changed) reads **held** before the run closes
COMPLETED; anything else closes HALTED with the unmet clauses named. It runs BEFORE Step 7's
self-clean.
```bash
# --- 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 (no issue — the run's own folder):
# evidence_base="${stm_base}_plans/evidence/list-plans/" ; slug="plans"
# 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-list-plans.json")
# Stop-condition gate (#464) — Step C0: evaluate the Done means BEFORE Step 7's self-clean.
python3 scripts/check_stop_condition.py \
--manifest "<play-dir>/stop-condition.yaml" \
--base "<working>/" \
--out "<working>/stop-condition-list-plans.yaml"
sc_exit=$? # 0 held · 1 unmet · 2 error
```
**Step C0 — bind the verdict.** `sc_exit == 0` (held) permits `status: COMPLETED`. Anything else
closes `HALTED` with `exit_reason: stop_condition_unmet` and the unmet clauses named. An
unevaluable verdict is never a pass.
**Step C1 — Write evidence file.** Gated by the resolved `evidence.record` flag (global +
per-play `evidence.plays.list-plans`; first match wins, absent ⇒ record). When false, skip and
record `evidence skipped (record=false)` in the report. Otherwise fill the `evidence-file.md`
slots (play `list-plans`, run_id `list-plans-${ts}`, status per C0; artifacts: the mode, the
template manifest, the view, the check record, the stop-condition verdict; step and scenario
eval results SE-1…SE-6 / SCE-1…SCE-5; checkpoint decisions: none; the session identity stamp
fields from $session_stamp) and write to `$evidence_dest`. Do NOT hand-author the body.
**Step C2 — Render delivery report.** Resolve this play in the Next-line map (`$next_map`) and
emit the **Next** line only when it names a command. Fill the `delivery-report.md` slots and
output: `## list-plans Delivered — plans`, the Run Summary table, the Pipeline Steps table from
the task DAG, the Artifacts Produced table (the mode, the number of plans), and a pointer to
`$evidence_dest`. Always emitted; never gated.
```bash
# --- end Standard Play Close ---
```
**Step 7 — Self-clean** · Owner: play · Depends on: Step 6
The terminal action: the view is presented and the close is written, so the working folder has
no further reader. Delete ONLY the working folder (C2); never the evidence folder.
```bash
rm -rf "<working>" # <working> = ${stm_base}_plans/list-plans/
```
## Scenario Validation
| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — every plan at once | developer | SCE-1 |
| S2 — plans against main | lead | SCE-2 |
| S3 — no plans yet | newcomer | SCE-3 |
| S4 — an old plan file | operator | SCE-4 |
| S5 — nothing changed and nothing drifted | auditor | SCE-5 |
| S6 — the direction as set | product owner | SCE-6 |
## Recovery
| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | the check finds a plan missing or listed twice | re-run the plan tool over the plans folder and check again; if it still fails, report the plan and close HALTED | autonomous |
| F2 | a plan file's hash changed during the run, or a write to the tracker or a branch was made | stop, report what changed, and leave it for a person; read only is never repaired by a retry | human |
| F3 | a line of the view does not match the template's layout | load the template again through template-manager and re-run the plan tool with it | autonomous |
| F4 | the two prints differ | re-run both prints; if they still differ, report the difference and close HALTED | autonomous |
| F5 | the plan tool exits 2 on a status it does not know | stop, name the plan file and its status, and show no list; a person fixes the plan file | human |
| F6 | a graph number does not equal git's count | re-run the graph and check again; if it still differs, close HALTED with both numbers | autonomous |
| F7 | the close would report COMPLETED without the Done means held | surface the unmet clauses and re-run the step that makes the missing record, or close HALTED | autonomous |
| F8 | a card's Status or Direction differs from the plan file | re-run the plan tool with the template and check again; never correct the card by hand — the plan file is the only source | autonomous |
## Pause and Resume
Steps run top to bottom. `/list-plans` does not resume: a view is only as good as the plan files
it was printed from, so any interruption means a fresh run. Prior files in `<working>/` are
overwritten. There is no status marker.
## Compilation Metadata
| Field | Value |
|-------|-------|
| fingerprint | sha256:004240cafed7ab99d5b550b4077f0f99a6cfc0f6ff627bfbe38fb9d099dc2dd4 (of `reference/ice.md`) |
| compiled_by | create-play (#719; stories #729, #806); edit-play (#983, #986) |
| pipeline_position | none |
| structural_constraints | C1 (the play's only reads are the plan tool over the plan files and git — no tracker or model path is opened anywhere); C4 (every line is printed by the plan tool from the template; the play presents it unchanged); C8 (the mode is `resolve_args.py`'s fixed choice); C10 (the plan tool reads Status and Direction from the plan file and has no code path that derives them) |
| workflow_structure | readiness-only (a view, no generation; no checkpoint) |
| stop_condition | stop-condition.yaml (D1–D4), gate live at Step C0 — evaluated BEFORE the Step 7 self-clean |
| domain_agents | 0 |
| utility_agents | 1 (template-manager) |
| tools | the plan tool (`.garura/core/tools/plan/plan.py`) |
| scripts | 5 (preflight.py, resolve_args.py, check_list.py, check_stop_condition.py, session_stamp.py) |
| step_evals | 7 (SE-1…SE-7; F1→SE-3, F2→SE-4, F3→SE-1+SE-3, F4→SE-3, F5→SE-2, F6→SE-5, F7→SE-6, F8→SE-7) |
| scenario_evals | 6 (SCE-1…SCE-6) |
| recovery_entries | 8 (one per failure condition; 6 autonomous / 2 human) |