Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
bump: minor
---

### Added

- `/planning:interview` checks at every round boundary whether the work is bigger than it looked, on two triggers (the context-guard zone report has worsened, or two rounds running opened more questions than they closed), and recommends `/planning:wayfind chart` with the ledger, constraints, starting-point disclosure and shorthand glossary carried over. The interview ledger gains a `## Starting point` section, so the intake disclosure survives a `/clear` before wayfind charts. It also takes a "this is small, ship it" exit at any round boundary: remaining open questions are deferred with the operator's reply as the reason and tagged `USER-RESERVED`, the Step 3 confirmation and the Step 4 `--brief` check still run, and the work hands off to `/implementation:implement`. The rules live in the interview's new `context/routing.md`.
- The interview states why its entry gate is diff size and retry cost rather than behavior change.
10 changes: 5 additions & 5 deletions plugins/planning/skills/interview/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,11 @@ Do NOT auto-clear or auto-invoke. Recommend; let the user pull the trigger.

Turn the interview's read of complexity and ambiguity into a recommendation for how the session carrying the work forward should be configured. *When* it lands follows from *what* it configures: an engineering interview recommends at the stop/handoff boundary, for the downstream execution session; a terminal interview (a general decision, per Step 5) recommends at the early post-survey surface and again at the stop boundary, for the current session.

Read [`context/session-config.md`](context/session-config.md) at that boundary, before forming the
recommendation: it owns the two orthogonal knobs and their picking signals, the advisor pairing,
the rule that current model and effort names are fetched live and never pinned (and that a failed
fetch degrades rather than halts), the advisory framing, and the per-surface wording. Do not form
the recommendation from this summary.
Read [`context/session-config.md`](context/session-config.md) at that boundary, before forming the recommendation: it owns the two orthogonal knobs and their picking signals, the advisor pairing, the rule that current model and effort names are fetched live and never pinned (and that a failed fetch degrades rather than halts), the advisory framing, and the per-surface wording. Do not form the recommendation from this summary.

## Routing by size and fog

Read [`context/routing.md`](context/routing.md) at entry and at every round boundary. It owns why the entry gate is diff size and retry cost, the bigger-than-you-thought check that recommends `/planning:wayfind chart` on fog or `/session-flow:handoff` on context size alone, what the wayfind handoff carries, and the "this is small, ship it" exit with the gates it still runs.

## What this skill does NOT do

Expand Down
85 changes: 85 additions & 0 deletions plugins/planning/skills/interview/context/routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Routing by size and fog

Reference detail for the `## Routing by size and fog` section of `SKILL.md`. Read it at entry
and at every round boundary: it owns the entry gate's reason, the bigger-than-you-thought check,
what the handoff to `/planning:wayfind` carries, and the "this is small, ship it" exit.
Comment thread
kyle-sexton marked this conversation as resolved.

## Entry: diff size and retry cost, not behavior change

A change whose diff is quick to review and cheap to retry skips the interview (SKILL.md "What
this skill does NOT do"): when the diff is tiny, a wrong build costs almost nothing, so aligning on
the diff after it exists beats aligning before it. Work that fails either test is interview-first,
and an effort too big and too foggy for one session is reached from here, never first
(`/planning:wayfind` sends a cold start back to this skill).

## Bigger than you thought? Check at every round boundary

After each reply is recorded and before the next round is written, answer one question: did this
turn out larger or foggier than it looked at entry? Each trigger has its own recommendation:

- **Fog: more branches opened than closed → `/planning:wayfind chart`.** Recompute the frontier
first, then count the branches this round's answers exposed (the questions the next round would
add) against the rows it moved to a terminal status. Register rows alone miss this: a new
branch gets its row only when it is asked. Two rounds running with more opened than closed is
the trigger; one is noise. This is the fog evidence wayfind's too-big AND foggy stop rule needs,
so wayfind is never recommended without it.
- **Size alone: the context zone has worsened → `/session-flow:handoff`.** The session's
context-guard report (the zone line the module injects, or its `mcp__context-guard__status`
tool) puts the session in a worse zone than the one it reported at entry. Use only a report the
harness already surfaced or that tool; do not poll your own context statistics, and write no
token or percentage figure here, because the zone thresholds belong to context-guard. No report,
or `unknown`, is not a trigger. With no fog trigger, this recommends the interview's own handoff
(Step 5: save-point, clear, resume), not wayfind. When both hold, recommend wayfind.

