From 18f8c898f8036c8367e3f82be14e111e1a79e56e Mon Sep 17 00:00:00 2001 From: bastien Date: Mon, 28 Sep 2026 14:54:52 +0200 Subject: [PATCH 1/3] feat(superpowers): vendor the 7 wired skills at v6.4.1, drop the plugin plugins.lock.json gains a superpowers entry (obra/superpowers @ 5bf4e78, path skills, per-skill file lists, always_on) that lib/vendor-skills.sh fetches byte-for-byte: brainstorming, writing-plans, subagent-driven-development, test-driven-development, requesting-code-review, using-git-worktrees, writing-skills. install-plugins STEP 8e vendors it, update-all refreshes it at the pin, link.sh links the seven, .gitignore ignores them. The plugin is no longer installed or protected: its 8 other skills duplicated personal flows and its SessionStart injection cost ~900 tokens per start, clear and compact. detect_superpowers is one file test on the linked skill; doctor and session-start stop charging the injection. doctor-vendored gains an always_on class (third lock column) so always-on externals are link-checked instead of reported parked. --- .gitignore | 23 ++++++++++ doctor.sh | 10 ++--- hooks/session-start.sh | 3 +- install-plugins.sh | 36 ++++++++------- lib/detect-plugins.sh | 12 ++--- lib/doctor-vendored.sh | 73 ++++++++++++++++++++++--------- lib/profile.sh | 14 +++--- lib/tests/doctor-vendored.test.sh | 33 +++++++++++--- lib/vendor-skills.sh | 3 ++ link.sh | 4 +- plugins.lock.json | 17 +++++++ update-all.sh | 10 +++-- 12 files changed, 170 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index aa05165..30f5f05 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,15 @@ skills/scroll-scrubbed-visual-sequence skills/scroll-scrubbed-word-reveal skills/scroll-progress-timeline +# superpowers, vendored (plugins.lock.json 'superpowers') +skills/brainstorming +skills/writing-plans +skills/subagent-driven-development +skills/test-driven-development +skills/requesting-code-review +skills/using-git-worktrees +skills/writing-skills + # Impeccable — NOT a symlink: `impeccable skills install --scope=global` # writes the skill dir (and its ~15 MB engine binary) straight in through the # ~/.claude/skills symlink. Machine-owned, regenerated by make plugin/update. @@ -206,6 +215,20 @@ skills-external/scroll-scrubbed-visual-sequence/ skills-external/scroll-scrubbed-word-reveal/ skills-external/scroll-progress-timeline/ +# superpowers, vendored (plugins.lock.json 'superpowers') — machine-owned, +# curl'd at the commit pinned in plugins.lock.json by install-plugins.sh +# Step 8e (when absent) and re-fetched at the SAME commit by update-all.sh, +# through the shared lib/vendor-skills.sh helper. Not vendored: this is a +# pin, not a tracked snapshot — bump the commit deliberately to pick up an +# upstream edit. +skills-external/brainstorming/ +skills-external/writing-plans/ +skills-external/subagent-driven-development/ +skills-external/test-driven-development/ +skills-external/requesting-code-review/ +skills-external/using-git-worktrees/ +skills-external/writing-skills/ + # 21st.dev skill pack — machine-owned: `21st skills install` output, staged by # install-plugins.sh Step 8.7 (the installer refuses to write through the # ~/.claude/skills symlink, so it runs under a throwaway HOME and the skills diff --git a/doctor.sh b/doctor.sh index e0b430a..2712d1b 100644 --- a/doctor.sh +++ b/doctor.sh @@ -223,9 +223,9 @@ else fi if detect_superpowers; then - pass "Superpowers plugin detected" + pass "superpowers skills linked (brainstorming found); per-skill check under Vendored skills" else - fail "Superpowers not detected — orchestrators (/init-project, /ship-feature) will fail" + fail "superpowers skills not linked — run: make plugin && make link" fi if detect_context7; then @@ -417,10 +417,10 @@ SKILL_DESC_TOKENS=$((SKILL_DESC_CHARS / 4)) # Plugin passive cost estimates (tokens) — session-start injections and # hook prompts that never show up as a skill description above. gstack, # context7 (find-docs) and graphifyy dropped 2026-09-28 (skill-catalog -# prune): their skills sit under ~/.claude/skills and are already counted -# by the stats above — a separate constant here double-counted them. +# prune); superpowers dropped the same day (tier 2, vendored instead): +# their skills sit under ~/.claude/skills and are already counted by the +# stats above — a separate constant here double-counted them. PLUGIN_TOKENS=0 -if detect_superpowers 2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 1500)); fi if detect_uiux_pro_max 2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 670)); fi TOTAL_TOKENS=$((CLAUDE_MD_TOKENS + SKILL_DESC_TOKENS + PLUGIN_TOKENS)) diff --git a/hooks/session-start.sh b/hooks/session-start.sh index 4bc1c2e..3ab0237 100644 --- a/hooks/session-start.sh +++ b/hooks/session-start.sh @@ -118,8 +118,9 @@ esac # Quick passive token cost estimate # Only count plugins that are ACTIVE (detected as ON), not just installed +# superpowers dropped 2026-09-28 (tier 2 of the skill-catalog prune): its +# 7 vendored skills are counted by the skill catalog, not a plugin cost. _passive_t=0 -detect_superpowers 2>/dev/null && _passive_t=$((_passive_t + 800)) # Token costs for toggle plugins — map display name to cost declare -A _plugin_costs=( diff --git a/install-plugins.sh b/install-plugins.sh index e9dfc67..5e2a0a0 100644 --- a/install-plugins.sh +++ b/install-plugins.sh @@ -487,8 +487,8 @@ install_plugin() { # copies the plugin into ~/.claude/plugins/cache — it does NOT register # it in settings.json's enabledPlugins map. Without an explicit enable, # the plugin sits dormant. Use this for plugins that should be ALWAYS ON -# (security-guidance, superpowers). Idempotent: skips if already -# present in enabledPlugins. +# (security-guidance). Idempotent: skips if already present in +# enabledPlugins. enable_plugin() { local name="$1" local source="$2" @@ -531,13 +531,10 @@ install_plugin "pr-review-toolkit" "claude-code-plugins" echo "" -# Superpowers (always on) -info "Adding Superpowers marketplace..." -claude plugin marketplace add obra/superpowers-marketplace 2>/dev/null || true -install_plugin "superpowers" "superpowers-marketplace" -enable_plugin "superpowers" "superpowers-marketplace" - -echo "" +# 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 # UI/UX Pro Max (toggle) info "Adding UI/UX Pro Max marketplace..." @@ -909,21 +906,25 @@ fi echo "" # ── Step 8e: Agent Skills (addyosmani/agent-skills) + Mengto scroll -# skills (MengTo/Skills) — both commit-pinned, vendored the emil-design-eng -# way (curl → skills-external//, symlinked by link.sh) through the -# shared lib/vendor-skills.sh helper. Shas/paths/file-lists live in -# plugins.lock.json ("agent-skills" / "mengto-skills" entries), never -# hardcoded here. -echo "── Step 8e: Agent Skills + Mengto scroll skills (pinned commit) ──" +# skills (MengTo/Skills) + superpowers (obra/superpowers) — all +# commit-pinned, vendored the emil-design-eng way (curl → +# skills-external//, symlinked by link.sh) through the shared +# lib/vendor-skills.sh helper. Shas/paths/file-lists live in +# plugins.lock.json ("agent-skills" / "mengto-skills" / "superpowers" +# entries), never hardcoded here. +echo "── Step 8e: Agent Skills + Mengto scroll skills + superpowers (pinned commit) ──" echo "" # shellcheck source=lib/vendor-skills.sh disable=SC1091 source "$REPO/lib/vendor-skills.sh" EXT_SKILL_NAMES=(observability-and-instrumentation deprecation-and-migration ci-cd-and-automation scroll-world-storytelling build-threejs-scroll-worlds scroll-scrubbed-visual-sequence scroll-scrubbed-word-reveal - scroll-progress-timeline) + scroll-progress-timeline brainstorming writing-plans + subagent-driven-development test-driven-development + requesting-code-review using-git-worktrees writing-skills) vendor_pinned_skills agent-skills vendor_pinned_skills mengto-skills +vendor_pinned_skills superpowers for _ext_skill in "${EXT_SKILL_NAMES[@]}"; do if [ -L "$HOME/.claude/skills/$_ext_skill" ]; then ok "$_ext_skill symlink OK" @@ -1207,7 +1208,7 @@ echo "" echo " ALWAYS ON (installed at user scope):" echo " ✅ security-guidance — regex hints on Edit/Write + out-of-band LLM reviews on commit/push (Stop review off via ENABLE_STOP_REVIEW=0; quota, not context) [claude-code-plugins]" echo " ✅ rtk — token compression hook (0 tokens)" -echo " ✅ superpowers — brainstorm/plan/implement/debug workflow" +echo " ✅ 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" echo "" echo " TOGGLE (plugin state = settings.json enabledPlugins; skills/CLIs = profiles):" echo " 🔄 gstack — disabled by default (toggle: lib/toggle-external.sh enable gstack)" @@ -1232,6 +1233,7 @@ echo " Frontend Design at: ~/.claude/skills/frontend-design/ (symlink → skill echo " Design Motion Principles at: ~/.claude/skills/design-motion-principles/ (symlink → skills-external)" echo " Agent Skills trio at: ~/.claude/skills/{observability-and-instrumentation,deprecation-and-migration,ci-cd-and-automation}/ (symlink → skills-external)" echo " Mengto scroll skills at: ~/.claude/skills/{scroll-world-storytelling,build-threejs-scroll-worlds,scroll-scrubbed-visual-sequence,scroll-scrubbed-word-reveal,scroll-progress-timeline}/ (symlink → skills-external)" +echo " Superpowers skills at: ~/.claude/skills/{brainstorming,writing-plans,subagent-driven-development,test-driven-development,requesting-code-review,using-git-worktrees,writing-skills}/ (symlink → skills-external)" echo " npx skills at: ~/.agents/skills/ (symlinked into ~/.claude/skills/)" echo "" echo " → Restart Claude Code — plugins load automatically" diff --git a/lib/detect-plugins.sh b/lib/detect-plugins.sh index 638904c..6707450 100644 --- a/lib/detect-plugins.sh +++ b/lib/detect-plugins.sh @@ -16,14 +16,10 @@ detect_rtk() { } detect_superpowers() { - # Fast check: filesystem (plugin cache) - local cache_dir="$HOME/.claude/plugins/cache" - if [ -d "$cache_dir" ]; then - compgen -G "$cache_dir"/*superpowers* &>/dev/null && return 0 - fi - # Slow fallback: CLI (only if fast check fails) - claude plugin list 2>/dev/null | grep -qi "superpowers" && return 0 - return 1 + # superpowers = 7 vendored skills since 2026-09-28; the plugin is gone. + # One file test on the linked vendored skill: proves vendored AND + # linked in one shot — no plugin cache glob, no `claude plugin list`. + [ -f "$HOME/.claude/skills/brainstorming/SKILL.md" ] } diff --git a/lib/doctor-vendored.sh b/lib/doctor-vendored.sh index 6cd9602..acbfcf5 100644 --- a/lib/doctor-vendored.sh +++ b/lib/doctor-vendored.sh @@ -5,8 +5,8 @@ # EXTERNAL_SKILLS array). doctor.sh's "GStack submodule" section only # covers the gstack submodule — this covers the OTHER external skill # packs (emil-design-eng, the agent-skills trio, the five Mengto scroll -# skills, and any name link.sh links with no lock entry at all, e.g. -# frontend-design, design-motion-principles). +# skills, the seven superpowers skills, and any name link.sh links with +# no lock entry at all, e.g. frontend-design, design-motion-principles). # # One entry point, `check_vendored_skills # [profile_file]`, sourced and called by doctor.sh. Two things checked @@ -21,7 +21,9 @@ # is passed — the "could not resolve the active profile" case), # the /skills/ symlink points at # /skills-external/. A name absent from the profile is -# reported parked, not failed. +# reported parked, not failed — unless its lock entry is +# "always_on": true (the superpowers entry is), in which case the +# symlink is checked regardless of the profile (see _dv_check_link). # # Lock parsing via python3 argv (never string-spliced) — same pattern as # lib/vendor-skills.sh's _vendor_read_lock. link.sh's EXTERNAL_SKILLS @@ -61,11 +63,14 @@ fi # _dv_lock_expectations — prints "\t" for every # skill named under a plugins.lock.json entry whose "managed_by" is -# "curl": a bare list defaults each name to ["SKILL.md"]; a dict names -# its own per-skill file list; an entry with neither (the -# emil-design-eng single-file "path" shape) is itself the skill name, -# file "SKILL.md" (the literal "path" value is upstream layout, not the -# local dest — never used here). Reads the lockfile via argv only. +# "curl", plus a THIRD column "\t1" when that entry is "always_on": true +# (the superpowers entry is) — read by _dv_is_always_on, ignored by the +# $1==n {print $2} awk in _dv_check_files: a bare list defaults each name +# to ["SKILL.md"]; a dict names its own per-skill file list; an entry +# with neither (the emil-design-eng single-file "path" shape) is itself +# the skill name, file "SKILL.md" (the literal "path" value is upstream +# layout, not the local dest — never used here). Reads the lockfile via +# argv only. # Every curl-managed entry's shape is validated ("skills" null, a list # of str, or a dict of str -> list of str; "path" a str when present) # BEFORE it is used, so a malformed entry is the same clean failure as @@ -118,12 +123,13 @@ for key, entry in data.items(): sys.exit(1) if not valid_skills(skills): sys.exit(1) + suffix = "\t1" if entry.get("always_on") is True else "" if skills is None: - print(f"{key}\tSKILL.md") + print(f"{key}\tSKILL.md{suffix}") continue for name, files in skill_files(skills).items(): for file in files: - print(f"{name}\t{file}") + print(f"{name}\t{file}{suffix}") PY } @@ -196,16 +202,30 @@ allowlist — skipped" [ "$all_ok" -eq 1 ] } -# _dv_check_link — when -# is non-empty and does not list , reports it -# parked (info), not failed. Otherwise (listed, or no was -# passed — active profile could not be resolved, every external is then -# expected linked) checks the /skills/ symlink points -# at /skills-external/. +# _dv_is_always_on — true when (the +# "\t[\t1]" lines from _dv_lock_expectations) carries the +# always_on third column for 's lock entry. +_dv_is_always_on() { + local name="$1" lock_out="$2" + awk -F'\t' -v n="$name" '$1 == n && $3 == 1 { found=1 } \ + END { exit !found }' <<< "$lock_out" +} + +# _dv_check_link — +# when is "1" (the name's lock entry is "always_on": true), +# the symlink is checked whatever says — never parked. +# Otherwise, when is non-empty and does not list , +# reports it parked (info), not failed. Otherwise (listed, always_on, or +# no was passed — active profile could not be resolved, +# every external is then expected linked) checks the +# /skills/ symlink points at +# /skills-external/. _dv_check_link() { - local claude_home="$1" repo="$2" name="$3" profile_file="$4" + local claude_home="$1" repo="$2" name="$3" profile_file="$4" \ + always_on="$5" local link target label - if [ -n "$profile_file" ] && ! _dv_profile_has "$profile_file" "$name"; then + if [ "$always_on" != "1" ] && [ -n "$profile_file" ] \ + && ! _dv_profile_has "$profile_file" "$name"; then label="$(basename "$profile_file" .profile)" info "$name: parked by profile $label" return @@ -220,6 +240,20 @@ lib/profile.sh apply )" fi } +# _dv_check_name — +# per-name dispatch for check_vendored_skills's loop: files first (the +# link check runs only when every expected file is present, same as +# before), then the symlink, passing _dv_is_always_on's verdict as +# _dv_check_link's 5th param. +_dv_check_name() { + local repo="$1" claude_home="$2" name="$3" profile_file="$4" lock_out="$5" + local always_on="" + _dv_is_always_on "$name" "$lock_out" && always_on=1 + _dv_check_files "$repo" "$name" "$lock_out" \ + && _dv_check_link "$claude_home" "$repo" "$name" "$profile_file" \ + "$always_on" +} + # check_vendored_skills [profile_file] — see the # file header. Either the lock or link.sh being unreadable (or a # malformed lock entry — _dv_lock_expectations rc 1) is a warn, never a @@ -251,7 +285,6 @@ check skipped" item-name allowlist — skipped" continue fi - _dv_check_files "$repo" "$name" "$lock_out" \ - && _dv_check_link "$claude_home" "$repo" "$name" "$profile_file" + _dv_check_name "$repo" "$claude_home" "$name" "$profile_file" "$lock_out" done <<< "$names" } diff --git a/lib/profile.sh b/lib/profile.sh index f4d0618..8dbb0d5 100755 --- a/lib/profile.sh +++ b/lib/profile.sh @@ -18,8 +18,10 @@ # and MCPs in the MANAGED_* allowlists are disabled when the profile # does not list them — nothing outside those lists is ever auto-toggled. # -# Always-on plugins (never toggled by `set`): security-guidance, -# superpowers + rtk hook + .claude internal. The script refuses to disable +# Always-on plugins (never toggled by `set`): security-guidance + rtk +# hook + .claude internal. superpowers is vendored skills now, not a +# plugin (never in PROTECTED_PLUGINS, never in MANAGED_EXTERNALS — same +# always-on class as darwin-skill). The script refuses to disable # anything in PROTECTED_PLUGINS. # # Usage: @@ -61,9 +63,10 @@ DEFAULT_PROFILE="full" # profile in force when none is selected (cache absent, source "$(dirname "${BASH_SOURCE[0]}")/gstack-removed.sh" # Plugins that are toggle-managed by `set`. Anything NOT in this list is -# never auto-disabled — protects always-on plugins (security-guidance, -# superpowers) and unrelated user plugins. Add a plugin here only when its -# enabled state is meaningfully driven by task type. +# never auto-disabled — protects always-on plugins (security-guidance; +# superpowers is vendored skills now, not a plugin) and unrelated user +# plugins. Add a plugin here only when its enabled state is meaningfully +# driven by task type. MANAGED_PLUGINS=( "ui-ux-pro-max@ui-ux-pro-max-skill" "plugin-dev@claude-code-plugins" @@ -106,7 +109,6 @@ MANAGED_MCPS=() # MANAGED_PLUGINS allowlist.) PROTECTED_PLUGINS=( "security-guidance@claude-code-plugins" - "superpowers@superpowers-marketplace" ) GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BLUE='\033[0;34m'; NC='\033[0m' diff --git a/lib/tests/doctor-vendored.test.sh b/lib/tests/doctor-vendored.test.sh index 7ee2006..639f079 100644 --- a/lib/tests/doctor-vendored.test.sh +++ b/lib/tests/doctor-vendored.test.sh @@ -17,9 +17,11 @@ # "skills" is neither null/list/dict degrading the same way with no # Python traceback leaking (LOCK_MALFORMED_ENTRY, rc 0), the # profile-name allowlist rejecting a path-traversal value -# (REJECTS_BAD_PROFILE_NAME), and the item-name allowlist rejecting a +# (REJECTS_BAD_PROFILE_NAME), the item-name allowlist rejecting a # link.sh entry with a ".." segment — warned and skipped, not failed -# (REJECTS_BAD_NAME). +# (REJECTS_BAD_NAME), and an "always_on": true lock entry's name, absent +# from the profile and with no symlink, checked (and failed) instead of +# reported parked (ALWAYS_ON_LINK_CHECKED). set -u ROOT="$(cd "$(dirname "$0")/../.." && pwd)" LIB="$ROOT/lib/doctor-vendored.sh" @@ -57,6 +59,11 @@ cat > "$REPO/plugins.lock.json" <<'JSON' "dict-entry": { "managed_by": "curl", "skills": {"dict-skill": ["SKILL.md", "references/notes.md"]} + }, + "always-on-entry": { + "managed_by": "curl", + "always_on": true, + "skills": ["always-on-skill"] } } JSON @@ -66,25 +73,27 @@ cat > "$REPO/link.sh" <<'SH' #!/usr/bin/env bash EXTERNAL_SKILLS=(ok-skill missing-skill dict-skill active-nolink-skill active-wronglink-skill - parked-skill noprofile-skill) + parked-skill noprofile-skill always-on-skill) SH # ── skills-external/ tree: every name's SKILL.md present, except # missing-skill (nothing at all) and dict-skill's references/notes.md. +# always-on-skill has its SKILL.md too — only its symlink is missing. for n in ok-skill dict-skill active-nolink-skill active-wronglink-skill \ - parked-skill noprofile-skill; do + parked-skill noprofile-skill always-on-skill; do mkdir -p "$REPO/skills-external/$n" echo "v1" > "$REPO/skills-external/$n/SKILL.md" done # ── claude_home symlinks: ok-skill correct, active-wronglink-skill -# points elsewhere, active-nolink-skill and noprofile-skill have none. +# points elsewhere, active-nolink-skill, noprofile-skill and +# always-on-skill have none. ln -sf "$REPO/skills-external/ok-skill" "$CLAUDE_HOME/skills/ok-skill" mkdir -p "$WORK/elsewhere" ln -sf "$WORK/elsewhere" "$CLAUDE_HOME/skills/active-wronglink-skill" -# ── active.profile: lists everything EXCEPT parked-skill and -# noprofile-skill (both proven absent from it). +# ── active.profile: lists everything EXCEPT parked-skill, +# noprofile-skill and always-on-skill (all three proven absent from it). cat > "$REPO/active.profile" <<'PROF' # DESC: fixture profile ok-skill external @@ -132,6 +141,16 @@ check_bool SYMLINK_PARKED \ grep -qF 'parked-skill: symlink missing/wrong' \ && echo 1 || echo 0)" +# ── always-on-skill: absent from active.profile (same as parked-skill) +# but its lock entry is "always_on": true — checked (and failed, no +# symlink) instead of reported parked. +check_bool ALWAYS_ON_LINK_CHECKED \ + "$(printf '%s' "$out1" | \ + grep -qF 'always-on-skill: symlink missing/wrong' \ + && ! printf '%s' "$out1" | \ + grep -qF 'always-on-skill: parked by profile' \ + && echo 1 || echo 0)" + # ── No profile file passed at all: noprofile-skill (absent from # active.profile, parked above) must now be treated as expected-linked. out2="$(check_vendored_skills "$REPO" "$CLAUDE_HOME" 2>&1)" diff --git a/lib/vendor-skills.sh b/lib/vendor-skills.sh index 8880703..72f4af7 100644 --- a/lib/vendor-skills.sh +++ b/lib/vendor-skills.sh @@ -18,6 +18,9 @@ # `skills` as a bare list defaults every named skill to `["SKILL.md"]` and # `path` to "skills" (the agent-skills shape); `skills` as a dict carries an # explicit per-skill file list (references/*, etc.) and `path` is required. +# `"always_on": true` (optional) is ignored by this helper (fetch is the +# same either way) — lib/doctor-vendored.sh reads it to expect the +# entry's skills linked regardless of the active profile. # # Raw URL: https://raw.githubusercontent.com///// # /. VENDOR_BASE_URL overrides the "https://…/" prefix diff --git a/link.sh b/link.sh index 3da8d76..57abf20 100644 --- a/link.sh +++ b/link.sh @@ -79,7 +79,9 @@ EXTERNAL_SKILLS=(emil-design-eng frontend-design design-motion-principles observability-and-instrumentation deprecation-and-migration ci-cd-and-automation scroll-world-storytelling build-threejs-scroll-worlds scroll-scrubbed-visual-sequence scroll-scrubbed-word-reveal - scroll-progress-timeline) + scroll-progress-timeline brainstorming writing-plans + subagent-driven-development test-driven-development + requesting-code-review using-git-worktrees writing-skills) for _ext_skill in "${EXTERNAL_SKILLS[@]}"; do if [ -d "$REPO/skills-external/$_ext_skill" ]; then if [ -L "$CLAUDE/skills/$_ext_skill" ] && [ "$(readlink "$CLAUDE/skills/$_ext_skill")" = "$REPO/skills-external/$_ext_skill" ]; then diff --git a/plugins.lock.json b/plugins.lock.json index 07b34b4..ecc14fb 100644 --- a/plugins.lock.json +++ b/plugins.lock.json @@ -64,6 +64,23 @@ "managed_by": "curl", "note": "Five scroll-choreography skills from MengTo/Skills (agent-skills/web-design), vendored the agent-skills way but with an explicit per-skill file list (SKILL.md + REFERENCES.md, or references/*.md + references/scroll-conductor.js for build-threejs-scroll-worlds) instead of the SKILL.md-only default. Never vendored: demo/, agents/, or any binary asset upstream ships alongside each skill. Text-only, byte-for-byte copies (Codex-isms in the source text stay). Bump the commit deliberately to pick up an upstream edit; install-plugins.sh Step 8e and update-all.sh 7.3 both read it from here via lib/vendor-skills.sh's vendor_pinned_skills(), never hardcoded." }, + "superpowers": { + "source": "https://github.com/obra/superpowers", + "commit": "5bf4e78011075bcfc0dc295f0724994cd123ee71", + "path": "skills", + "skills": { + "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"] + }, + "managed_by": "curl", + "always_on": true, + "note": "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 as `bash scripts/`, 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." + }, "impeccable": { "source": "npm:impeccable", "version": "4.1.0", diff --git a/update-all.sh b/update-all.sh index 5929c9b..bc9f24f 100644 --- a/update-all.sh +++ b/update-all.sh @@ -377,9 +377,10 @@ else info "design-motion-principles not installed — skipping" fi -# ── 7.3. Update Agent Skills + Mengto scroll skills (pinned commit) ── -# Both re-fetched at the SAME pinned commit (never advances the pin) via -# the shared lib/vendor-skills.sh helper — see install-plugins.sh Step 8e. +# ── 7.3. Update Agent Skills + Mengto scroll skills + superpowers +# (pinned commit) — all three re-fetched at the SAME pinned commit +# (never advances the pin) via the shared lib/vendor-skills.sh helper — +# see install-plugins.sh Step 8e. echo "" echo "── Updating Agent Skills (addyosmani/agent-skills)..." # shellcheck source=lib/vendor-skills.sh disable=SC1091 @@ -388,6 +389,9 @@ vendor_pinned_skills agent-skills refresh echo "" echo "── Updating Mengto scroll skills (MengTo/Skills)..." vendor_pinned_skills mengto-skills refresh +echo "" +echo "── Updating superpowers skills (obra/superpowers)..." +vendor_pinned_skills superpowers refresh # ── Impeccable (design detector + skill + subagents) ── # Global scope: the installer writes through the ~/.claude/{skills,agents} From ddea411491ee3bd4309d25d06a59239f203713bb Mon Sep 17 00:00:00 2001 From: bastien Date: Mon, 28 Sep 2026 14:54:53 +0200 Subject: [PATCH 2/3] chore(config): superpowers citers by bare name, routing map, docs, settings Every superpowers-prefixed skill call in ship-feature, init-project, tour, deploy, audit-delta, plugin-advisor and lib/analyze-before-plan now names the vendored skill directly. finishing-a-development-branch is described as the upstream skill this config does not vendor (gitflow finish is the integration path). CLAUDE.global.md Skill routing maps the four non-vendored skills the vendored text still references. settings.json loses the plugin key and its marketplace block; README, USAGE, plugin-advisor and the profile skill describe superpowers as vendored skills, always on, zero plugin cost. CHANGELOG entry with a known residual. --- CHANGELOG.md | 32 ++++++++++++++++++++++++++ CLAUDE.global.md | 6 +++++ README.md | 2 +- USAGE.md | 31 +++++++++++++------------ agents/plugin-advisor.md | 44 +++++++++++++++++++----------------- lib/analyze-before-plan.md | 7 +++--- lib/capitalize-commit.md | 18 ++++++++------- lib/doc-commit.md | 9 ++++---- settings.json | 7 ------ skills/audit-delta/SKILL.md | 3 ++- skills/deploy/SKILL.md | 2 +- skills/gitflow/SKILL.md | 8 ++++--- skills/init-project/SKILL.md | 8 +++---- skills/profile/SKILL.md | 6 +++-- skills/ship-feature/SKILL.md | 8 +++---- skills/tour/SKILL.md | 7 +++--- 16 files changed, 121 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4eba6b..46be703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -379,6 +379,21 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). `plugins.lock.json` pin 3.2.0 → 4.1.0 (the CLI only: the skill dist and the engine binary have their own release tracks). `link.sh` drops impeccable from `EXTERNAL_SKILLS`; `skills-external/impeccable/` is gone. +- **Superpowers plugin replaced by 7 vendored skills** (tier 2 of the + skill-catalog prune, BDR-105/106). `brainstorming`, `writing-plans`, + `subagent-driven-development`, `test-driven-development`, + `requesting-code-review`, `using-git-worktrees` and `writing-skills` are + curled byte-for-byte from `obra/superpowers` at the v6.4.1 commit + (`5bf4e78011075bcfc0dc295f0724994cd123ee71`) via `lib/vendor-skills.sh` + (new `superpowers` entry in `plugins.lock.json`, `always_on: true`), + linked by `link.sh` like the other externals: always on, no profile lists + them, same as `darwin-skill`. Every `superpowers:` citer across + `skills/`, `agents/` and `lib/` is renamed to the bare skill name. + `CLAUDE.global.md` Skill routing gains a map for the 4 dropped skills this + config used to reference: `executing-plans` to + `subagent-driven-development`, `finishing-a-development-branch` to + `gitflow finish`, `systematic-debugging` to `/bugfix`, + `verification-before-completion` to the verifier gates. ### Security - **Ten secret-reader deny rules added**: `sed`, `awk`, `cut`, `tr`, @@ -433,6 +448,15 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). with it: the 4 `mcp__magic__*` `permissions.ask` entries (BDR-059), the `MAGIC_API_KEY` block in `.env.example`, `link.sh`'s missing-key warning, and the dead `MAGIC_API_KEY=abc123` gitleaks allowlist regex. +- **Superpowers plugin uninstalled**: its 8 other skills + (`executing-plans`, `finishing-a-development-branch`, + `systematic-debugging`, `verification-before-completion`, + `dispatching-parallel-agents`, `receiving-code-review`, + `using-superpowers`, `diagnosing-superpowers`) and its SessionStart + injection (`using-superpowers`, ~3.6 KB every session start) are gone + with it. `lib/profile.sh` no longer protects it; `lib/detect-plugins.sh` + `detect_superpowers` now checks the linked vendored skill instead of the + plugin cache or `claude plugin list`. ### Fixed - **gstack's shared helper tree was mostly unreachable.** gstack skills @@ -505,6 +529,14 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). `21st-ui-build` and `21st-cli-use` still point at the now-`max`-only 21st trio. A Skill call on a parked name fails, and the doctrine routing in `CLAUDE.global.md` applies instead. +- The 7 vendored superpowers skills are byte-for-byte upstream text, never + edited: their internal `superpowers:` mentions and references to the + 8 non-vendored skills stay in the prose (their own text, not ours to + patch). `CLAUDE.global.md` Skill routing carries the map for the 4 of + those this config used to reference. After a rollback that re-installs + the plugin while the 7 symlinks are still linked, delete the + `skills/<7>` symlinks or re-run `make plugin` to avoid duplicate skill + descriptions. ## [1.5.0] — 2026-09-13 diff --git a/CLAUDE.global.md b/CLAUDE.global.md index 505fe6e..220c268 100644 --- a/CLAUDE.global.md +++ b/CLAUDE.global.md @@ -258,6 +258,12 @@ cryptic names. - Design / UI (build, system, audit, polish) → "Design work" below - Architecture review → plan-eng-review - Before /clear or /compact → capitalize; end-of-session ritual → close +- superpowers skills are vendored, called by bare name; an upstream + `superpowers` prefix names the same skill. Not vendored here: + executing-plans → subagent-driven-development + finishing-a-development-branch → `gitflow finish` (human signal) + systematic-debugging → bugfix + verification-before-completion → the verifier gates - SEO+GEO → seo (GEO only → geo); W3C + WCAG a11y → web-validate; security audit (secrets, CVE, OWASP) → cso gstack OFF → its skills (investigate, qa, review, health, retro, diff --git a/README.md b/README.md index 2716368..3a5ad36 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ ctx7 login # optional: OAuth / API key for higher rate limits | Component | Type | Description | Docs | |---|---|---|---| -| **Superpowers** | Plugin (required) | Brainstorming, planning, subagent-driven dev, code review, branch finishing. Required by `/init-project` and `/ship-feature`. | [obra/superpowers-marketplace](https://github.com/obra/superpowers-marketplace) | +| **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](https://github.com/obra/superpowers) | | **GStack** | Plugin (toggle) | Full-product workflow: UI + design + deploy + browser QA. Skip for backend/CLI projects. | [garrytan/gstack](https://github.com/garrytan/gstack) | | **GSD v2** | External CLI | Multi-session orchestration: crash recovery, cost tracking, parallel workers, context-fresh execution. | [gsd-build/gsd-2](https://github.com/gsd-build/gsd-2) | | **RTK** | Plugin (always on) | Code rewrite hook. Zero passive cost. | [rtk-ai/rtk](https://github.com/rtk-ai/rtk) | diff --git a/USAGE.md b/USAGE.md index 7b36a20..55fe619 100644 --- a/USAGE.md +++ b/USAGE.md @@ -181,8 +181,8 @@ Deploy + QA browser → gstack ON Next.js/React/Prisma → context7 ON (WARN si absent, pas BLOCK) Multi-session (>1 jour) → gsd v2 CLI (gsd dans terminal) -Backend/CLI seulement → tout OFF sauf superpowers -Hotfix/quick fix → tout OFF sauf superpowers +Backend/CLI seulement → tout OFF (skills superpowers vendorisés, toujours actifs, 0 t passif) +Hotfix/quick fix → tout OFF (skills superpowers vendorisés, toujours actifs, 0 t passif) ``` **GSD v2** n'est pas un plugin Claude Code — c'est un CLI externe. Il ne consomme pas de tokens passifs. Tu le lances dans un terminal séparé avec `gsd`, puis `/gsd auto` pour le mode autonome. @@ -586,7 +586,7 @@ ONBOARD COMPLETE: mycli → SIGNALS: none (CLI pur) → DISABLE: ui-ux-pro-max, gstack, context7 -→ KEEP: superpowers +→ (skills superpowers vendorisés, toujours actifs, 0 t passif) → COST: ~800t (minimal) → ACTION REQUIRED? NO ``` @@ -647,7 +647,7 @@ DO NOT TOUCH: /plugin-check "CLI Rust, convertisseur de fichiers JSON/CSV/TOML, pas de réseau, pas de frontend" → SIGNALS: none (CLI pur, pas de deploy, pas de frontend) -→ KEEP: superpowers +→ (skills superpowers vendorisés, toujours actifs, 0 t passif) → DISABLE: ui-ux-pro-max, gstack, context7 → COST: ~800t (base seulement) → ACTION REQUIRED? NO @@ -748,7 +748,7 @@ Simple à valider. L'architecture proposée est plate, pas de surprise. **Contexte :** module `services/payment_service.py` dans un projet FastAPI existant. Écrit il y a 2 ans, jamais refactorisé. Violations connues : fonctions de 80 lignes, global state, pas de tests unitaires, logique métier mélangée avec appels HTTP. -**Setup :** projet déjà onboardé (CLAUDE.md présent), superpowers actif, plugins inutiles désactivés. +**Setup :** projet déjà onboardé (CLAUDE.md présent), skills superpowers vendorisés (toujours actifs, 0 t passif), plugins inutiles désactivés. #### Étape 1 — Analyse avant toute modification @@ -861,7 +861,7 @@ PROJECT STATUS CONFIG Version : v2.5.0 - Plugins ON: superpowers, context7 (~1000t) + Plugins ON: context7 (~200t), skills superpowers vendorisés (toujours actifs, 0 t passif) GSD v2 : installed (2.64.0) PROJECT @@ -956,19 +956,20 @@ GSD v2 met à jour le plan dans `.gsd/ROADMAP.md` sans perdre le travail déjà /plugin-check "Firmware C STM32, bare-metal, pas de réseau, pas de frontend, pas de Docker" SIGNALS: simple, CLI/embedded -COST: ~800t (superpowers seul) +COST: ~0t (skills superpowers vendorisés, toujours actifs, 0 t passif) RECOMMENDATIONS: - OK KEEP : superpowers (peut être utile pour brainstorm initial) DISABLE : ui-ux-pro-max, gstack, context7 - NOTE : Pour un firmware vraiment simple (hotfix, modification ciblée), - même superpowers peut être désactivé → ~0t passif + NOTE : skills superpowers (brainstorming, writing-plans...) restent + disponibles par nom bare sans coût passif, même pour un + firmware minimal. ``` **Workflow minimaliste — modification d'un driver existant :** ``` -# Pas de /init-project, pas de GSD, pas de superpowers +# Pas de /init-project, pas de GSD ; skills superpowers vendorisés +# (toujours actifs, 0 t passif) mais non invoqués ici # 1. Comprendre avant de modifier /analyze src/drivers/uart.c @@ -992,7 +993,7 @@ OUTPUT: /ship-feature "Corriger l'accès non-atomique au ring_buffer_head dans l'ISR" STEP 0b — CLAUDE.md found -STEP 0 — plugin check: superpowers OK (ou désactivé si YOLO mode) +STEP 0 — plugin check: skills superpowers vendorisés (toujours actifs, 0 t passif) STEP 1 — BRAINSTORM (rapide, contexte déjà clair depuis /analyze): Design: protéger ring_buffer_head avec __disable_irq()/__enable_irq() @@ -1015,7 +1016,7 @@ STEP 4 — IMPLEMENT (subagents légers, modifications chirurgicales) ``` **Points clés :** -- `/plugin-check` confirme "superpowers seulement" → aucun plugin inutile actif. +- `/plugin-check` confirme qu'aucun plugin inutile n'est actif (skills superpowers vendorisés, toujours actifs, 0 t passif). - `/analyze` est particulièrement utile sur du code C bas-niveau : l'analyzer identifie les accès non-atomiques, les race conditions, les violations de normes, **sans proposer de fix**. - Pour un firmware, le workflow `analyze → ship-feature` peut se réduire à `analyze → edit direct` si la modification est triviale. - GSD v2 n'est jamais pertinent pour du firmware : les sessions sont courtes et les tâches atomiques. @@ -1031,7 +1032,7 @@ Prisma / Supabase → context7 ON "design élaboré" / tokens → ui-ux-pro-max ON Docker + QA browser → gstack ON "plusieurs semaines" → gsd v2 CLI -Rust / Python / Go / C → tout OFF sauf superpowers +Rust / Python / Go / C → tout OFF (skills superpowers vendorisés, 0t) Mobile / Flutter / RN → gstack OFF -Hotfix / script rapide → tout OFF sauf superpowers +Hotfix / script rapide → tout OFF (skills superpowers vendorisés, 0t) ``` diff --git a/agents/plugin-advisor.md b/agents/plugin-advisor.md index 61c5f1c..1772299 100644 --- a/agents/plugin-advisor.md +++ b/agents/plugin-advisor.md @@ -77,7 +77,7 @@ Factors (weighted): | Infra/deploy | 15% | Local only | Single deploy target | Multi-env, CI/CD, containers, monitoring | **Score thresholds:** -- **0-30% (simple)**: superpowers only. No gstack, no gsd, no ctx7, no graphify. +- **0-30% (simple)**: superpowers skills only (vendored, always on). No gstack, no gsd, no ctx7, no graphify. _Examples: site vitrine, landing page, script CLI, simple CRUD._ - **30-60% (moderate)**: + context7 if fast-libs. graphify only once the codebase passes 200 tracked code files (session-start banner informs, the user decides — BDR-097), never at scaffold. _Examples: blog with auth, dashboard with charts, API with validation._ @@ -143,7 +143,7 @@ ACTION REQUIRED? YES / NO | `fast-libs` | context7 | — | Doc freshness critical | | `multi-agent` + `complex-arch` | gsd v2 CLI | — | GSD v2 preferred for multi-session coordination | | `simple` / single-session | — | gsd, gstack, ui-ux-pro-max | Saves ~3000-5000t | -| `embedded` / firmware | — | all toggles; superpowers optional | workflow: /analyze → /hotfix or /bugfix or /ship-feature | +| `embedded` / firmware | — | all toggles (superpowers skills vendored, always on) | workflow: /analyze → /hotfix or /bugfix or /ship-feature | | backend/lib/CLI only | — | ui-ux-pro-max, gstack | ~3100t saved | | small project / hotfix | — | gstack, gsd | Use /hotfix, /bugfix, or /feat | @@ -174,12 +174,12 @@ When the plugin-advisor detects a `simple` or `hotfix` signal, suggest the appro | Pair | Relation | Verdict | |---|---|---| | gstack ↔ gsd v2 | ✅ Complementary | GStack = full-product CC workflow. GSD v2 = multi-session CLI. Different scopes, no conflict. | -| superpowers ↔ gsd v2 | ✅ Complementary | Superpowers = single-session execution. GSD v2 = multi-session CLI orchestration. No conflict. | -| superpowers ↔ gstack | ✅ Complementary | Used together in /init-project and /ship-feature. Superpowers = engine, GStack = full-product skills. | +| superpowers ↔ gsd v2 | ✅ Complementary | superpowers skills (vendored) = single-session execution. GSD v2 = multi-session CLI orchestration. No conflict. | +| superpowers ↔ gstack | ✅ Complementary | Used together in /init-project and /ship-feature. superpowers skills (vendored) = engine, GStack = full-product skills. | | context7 ↔ any | ✅ Independent | Doc lookup CLI (ctx7), no workflow overlap. Always safe to combine. | -| plugin-dev ↔ superpowers | ⚠️ Minor overlap | Superpowers can create skills too. Keep plugin-dev only when actively building new plugins/skills. | +| plugin-dev ↔ superpowers | ⚠️ Minor overlap | superpowers skills (vendored) can create skills too (writing-skills). Keep plugin-dev only when actively building new plugins. | | ui-ux-pro-max ↔ gstack | ✅ Complementary | GStack = deploy/QA layer; ui-ux-pro-max = UI quality layer. Different concerns. | -| pr-review-toolkit ↔ superpowers | ✅ Complementary | superpowers:requesting-code-review and /pr-review-toolkit:review-pr cover different review styles. | +| pr-review-toolkit ↔ superpowers | ✅ Complementary | `requesting-code-review` (vendored superpowers skill) and /pr-review-toolkit:review-pr cover different review styles. | | rtk ↔ any | ✅ Independent | Hook-only token compression. Zero interaction with any plugin. | | security-guidance ↔ any | ✅ Independent | Hooks + out-of-band LLM reviews (agentic review on commit/push; Stop diff review disabled by ENABLE_STOP_REVIEW=0). No context injection unless a regex hits. | @@ -187,15 +187,15 @@ When the plugin-advisor detects a `simple` or `hotfix` signal, suggest the appro | Project type | Plugins ON | OFF | Passive cost | |---|---|---|---| -| Backend API / microservice | superpowers, context7 (if fast libs) | ui-ux-pro-max, gstack | ~800t | -| Frontend SPA / SSR | superpowers, ui-ux-pro-max, frontend-design, design-motion-principles, context7 | gstack | ~1400t | -| Full-stack SaaS | superpowers, gstack, ui-ux-pro-max, frontend-design, design-motion-principles, context7 | — | ~4200t | -| CLI tool / library | superpowers | all toggles | ~800t | -| Multi-session large feature | superpowers + gsd v2 CLI (external) | — | ~800t CC | -| Quick fix / hotfix | superpowers | all toggles | ~800t | -| Design system / component lib | superpowers, ui-ux-pro-max, frontend-design, design-motion-principles | gstack, gsd | ~1200t | -| Fast-evolving libs (Next.js etc.) | superpowers, context7 | — | ~1000t | -| Enterprise multi-agent orchestration | superpowers + gsd v2 (external) | plugin-dev | ~800t CC | +| Backend API / microservice | (superpowers skills always on), context7 (if fast libs) | ui-ux-pro-max, gstack | ~0t | +| Frontend SPA / SSR | (superpowers skills always on), ui-ux-pro-max, frontend-design, design-motion-principles, context7 | gstack | ~600t | +| Full-stack SaaS | (superpowers skills always on), gstack, ui-ux-pro-max, frontend-design, design-motion-principles, context7 | — | ~3400t | +| CLI tool / library | (superpowers skills always on) | all toggles | ~0t | +| Multi-session large feature | (superpowers skills always on) + gsd v2 CLI (external) | — | ~0t CC | +| Quick fix / hotfix | (superpowers skills always on) | all toggles | ~0t | +| Design system / component lib | (superpowers skills always on), ui-ux-pro-max, frontend-design, design-motion-principles | gstack, gsd | ~400t | +| Fast-evolving libs (Next.js etc.) | (superpowers skills always on), context7 | — | ~200t | +| Enterprise multi-agent orchestration | (superpowers skills always on) + gsd v2 (external) | plugin-dev | ~0t CC | > rtk is always on at 0 context tokens; security-guidance is always on and > costs quota out of band (LLM reviews), not context — both omitted from @@ -239,8 +239,9 @@ RULE: IF "simple" OR "hotfix": RULE: IF "embedded" signal (firmware, bare-metal, microcontroller, or Makefile+C without Node/Rust/Go): → Disable ALL toggles including gstack, context7, plugin-dev - → superpowers OPTIONAL: useful for initial design brainstorm on complex drivers, - but unnecessary for single-function patches — user decides + → superpowers skills stay on (vendored, no toggle): useful for initial + design brainstorm on complex drivers, unnecessary for single-function + patches; just don't invoke them, no disable needed → GSD v2 CLI: not recommended (sessions are short, tasks are atomic) → Recommend workflow: /analyze → /hotfix (patch) or /bugfix (investigation) or /ship-feature (multi-file) → NOTE: print "embedded project detected — minimal plugin footprint recommended" @@ -251,7 +252,7 @@ RULE: IF plugin-dev ON AND no `skill-creation` signal detected: RULE: IF `skill-creation` signal: → plugin-dev ON (~100t) - → superpowers ON — required for skill scaffolding + → superpowers skills (vendored, always on): used for skill scaffolding (writing-skills) RULE: IF `browser-qa` signal (e2e tests, Playwright/Cypress/Puppeteer in deps): → gstack ON — browser automation and QA @@ -295,8 +296,9 @@ gstack + managed plugins — sessions stay focused and passive token cost drops. `profile set ` actually toggles plugins (`claude plugin enable|disable`) and external skill packs (delegates to `lib/toggle-external.sh`) — not just -advisory. No MCP server is auto-toggled today. Always-on plugins (`security-guidance`, `superpowers`) -are protected. Managed plugins that `set` may toggle: +advisory. No MCP server is auto-toggled today. Always-on plugins (`security-guidance`) +and the vendored superpowers skills are never toggled by a profile. Managed +plugins that `set` may toggle: `ui-ux-pro-max@ui-ux-pro-max-skill`, `plugin-dev@claude-code-plugins`, `pr-review-toolkit@claude-code-plugins`. Other plugins are never auto-toggled. @@ -321,7 +323,7 @@ toggles the managed plugins like any `set`). ## BLOCK if -- Superpowers not active → install: `claude plugin marketplace add obra/superpowers-marketplace && claude plugin install --scope user superpowers@superpowers-marketplace` +- Superpowers skills missing → `make plugin` (vendors them) then `make link` - Full-product (UI+deploy+QA) + gstack not installed ## WARN (no block) diff --git a/lib/analyze-before-plan.md b/lib/analyze-before-plan.md index 7be44a4..6a7eca0 100644 --- a/lib/analyze-before-plan.md +++ b/lib/analyze-before-plan.md @@ -103,9 +103,10 @@ backfill, if ever wanted, is `/prune-memory` passe D — never this snippet. ## ORDERING (orchestrators only) -`superpowers:brainstorming` / `writing-plans` are external skills — we cannot make them -read our registries. So this runs BEFORE them, pre-loading the disposition into the plan -they form. Mirror of capitalize-commit running BEFORE finishing-a-development-branch: there +`brainstorming` / `writing-plans` (vendored superpowers skills) are external skills — we +cannot make them read our registries. So this runs BEFORE them, pre-loading the +disposition into the plan they form. Mirror of capitalize-commit running BEFORE +`gitflow finish` (the upstream finishing-a-development-branch is not vendored): there the memory commit must precede integration; here the memory read must precede planning. ## NO-OP / IDEMPOTENT diff --git a/lib/capitalize-commit.md b/lib/capitalize-commit.md index 5c96210..c433631 100644 --- a/lib/capitalize-commit.md +++ b/lib/capitalize-commit.md @@ -17,9 +17,10 @@ code already committed. - Inline-commit flows (feat / hotfix / bugfix / commit-change): run it right after writing the entries, on the current branch. -- Orchestrators that integrate via `superpowers:finishing-a-development-branch` - (ship-feature / init-project): run it BEFORE the FINISH step — otherwise the - memory commit strands outside the merge/PR. See ORDERING. +- Orchestrators that integrate via `gitflow finish` (the upstream + finishing-a-development-branch is not vendored; ship-feature / init-project): + run it BEFORE the FINISH step — otherwise the memory commit strands outside + the merge/PR. See ORDERING. This snippet commits whatever is PENDING under `.claude/memory` + `.claude/tasks`; it does NOT decide content. A flow whose gate wrote only a journal line yields a @@ -65,11 +66,12 @@ no-match pathspec is filtered, not fatal). ## ORDERING (orchestrators only) -`finishing-a-development-branch` may merge-and-delete the branch or push a PR. A -memory commit created AFTER it lands outside the integrated history — stranded -on the PR path. So in ship-feature / init-project this snippet runs BEFORE -FINISH. The code commits already exist (implementation step), so the entries' -hash references are valid at this point. +`finishing-a-development-branch` (upstream superpowers skill, not vendored +here; `gitflow finish` is the only integration path) may merge-and-delete the +branch or push a PR. A memory commit created AFTER it lands outside the +integrated history — stranded on the PR path. So in ship-feature / init-project +this snippet runs BEFORE FINISH. The code commits already exist (implementation +step), so the entries' hash references are valid at this point. ## WHAT THIS DOES NOT DO diff --git a/lib/doc-commit.md b/lib/doc-commit.md index f7e0d1b..2a2ee6e 100644 --- a/lib/doc-commit.md +++ b/lib/doc-commit.md @@ -81,10 +81,11 @@ do NOT bypass them: ## ORDERING (orchestrators) -`finishing-a-development-branch` merges/pushes COMMITTED history only — it never commits -working-tree changes. A doc patch left uncommitted (or committed AFTER it) never reaches -the merge/PR. So this snippet runs BEFORE FINISH: the doc commit lands on the branch FINISH -integrates. Consumption is MECHANICAL (LRN-057 case a, like the memory commit) — production +`finishing-a-development-branch` (upstream superpowers skill, not vendored here; +`gitflow finish` is the only integration path) merges/pushes COMMITTED history only — it +never commits working-tree changes. A doc patch left uncommitted (or committed AFTER it) +never reaches the merge/PR. So this snippet runs BEFORE FINISH: the doc commit lands on +the branch FINISH integrates. Consumption is MECHANICAL (LRN-057 case a, like the memory commit) — production on the branch = consumption by the merge, automatic. ## ACKNOWLEDGMENTS (conscious, not glossed) diff --git a/settings.json b/settings.json index d161da1..d34217e 100644 --- a/settings.json +++ b/settings.json @@ -420,7 +420,6 @@ "example-skills@anthropic-agent-skills": false, "ui-ux-pro-max@ui-ux-pro-max-skill": true, "security-guidance@claude-code-plugins": true, - "superpowers@superpowers-marketplace": true, "pr-review-toolkit@claude-code-plugins": false, "brightdata-plugin@synced": false }, @@ -431,12 +430,6 @@ "repo": "anthropics/claude-code" } }, - "superpowers-marketplace": { - "source": { - "source": "github", - "repo": "obra/superpowers-marketplace" - } - }, "ui-ux-pro-max-skill": { "source": { "source": "github", diff --git a/skills/audit-delta/SKILL.md b/skills/audit-delta/SKILL.md index a5195f4..82f8b43 100644 --- a/skills/audit-delta/SKILL.md +++ b/skills/audit-delta/SKILL.md @@ -318,7 +318,8 @@ Then offer to capitalize (per CLAUDE.md): recurring finding patterns → ## TDD note (skill itself) -Baseline-tested per superpowers:writing-skills (2026-06-11, isolated +Baseline-tested per writing-skills (vendored superpowers skill; +2026-06-11, isolated worktree, no skill): the agent (1) guessed the boundary from the most recent file date in `.claude/audits/` — wrong file, date-based; (2) wrote its checkpoint as prose in a dated report — unparseable next run; (3) kept diff --git a/skills/deploy/SKILL.md b/skills/deploy/SKILL.md index d23c995..7413e52 100644 --- a/skills/deploy/SKILL.md +++ b/skills/deploy/SKILL.md @@ -512,7 +512,7 @@ The deploy succeeded. Lay the oracle and close out. ## Note on this skill (authoring) -Shaped via `superpowers:writing-skills`. The **cold cross-session resume** is the +Shaped via `writing-skills` (vendored superpowers skill). The **cold cross-session resume** is the novel form (design §10): the disk alone must carry the deploy across the out-of-band gap, so `PENDING.json`'s presence marks the wait and STEP 0 resumes from it without conversation memory — the `audit-delta` "state file is the only diff --git a/skills/gitflow/SKILL.md b/skills/gitflow/SKILL.md index efc9109..fdffdd3 100644 --- a/skills/gitflow/SKILL.md +++ b/skills/gitflow/SKILL.md @@ -13,8 +13,10 @@ fan-out, init, `.gitignore` reconcile, the protected-base predicate — are in and bulletproofs the single judgment call: **`finish` merges only on an explicit human signal.** -Replaces `finishing-a-development-branch` for gitflow flows — that skill is -single-target and cannot do the directed / fan-out merges below. +Replaces `finishing-a-development-branch` (upstream superpowers skill, not +vendored here; `gitflow finish` is the only integration path) for gitflow +flows — that skill is single-target and cannot do the directed / fan-out +merges below. ## When to Use @@ -107,7 +109,7 @@ stays human-gated. ## Common Mistakes -- Using `finishing-a-development-branch` for a gitflow merge → it can't do directed/fan-out merges. Use `gitflow finish`. +- Using `finishing-a-development-branch` (upstream superpowers skill, not vendored here) for a gitflow merge → it can't do directed/fan-out merges anyway. Use `gitflow finish`, the only integration path. - Hand-writing `git merge` instead of `gitflow finish` → loses fan-out, branch delete, base sync. - Calling `finish` because the work *looks* done → see the gate. - `git branch -d`/`-D` by hand → denied; a branch the lib refuses to delete still holds work. Keep it, say so. diff --git a/skills/init-project/SKILL.md b/skills/init-project/SKILL.md index 239f702..a156cf7 100644 --- a/skills/init-project/SKILL.md +++ b/skills/init-project/SKILL.md @@ -68,7 +68,7 @@ contract. Load `$HOME/.claude/agents/analyzer.md`. Analyze BRIEF: existing code, stack constraints, infra risks, open decisions. Produce ANALYSIS REPORT. ## STEP 3 — DESIGN -Invoke `superpowers:brainstorming` with BRIEF + ANALYSIS REPORT. +Invoke `brainstorming` (vendored superpowers skill) with BRIEF + ANALYSIS REPORT. Produce DESIGN: stack+versions, full folder tree, module responsibilities, data flow, interfaces (signatures only), config+tooling, test strategy, resolved decisions, prereqs list. Then run pass B of `$HOME/.claude/lib/contract-interview.md` against the DESIGN (minus what the BRIEF and the brainstorm settled): one batch before STEP 4; @@ -179,7 +179,7 @@ This is the deterministic scaffold commit owner (closes BLK-010). The MVP is implemented on a `feature/*` branch off `develop` (STEP 8). ## STEP 6 — PLAN -Invoke `superpowers:writing-plans` with BRIEF + skeleton. +Invoke `writing-plans` (vendored superpowers skill) with BRIEF + skeleton. Granular tasks (2-5 min each), exact file paths, TDD: tests before code. ## STEP 6b — CHALLENGE THE PLAN (before the gate) @@ -212,7 +212,7 @@ Start the MVP feature branch off develop, then implement on it: ```bash bash "$HOME/.claude/lib/gitflow.sh" start feature mvp ``` -Invoke `superpowers:subagent-driven-development` for the per-task implement loop +Invoke `subagent-driven-development` (vendored superpowers skill) for the per-task implement loop **and** the final whole-branch review **only**. Do NOT run its terminal `finishing-a-development-branch` step — this orchestrator owns integration via `gitflow finish` (STEP 11). When SDD's flow reaches "Use @@ -256,7 +256,7 @@ against the founding contract. Distinct axis from STEP 10 code review ([[LRN-095]]) — both run. ## STEP 10 — CODE REVIEW -Invoke `superpowers:requesting-code-review`. **Model routing (BDR-077):** the +Invoke `requesting-code-review` (vendored superpowers skill). **Model routing (BDR-077):** the review subagent it dispatches MUST carry `model: "opus"` in the Agent call — craft review is dispatched judgment, never inherited from the session. Fix all CRITICAL before proceeding. diff --git a/skills/profile/SKILL.md b/skills/profile/SKILL.md index 6351a67..1815d51 100644 --- a/skills/profile/SKILL.md +++ b/skills/profile/SKILL.md @@ -56,8 +56,10 @@ lists items + types: | `mcp` | advisory — prints manual `claude mcp add …` command (no server is managed today: `MANAGED_MCPS` is empty since 21st.dev moved to a CLI) | | `cli` | advisory only — reports installed/not-installed | -**Always-on plugins** (`security-guidance`, `superpowers`) are -protected — `set` will refuse to disable them even if the profile omits them. +**Always-on plugins** (`security-guidance`) and the vendored superpowers +skills are never toggled by a profile — `set` will refuse to disable the +plugin even if the profile omits it, and the 7 superpowers skills are +linked outside any profile. **Managed plugins** that `set` may disable when not in profile: `ui-ux-pro-max@ui-ux-pro-max-skill`, `plugin-dev@claude-code-plugins`, `pr-review-toolkit@claude-code-plugins`. Other plugins are never auto-toggled. diff --git a/skills/ship-feature/SKILL.md b/skills/ship-feature/SKILL.md index bc01d3e..17a4233 100644 --- a/skills/ship-feature/SKILL.md +++ b/skills/ship-feature/SKILL.md @@ -100,7 +100,7 @@ approved at STEP 3 ENRICHES it, and STEP 5's verifier judges the diff against the ENRICHED contract. This is the only flow where the contract grows mid-run. ## STEP 1 — BRAINSTORM -Invoke `superpowers:brainstorming` — but FEED it the STEP 0d digest as binding context, +Invoke `brainstorming` (vendored superpowers skill) — but FEED it the STEP 0d digest as binding context, not the raw request alone: "Feature request: <$ARGUMENTS>. In-force constraints (must hold): ``` -Invoke `superpowers:subagent-driven-development` for the per-task implement loop +Invoke `subagent-driven-development` (vendored superpowers skill) for the per-task implement loop **and** the final whole-branch review **only**. Do NOT run its terminal `finishing-a-development-branch` step — this orchestrator owns integration via `gitflow finish` (STEP 9). When SDD's flow reaches "Use @@ -234,7 +234,7 @@ conformity + security vs. craft/design) — both run, neither subsumes the other ([[LRN-095]]). ## STEP 6 — CODE REVIEW -Invoke `superpowers:requesting-code-review`. **Model routing (BDR-077):** the +Invoke `requesting-code-review` (vendored superpowers skill). **Model routing (BDR-077):** the review subagent it dispatches MUST carry `model: "opus"` in the Agent call — craft review is dispatched judgment, never inherited from the session. Fix all CRITICAL before proceeding. diff --git a/skills/tour/SKILL.md b/skills/tour/SKILL.md index b334aac..7cb455f 100644 --- a/skills/tour/SKILL.md +++ b/skills/tour/SKILL.md @@ -315,9 +315,10 @@ without that approval — neither this repo's nor any target project's. ## TDD note (skill itself) -Baseline-tested per superpowers:writing-skills (2026-07-04, seeded -fixture, no skill): the agent branched correctly via gitflow and did not -merge, BUT (1) silently rewrote the target TODO (checked boxes, +Baseline-tested per writing-skills (vendored superpowers skill; +2026-07-04, seeded fixture, no skill): the agent branched correctly via +gitflow and did not merge, BUT (1) silently rewrote the target TODO (checked +boxes, restructured) during "reconcile"; (2) authored BDR/journal registry entries autonomously; (3) ran security as ad-hoc grep + ruff — no semgrep, no pinned rulesets; (4) left findings only in its final chat From 7177258f3d41e47e248131e625a4b7374ee2cec8 Mon Sep 17 00:00:00 2001 From: bastien Date: Mon, 28 Sep 2026 14:54:53 +0200 Subject: [PATCH 3/3] =?UTF-8?q?chore(memory):=20BDR-106=20superpowers=20ve?= =?UTF-8?q?ndored=20=E2=80=94=20contract,=20plan=20r3,=20oracles,=20TODO,?= =?UTF-8?q?=20journal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/memory/decisions.md | 10 + .claude/memory/journal.md | 1 + .claude/tasks/TODO.md | 20 ++ .../2026-09-28-superpowers-vendored-1357.md | 69 +++++ .../c1.py | 16 ++ .../c2.py | 17 ++ .../2026-09-28-superpowers-vendored-1357.md | 271 ++++++++++++++++++ 7 files changed, 404 insertions(+) create mode 100644 .claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.md create mode 100644 .claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c1.py create mode 100644 .claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c2.py create mode 100644 .claude/tasks/plans/2026-09-28-superpowers-vendored-1357.md diff --git a/.claude/memory/decisions.md b/.claude/memory/decisions.md index 4e06f58..2d32cd3 100644 --- a/.claude/memory/decisions.md +++ b/.claude/memory/decisions.md @@ -127,6 +127,7 @@ rules: | BDR-103 | 2026-09-27 | 6-repo review: 5 verdicts, 3 criteria (grep-verified coverage, per-session cost, doctrine conflict); stars decided nothing | accepted | | BDR-104 | 2026-09-28 | MengTo motion pack: vendor 5 scroll skills pinned via shared lib/vendor-skills.sh + build personal skill site-motion; 17 skipped | accepted | | BDR-105 | 2026-09-28 | skill-catalog prune: 9 gstack out via GSTACK_REMOVED, full ⊇ every profile, max = everything, brightdata + frontend-design plugin off, security-guidance Stop review off, design gate asks `21st login` and waits | accepted | +| BDR-106 | 2026-09-28 | superpowers: 7 wired skills vendored at v6.4.1 via lib/vendor-skills.sh (always_on lock class), plugin + marketplace dropped, citers by bare name, doctrine map for the 4 non-vendored refs | accepted | --- @@ -1319,3 +1320,12 @@ Branch feature/user-writing-web-rules, UNMERGED (human gate). - **Alternatives rejected**: rm symlinks by hand (set/reset re-materialize, `gstack on` restores everything → denylist instead); per-skill toggles inside ui-ux-pro-max (all-or-nothing, unverified); drop superpowers in the same run (7 skills wired in ship-feature/init-project → tier 2, own branch); keep the 21st trio in design profiles (redundant with impeccable + ui-ux-pro-max, CLI signed out); raise `SLASH_COMMAND_TOOL_CHAR_BUDGET` (costs context, the opposite goal); keep the official frontend-design plugin and drop the copy (copy is profile-managed and gate-checked); shared 21st auth helper across 3 scripts (breaks 4 fixture suites, changes installer semantics — [[LRN-178]]); in-session `export TWENTYFIRST_TOKEN` remedy (env does not persist across tool calls). - **Caveats**: kept gstack skills still route to removed names in their upstream prose (Skill call fails, doctrine applies); helper tree links every top-level submodule entry (no SKILL.md exposed, asserted); security-guidance commit review quota unmeasured; doctor constants rebased on 2026-09-28 measures; `apply` is additive → other machines run `set full`, not `apply`. - **Reference**: f83f8f7 02b62f7 4c86d6d 729d715 (prune), bd3e525 132bcdf (21st gate); contracts `2026-09-28-skill-catalog-prune-0554` (18 criteria, oracles in `.oracles/`) and `2026-09-28-21st-signin-gate-1215` (7); plans r4 / r3 after 3 challengers + 1 confirmation each; GATE 0 MET, verifiers CONFORME (iter 2 / iter 1), security PASS ×2; 42 suites green minus 2 pre-existing T16a. Links [[BDR-030]] [[BDR-101]] [[BDR-093]] [[BDR-095]] [[BDR-080]] [[BDR-025]] [[BDR-070]] [[LRN-175]] [[LRN-176]] [[LRN-177]] [[LRN-178]] [[BLK-023]] [[EVAL-034]]. + +## BDR-106 — superpowers: 7 skills vendored at v6.4.1, plugin dropped +- **Date**: 2026-09-28 +- **Status**: accepted, feature/superpowers-vendored, UNMERGED (human gate) +- **Decision**: (1) plugins.lock.json `superpowers` entry (obra/superpowers @ 5bf4e78 = tag v6.4.1, path `skills`, per-skill file lists, `always_on: true`), fetched byte-for-byte by lib/vendor-skills.sh: brainstorming, writing-plans, subagent-driven-development, test-driven-development, requesting-code-review, using-git-worktrees, writing-skills; STEP 8e vendors, update-all refreshes at the pin, link.sh links, .gitignore ignores. (2) Plugin + marketplace uninstalled (one shot by hand after the fetch proved byte-identical), settings.json keys removed by hand, PROTECTED_PLUGINS = security-guidance only; `detect_superpowers` = `[ -f ~/.claude/skills/brainstorming/SKILL.md ]`, no plugin fallback; doctor/session-start no longer charge the injection. (3) doctor-vendored `always_on` class: third lock column, `_dv_check_link` 5th param — always-on externals are link-checked, never "parked". (4) Citers call the bare names; CLAUDE.global.md maps the four non-vendored skills the vendored text still references (executing-plans → SDD, finishing-a-development-branch → gitflow finish, systematic-debugging → bugfix, verification-before-completion → verifier gates). Vendored text never edited (BDR-104 rule). +- **Why**: 7 skills wired (ship-feature, init-project, writing-skills TDD), 8 duplicate personal flows; SessionStart injection 3.6 KB per start/clear/compact + a competing router ("1 % → MUST invoke", BDR-080 conflict); 15 descriptions → 7. Tier 2 of [[BDR-105]]. +- **Alternatives rejected**: shared auth/detect helpers sourced at top level (break the fixture `cp` suites, [[LRN-178]]); installer-side uninstall (plugin gone before the fetch on a network failure; precedent = comment only, one-shot by hand); detect with plugin-cache fallback (the marketplace dir matches `*superpowers*` → "vendored" on a plugin-only machine, fail-open); rewriting vendored text to fix cross-refs; vendoring all 15; map text spelling the colon form or wrapping identifiers (criteria 3/7 grep line by line — both caught by challengers). +- **Caveats**: upstream cross-refs to the plugin prefix and the 8 dropped skills remain in the vendored text (a call on a dropped name fails, doctrine map applies); no upstream auto-update (bump the pin deliberately); the harness hot-loaded the 7 bare names in the running session after link.sh, the plugin names leave at restart; `superpowers-marketplace` cache dir may linger empty; other machines: `make plugin` (vendors) + `make link`, then uninstall the cached plugin by hand (CHANGELOG). +- **Reference**: 18f8c89 (wiring), ddea411 (citers/docs/settings); contract `2026-09-28-superpowers-vendored-1357` (12 criteria, oracles in `.oracles/`), plan r3 after 3 challengers (simplicity CONCERNS(2), robustness CONCERNS(3), correctness FATAL(5)) + confirmation CONCERNS(1); executors 2/2 DONE first pass; GATE 0 MET, verifier CONFORME 12/12, security PASS; catalog 82 skills, plugin passive cost 670 t (ui-ux-pro-max only). Links [[BDR-105]] [[BDR-102]] [[BDR-104]] [[BDR-065]] [[LRN-178]] [[EVAL-034]]. diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 27d1327..3948d22 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -538,3 +538,4 @@ rules: - Skill-catalog audit (user: "tour des skills, doublons, économiser tokens"): 5 analyzers over 150 skills / 53.5k chars desc; 78 listed name-only this session (listing budget ≈1 % ctx, least-invoked lose desc → gain = routing quality + no broken 100 KB body invoked, not listing chars). Found: frontend-design plugin byte-dup of managed copy; brightdata 21 skills keyless + hostile WebFetch routing; gstack ship trunk-based (origin/HEAD=main), land-and-deploy auto-merge+deploy, autoplan/make-pdf/diagram/careful/guard/freeze dead paths (only bin + browse/dist linked); security-guidance = Opus call per code turn + agentic commit review, 0 findings/6 days; doctor.sh undercount ×6. User go: tier 1, superpowers vendor-7 (tier 2 later), 21st trio parked (CLI `Not logged in`), rule "full ⊇ every profile, max = everything". Live: brightdata disabled, frontend-design plugin uninstalled, `set full` → 75 skills (was 89). - /feat by hand on feature/skill-catalog-prune: contract 18 criteria; plan r1→r4 (3 challengers, confirmation FATAL(4): nested SKILL.md in browser-skills/openclaw/node_modules, ./setup global symlink, update-all 3rd copy); 4 feater parallel DONE; GATE 0 UNMET(4) = MY heredoc CHECKs (gates.sh single-line) → oracles to `.oracles/*.py` → MET; verifier ECARTS(1) = floor-guard `xit(` false-positive on `sys.exit(` → restructure → CONFORME; security PASS. 41 suites green minus 2 pre-existing T16a, shellcheck clean. UNMERGED — human gate. Registries pending user approval. - User: "quand on détecte qu'on a besoin de 21st, on demande de log si c'est pas fait et on attend". /feat by hand on the same branch: design gate gains exit 12 `SIGN-IN REQUIRED` (three-state whoami probe, unknown → 11 with diagnostic, explicit "proceed without 21st" only skip); challenge round dropped my shared-helper idea (would break 4 fixture suites + change installer semantics) and my in-session `export TWENTYFIRST_TOKEN` remedy (env does not persist across tool calls). Executor DONE first pass, GATE 0 MET, verifier CONFORME 7/7, security PASS, 8/8 hermetic. Gate now exits 12 live here until `21st login`. +- User go "merge le tout, écris les registres, fais le tier 2": tier 1 registries (BDR-105, LRN-175..178, BLK-023, EVAL-034) written, feature/skill-catalog-prune finished → develop c39c0e1. Tier 2 on feature/superpowers-vendored: 7 superpowers skills vendored at v6.4.1 through lib/vendor-skills.sh (`always_on` lock class for doctor-vendored), plugin + marketplace uninstalled, settings.json hand-edited, citers by bare name, doctrine map. Challenge round: correctness FATAL(5) caught my map text containing the forbidden `superpowers` colon form; confirmation caught an identifier wrapped across lines (grep is line-based). Executors 2/2 DONE, GATE 0 MET, verifier CONFORME 12/12, security PASS. Catalog 82 skills, passive plugin cost 670 t, injection gone; harness hot-loaded the bare names in-session. 18f8c89 ddea411. UNMERGED — human gate. [[BDR-106]] diff --git a/.claude/tasks/TODO.md b/.claude/tasks/TODO.md index 5c672d2..0a494e5 100644 --- a/.claude/tasks/TODO.md +++ b/.claude/tasks/TODO.md @@ -1,5 +1,25 @@ # TODO +## 2026-09-28 — tier 2: vendor 7 superpowers skills, drop the plugin (feature/superpowers-vendored) +User go "fais le tier 2" (decision 2026-09-28, batch 1). Contract +`.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.md`. +- [x] V1 plugins.lock.json `superpowers` entry (obra/superpowers @ 5bf4e78 = v6.4.1, + path skills, dict of 7 file lists); install-plugins.sh STEP 5 stops installing + the plugin, STEP 8e vendors it; update-all.sh refresh; link.sh EXTERNAL_SKILLS; + .gitignore; profile.sh PROTECTED_PLUGINS; detect-plugins/session-start/doctor + read the vendored dir, injection cost gone. +- [x] V2 citers: `superpowers:` → `` in ship-feature, init-project, tour, deploy, + audit-delta, lib/analyze-before-plan, plugin-advisor; finishing-a-development- + branch prose in capitalize-commit/doc-commit/gitflow; CLAUDE.global.md routing + map for the 8 dropped skills; README/USAGE/plugin-advisor/profile SKILL.md; + CHANGELOG. +- [x] V3 plan r1→r3 (3 challengers + confirmation), 2 feater DONE, live vendor + link + (VENDORED_LINKED), settings.json hand-edited, plugin + marketplace uninstalled, + GATE 0 MET 10/10, verifier CONFORME 12/12, security PASS; 18f8c89 ddea411; BDR-106. + Catalog 82 skills, passive plugins 670 t. UNMERGED — human gate. Other machines: + `make plugin` + `make link`, uninstall the cached plugin by hand. User: remove + `/tmp/tmp.PKDTRyaCw8` `/tmp/tmp.99Fu0dm8ll` (executor fixtures, rm refused). + ## 2026-09-28 — design gate asks for `21st login` and waits (feature/skill-catalog-prune) User: "si on veut l'utiliser, on demande à l'utilisateur de se log, plus simple que dire c'est pas logged on utilise pas… on demande de log si c'est pas fait et on diff --git a/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.md b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.md new file mode 100644 index 0000000..c49515e --- /dev/null +++ b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.md @@ -0,0 +1,69 @@ +# CONTRACT — superpowers-vendored +- date: 2026-09-28 | flow: feat (ad-hoc dispatch, /feat gates replayed by the orchestrator, 2 parallel feater executors) | branch: feature/superpowers-vendored +- status: active + +## REQUEST (verbatim — IMMUTABLE) +> ok merge le tout et écris les registres puis fais le tier 2 + +Tier 2 as decided 2026-09-28 (batch 1, option "Vendoriser 7, retirer le plugin (Recommended)"): vendor brainstorming, writing-plans, subagent-driven-development, test-driven-development, requesting-code-review, using-git-worktrees, writing-skills from obra/superpowers at the v6.4.1 commit via `lib/vendor-skills.sh`, drop the superpowers plugin (its 8 other skills and its session-start injection), rename the `superpowers:` citers. + +## CLARIFICATIONS +- Pass A: none — request complete (the decision batch fixed scope and outcome). +- Pass B: no visible / public-name choice left open — the vendored skills keep their upstream names (bare, no `superpowers:` prefix; renaming would break their internal cross-references), the lock key is `superpowers`, the always-on status is inherited (not in MANAGED_EXTERNALS, like darwin-skill). Proceeds silently. +- Byte-for-byte upstream text (BDR-104 convention): the vendored files are never edited, so their internal `superpowers:` mentions and references to the 8 dropped skills (executing-plans, finishing-a-development-branch, systematic-debugging, verification-before-completion, dispatching-parallel-agents, receiving-code-review, using-superpowers, diagnosing-superpowers) stay in the text; CLAUDE.global.md carries the routing map (bare names; executing-plans → subagent-driven-development; finishing-a-development-branch → `gitflow finish` on a human signal; systematic-debugging → bugfix; verification-before-completion → the verifier gates). Known residual, documented. +- Scripts inside the vendored skills are invoked as `bash scripts/` upstream: no exec bit needed after curl. +- `docs/superpowers/{specs,plans}` stays the transient path (brainstorming/writing-plans still write there; gitflow purge unchanged, BDR-065). +- Live steps are the orchestrator's: criterion 2 runs the vendor helper (network) + link.sh; the plugin uninstall (`claude plugin uninstall superpowers@superpowers-marketplace`) runs AFTER the 7 skills are linked, then criterion 8 checks the catalog. Executors never run `claude plugin …`, the vendor helper against the network, link.sh, `profile.sh set`, never commit. +- [challenge 2026-09-28, 3 lenses: simplicity CONCERNS(2), robustness CONCERNS(3), correctness FATAL(5); every BLOCKER/MAJOR closed by a named plan change, r2] (a) CLAUDE.global.md map never spells the colon form; (b) `always_on` lock field + doctor-vendored always-on class, test case; (c) no uninstall code in the installer, one-shot by the orchestrator after criterion 2, marketplace removed too, rollback step; (d) settings.json hand-edited (enabledPlugins key + marketplace block) and committed; (e) detect_superpowers = file test on the linked skill, no fallback, negative control in criterion 5; (f) map trimmed, lock note trimmed, session-start line deleted plainly. +- [confirmation pass 2026-09-28, correctness CONCERNS(1), all closed by named changes, r3] map identifiers kept whole per line (grep is line-based); `always_on` mechanism pinned (third lock column, 5th `_dv_check_link` param, headers); settings.json edited by the orchestrator only after criterion 2 is green; stale installer edge case removed; doctor pass line worded on what it proves. +- Functions ≤ 25 logic lines, 80-char lines, shellcheck clean. + +## ACCEPTANCE CRITERIA +1. plugins.lock.json carries the `superpowers` entry: obra/superpowers, commit 5bf4e78011075bcfc0dc295f0724994cd123ee71 (v6.4.1), path `skills`, dict of exactly the 7 skills with every upstream file listed (SKILL.md each; SDD scripts, code-reviewer.md, anthropic-best-practices.md included). + CHECK: python3 .claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c1.py + EXPECT: LOCK_OK + EVIDENCE: MET exit=0 marker-found :: LOCK_OK +2. Vendored + linked live: every listed file is under skills-external//, byte-identical to the plugin cache copy, and the 7 symlinks resolve under ~/.claude/skills. + CHECK: bash -c 'source lib/vendor-skills.sh; vendor_pinned_skills superpowers' >/dev/null 2>&1; bash link.sh >/dev/null 2>&1; python3 .claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c2.py + EXPECT: VENDORED_LINKED + EVIDENCE: MET exit=0 marker-found :: VENDORED_LINKED +3. No `superpowers:` prefix remains in the personal catalog, agents, lib, hooks or doctrine (fixtures excluded; positive control first). + CHECK: echo 'x superpowers:brainstorming' | grep -q 'superpowers:' || exit 1; if git grep -n 'superpowers:' -- skills agents lib hooks CLAUDE.global.md ':!lib/tests/fixtures' | grep -v '^skills/synced'; then exit 1; fi; echo NO_PREFIX + EXPECT: NO_PREFIX + EVIDENCE: MET exit=0 marker-found :: NO_PREFIX +4. Installers and link wired: install-plugins.sh no longer installs/enables the plugin and vendors `superpowers` in STEP 8e; update-all.sh refreshes it; link.sh EXTERNAL_SKILLS lists the 7; .gitignore ignores the 7 skill symlinks and the 7 skills-external dirs. + CHECK: ! grep -qE 'install_plugin +"superpowers"|enable_plugin +"superpowers"' install-plugins.sh && grep -q 'vendor_pinned_skills superpowers' install-plugins.sh && grep -q 'vendor_pinned_skills superpowers refresh' update-all.sh && for s in brainstorming writing-plans subagent-driven-development test-driven-development requesting-code-review using-git-worktrees writing-skills; do grep -qE "^skills/$s\$" .gitignore || { echo "gitignore skills/$s"; exit 1; }; grep -qE "^skills-external/$s/\$" .gitignore || { echo "gitignore ext $s"; exit 1; }; sed -n '/^EXTERNAL_SKILLS=(/,/)/p' link.sh | grep -qw "$s" || { echo "link $s"; exit 1; }; done && echo WIRED + EXPECT: WIRED + EVIDENCE: MET exit=0 marker-found :: WIRED +5. profile.sh no longer protects the plugin; detect_superpowers is true on the linked vendored skill alone and false under an empty HOME (no plugin-cache glob, no claude call). [challenge r2] + CHECK: ! grep -q 'superpowers@superpowers-marketplace' lib/profile.sh && bash -c 'source lib/detect-plugins.sh; detect_superpowers' && E=$(mktemp -d) && ! HOME="$E" bash -c 'source lib/detect-plugins.sh; detect_superpowers' && rmdir "$E" && ! grep -qE 'compgen.*superpowers|plugin list.*superpowers' lib/detect-plugins.sh && echo DETECT_OK + EXPECT: DETECT_OK + EVIDENCE: MET exit=0 marker-found :: DETECT_OK +6. Suites and shellcheck: vendor-skills, doctor-vendored (with the new ALWAYS_ON_LINK_CHECKED case), doctrine-citers, skill-routing-census (live catalog with the 7), profile-default, profile-set-managed green; shellcheck clean on every touched shell file. [challenge r2] + CHECK: shellcheck install-plugins.sh update-all.sh link.sh lib/profile.sh lib/detect-plugins.sh hooks/session-start.sh doctor.sh lib/doctor-vendored.sh lib/vendor-skills.sh lib/tests/doctor-vendored.test.sh && out=$(make test suite=lib/tests/doctor-vendored.test.sh 2>&1) && echo "$out" | grep -q 'PASS ALWAYS_ON_LINK_CHECKED' && for s in vendor-skills doctor-vendored doctrine-citers skill-routing-census profile-default profile-set-managed; do out=$(make test suite=lib/tests/$s.test.sh 2>&1) || { echo "$s rc"; exit 1; }; echo "$out" | grep -qE 'FAIL=[1-9]|^FAIL ' && { echo "$s FAIL"; exit 1; }; done; echo SUITES_OK + EXPECT: SUITES_OK + EVIDENCE: MET exit=0 marker-found :: SUITES_OK +7. CLAUDE.global.md Skill routing carries the map for the dropped skills and says the seven are vendored, bare names. + CHECK: grep -q 'finishing-a-development-branch' CLAUDE.global.md && grep -q 'executing-plans' CLAUDE.global.md && grep -q 'systematic-debugging' CLAUDE.global.md && grep -qi 'vendored' CLAUDE.global.md && echo ROUTING_OK + EXPECT: ROUTING_OK + EVIDENCE: MET exit=0 marker-found :: ROUTING_OK +8. Live after the orchestrator's uninstall + marketplace removal: no superpowers plugin installed, no enabledPlugins key, no extraKnownMarketplaces block, the 7 skills still resolve, `make doctor` reports superpowers as vendored, not failed. [challenge r2] + CHECK: ! claude plugin list 2>/dev/null | grep -q 'superpowers@superpowers-marketplace' && python3 -c "import json,sys;d=json.load(open('settings.json'));assert 'superpowers@superpowers-marketplace' not in d['enabledPlugins'];assert 'superpowers-marketplace' not in d.get('extraKnownMarketplaces',{})" && for s in brainstorming writing-plans subagent-driven-development test-driven-development requesting-code-review using-git-worktrees writing-skills; do [ -f "$HOME/.claude/skills/$s/SKILL.md" ] || { echo "missing $s"; exit 1; }; done && bash doctor.sh 2>/dev/null | grep -qi 'superpowers.*vendored' && ! bash doctor.sh 2>/dev/null | grep -qi 'Superpowers not detected' && echo PLUGIN_GONE + EXPECT: PLUGIN_GONE + EVIDENCE: MET exit=0 marker-found :: PLUGIN_GONE +9. doctor.sh and session-start.sh stop charging the plugin injection (no `+ 1500` / `+ 800` superpowers constant; doctor message names the vendored skills). + CHECK: ! grep -qE 'detect_superpowers.*\+ ?(1500|800)' doctor.sh hooks/session-start.sh && grep -qi 'vendored' doctor.sh && echo DOCTOR_OK + EXPECT: DOCTOR_OK + EVIDENCE: MET exit=0 marker-found :: DOCTOR_OK +10. Docs: README component table row (vendored skills, pinned v6.4.1, lock entry), USAGE.md mentions of "superpowers" as a plugin or a passive cost reworded, agents/plugin-advisor.md compatibility/recommended-set rows and the "not active → install" remedy reworded, skills/profile/SKILL.md:59 always-on sentence updated, CHANGELOG `[Unreleased]` entry (Changed: superpowers plugin → 7 vendored skills; Removed: the 8 other skills + injection; Known residual: upstream cross-references). +11. lib/capitalize-commit.md, lib/doc-commit.md, lib/analyze-before-plan.md and skills/gitflow/SKILL.md describe finishing-a-development-branch as the upstream skill this config does not vendor (gitflow finish replaces it), not as an active skill. +12. doctor-vendored treats the 7 as always-on: `bash doctor.sh` prints a pass line for each of the 7 (linked) and never "parked" for them. [challenge r2] + CHECK: out=$(bash doctor.sh 2>/dev/null); for s in brainstorming writing-plans subagent-driven-development test-driven-development requesting-code-review using-git-worktrees writing-skills; do echo "$out" | grep -qE "✓.*\b$s\b" || { echo "no pass for $s"; exit 1; }; echo "$out" | grep -qE "$s.*parked" && { echo "parked $s"; exit 1; }; done; echo ALWAYS_ON_OK + EXPECT: ALWAYS_ON_OK + EVIDENCE: MET exit=0 marker-found :: ALWAYS_ON_OK + +## FILE SCOPE +- plugins.lock.json, install-plugins.sh (STEP 5 superpowers block, STEP 8e, summary lines), update-all.sh (7.3), link.sh (EXTERNAL_SKILLS), .gitignore, lib/profile.sh (PROTECTED_PLUGINS + comments), lib/detect-plugins.sh, hooks/session-start.sh, doctor.sh, lib/doctor-vendored.sh, lib/tests/doctor-vendored.test.sh, lib/vendor-skills.sh (lock-shape header comment line) +- 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 (Skill routing lines), README.md, USAGE.md, CHANGELOG.md +- Orchestrator-only, after criterion 2: settings.json (enabledPlugins key + extraKnownMarketplaces block, hand edit), `claude plugin uninstall` + `claude plugin marketplace remove` (cache), rollback if criterion 8 fails; skills-external/<7> (gitignored, curl) and ~/.claude/skills symlinks are written by criterion 2 +- Orchestrator-only: .claude/tasks/**, .claude/memory/** diff --git a/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c1.py b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c1.py new file mode 100644 index 0000000..6d85327 --- /dev/null +++ b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c1.py @@ -0,0 +1,16 @@ +import json,re +d=json.load(open('plugins.lock.json')) +e=d['superpowers'] +assert e['source']=='https://github.com/obra/superpowers', e['source'] +assert e['commit']=='5bf4e78011075bcfc0dc295f0724994cd123ee71', e['commit'] +assert e['path']=='skills', e.get('path') +assert e.get('managed_by')=='curl' +want={'brainstorming','writing-plans','subagent-driven-development','test-driven-development','requesting-code-review','using-git-worktrees','writing-skills'} +assert set(e['skills'])==want, set(e['skills'])^want +for k,files in e['skills'].items(): + assert 'SKILL.md' in files, k + for f in files: assert re.fullmatch(r'[A-Za-z0-9._/-]+',f) and '..' not in f, f +assert 'scripts/sdd-workspace' in e['skills']['subagent-driven-development'] +assert 'code-reviewer.md' in e['skills']['requesting-code-review'] +assert 'anthropic-best-practices.md' in e['skills']['writing-skills'] +print('LOCK_OK') diff --git a/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c2.py b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c2.py new file mode 100644 index 0000000..566a4b0 --- /dev/null +++ b/.claude/tasks/contracts/2026-09-28-superpowers-vendored-1357.oracles/c2.py @@ -0,0 +1,17 @@ +import json,os,hashlib,glob +H=os.path.expanduser('~') +e=json.load(open('plugins.lock.json'))['superpowers'] +cache=glob.glob(H+'/.claude/plugins/cache/superpowers-marketplace/superpowers/6.4.1/skills') +missing=[];mism=[] +for k,files in e['skills'].items(): + for f in files: + p=f'skills-external/{k}/{f}' + if not os.path.isfile(p): missing.append(p); continue + if cache: + c=f'{cache[0]}/{k}/{f}' + if os.path.isfile(c) and hashlib.md5(open(p,'rb').read()).hexdigest()!=hashlib.md5(open(c,'rb').read()).hexdigest(): mism.append(p) + link=f'{H}/.claude/skills/{k}' + if not (os.path.islink(link) and os.path.isfile(link+'/SKILL.md')): missing.append(link) +assert not missing, missing +assert not mism, ('byte mismatch vs plugin cache',mism) +print('VENDORED_LINKED') diff --git a/.claude/tasks/plans/2026-09-28-superpowers-vendored-1357.md b/.claude/tasks/plans/2026-09-28-superpowers-vendored-1357.md new file mode 100644 index 0000000..43c2ab8 --- /dev/null +++ b/.claude/tasks/plans/2026-09-28-superpowers-vendored-1357.md @@ -0,0 +1,271 @@ +# 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_on` mechanism pinned: the python lock + reader emits a third column, `_dv_check_link` gets a 5th param, headers + updated, a helper extracted if `check_vendored_skills` would 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 at + `https://raw.githubusercontent.com/obra/superpowers//skills//`, + 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//`): + 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 as `bash scripts/` (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.sh` `vendor_pinned_skills [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 + unless `refresh`. install-plugins.sh STEP 8e calls it for agent-skills and + mengto-skills with `EXT_SKILL_NAMES` symlink check; update-all.sh 7.3 calls + it with `refresh`. link.sh `EXTERNAL_SKILLS=(…)` symlinks + `skills-external/` into `~/.claude/skills/`; .gitignore lists + `skills/` (symlink) and `skills-external//` (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 allowlist + `set` parks — the 7 are NOT added (always on, like darwin-skill). +- lib/detect-plugins.sh `detect_superpowers`: plugin cache glob then `claude + plugin list`. Consumers: hooks/session-start.sh:122 (`+ 800` passive), + 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). +1. plugins.lock.json: new entry `"superpowers"` after `"mengto-skills"`: + source `https://github.com/obra/superpowers`, commit + `5bf4e78011075bcfc0dc295f0724994cd123ee71`, path `skills`, `skills` = the + dict above (exact file lists), managed_by `curl`, `"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 as `bash scripts/`, 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." +2. 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_plugin` comment (:490) to name only security-guidance. + STEP 8e: heading/comment mention superpowers; `EXT_SKILL_NAMES` += the 7; + `vendor_pinned_skills superpowers` after 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)". +3. update-all.sh 7.3: `echo "── Updating superpowers skills (obra/superpowers)..."` + + `vendor_pinned_skills superpowers refresh`; comment names it. +4. link.sh EXTERNAL_SKILLS += the 7 (keep the array multi-line ≤ 80 chars). +5. .gitignore: 7 `skills/` lines next to the other external symlinks + (:65-68 block) and 7 `skills-external//` lines next to the mengto + block (:203-207), each block with a one-line comment "superpowers, vendored + (plugins.lock.json 'superpowers')". +6. 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"). +7. 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, no + `claude 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` + (the `superpowers` entry does). Skills of such an entry are expected + LINKED whatever the active profile says (today every EXTERNAL_SKILLS name + absent from the profile is reported `parked`, link unchecked — the 7 are + in no profile by design). Mechanism: `_dv_lock_expectations` (python) + prints a THIRD column `name\tfile\t1` for skills of an `always_on` entry + (awk `$1==n {print $2}` in `_dv_check_files` keeps working unchanged); + `check_vendored_skills` reads the flag and passes it as a 5th parameter to + `_dv_check_link`, which treats `1` as "expected linked whatever the + profile says". If `check_vendored_skills` would 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 case + `ALWAYS_ON_LINK_CHECKED` to lib/tests/doctor-vendored.test.sh (fixture + entry with always_on true, name absent from the profile, link missing → + fail line, never `parked`). Document the field in lib/vendor-skills.sh's + lock-shape header comment (one line: ignored by the vendor helper, read + by doctor-vendored). +8. 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 what `detect_superpowers` proves + ("superpowers skills linked (brainstorming found); per-skill check under + Vendored skills"); :423 delete the `+ 1500` line (comment: counted by the + skill catalog stats). +9. 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. +1. `superpowers:` → `` (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: "Invoke `brainstorming` + (vendored superpowers skill)" on first mention per file, bare afterwards. +2. 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 finish` is the only + integration path" where they present it as available. +3. 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 + `superpowers` prefix 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 greps + `finishing-a-development-branch`, `executing-plans`, `systematic-debugging` + line by line); wrap at spaces only. +4. 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. +5. 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. +6. 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) then `make link`". +7. skills/profile/SKILL.md:59: "Always-on plugins (`security-guidance`) and + the vendored superpowers skills are never toggled by a profile". +8. 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": true` key from `enabledPlugins` and + the whole `extraKnownMarketplaces."superpowers-marketplace"` block, nothing + else; validate with `python3 -c 'import json;json.load(open("settings.json"))'`. +- Then, one shot by hand: `claude plugin uninstall superpowers@superpowers-marketplace` + and `claude plugin marketplace remove superpowers-marketplace`; re-check + `git diff settings.json` afterwards (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 `superpowers` skills until restart; + the bare names appear after `make 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.