Эх сурвалжийг харах

chore(memory): capitalize BDR-007 + BDR-008 from profile system

- BDR-007: Skill profiles partition gstack by usage (v1, skill-only).
  Decision to ship lib/profile.sh + symlink-based toggle for skills,
  with plugin/MCP entries advisory in v1. Rationale: the existing
  toggle-external.sh enable|disable gstack is too coarse — it
  disables checkpoint/ship/learn alongside design skills. Profiles
  hide the irrelevant skills without uninstalling the gstack repo.
  Alternatives rejected: forking SKILL.md to strip the gstack
  preamble (re-fork on every upgrade — preamble already degrades
  gracefully via `|| true`); per-skill toggle via claude plugin
  enable/disable (gstack skills are not marketplace plugins);
  removing symlinks (lossy if user has local edits).

- BDR-008: Profile system v2 — extend to plugins + MCPs + CLIs.
  Reverses the "advisory only" stance from BDR-007 alternative #4.
  User feedback: pure-skill toggling left ui-ux-pro-max/magic always
  loaded regardless of profile, so passive token cost didn't drop
  enough on profile switch. Solution: real claude plugin enable/
  disable for an explicit MANAGED_PLUGINS allowlist (3 entries) +
  PROTECTED_PLUGINS denylist for always-on (caveman, security-
  guidance, superpowers). MCP magic delegated to toggle-external.sh.
  Other MCPs stay advisory because each needs specific config. Adds
  4 new profiles: web, seo, web-full, backend.

- Journal: 2026-05-04 entry summarizing the v1 ship, then a follow-up
  block for the v2 extension (new profiles, plugin auto-toggle, tie-
  breaker for `current`).

- TODO.md: marked done — v1 (Skill profiles) section and v2 (Profile
  system v2 — extension plugins/MCPs/CLIs) section, both with their
  full subtask lists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bastien 1 долоо хоног өмнө
parent
commit
d694a9e0da

+ 38 - 0
.claude/memory/decisions.md

@@ -112,3 +112,41 @@ rules:
   - Caveman's `hooks/install.sh` writes absolute paths (`$HOME/.claude/hooks/caveman-*.js`) into `settings.json`. Since `settings.json` is symlinked into the repo, the absolute path would commit a username. STEP 5.5 runs a Python post-process to rewrite to portable `~/.claude/hooks/...` form (bash expands `~` before passing to `node`).
   - Caveman's hook files materialize in `hooks/` (the repo dir, not `~/.claude/hooks/`) because the latter is a symlink. They're added to `.gitignore` to prevent accidental commit of user-scope state.
 - **Reference**: install-plugins.sh STEP 5.5, lib/detect-plugins.sh `detect_caveman*` + `plugin_enabled`, doctor.sh caveman block, commit `9b20b84`.