On a trigger, recommend its route to the user in one short block (the trigger and its evidence,
what it would carry over); never switch on your own. If it is not a trigger, say nothing and ask
the next round. After the user declines, raise it again only when it escalates: the zone worsens
further, or the other trigger fires.

## The handoff to wayfind

When the user accepts, the handoff carries everything this interview already holds, so nothing is
asked twice. Wayfind's chart step reads the ledger
(`<memory_dir>/<topic-slug>/interview-checklist.md`), so everything goes there before the handoff,
where a `/clear` between the two skills cannot lose it:

- answered rows: decisions so far;
- `open`, `deferred` and `blocked` rows: candidate decision items;
- the `## Constraint ledger`: the constraints the user stated;
- the `## Starting point` section: the user's starting-point disclosure from intake. When the
ledger has none yet, or holds only the template's placeholder, write it now, one line in the user's words or a faithful paraphrase;
- the session-shorthand glossary.

The recommendation block names the ledger path, so a fresh session that runs
`/planning:wayfind chart` finds it.

## Small after all: ship it

At any round boundary the user can say the work is small ("this is small, ship it"), and the
model can propose the same when the diff now looks quick to review and cheap to retry. The model's
proposal waits for the user's yes, because the remaining questions are the user's to drop.

On that yes, stop asking and close out through the normal gates; ship-it drops questions, never a
gate:

