/which-shape
Recommend an operating loop, not a single tool. /which-skill answers
"which skill?" after the work shape is clear. /which-shape answers
"what kind of work are we doing?"
This is advisory-only in v1. It never invokes the recommended skills.
Forms
Before invoking, check the conversation for the discriminating dimensions — recurrence? approved proposal in hand? unknown or inherited repo? scope width? durable choice? — and carry those words verbatim into the task string. The matcher is keyword-based, so the paraphrase IS the routing decision.
/which-shape "this inherited repo feels slow and chaotic"
/which-shape "unknown project; where should an agent start?"
/which-shape "this bug keeps coming back"
Running the script is mandatory — the recommendation must come from a
real run, never composed from this file. Paste the script's
Project context: and Confidence: ... (score=N) lines verbatim in
your reply.
PROJECT_ROOT="$PWD"
(
cd "$PROJECT_ROOT/.agents/skills/which-shape"
python3 scripts/route.py \
"this inherited repo feels slow and chaotic" \
--project-root "$PROJECT_ROOT"
)
Use --json for machine-readable output and --skip-log for tests.
Treat the script output as a lexical prior, not the decision. If conversation evidence contradicts the cue match (negation, paraphrase, sarcasm), override it, say so, and name the cue collision in your reply so telemetry can see the override.
When a status projection exists (.engineering/local/status.json, ADR
0037 — generated by scripts/status.py), the rationale additionally
cites up to three projection-derived signals (pending approvals, stale
artifacts, staged queue items, in-flight plans). The live
project-context read stays authoritative: a stale or malformed
projection is dropped silently, and with the file absent the output is
byte-identical to an ungrounded run. --status <path> overrides the
default location.
Output
The recommendation includes:
- shape id and title;
- confidence and rationale;
- first next command;
- short loop sequence;
- stop/reassess condition;
- alternatives.
- an on-demand handoff for the first skill plus any companions declared by the shape, with exact local guide/tool paths, shared source inventory, validated language/fact/outcome capability rows for that closure, and a fresh non-context-sub-agent default;
- a pinned ambient-install command only as an explicit optional alternative when every selected closure member has passed install evidence; otherwise the output reports why that optional path is unavailable.
If the script reports confidence: low — or any rationale line reads
"fallback shape candidate" — do not present a single shape. Present the
top 2-3 alternatives by score and ask one discriminating question
(see the pre-run dimensions under Forms) before routing.
Registry
The explicit shape registry lives in shapes.json — the sole shape
inventory; this file deliberately does not mirror the list. Keep it
small and loop-level. Do not mirror the whole skill catalog.
When adding or materially repurposing skills, run
/check-ecosystem-consistency and review whether shapes.json needs an
update. Add a skill to a shape only when it changes the operating loop;
purely tactical skills can stay out after that review is captured in the
ecosystem state.
Boost weights are registry data too: every shape declares a boost:
block in shapes.json (simple cues/weight/rationale, or a small
schema-validated rules form for conditional boosts; boost: {} is an
explicit opt-out), plus the narrow_signal and context_exempt flags.
The scorer holds no per-shape table — adding a shape never requires
editing scripts/route.py. After editing shapes.json, run
route.py --validate — it checks the schema, including every boost
block.
Project Context
The router reads .engineering/project/adapter.yml,
.engineering/project/profile.yml, and
.engineering/project/open-questions.md when present.
Missing project context is a routing signal, not a universal blocker.
Broad unknown-project prompts should route to project-intake; narrow
typos and concrete bugs should still route directly.
Telemetry
The router logs event_kind: recommendation events to
.claude/skill-use/log.jsonl with outcome: unscored by default — a
recommendation is not evidence of usefulness at the moment it is made.
Projection and compaction keep these separate from actual skill-run
useful rates, and the compaction digest's overridden% counts only
scored events.
The correction path runs when a human notices a misroute: rerun the same route with an explicit outcome (the rerun appends a second recommendation event; it does not amend the first):
cd .agents/skills/which-shape
python3 scripts/route.py \
"this inherited repo feels slow and chaotic" \
--outcome overridden \
--human-override "wrong-shape: should have started with project-intake"
Relationship To /which-skill
Use /which-shape first when the operating mode is unclear. Use
/which-skill once the shape is known and the question is tactical.
Bad pattern: asking /which-skill to decide how to onboard or stabilize
an unknown repo. That is exactly what /which-shape exists to handle.