+
+## BDR-007 — Skill profiles partition gstack by usage (design / dev / qa / audit / minimal)
+
+- **Date**: 2026-05-04
+- **Status**: accepted
+- **Decision**: ship `lib/profile.sh` + `lib/profiles/*.profile` to give the user fine-grained, task-shaped activation of skills. A profile is a plain-text file listing skill names + types (`gstack`, `external`, `personal`, `plugin`, `mcp`). `profile set <name>` enables the listed skills and disables every gstack-origin skill not in the profile, by moving symlinks between `skills/` and `skills-disabled/`. `profile reset` re-enables all of gstack. Plugin/MCP entries are advisory — script prints the manual `claude plugin enable` / `claude mcp add` command but never runs it. Surface area: one CLI (`bash lib/profile.sh`), one slash command (`/profile`), four Makefile targets, and a section in `agents/plugin-advisor.md`.
+- **Why**: when the user works on a focused kind of task (design only, qa only, audit only) the full gstack (~38 skills) injects irrelevant skill descriptions into every session. The existing `lib/toggle-external.sh enable|disable gstack` is too coarse — it disables the whole gstack including infrastructure skills the user does want (checkpoint, ship, learn). Profiles give the user a curated middle ground: keep the gstack repo installed, hide the skills not relevant to this session.
+- **Alternatives rejected**:
+  - Fork SKILL.md files to strip the ~70-line gstack preamble — rejected: every gstack upgrade would need to re-fork, and the preamble already degrades gracefully (`|| true`) when `gstack/bin/` is unavailable. Hiding the skill is cheaper than rewriting it.
+  - Per-skill toggle via `claude plugin enable/disable` — rejected: gstack skills are not marketplace plugins, they're symlinks owned by `skills-external/gstack/`. The CLI doesn't reach them.
+  - Disable via removing symlinks (rm + recreate on enable) — rejected: lossy if the user has local edits, and re-creation requires running gstack's own setup. Move-based toggle preserves the symlink intact.
+  - Auto-toggle plugins (`ui-ux-pro-max`) and MCPs as part of `set` — rejected: those affect global Claude Code state and may carry API keys (magic). Keep them advisory; user runs the CLI command knowingly.
+  - Build a giant `gstack-profile` CLI that wraps `gstack/bin/*` directly — rejected: scope creep into gstack internals. The repo already has its own toggle infra (`lib/toggle-external.sh`); profile.sh sits alongside it as a finer tool.
+- **Caveats**:
+  - Profiles do NOT change `gstack/bin/` infrastructure — preamble in disabled skills still references it, and re-enabling restores normal behavior. No telemetry/learnings data is touched.
+  - `cmd_set` only auto-disables skills returned by `gstack_skills()` (those with a `SKILL.md` under `skills-external/gstack/*/`). Personal skills (real dirs in `skills/`) are never auto-disabled by `set` — only added back if listed in the profile.
+  - `cmd_current` returns "full" when nothing has been disabled, even if a profile happens to be 100% covered by the current state. The active-profile heuristic requires at least one `gstack__*` entry in `skills-disabled/` so we don't lie about a profile being "set" when no `set` ever ran.
+  - Personal skills use `external`-style move (no `gstack__` prefix) so name-collision with gstack skills can't happen during disable.
+- **Reference**: `lib/profile.sh`, `lib/profiles/{design,dev,qa,audit,minimal}.profile`, `skills/profile/SKILL.md`, `agents/plugin-advisor.md` (DETECT block + TOGGLING EXTERNAL TOOLS section), `Makefile` targets `profile*`, `lib/toggle-external.sh` header pointer.
+
+## BDR-008 — Profile system v2: extend to plugins + MCPs + CLIs (web/seo/web-full/backend)
+
+- **Date**: 2026-05-04
+- **Status**: accepted
+- **Decision**: extend `profile.sh` to actually toggle Claude plugins (`claude plugin enable|disable <name>@<marketplace>`) and MCP servers (delegated to `lib/toggle-external.sh` for the `magic` MCP, advisory for others), and add CLI status reporting. New profile syntax uses `plugin@<marketplace>` so the script knows where to enable from. New profiles shipped: `web` (frontend website), `seo` (SEO/GEO/W3C audit), `web-full` (web + seo combined), `backend` (API/system dev — no design, no SEO). Reverted v1 decision (BDR-007 alternative #4 "advisory only for plugins/MCPs"): user explicitly asked for actual toggling so `set web` actively enables `ui-ux-pro-max` + `magic` and `set seo` actively disables `ui-ux-pro-max`. Always-on plugins (`caveman`, `security-guidance`, `superpowers`) are protected by both an allowlist (`MANAGED_PLUGINS`) and a denylist (`PROTECTED_PLUGINS`).
+- **Why**: v1 profiles only managed skills (symlink toggle). User feedback: "active TOUT le splugins necessaire pour tel profile et desactive les autre". Pure-skill toggling left ui-ux-pro-max/magic always loaded regardless of profile, so passive token cost didn't drop as much as expected when switching to a non-design profile. Auto-toggling plugins shifts the design from "show me the right skills" to "set up the right session" — closer to what the user actually wants.
+- **Alternatives rejected**:
+  - Keep plugins advisory + add a `--apply-plugins` flag — rejected: user would have to type the flag every time, defeating the "switch profile to switch context" workflow.
+  - Disable ALL non-listed plugins (including third-party user-installed ones) — rejected: too aggressive. Profile system has no business touching plugins the user installed for their own reasons. Solution: explicit `MANAGED_PLUGINS` allowlist (currently 3 entries) — the script touches only those.
+  - Treat MCPs identically to plugins (auto-toggle any MCP) — rejected: MCPs typically need env vars / API keys / specific commands. Auto-registering with wrong config produces broken MCPs (LRN-006). Compromise: auto-toggle ONLY `magic` because we already have its config in `lib/toggle-external.sh`. Other MCPs stay advisory.
+  - Track plugin state across `set/reset` cycles and restore on reset — rejected: complexity not worth it. `reset` re-enables gstack skills only. To re-enable a managed plugin, the user runs `apply <profile>` or the explicit `claude plugin enable` command. Documented in the `info` line printed at the end of `reset`.
+- **Caveats**:
+  - `MANAGED_PLUGINS` is hardcoded — adding a new toggle-managed plugin requires editing `profile.sh`. Acceptable for now (3 entries, rarely changes); revisit if it grows.
+  - `claude plugin enable` returns success even for already-enabled plugins, so the parser greps for "enabled|already" in stdout/stderr. Works on the current Claude CLI; brittle if the CLI rewords its messages. Acceptable risk.
+  - The `current` heuristic now counts `installed` (CLI status) as available. Without that, profiles listing CLIs would never reach 100% match. Tiebreaker: when two profiles tie on %, the larger total wins (web-full > web > design when all are 100%).
+  - `cmd_show` widened the TYPE column to 30 chars to fit `plugin@ui-ux-pro-max-skill` without breaking alignment.
+  - `mcp magic` toggle delegates to `lib/toggle-external.sh enable magic` which requires `MAGIC_API_KEY` in `.env`. If the key is missing, profile.sh prints an info line and continues — the rest of the profile still applies.
+- **Reference**: `lib/profile.sh` (`MANAGED_PLUGINS`/`PROTECTED_PLUGINS` arrays, `skill_status` plugin@/cli/mcp branches, `enable_skill`/`disable_skill` plugin@ + mcp branches, `cmd_set` plugin disable loop, `cmd_current` available-counting), `lib/profiles/{web,seo,web-full,backend}.profile`, refined `lib/profiles/{design,dev,qa,audit}.profile` (use `plugin@<marketplace>` syntax + `cli` entries), `skills/profile/SKILL.md` (updated profile table + mechanism table), `agents/plugin-advisor.md` (extended profile recommendation table).

+ 9 - 0
.claude/memory/journal.md

@@ -35,3 +35,12 @@ rules:
 - Discovered two co-masking bugs: `claude plugin install` doesn't enable (LRN-005) and `session-start.sh` was hardcoding "✅ ON: security-guidance rtk superpowers" regardless of actual state. Added `enable_plugin()` helper + `plugin_enabled()` detector reading `enabledPlugins` from `settings.json`. Banner now reflects reality.
 - Side fix: doctor.sh exited under `set -euo pipefail` when gstack/skills/ was missing — wrapped find in brace + `|| true`.
 - 3 atomic commits (`0184818..2ec7935`).
+
+## 2026-05-04
+
+- Built skill profile system (BDR-007): `lib/profile.sh` + `lib/profiles/{design,dev,qa,audit,minimal}.profile` partition gstack + personal skills by purpose. Activation toggles symlinks `skills/` ↔ `skills-disabled/`.
+- Wired into `agents/plugin-advisor.md` (DETECT call to `profile.sh current` + new `PROFILE` line in OUTPUT + new "Skill profiles" subsection in TOGGLING EXTERNAL TOOLS), `lib/toggle-external.sh` (header pointer), `Makefile` (4 targets), and `skills/profile/SKILL.md` (`/profile` slash command).
+- `cmd_current` honestly reports "full" when no `gstack__*` entry exists in `skills-disabled/` — avoids the "100% match" trap when the full gstack is on.
+- Tested end-to-end: list/show/current/diff/set/reset/apply all green; shellcheck clean; symlink state restored after reset.
+- Profile system v2 (BDR-008): extended `profile.sh` to actually toggle Claude plugins (`claude plugin enable|disable`) and MCP servers (`magic` via `lib/toggle-external.sh`). Added 4 new profiles: `web`, `seo`, `web-full`, `backend`. Refined existing profiles to use `plugin@<marketplace>` syntax + `cli` entries. Always-on plugins protected by `MANAGED_PLUGINS` allowlist + `PROTECTED_PLUGINS` denylist.
+- Verified: `set web` enables ui-ux-pro-max + magic; `set seo` disables ui-ux-pro-max; `set minimal` disables ui-ux-pro-max but spares caveman/security-guidance/superpowers. `current` heuristic respects ties (web-full beats web at 100%).

+ 26 - 0
.claude/tasks/TODO.md

@@ -127,3 +127,29 @@ Subtasks :
 - [ ] Patcher les skills perso restants : analyze, bugfix, code-clean, commit-change, doc, feat, geo, graphify, harden, hotfix, init-project, make-pdf, onboard, plan-tune, plugin-check, refactor, seo, ship-feature, skills-perso, status, benchmark-models, context-save, context-restore
 - [ ] Mettre à jour `~/.claude/CLAUDE.md` — mentionner convention --help disponible sur tous les skills perso
 - [ ] Note : skills-external/gstack ont leur propre convention, ne pas toucher
+
+## Skill profiles (partition gstack par usage)
+- [x] Plan
+- [x] `lib/profile.sh` — list/show/current/apply/set/reset/diff via symlink toggle
+- [x] `lib/profiles/{design,dev,qa,audit,minimal}.profile` — 5 profils
+- [x] `skills/profile/SKILL.md` — slash command `/profile`
+- [x] Wire `agents/plugin-advisor.md` — DETECT call profile.sh current + OUTPUT line PROFILE + nouvelle section "Skill profiles" dans TOGGLING EXTERNAL TOOLS
+- [x] Wire `lib/toggle-external.sh` — header pointer vers profile.sh
+- [x] `Makefile` — targets profile/profile-list/profile-current/profile-reset
+- [x] Tests : list/show/current/diff/set/reset/apply tous OK, shellcheck propre, symlinks bien restaurés après reset
+
+## Profile system v2 — extension plugins/MCPs/CLIs
+- [x] Inventaire complet : 7 plugins (4 ON / 3 OFF), 0 MCP local, 4 CLIs installés
+- [x] Définir `MANAGED_PLUGINS` (ui-ux-pro-max, plugin-dev, pr-review-toolkit) + `PROTECTED_PLUGINS` (caveman, security-guidance, superpowers)
+- [x] `profile.sh` étendu : nouveau type `plugin@<marketplace>` (auto-toggle via `claude plugin enable/disable`), `mcp` (delegate à toggle-external.sh pour magic), `cli` (advisory only)
+- [x] `cmd_set` désactive aussi les MANAGED_PLUGINS hors profil
+- [x] `cmd_reset` ne touche PAS aux plugins (info line explicite — re-enable manuel ou via apply)
+- [x] `cmd_current` : compte `enabled` + `installed`, tiebreaker = total le plus grand
+- [x] `cmd_show` : colonne TYPE élargie à 30 chars pour `plugin@ui-ux-pro-max-skill`
+- [x] 4 nouveaux profils : `web`, `seo`, `web-full`, `backend`
+- [x] Profils existants raffinés (design, dev, qa, audit) avec `plugin@<marketplace>` + `cli`
+- [x] `skills/profile/SKILL.md` : table profils mise à jour + table mécanisme par type
+- [x] `agents/plugin-advisor.md` : table de recommandations étendue avec web/seo/web-full/backend
+- [x] Tests : `set web` enable ui-ux-pro-max+magic, `set seo` disable ui-ux-pro-max, `set minimal` épargne always-on, `reset` restaure 64 skills
+- [x] Memoire : BDR-008 (v2 décision) + journal entry 2026-05-04
+- [x] Shellcheck propre