1. Move each `open` row to `deferred`, with the user's reply as its resolution, so the
register gate passes without inventing an answer. Skip the assumption sweep: it exists to find
more questions, which the user just declined; say so in the restatement.
Comment thread
kyle-sexton marked this conversation as resolved.
2. **Step 3 still runs, confirmation gate included.** The yes to ship it drops the remaining
questions; it does not confirm the shared understanding. Run the register gate and the
`--procedure` check, restate with the register recap (the deferred rows visible in it), and get
the user's confirmation.
3. **Step 4 as usual.** An engineering session writes the Brief: each deferred row goes under
`### Deferred questions`, led by its `Q<N>` id, tagged **arbiter: USER-RESERVED** (the handoff
skips `/planning:plan`, so no plan stage would resolve a `/planning:plan` tag). No later stage
resolves these rows: the user dropped them, and the tag records that only the user re-raises
Comment thread
kyle-sexton marked this conversation as resolved.
one. The `--brief` cross-check must exit 0 before handing off. A `scope` run writes no Brief:
it returns each deferred row as a `Deferred: Q<N> ... (arbiter: USER-RESERVED)` line in its
`Scope decisions:` section. A general session writes the shared-understanding summary with the
deferred rows listed.
4. Hand off by what the session produced, never to `/planning:plan`: engineering work that is not
design-significant goes to implementation (`/implementation:implement`), design-significant
work goes to `/planning:design` first (SKILL.md Step 5), a general session delivers its summary
and stops, and a `scope` run returns to its caller. The handoff message lists each deferred
row by its `Q<N>` id and question, because `/planning:plan`'s approval gate, the usual place a
`USER-RESERVED` row comes back to the user, does not run on this path.
10 changes: 9 additions & 1 deletion plugins/planning/skills/interview/templates/checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ Planning version: <the `version` in `${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin
- [ ] Step 1: Survey before you ask. Read existing context, the topic's memory slice, conversation history; identify what's already settled
- [ ] Step 1.5: Auto-detect (default action only). If intent already crisp from survey, route to direct synthesis (skip Q&A loop)
- [ ] Step 2: Drive the frontier-rounds loop. Each round asks every settled-prerequisite question as one numbered set in **inline prose** (`AskUserQuestion` only via the `use_ask_user_question` opt-in; `lock` synthesizes without Q&A); order rounds by blast radius; restate decided/open after each round
- [ ] Step 2 exit: Assumption sweep (`me` and `auto` with a register, the `auto` Mixed path included; not `lock`). Once the frontier is empty, a fresh-context sub-agent inventories undecided details, hidden defaults, contradictions, and hedged or free-text rows; each becomes a register row at the next `Q<N>` or a stated fact, and an `open` row returns the run to Step 2 (`context/assumption-sweep.md`)
- [ ] Step 2 exit: Assumption sweep (`me` and `auto` with a register, the `auto` Mixed path included; not `lock`, not a ship-it exit). Once the frontier is empty, a fresh-context sub-agent inventories undecided details, hidden defaults, contradictions, and hedged or free-text rows; each becomes a register row at the next `Q<N>` or a stated fact, and an `open` row returns the run to Step 2 (`context/assumption-sweep.md`)
- [ ] Step 3: Recognize the stop condition. The open-question register grades clean (`check-open-questions.sh` exits 0; skipped only when the run asked no question at all and so wrote no register), the frontier is empty (every unknown the task depends on resolved or captured as a named assumption) AND user has confirmed the restated shared understanding, which opens with the register recap and cites the `--procedure` check's exit code (`me`/`auto`; `lock` is exempt, since invoking it IS the confirmation)
- [ ] Step 4: Persist the contract. Engineering: write the PLAN.md Brief section with goal + constraints + acceptance criteria + captured assumptions; general: write the shared-understanding summary, never a Brief (`me` mode: persist each answer incrementally as it locks in, so a handoff at any round boundary loses nothing)
- [ ] Every round boundary: bigger-than-you-thought check (`context/routing.md`). Two rounds running with more branches opened than closed → recommend `/planning:wayfind chart`; a worsened context zone with no such fog → recommend `/session-flow:handoff`, never wayfind. Recommend only; the user decides
- [ ] Step 5: Hand off. Engineering: recommend the next skill (exploration/research for engineering-internal; chain after `/planning:prd` for product-driven); general: deliver the summary and stop, no pipeline handoff. Both: recommend model / effort / advisor per the live-doc-sourced session-config guidance (never a pinned model name). Engineering configures the **downstream execution session** it hands off to; general/terminal configures the **current/next session**, applied now (nothing downstream exists), first surfaced early, post-survey, so it could shape the rounds themselves; here refresh it and, if raised only now, offer to re-evaluate the result under the raised config

## Constraint ledger
Expand All @@ -21,6 +22,12 @@ One row per constraint, `- C<N> | confirmed|inherited | <constraint> | <source>`
- C1 | confirmed | V1 ships without SSO | user, round 1
- C2 | inherited | no new runtime dependencies | prior Brief

## Starting point

One line: what the user disclosed at intake about where they start (SKILL.md Stance, "Intake the starting point"). `/planning:wayfind chart` carries it into its map's Notes, so a session cleared between the two skills keeps it (`context/routing.md` "The handoff to wayfind"). Replace the placeholder line with this run's disclosure.

- <the user's starting-point disclosure>

## Open-question register

**Write a row the moment a round is ASKED, before any reply arrives.** The register is a byproduct of asking, not of resolving: a question that only lands on disk once it is answered cannot record the failure of never being answered. Statuses: `open` | `answered` | `deferred` | `withdrawn` | `blocked` | `superseded-by-plan` (set by `/planning:plan` when a plan change displaces an answer, resolution `plan proposes: <new>; was: <old>`; not terminal; row shape and how it clears: `context/loop.md` "Superseded by plan"). `Q<N>` matches the terminal numbering and runs continuously across rounds with no gaps.
Expand Down Expand Up @@ -71,6 +78,7 @@ No question cap. If branches outgrow the session, hand off (save-point + resume
## Skip criteria

- Step 2 SKIPPED when Step 1.5 auto-detect routes to direct synthesis
- Step 2 assumption sweep SKIPPED on a ship-it exit: the user's yes deferred the open rows (`context/routing.md` "Small after all: ship it")
- Step 1.5 SKIPPED when user explicit-mode (`lock` forces synthesis; `me` forces Q&A loop)
- Step 3 confirmation gate SKIPPED only for `lock` (invoking it IS the confirmation); direct synthesis in `auto` still passes through it
- Step 3 **register** gate SKIPPED only when the run asked no question and wrote no register (`lock` synthesizing with no gap; `auto` routing to synthesize-directly with no open decision). Any question at all, whether asked, surfaced mid-synthesis, or blocked unattended, means a register exists and the gate applies. This is about the absence of questions, not about the action
Expand Down
4 changes: 3 additions & 1 deletion plugins/planning/skills/wayfind/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ session. Do not fabricate a map.
resolution comment lists them; it is closed at once with one *Decisions-so-far* pointer (the
work-mode step 5 sequence). Its open, deferred and blocked questions become candidate
decision items, and its self-answered facts are distilled into *Notes* as text, never as a
path. Sort every remaining uncertainty through the fog test: sharp → candidate decision
path. Its constraint ledger, its `## Starting point` line, and its session-shorthand glossary
ride into *Notes* the same way, so nothing the interview already asked is asked again. Sort
every remaining uncertainty through the fog test: sharp → candidate decision
item; foggy → *Not-yet-specified* prose. **No-fog bail-out:** if the survey
leaves *both* halves of the trigger unmet. Every uncertainty is already sharp, or the
whole effort fits one session. This effort does not need a map. STOP and route out
Expand Down
Loading