v-adr
Capture one genuine architecture decision as a thin, human-confirmed ADR under docs/superpowers/adr/NNNN-slug.md — decision-with-alternatives-and-consequences,…
Classify one change request before any work starts — resolve, score, and write plus COMMIT the pre-eval triage record, then print the tier (DIRECT | SCOPED | FULL) with the predicates that decided it. DIRECT means the human implements in place, runs the test floor, and commits
> /plugin marketplace add procoders/superpowers-v > /plugin install superpowers-v@procoders
How it fires
How this command gets triggered: by you, by Claude, or both.
/v-triageContext preview
What this command does when you run it.
Classify one change request before any work starts — resolve, score, and write plus COMMIT the pre-eval triage record, then print the tier (DIRECT | SCOPED | FULL) with the predicates that decided it. DIRECT means the human implements in place, runs the test floor, and commits
description: Classify one change request before any work starts — resolve, score, and write plus COMMIT the pre-eval triage record, then print the tier (DIRECT | SCOPED | FULL) with the predicates that decided it. DIRECT means the human implements in place, runs the test floor, and commits the change together with its record.
You are running **`/v:triage`** — the **entry point** to Compound V's sizing engine.
`scripts/compound-v-preeval.py` and its five siblings are ~10,400 lines of deterministic scoring that, until this command existed, **nothing ever called**: `docs/superpowers/pre-eval/` had never appeared in this repository's git history and no run had ever been bound to a record. Every other v3.0 mechanism — the validator's `triage` block, the Stop-hook coverage gate, the outcome stream, the circuit breaker — consumes a record that only Phase T produces.
The argument is `{{args}}`.
The `scripts/` this command calls ship with the plugin — they are not files in your own repository. Resolve the plugin root once per session before calling any of them:
CV="${CLAUDE_PLUGIN_ROOT:-$(ls -d "$HOME"/.claude/plugins/cache/*/superpowers-v/*/ 2>/dev/null | sort -V | tail -1)}"
CV="${CV:-$PWD}"; CV="${CV%/}"`CLAUDE_PLUGIN_ROOT` is set for hooks but is not set in this Bash environment, so treat it as a hint, never the whole answer — the fallback line covers an installed plugin cache or a checkout of this repo.
`hooks/triage-prompt-nudge.sh` fires on `UserPromptSubmit` and runs **the same subcommand Phase T runs below**, so a change request that arrives as an ordinary prompt is usually already sized and already has a record — written, bound to the session, and **uncommitted**, because a hook must not run git. Before scoring, check whether that record exists and covers this work:
ls -t docs/superpowers/pre-eval/*.json 2>/dev/null | head -5
If one carries this session's id, **do not mint a second**: commit it (step T3) and go. A record per prompt is how the outcome stream the circuit breaker reads stops meaning anything. Run Phase T when the hook did not fire — a slash-command invocation, a second request in the same session, or any session the hook was not registered in.
As of **v3.4.1 a request needing T3 is no longer one of those cases**: the hook finishes the classify itself with the headless one-shot (see T2) and records a real tier. It falls back to its reminder only when no classifier could be RUN at all — no `claude`/`codex` CLI on the machine, or one that hung past the cap — and that reminder is the signal to run Phase T here.
`/v:triage <request>` is **Phase T** — resolve localization, classify, score, write **and commit** the record, then print the tier and predicates 1-6. Run it before any work starts, when no record already covers the request.
DIRECT means "implement in place, run the floor, commit on the branch". That commit is an **ordinary `git commit`**: make the edit, run the test floor, commit it together with the triage record, and let review and the human be the enforcement they already are. There is no separate landing gate — the triage record and the Stop-hook coverage gate are what bind the change to its decision.
SCOPED and FULL are unchanged: they still require a human offer and acceptance, then `/v:orchestrate` and `/v:dispatch`.
**Never re-spell a decision string or a tier token.** `DECISION_FASTPATH` / `DECISION_SCOPED` / `DECISION_FULL` and the `DECISION_TO_TIER` map live in `scripts/compound-v-preeval.py`; Phase T reads them by calling the engine's own `triage` subcommand. A duplicated wire vocabulary is how the two halves of this release drift apart, and the one ratified exception (a sibling analyser consuming the value as JSON off a record, with a selftest asserting equality) does not apply here.
The same rule governs the `sensitive` set: it comes from the taxonomy via `compound-v-taxonomy.match_auto_route()`, **never** from a list written here. `MANDATORY_SENSITIVE` in that module is the code-level floor that keeps a taxonomy which forgets the two policy files from re-opening the self-widening hole; this command adds nothing to it.
---
| # | Predicate | Evaluated | |---|---|---| | 1 | Tier is `DIRECT` and **no override fired** | Phase T, from the record's `decision` + `override_fired` | | 2 | Exactly one resolved path, and it is a **literal** | Phase T, via the engine's own `_is_single_literal_path` | | 3 | Taxonomy present and **digest-matched**; never a fail-closed `unknown` band | Phase T, against the record's pinned snapshot | | 4 | Path matches the taxonomy's `auto_route_allow` | Phase T, via `match_auto_route` | | 5 | Path matches **no** entry in the `sensitive` set | Phase T, via `match_auto_route` (taxonomy + mandatory floor) | | 6 | **No test file touched** | Phase T, on the resolved path |
Predicates 1-6 decide *membership*, and Phase T reports them for every record — a DIRECT change gets the six as evidence, and then commits ordinarily.
---
git rev-parse --show-toplevel
printf '%s\n' "${CLAUDE_CODE_SESSION_ID:-}"Read what that prints before running T2 — it is what the record binds, and its consequences are under "On the session id" below.
The whole of Phase T is a subcommand of the engine. Put the request text in `V_TRIAGE_REQUEST` (never on argv: a request is arbitrary text, it has to survive shell quoting, and argv is visible to every process on the machine) and run this from the repo root:
V_TRIAGE_REQUEST='<the request text>' python3 "$CV/scripts/compound-v-preeval.py" triage \
--request-env V_TRIAGE_REQUEST --repo . \
--session-id "${CLACompound V — a multi-model coding sidekick for Superpowers, running on Claude Code. You describe a feature. Claude sizes the request, plans it, splits it into non-overlapping pieces, and hands each piece to a worker in its own isolated worktree.
Capture one genuine architecture decision as a thin, human-confirmed ADR under docs/superpowers/adr/NNNN-slug.md — decision-with-alternatives-and-consequences,…
Re-run the collect + scope-gate + review tail of a Compound V run by run-id. Normalizes each job's output into results/<id>.json, re-runs the git-derived scope…
Execute a Compound-V-ready plan, manifest, or run-id on Engine C — the native Workflow dispatch engine. Accepts a bare plan path (auto-materializes the…
Drive an EPIC — chain several features into one autonomous, resumable, dependency-ordered build on a single branch. Each feature runs through the FULL v1.0…
Initialize Compound V in this project — detect backends and capabilities (Codex, Context7, required skills/agents), walk through any missing installs one at a…
(Re)index docs/superpowers prose into the local V-memory cache so recall is current. Incremental by file hash; runs fully offline (FTS5, pure stdlib).…