Skip to content
Back to skills

Show Plan

ASecurity

See one plan as a tree, from its plan file alone, and know where it stands after two days away — /show-plan <id>, where the ID is the business intent''s issue number, or /show-plan with no number on a plan''s branch (plan/<id>/…), which shows that plan; on a branch in no plan it says so plainly. One node per line, its status mark, issue number and title; the work that is Not Started, In Progress, Now or Blocked is shown, Done and Dropped are hidden and counted on the last line (a hidden node ...

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
toolspythongobashnodegit

Works with

  • terminal

Security analysis

A93/100
  • highPerforms destructive filesystem operations

Pro scans all 10 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add intent-driven-ai/garura --skill show-plan --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Show Plan?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Show Plan
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intent-driven-ai-show-plan/badge)](https://www.skillsdirectory.com/skills/intent-driven-ai-show-plan)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: show-plan
position: none
description: 'See one plan as a tree, from its plan file alone, and know where it stands after two days away — /show-plan <id>, where the ID is the business intent''s issue number, or /show-plan with no number on a plan''s branch (plan/<id>/…), which shows that plan; on a branch in no plan it says so plainly. One node per line, its status mark, issue number and title; the work that is Not Started, In Progress, Now or Blocked is shown, Done and Dropped are hidden and counted on the last line (a hidden node with a shown node under it is still printed, so it keeps its place; an open node whose children are all Done or Dropped prints them, one level down, so a person can decide on it), and each plan it needs is printed after it. Reads only the plan files (.garura/project/plans/); never the tracker or the product model, and no model call makes the tree: the plan tool prints it from the plan-view template, so the same file prints the same tree every time. Read only and position none: it writes nothing and runs on any branch. A number no plan has gets a plain message; a plan file with a status the template does not know stops the play with the file named. Use when someone asks "where does plan 717 stand", "show me the plan", "what is left in this plan", or "what is being worked on in this plan".'
user-invocable: true
---

# show-plan

Print one plan as a tree, from its plan file alone: what is left and what is moving, with the
finished work counted, and each plan it needs after it. The plan tool prints the tree from the
plan-view template; a check re-derives the tree from the plan file and proves it, the same way
twice, with nothing changed.

## Compiled From

This play was compiled from the show-plan ICE (`reference/ice.md`) by create-play (#719, story
#628), and recompiled by edit-play (#1005, #1000). Intent defines constraints (C1–C9) and failure conditions (F1–F8); the expectation
defines success scenarios (S1–S7), 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 plan number, the tree, the check — is a script (C7): the plan tool
prints the tree, `check_tree.py` re-derives it from the plan file and 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
(C1/F5); writing a plan file, an issue or a branch (C2/F4); writing, editing, re-wording,
re-ordering or adding to any line of the tree yourself — you present the plan tool's output as
it is (C3/C6/F5); guessing a plan when the number has none, or showing a tree when the plan
tool stopped (C8/F7).

**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 |
| One plan: the number typed, else the current branch's plan, via `scripts/resolve_args.py` | C8 | **Hard halt** — print its `error` line; never guess a plan |
| The plan tool is installed (`.garura/core/tools/plan/plan.py`) | C1 / C6 | Hard halt — without it there is no deterministic tree |

```
python3 scripts/preflight.py --play show-plan --config .garura/core/config.yaml \
    --branch "$(git branch --show-current)"
python3 scripts/resolve_args.py --args="<the play's arguments>" \
    --branch "$(git branch --show-current)" --out <working>/plan.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/show-plan/` (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/`; `<id>` is `plan.json`'s `plan`.

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-show-plan.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 tree                 blockedBy: [T1]
[T3] Check the tree                 blockedBy: [T2]
[T4] Present the tree               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 tree'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-show-plan.json" },
      "task_id": "load-templates" }

`<template>` is `<working>/context/templates/standards/templates/plan-view.md`.
**SE-1 (C6/F5):** 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 (REC5) — the play never prints a layout of its own.

### Phase: Tree

**Step 2 — Print the tree** · Owner: play (script) · Depends on: Step 1
Record the plan files' hashes, then print the tree twice with the plan tool — the second print
is the determinism proof (C7):

```
python3 scripts/check_tree.py hash --plans-dir <plans> --out <working>/before.json
python3 .garura/core/tools/plan/plan.py show --template <template> --plans-dir <plans> --plan <id> \
    > <working>/view.txt 2> <working>/tool-error.txt; echo "{\"exit\": $?}" > <working>/tool-exit.json
python3 .garura/core/tools/plan/plan.py show --template <template> --plans-dir <plans> --plan <id> \
    > <working>/view2.txt 2>> <working>/tool-error.txt
```

**SE-2 (C8/F7):** `tool-exit.json` reads 0 (a tree), or 1 (no plan has that number — `view.txt`
is the template's one no-plan line and nothing else). An exit of 2 is a hard halt: print
`tool-error.txt` (it names the plan file and its status) and show no tree (REC7).

**Step 3 — Check the tree** · Owner: play (script) · Depends on: Step 2

```
python3 scripts/check_tree.py check --plans-dir <plans> --template <template> --plan <id> \
    --tool-exit <working>/tool-exit.json --view <working>/view.txt --view2 <working>/view2.txt \
    --before <working>/before.json --out <working>/check.json
```

**SE-3 (C3/C4/C6, F1/F2/F5):** `check.json` reads `lines_ok: true` — the legend is the
template's; the first line is the business intent's root line, with no mark; every node the plan file says to show is printed as the template's line (mark,
issue number, title — F2); no Done or Dropped node is printed unless a shown node sits under it,
or it is a child of a shown node whose children are all Done or Dropped, and every such child is
printed (F1) — and `hidden_ok: true`: the count line is the template's, with the right count for each
hidden status (F1). On a GAP, apply REC1/REC2/REC5 and re-run Steps 2–3.
**SE-4 (C5/F3):** `check.json` reads `needs_ok: true`: each plan in `needs_plans` is printed
after the plan, or named with the template's no-plan line when its file is missing. On a GAP,
apply REC3.
**SE-5 (C2/C7, F4/F6):** `check.json` reads `same_twice: true` (F6) and `unchanged: true` —
every plan file hashes the same as before the tool ran — and no tracker or branch verb was run
in this play (F4). A changed hash is a hard halt (REC4).
**SE-6 (C1/C8, F7):** `plan.json` reads `from: args` when a number was typed and `from: branch`
when none was, and then its `plan` is the number in the branch name; for a number no plan has, `check.json` reads `no_plan_plain: true` and
no node line is in `view.txt`; for a plan that exists, `check.json` reads `tree_ok: true`. On a
GAP, apply REC7.

**Step 4 — Present the tree** · 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 naming the plan. Never re-word, sort, trim or add to a line of it (C3/C6).

### Phase: Scenario Validation

**Step 5 — Scenario evals** · Owner: play · Depends on: Step 4
- **SCE-1 (S1 — returning developer, where does it stand):** `check.json` reads
  `lines_ok: true` and `hidden_ok: true`.
- **SCE-2 (S2 — developer, a bug under finished work):** for a Done node with a Not Started node
  under it, `check.json` reads `lines_ok: true` — the Done node is printed and is not in the
  hidden count.
- **SCE-3 (S3 — lead, a plan that needs another):** `check.json` reads `needs_ok: true`.
- **SCE-4 (S4 — anyone, a wrong number):** `tool-exit.json` reads 1 and `check.json` reads
  `no_plan_plain: true`.
- **SCE-5 (S5 — auditor, nothing changed and nothing drifted):** `check.json` reads
  `same_twice: true`, `unchanged: true` and `lines_ok: true` (or `no_plan_plain: true`).
- **SCE-7 (S7 — product owner, no number on a plan's branch):** `plan.json` reads `plan: <id>`
  and `from: branch` for a branch `plan/<id>/…`, and `check.json` reads `tree_ok: true`; on a
  branch in no plan, `plan.json` reads `plan: null` with its error and no `view.txt` exists.
- **SCE-6 (S6 — product owner, a feature whose stories are all finished):** for an open node
  whose children are all Done or Dropped, `check.json` reads `lines_ok: true` and
  `hidden_ok: true` — each child is printed under it and is not in the hidden count.

### Phase: Evidence & Close

**Step 6 — Close** · Owner: play · Depends on: Step 5
Run the Standard Play Close. `/show-plan` 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-7 (F8/C9):** the close is stop-condition gated — `check_stop_condition.py` over
`stop-condition.yaml` (D1 the view exists; D2 the tree is what the plan file and the template
say; D3 the same file 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/show-plan/" ; slug="plan ${id}"
# 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-show-plan.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-show-plan.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.show-plan`; 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 `show-plan`, run_id `show-plan-${ts}`, status per C0; artifacts: the plan number,
the template manifest, the view, the check record, the stop-condition verdict; step and
scenario eval results SE-1…SE-7 / SCE-1…SCE-7; 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: `## show-plan Delivered — plan ${id}`, the Run Summary table, the Pipeline Steps table
from the task DAG, the Artifacts Produced table (the plan, the plans it needs), 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 tree 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/show-plan/
```

## Scenario Validation

| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — where does it stand | returning developer | SCE-1 |
| S2 — a bug under finished work | developer | SCE-2 |
| S3 — a plan that needs another | lead | SCE-3 |
| S4 — a wrong number | anyone | SCE-4 |
| S5 — nothing changed and nothing drifted | auditor | SCE-5 |
| S6 — a feature whose stories are all finished | product owner | SCE-6 |
| S7 — no number on a plan's branch | product owner | SCE-7 |

## Recovery

| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | the check finds a hidden node shown, the finished children of an open parent left out or counted, or a wrong or missing count line | re-run the plan tool and check again; if it still fails, report the node and close HALTED | autonomous |
| F2 | the check finds a line with no title or no number | re-run the plan tool and check again; if the plan file has a node with no title, name it for a person | human |
| F3 | a needed plan is missing from the view | re-run the plan tool and check again; if the needed plan's file is missing, the tree says so with the template's no-plan line | autonomous |
| F4 | 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 |
| F5 | 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 |
| F6 | the two prints differ | re-run both prints; if they still differ, report the difference and close HALTED | autonomous |
| F7 | a missing plan, an unknown status or a branch in no plan got a tree | show the template's no-plan line, or stop and name the file and its status, or the branch; never a guessed tree | autonomous |
| F8 | 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 |

## Pause and Resume

Steps run top to bottom. `/show-plan` does not resume: a tree is only as good as the plan file 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:789fdc5ee521c9e46aa872ef242fbd4cad364e95a3d3430d22bbfaaae9a77222 (of `reference/ice.md`) |
| compiled_by | create-play (#719; story #628); edit-play (#1005; #1000) |
| pipeline_position | none |
| structural_constraints | C1 (the play's only read is the plan tool over the plan files — no tracker or model path is opened anywhere); C3/C6 (every line is printed by the plan tool from the template; the play presents it unchanged); C8 (the plan number is `resolve_args.py`'s fixed rule: the number typed, else the branch's plan) |
| 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_tree.py, check_stop_condition.py, session_stamp.py) + test_resolve_args.py |
| step_evals | 7 (SE-1…SE-7; F1→SE-3, F2→SE-3, F3→SE-4, F4→SE-5, F5→SE-1+SE-3, F6→SE-5, F7→SE-2+SE-6, F8→SE-7) |
| scenario_evals | 7 (SCE-1…SCE-7) |
| recovery_entries | 8 (one per failure condition; 6 autonomous / 2 human) |

Files in this skill

  • SKILL.md17.3 KB
  • reference/ice.md8.3 KB
  • scripts/check_stop_condition.py5 KB
  • scripts/check_tree.py7.2 KB
  • scripts/preflight.py7 KB
  • scripts/resolve_args.py2 KB
  • scripts/session_stamp.py4.8 KB
  • scripts/test_check_tree.py3.2 KB
  • scripts/test_resolve_args.py1.9 KB
  • stop-condition.yaml972 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.