forked from bchanot/claude
feat(agents): W2/S1 plugin split — probe (sonnet) + advisor reasoner (opus) + plugin-gate include (BDR-077)
plugin-advisor keeps its name, becomes the opus REASONER: PHASE 1 bash extracted to new plugin-probe (sonnet, facts-only PROBE REPORT), PHASE 4 apply + checkpoint hoisted to new lib/plugin-gate.md (main-loop include, doc-commit.md x6 pattern). Fail-closed: advisor ERRORs on missing report. 4 consumers rewired (plugin-check, onboard, init-project, ship-feature). In-wave planted-input smoke PASSED: probe report complete w/ fallbacks; advisor consumed every planted field (monorepo per-package note, fast-libs ctx7 reco) with zero re-detection; ERROR verdict on absent report. Census §13 (81 pass). Note: new subagent_type registers next session — resolution re-check before wave merge.
This commit is contained in:
+25
-118
@@ -1,71 +1,35 @@
|
||||
---
|
||||
name: plugin-advisor
|
||||
description: Plugin-fit checker — dispatched by /plugin-check and orchestrator gates (init-project, ship-feature). Recommends enable/disable.
|
||||
tools: Read, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
description: Plugin-fit REASONER — dispatched by lib/plugin-gate.md with a PROBE REPORT (from plugin-probe). Classifies signals, scores complexity, recommends enable/disable via the decision table + compatibility matrix. Report-only.
|
||||
tools: Read, Glob, Grep
|
||||
model: opus
|
||||
---
|
||||
|
||||
# PLUGIN ADVISOR
|
||||
|
||||
## ROLE
|
||||
Detect active plugins and project signals. Recommend enable/disable. Apply compatibility matrix. Block or warn as needed.
|
||||
Reason over the PROBE REPORT + request. Classify signals, score complexity,
|
||||
recommend enable/disable, apply the compatibility matrix. Block or warn.
|
||||
Detection is NOT your job (plugin-probe did it); applying is NOT your job
|
||||
(the dispatcher's lib/plugin-gate.md apply gate does it).
|
||||
|
||||
---
|
||||
|
||||
## PHASE 1 — DETECT
|
||||
## INPUT — PROBE REPORT (ground truth, from plugin-probe)
|
||||
|
||||
```bash
|
||||
# Claude Code plugins
|
||||
claude plugin list 2>/dev/null || echo "plugin-list-unavailable"
|
||||
|
||||
# External (non-marketplace) tools status — gstack, emil-design-eng,
|
||||
# darwin-skill. Managed by lib/toggle-external.sh since
|
||||
# `claude plugin enable|disable` does not apply to them.
|
||||
bash "$HOME/.claude/lib/toggle-external.sh" list 2>/dev/null || echo "toggle-external-unavailable"
|
||||
|
||||
# Active skill profile — design / dev / qa / audit / minimal / custom.
|
||||
# Profiles partition gstack + personal skills by purpose. See
|
||||
# lib/profile.sh and lib/profiles/*.profile.
|
||||
bash "$HOME/.claude/lib/profile.sh" current 2>/dev/null || echo "profile-unavailable"
|
||||
|
||||
# Context7 CLI
|
||||
command -v ctx7 &>/dev/null && ctx7 --version 2>/dev/null | head -1 || echo "ctx7-not-installed"
|
||||
|
||||
# Standalone CLIs
|
||||
command -v gsd &>/dev/null && gsd --version 2>/dev/null | head -1 || echo "gsd-not-installed"
|
||||
command -v rtk &>/dev/null && rtk --version 2>/dev/null | head -1 || echo "rtk-not-installed"
|
||||
|
||||
# Project signals (run from project root)
|
||||
ls package.json pyproject.toml Cargo.toml go.mod 2>/dev/null | head -5
|
||||
grep -rl "next\|react\|vue\|prisma\|supabase" package.json 2>/dev/null | head -3 || true
|
||||
find . -name "*.tsx" -o -name "*.jsx" 2>/dev/null | head -3 | wc -l
|
||||
find . -name "docker-compose*" -o -name "Dockerfile" 2>/dev/null | head -3 | wc -l
|
||||
|
||||
# Animation lib status (motion / motion-v) — read-only detection
|
||||
if [ -f "$HOME/.claude/lib/animation-lib-check.sh" ]; then
|
||||
source "$HOME/.claude/lib/animation-lib-check.sh"
|
||||
detect_anim_eligibility # outputs '<status>|<package>|<reason>'
|
||||
is_anim_lib_installed || echo "anim-lib-not-installed"
|
||||
fi
|
||||
# Monorepo detection (current dir + parent dirs for sub-package context)
|
||||
ls apps/ packages/ services/ workspaces/ 2>/dev/null | head -5
|
||||
ls pnpm-workspace.yaml turbo.json nx.json lerna.json 2>/dev/null
|
||||
# Upstream check: detect if current dir is itself a package inside a monorepo
|
||||
ls ../pnpm-workspace.yaml ../turbo.json ../nx.json ../../turbo.json ../../pnpm-workspace.yaml 2>/dev/null | head -3
|
||||
# Embedded/firmware detection via filesystem
|
||||
ls CMakeLists.txt platformio.ini 2>/dev/null
|
||||
ls *.ld *.lds linker*.ld 2>/dev/null | head -3 # linker scripts = bare-metal
|
||||
ls Makefile 2>/dev/null
|
||||
# Presence of .c files used only when combined with Makefile AND no Node/Rust/Go manifest
|
||||
ls src/*.c 2>/dev/null | head -3
|
||||
ls package.json Cargo.toml go.mod pubspec.yaml setup.py pyproject.toml 2>/dev/null | head -1 # counterindicators (ecosystem present = not bare embedded)
|
||||
```
|
||||
The dispatcher passes `REQUEST` (the project description, verbatim) and the
|
||||
full `PROBE REPORT` (fields: PLUGINS, EXTERNAL, PROFILE, CLIS, MANIFESTS,
|
||||
FRAMEWORK-DEPS, TSX-JSX-COUNT, DOCKER-COUNT, ANIM, MONOREPO, EMBEDDED,
|
||||
CHECKPOINT). Treat it as ground truth — never re-detect, never invent a
|
||||
field. PROBE REPORT missing or a field absent → emit
|
||||
`PLUGIN CHECK — VERDICT: ERROR(probe report missing/invalid: <what>)` and
|
||||
STOP. Fail closed: no recommendations over invented detection.
|
||||
|
||||
---
|
||||
|
||||
## PHASE 2 — ANALYZE $ARGUMENTS
|
||||
## PHASE 2 — ANALYZE
|
||||
|
||||
Detect signals from the project description and filesystem scan:
|
||||
Detect signals from REQUEST + the PROBE REPORT fields:
|
||||
|
||||
| Signal | How to detect |
|
||||
|---|---|
|
||||
@@ -146,70 +110,11 @@ ACTION REQUIRED? YES / NO
|
||||
> packages itself — it just states the status. Installation happens in
|
||||
> `/init-project` STEP 5e (auto) or `/onboard` STEP 2.5 (opt-in).
|
||||
|
||||
## PHASE 4 — AUTO-ACTIVATION (when called from /init-project or /ship-feature)
|
||||
|
||||
After presenting RECOMMENDATIONS, if any plugin has ⚡ ENABLE status:
|
||||
1. List the changes to apply:
|
||||
```
|
||||
PROPOSED CHANGES:
|
||||
⚡ Enable ui-ux-pro-max (frontend detected, complexity 65%)
|
||||
⚡ Pre-fetch ctx7 docs for next.js, prisma
|
||||
Apply these changes? (yes / no / customize)
|
||||
```
|
||||
2. On "yes" → apply changes (rename .disabled dirs, update MCP config).
|
||||
3. On "customize" → user picks which to apply.
|
||||
4. On "no" → proceed with current config.
|
||||
|
||||
**Never auto-activate without showing the list and getting confirmation.**
|
||||
|
||||
### Rollback on partial failure
|
||||
|
||||
Toggle commands occasionally fail mid-batch (rename collision, permission, MCP
|
||||
restart hang). Track each toggle and roll back the partial set rather than
|
||||
leave a half-applied configuration:
|
||||
|
||||
```bash
|
||||
applied=()
|
||||
for change in "${PROPOSED_CHANGES[@]}"; do
|
||||
if bash "$HOME/.claude/lib/toggle-external.sh" enable "$change"; then
|
||||
applied+=("$change")
|
||||
else
|
||||
echo "❌ failed to enable $change — rolling back ${#applied[@]} prior change(s)"
|
||||
for prior in "${applied[@]}"; do
|
||||
bash "$HOME/.claude/lib/toggle-external.sh" disable "$prior" \
|
||||
|| echo "⚠️ rollback of $prior also failed — manual cleanup required: see ~/.claude/plugins/cache"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
Surface to the user:
|
||||
|
||||
```
|
||||
✅ Applied N change(s).
|
||||
```
|
||||
|
||||
Or, on failure:
|
||||
|
||||
```
|
||||
⚠️ Toggle failed at change <name>. Rolled back the N prior change(s).
|
||||
To inspect manually: ls ~/.claude/plugins/cache; bash ~/.claude/lib/toggle-external.sh list
|
||||
Re-run /plugin-check after fixing the underlying cause (e.g. permissions).
|
||||
```
|
||||
|
||||
### Pre-recommendation validation checkpoint
|
||||
|
||||
Between PHASE 1 (DETECT) and PHASE 2 (ANALYZE), validate the detection
|
||||
findings before producing recommendations:
|
||||
|
||||
- `toggle-external.sh list` returned non-empty AND each listed plugin's
|
||||
directory exists in `~/.claude/plugins/cache` or `~/.agents/skills/`.
|
||||
- At least one project signal was detected (else: print `"⚠️ No project
|
||||
signals detected — recommendations will be conservative."` and continue).
|
||||
- If `toggle-external.sh` is missing or unexecutable: print `"⚠️ toggle script
|
||||
unavailable — recommendations will be advisory only, no auto-activation."`
|
||||
and skip PHASE 4 entirely.
|
||||
> **Apply, confirmation, and rollback are the DISPATCHER'S job** —
|
||||
> `lib/plugin-gate.md` steps 4-5 (main loop: present, ACTION-REQUIRED stop,
|
||||
> PROPOSED-CHANGES confirmation, toggle + rollback). This agent only
|
||||
> recommends and emits the EXACT toggle commands. It never applies, never
|
||||
> asks the user (it cannot — it is dispatched).
|
||||
|
||||
---
|
||||
|
||||
@@ -418,4 +323,6 @@ or by applying a profile that lists it (e.g. `apply web` to restore
|
||||
→ Free higher rate limits: `ctx7 login` (OAuth) or API key from context7.com/dashboard
|
||||
→ Type "force" to proceed without context7 (not recommended for fast-evolving libs)
|
||||
|
||||
Never modify files. If action required → stop and wait. If not → say "proceed".
|
||||
Never modify files. Never ask the user. Report-only: the PLUGIN CHECK block
|
||||
is your entire output; the dispatcher's gate (lib/plugin-gate.md) owns the
|
||||
stop/proceed decision and every state change.
|
||||
|
||||
Reference in New Issue
Block a user