18 KiB
18 KiB
PLAN — superpowers-vendored (feat, ad-hoc dispatch) — r3 (after confirmation pass)
- r3 closes the confirmation pass (correctness CONCERNS(1)): MAJOR 1 — the
CLAUDE.global.md map keeps every skill identifier whole on one line (grep
is line-based); MINOR 2 —
always_onmechanism pinned: the python lock reader emits a third column,_dv_check_linkgets a 5th param, headers updated, a helper extracted ifcheck_vendored_skillswould exceed 5 locals; MINOR 3 — stale "uninstall || true" edge case deleted; MINOR 4 — settings.json edit moves to the orchestrator, AFTER criterion 2 is green (a disabled plugin + a failed fetch must never coincide); MINOR 5 — profile.sh comments located by grep, doctor pass line worded on what is proven. - r2 closes: correctness BLOCKER 1 (the CLAUDE.global.md map never spells the
colon form — criterion 3 greps it), MAJOR 2 (doctor-vendored gains an
always-on class driven by a lock field
always_on, so the 7 are link-checked instead of "parked"), MAJOR 3 + robustness MAJOR 1 (NO uninstall code in the installer — comment only, one-shot by the orchestrator after criterion 2 is green), MAJOR 4 + robustness MAJOR 3 (settings.json hand-edited: enabledPlugins key and extraKnownMarketplaces.superpowers-marketplace block removed, committed), MAJOR 5 + robustness MAJOR 2 + simplicity MAJOR 1 (detect_superpowers = one file test on the linked skill, no plugin fallback, no new global), simplicity MAJOR 2 (same: no installer uninstall), MINORs: session-start line deleted plainly, map trimmed to the four referenced skills, lock note kept to maintainer facts, summary line placement pinned, rollback step, mixed-version rollback note. - date: 2026-09-28 | contract: contracts/2026-09-28-superpowers-vendored-1357.md
- branch: feature/superpowers-vendored
- executors: 2 feater (sonnet-pinned), parallel, disjoint file sets
Ground truth (verified 2026-09-28)
- Plugin superpowers 6.4.1 installed at
~/.claude/plugins/cache/superpowers-marketplace/superpowers/6.4.1/(gitCommitSha 5bf4e78011075bcfc0dc295f0724994cd123ee71 = upstream tag v6.4.1 on obra/superpowers; raw files served athttps://raw.githubusercontent.com/obra/superpowers/<sha>/skills/<skill>/<file>, brainstorming/SKILL.md md5 identical local vs raw). Enabled in settings.json (superpowers@superpowers-marketplace: true), PROTECTED in lib/profile.sh, installed + enabled by install-plugins.sh STEP 5 (marketplace add, install_plugin, enable_plugin), summary line "ALWAYS ON … superpowers". Its hooks.json SessionStart (startup|clear|compact) injects using-superpowers (~3.6 KB) every start. - The 7 skills to vendor and their files (upstream layout
skills/<name>/): brainstorming: SKILL.md, spec-document-reviewer-prompt.md, visual-companion.md, scripts/frame-template.html, scripts/helper.js, scripts/server.cjs, scripts/start-server.sh, scripts/stop-server.sh writing-plans: SKILL.md, plan-document-reviewer-prompt.md subagent-driven-development: SKILL.md, implementer-prompt.md, re-review-prompt.md, task-reviewer-prompt.md, scripts/review-package, scripts/sdd-workspace, scripts/task-brief test-driven-development: SKILL.md, writing-good-tests.md requesting-code-review: SKILL.md, code-reviewer.md using-git-worktrees: SKILL.md writing-skills: SKILL.md, anthropic-best-practices.md, examples/CLAUDE_MD_TESTING.md, graphviz-conventions.dot, persuasion-principles.md, render-graphs.js, testing-skills-with-subagents.md Scripts are invoked upstream asbash scripts/<x>(SDD lines 137, 252, 290…; brainstorming visual-companion.md) → no exec bit needed. - Internal cross-references that will dangle (byte-for-byte text): writing-plans → superpowers:subagent-driven-development, superpowers:executing-plans (dropped), superpowers:using-git-worktrees; SDD → superpowers:finishing-a-development-branch ×4 (dropped), superpowers:using-git-worktrees, superpowers:requesting-code-review, executing-plans ×2; TDD → superpowers:writing-skills; writing-skills → superpowers:test-driven-development ×4, superpowers:systematic-debugging (dropped), using-superpowers, verification-before-completion.
lib/vendor-skills.shvendor_pinned_skills <lock-key> [refresh]: lock entry{source, commit (40 hex), path, skills: {name: [files]}, managed_by}; files must match[A-Za-z0-9._/-]+, no..; tmp+mv; skips existing files unlessrefresh. install-plugins.sh STEP 8e calls it for agent-skills and mengto-skills withEXT_SKILL_NAMESsymlink check; update-all.sh 7.3 calls it withrefresh. link.shEXTERNAL_SKILLS=(…)symlinksskills-external/<name>into~/.claude/skills/<name>; .gitignore listsskills/<name>(symlink) andskills-external/<name>/(vendored text) per external. lib/doctor-vendored.sh reads the lock + EXTERNAL_SKILLS generically.- lib/profile.sh:
PROTECTED_PLUGINS=("security-guidance@claude-code-plugins" "superpowers@superpowers-marketplace"); MANAGED_EXTERNALS is the allowlistsetparks — the 7 are NOT added (always on, like darwin-skill). - lib/detect-plugins.sh
detect_superpowers: plugin cache glob thenclaude plugin list. Consumers: hooks/session-start.sh:122 (+ 800passive), doctor.sh:225-228 (pass/fail "Superpowers plugin detected / not detected — orchestrators will fail") and :423 (+ 1500). superpowers:citers (personal): skills/ship-feature:103,117,176,237; skills/init-project:71,182,215,259; skills/tour:318; skills/deploy:515; skills/audit-delta:321; lib/analyze-before-plan.md:106; lib/capitalize-commit.md:20 (finishing-a-development-branch); agents/plugin-advisor.md:182. Prose mentions of finishing-a-development-branch: lib/capitalize-commit.md:68, lib/doc-commit.md:84, lib/analyze-before-plan.md:108, skills/gitflow:16,110. Docs: README.md:121 (component table), USAGE.md ×19 (plugin/cost narrative), agents/plugin-advisor.md ×19 (matrix, recommended sets, remedy :324), skills/profile/SKILL.md:59, install-plugins.sh:1210 summary.docs/superpowers/paths (CLAUDE.md, gitflow, onboard) stay: brainstorming and writing-plans still write there.- lib/tests: gitflow-test.sh mentions superpowers only through the purge path (unchanged). No suite asserts PROTECTED_PLUGINS content.
Approach
E1 — wiring (lock, installers, link, gitignore, profile, detect, doctor)
Files: plugins.lock.json, install-plugins.sh, update-all.sh, link.sh, .gitignore, lib/profile.sh, lib/detect-plugins.sh, hooks/session-start.sh, doctor.sh, lib/doctor-vendored.sh, lib/tests/doctor-vendored.test.sh, lib/vendor-skills.sh (header comment line only).
- plugins.lock.json: new entry
"superpowers"after"mengto-skills": sourcehttps://github.com/obra/superpowers, commit5bf4e78011075bcfc0dc295f0724994cd123ee71, pathskills,skills= the dict above (exact file lists), managed_bycurl,"always_on": true, note (maintainer facts only, history lives in CHANGELOG/BDR-106): "Seven superpowers skills vendored byte-for-byte at the v6.4.1 tag commit (obra/superpowers), always on (no profile lists them). Bump the commit deliberately. Scripts inside run asbash scripts/<x>, no exec bit needed. Upstream cross-references to the plugin prefix and to the 8 non-vendored skills stay in the text; CLAUDE.global.md Skill routing maps them." - install-plugins.sh STEP 5: delete the three superpowers lines (marketplace
add, install_plugin, enable_plugin) and replace with a 3-line comment
"Superpowers plugin removed 2026-09-28 (tier 2 of the skill-catalog prune):
its 7 wired skills are vendored in Step 8e (plugins.lock.json
'superpowers'); a still-cached plugin is uninstalled by hand once
(claude plugin uninstall superpowers@superpowers-marketplace), never here".
NO uninstall code in the installer (precedent: frontend-design, caveman).
Update the
enable_plugincomment (:490) to name only security-guidance. STEP 8e: heading/comment mention superpowers;EXT_SKILL_NAMES+= the 7;vendor_pinned_skills superpowersafter mengto. Summary: replace line ~1210 ("✅ superpowers — brainstorm/plan/implement/debug workflow", ALWAYS ON block) by "✅ superpowers skills — 7 vendored (brainstorming, writing-plans, subagent-driven-development, test-driven-development, requesting-code-review, using-git-worktrees, writing-skills), pinned v6.4.1, curl → symlink, no plugin, no session injection"; add one "at:" line right after the mengto "at:" line (~1234): "Superpowers skills at: ~/.claude/skills/{brainstorming,…}/ (symlink → skills-external)". - update-all.sh 7.3:
echo "── Updating superpowers skills (obra/superpowers)..."vendor_pinned_skills superpowers refresh; comment names it.
- link.sh EXTERNAL_SKILLS += the 7 (keep the array multi-line ≤ 80 chars).
- .gitignore: 7
skills/<name>lines next to the other external symlinks (:65-68 block) and 7skills-external/<name>/lines next to the mengto block (:203-207), each block with a one-line comment "superpowers, vendored (plugins.lock.json 'superpowers')". - lib/profile.sh: PROTECTED_PLUGINS keeps only security-guidance; every
comment naming superpowers as an always-on plugin (
grep -n superpowers lib/profile.sh, currently ~:22 and ~:65) reworded ("superpowers is vendored skills now, not a plugin"). - lib/detect-plugins.sh
detect_superpowers: exactly[ -f "$HOME/.claude/skills/brainstorming/SKILL.md" ](the linked vendored skill: proves vendored AND linked; no plugin cache glob, noclaude plugin list, no new global, no fallback). Comment: "superpowers = 7 vendored skills since 2026-09-28; the plugin is gone". A negative control (empty HOME) must return 1. 7b. lib/doctor-vendored.sh: lock entries may carry"always_on": true(thesuperpowersentry does). Skills of such an entry are expected LINKED whatever the active profile says (today every EXTERNAL_SKILLS name absent from the profile is reportedparked, link unchecked — the 7 are in no profile by design). Mechanism:_dv_lock_expectations(python) prints a THIRD columnname\tfile\t1for skills of analways_onentry (awk$1==n {print $2}in_dv_check_fileskeeps working unchanged);check_vendored_skillsreads the flag and passes it as a 5th parameter to_dv_check_link, which treats1as "expected linked whatever the profile says". Ifcheck_vendored_skillswould exceed 5 locals, extract the per-name dispatch into a helper (≤ 25 logic lines each). Update the file header ("A name absent from the profile is reported parked" → "… unless its lock entry is always_on") and the test header. Message unchanged for the linked case, fail ": symlink missing/wrong — run: make link" when absent. Add a caseALWAYS_ON_LINK_CHECKEDto lib/tests/doctor-vendored.test.sh (fixture entry with always_on true, name absent from the profile, link missing → fail line, neverparked). Document the field in lib/vendor-skills.sh's lock-shape header comment (one line: ignored by the vendor helper, read by doctor-vendored). - hooks/session-start.sh: delete line 122 (
detect_superpowers … + 800) outright — the banner's ALWAYS_ON list comes from detect_rtk + settings enabledPlugins (lines ~147-160), not from this call. doctor.sh :225-228: pass "superpowers: 7 skills vendored + linked (plugins.lock.json, v6.4.1)" / fail "superpowers skills not linked — run: make plugin && make link"; the pass line is worded on whatdetect_superpowersproves ("superpowers skills linked (brainstorming found); per-skill check under Vendored skills"); :423 delete the+ 1500line (comment: counted by the skill catalog stats). - settings.json: NOT an executor file any more — the orchestrator edits it after criterion 2 is green (see Orchestrator steps), so a disabled plugin never coincides with a failed fetch.
E2 — citers, routing map, docs
Files: skills/{ship-feature,init-project,tour,deploy,audit-delta,gitflow,profile}/SKILL.md, lib/{analyze-before-plan,capitalize-commit,doc-commit}.md, agents/plugin-advisor.md, CLAUDE.global.md, README.md, USAGE.md, CHANGELOG.md.
superpowers:<x>→<x>(bare) in ship-feature ×4, init-project ×4, tour:318, deploy:515, audit-delta:321, lib/analyze-before-plan.md:106, agents/plugin-advisor.md:182. Wording around them: "Invokebrainstorming(vendored superpowers skill)" on first mention per file, bare afterwards.- finishing-a-development-branch prose: lib/capitalize-commit.md:20 → "Orchestrators
that integrate via
gitflow finish(the upstream finishing-a-development-branch is not vendored)"; :68, lib/doc-commit.md:84, lib/analyze-before-plan.md:108, skills/gitflow:16,110 → say "upstream superpowers skill, not vendored here;gitflow finishis the only integration path" where they present it as available. - CLAUDE.global.md § Skill routing, after the "Before /clear or /compact"
line, ≤ 80 chars per line, about 4 lines, and NEVER the literal
"superpowers" followed by a colon (criterion 3 greps that string):
"- superpowers skills are vendored, called by bare name; an upstream
superpowersprefix means the bare skill. Not vendored: executing-plans → subagent-driven-development; finishing-a-development-branch →gitflow finish(human signal); systematic-debugging → bugfix; verification-before-completion → the verifier gates." Every skill identifier stays WHOLE on its line (criterion 7 grepsfinishing-a-development-branch,executing-plans,systematic-debuggingline by line); wrap at spaces only. - README.md:121 row → "Superpowers skills | Vendored (7, always on) | brainstorming, writing-plans, subagent-driven development, TDD, code review request, git worktrees, writing-skills — pinned v6.4.1 in plugins.lock.json, no plugin, no session injection | obra/superpowers". README:208 unchanged.
- USAGE.md: every line presenting superpowers as a plugin to keep ON/OFF or as ~800 t passive (184-185, 589, 650, 751, 864, 959-965, 971, 995, 1018) → "skills superpowers (vendorisés, toujours actifs, 0 t passif)" or the equivalent in the sentence's French; keep the narrative otherwise.
- agents/plugin-advisor.md: rows 177-182 (compat matrix) → "superpowers
skills (vendored)" wording, drop the plugin-dev overlap row's "plugin"
framing; recommended-set table 190-198: replace "superpowers" by
"(superpowers skills always on)" in the ON column and subtract ~800 t from
each cost; :80, :146, :242, :254, :298 reword; :324 remedy → "Superpowers
skills missing →
make plugin(vendors them) thenmake link". - skills/profile/SKILL.md:59: "Always-on plugins (
security-guidance) and the vendored superpowers skills are never toggled by a profile". - CHANGELOG
[Unreleased]: Changed (superpowers plugin → 7 vendored skills, pinned, always on;superpowers:citers renamed), Removed (plugin, its 8 duplicate skills, the SessionStart injection), Known residual (upstream cross-references inside the vendored text; CLAUDE.global.md map).
Orchestrator steps
- Criterion 2 vendors + links live (network fetch of 30 files); only when every file is present and byte-identical (c2.py) does the next step run.
- Then the orchestrator edits settings.json by hand: remove the
"superpowers@superpowers-marketplace": truekey fromenabledPluginsand the wholeextraKnownMarketplaces."superpowers-marketplace"block, nothing else; validate withpython3 -c 'import json;json.load(open("settings.json"))'. - Then, one shot by hand:
claude plugin uninstall superpowers@superpowers-marketplaceandclaude plugin marketplace remove superpowers-marketplace; re-checkgit diff settings.jsonafterwards (the CLI must not have re-added anything), then criterion 8. - Rollback if criterion 8 fails:
claude plugin marketplace add obra/superpowers-marketplace && claude plugin install superpowers@superpowers-marketplace,git checkout -- settings.json, stop and report. - Verifier; security; commit; BDR-106 + journal.
Edge cases
- Mid-migration machine (plugin cached, skills not yet vendored): doctor fails "not vendored or linked — run make plugin && make link"; the user uninstalls the plugin by hand (CHANGELOG says so). No fallback that could print "vendored" for a plugin-only machine.
- Mixed-version rollback (an older checkout re-installs the plugin while the 7 symlinks are still linked → duplicate descriptions): CHANGELOG note "after a rollback, delete skills/<7> symlinks or re-run the new make plugin".
- The running session keeps the plugin's
superpowersskills until restart; the bare names appear aftermake link+ a new session. - Fresh clone: link.sh symlinks a non-existent skills-external dir only if
present (existing
[ -d ]guard). - skill-routing-census live run gains 7 descriptions: brainstorming's "You MUST use this before any creative work" vs personal descriptions — the suite's live FAIL threshold must not trip (check by running it).
Tests
- make test suite= vendor-skills, doctor-vendored (with the new ALWAYS_ON_LINK_CHECKED case), doctrine-citers, skill-routing-census, profile-default, profile-set-managed.
- shellcheck on every touched shell file.
Disposition (RELATED MEMORY)
- honors BDR-102 / BDR-104 — vendor over plugin, shared helper, pinned commit, byte-for-byte text.
- honors BDR-105 — tier 2 of the prune decision.
- honors BDR-065 — docs/superpowers transient path unchanged.
- honors LRN-178 — no new top-level
source; detect-plugins reads a path. - honors BDR-077 — requesting-code-review's reviewer dispatch keeps the model-routing note in ship-feature/init-project.