12 KiB
CONTRACT — default-profile-full
- date: 2026-09-25 | flow: feat | branch: feature/default-profile-full
- status: active
REQUEST (verbatim — IMMUTABLE)
User message:
il faudrait retirer l'API de magic 21st comme on en a plus besoin vu qu'on utilise le cli maintenant. egalement, il faudrait mettre un profil par defaut, quand aucunprofil n'est selectionne il faudrait que ca soit le full qui est actif
/feat $ARGUMENTS:
Profil par défaut = full : quand aucun profil n'est sélectionné (
.active-profileabsent, vide ou "none", aprèsreset), c'est le profilfullqui est actif (statusline,profile current,gstack off,reset). Même lot : retirer les résidus de l'API Magic 21st (commentaires/docs périmés MAGIC_API_KEY / magic MCP) puisque le CLI21sta remplacé le MCP.
CLARIFICATIONS
Pass A: none — request complete (outcome, scope and constraints derivable).
Ground truth found before pass B: the magic MCP wiring is already gone from
the live code (BDR-093, 2026-09-22): no mcpServers entry in ~/.claude.json,
no claude() wrapper in ~/.bashrc, MANAGED_MCPS empty. What remains is
prose: stale comments in lib/profile.sh (incl. a wrong usage() NOTE
claiming set toggles "the magic MCP"), .env.example, .gitleaks.toml,
install-plugins.sh, plugins.lock.json, lib/tests/profile-set-managed.test.sh,
README.md — plus ONE live MAGIC_API_KEY= line still in ~/.claude/.env
(count only; value never read).
Pass B [gated 2026-09-25] — 4 questions, all answered:
Q: reset semantics now that full is the default?
A: reset = set full (exclusive): the 20 gstack skills full does not list
are parked, the 5 design skills of the 21st pack + full's plugins/externals
are enabled. Label and state coincide (LRN-020).
Q: Fresh install (make plugin) — apply the default profile when none is selected?
A: Yes. install-plugins.sh ends by applying the default profile
(bash lib/profile.sh reset) when .active-profile is absent, empty or
reads none; an existing selection is left alone. Adds install-plugins.sh
to the executor scope (6 files — /feat cap of 5 exceeded by one 15-line
guarded block; accepted, not escalated to /ship-feature).
Q: README depth for the magic-MCP mentions?
A: One sentence of history: the 21st section is renamed "21st.dev CLI", keeps
one sentence ("replaces the former magic MCP, same endpoint, no key"),
drops the MCP-era risk / API-key / bashrc-wrapper paragraphs (that wrapper
no longer exists in ~/.bashrc). CHANGELOG untouched.
Q: Delete the leftover MAGIC_API_KEY= line in ~/.claude/.env?
A: Yes — done by the orchestrator (targeted sed -i on that one line, count
before 1 / after 0; value never read).
ACCEPTANCE CRITERIA
-
lib/profile.shdeclares the default profile ONCE,DEFAULT_PROFILE="full", andhooks/statusline.shderives its fallback from that constant (reads it from the lib; a literalfullmay exist there only as the unreadable-lib fallback). CHECK: grep -q '^DEFAULT_PROFILE="full"' lib/profile.sh && grep -q 'DEFAULT_PROFILE' hooks/statusline.sh && echo CONST_OK EXPECT: CONST_OK EVIDENCE: MET exit=0 marker-found :: CONST_OK -
[revised after challenge, 2026-09-25]
profile.sh currentis label-driven: it names$(active_profile)as its FIRST WORD in every state and never infers the profile from the parked-gstack count. With.active-profileabsent, empty ornonethe line containsdefault — not applied yet; with a cache naming a profile it contains% match; with a cache naming a profile that has no.profilefile it containsunknown profile. Right afterreseton a clean tree (no gstack linked, nothing parked — how a real tree looks under BDR-030) the line contains100% matchand NOTnot applied. No output claims "all gstack skills enabled". (judgement + suite criterion 6, tests T1/T4/T5/T6/T7) -
profile.sh gstack offwith.active-profileabsent, empty, or readingnoneexits 0 and trims gstack to the default profile's list (no "no active profile" error for those three states). A cache naming a profile whose file does not exist still errors (rc 1). (judgement + suite criterion 6, tests T2/T2b/T3/T4) -
profile.sh resetlands on the default profile: it writesfullto.active-profile, and the resulting skill/plugin/external state is what the gated answer below specifies. The literalwrite_active "none"no longer exists; nothing inlib/profile.shwritesnoneto the cache. CHECK: ! grep -q 'write_active "none"' lib/profile.sh && ! grep -qE 'write_active +none' lib/profile.sh && echo NONE_GONE EXPECT: NONE_GONE EVIDENCE: MET exit=0 marker-found :: NONE_GONE -
hooks/statusline.shprintsprofile: fullwhen.active-profileis absent, empty or readsnone, andprofile: <name>when the cache names a profile. (judgement + suite criterion 6, tests T8/T9/T10/T11) -
New hermetic suite
lib/tests/profile-default.test.sh(fixture repo viaPROFILE_REPO_OVERRIDE+TOGGLE_EXTERNAL_REPO_OVERRIDE, fakeclaudeon PATH, same harness asprofile-set-managed.test.sh) passes and covers criteria 2, 3, 4, 5. CHECK: bash lib/tests/profile-default.test.sh 2>&1 | tail -1 | grep -qE '^PASS=[0-9]+ FAIL=0$' && echo DEFAULT_SUITE_OK EXPECT: DEFAULT_SUITE_OK EVIDENCE: MET exit=0 marker-found :: DEFAULT_SUITE_OK -
The existing managed-set suite stays green. CHECK: bash lib/tests/profile-set-managed.test.sh 2>&1 | tail -1 | grep -qE '^PASS=[0-9]+ FAIL=0$' && echo MANAGED_SUITE_OK EXPECT: MANAGED_SUITE_OK EVIDENCE: MET exit=0 marker-found :: MANAGED_SUITE_OK
-
Help and docs in scope describe the new behaviour:
usage()+ the header block oflib/profile.sh,skills/profile/SKILL.md(reset line, output policy, failure-mode row aboutcurrentsayingnone), and the Makefileprofile-resethelp string name the default profile and no longer describeresetas "re-enable all gstack skills" norcurrentas returningnone. CHECK: grep -qi 'default profile' skills/profile/SKILL.md && grep -qi 'default' Makefile && ! grep -q 'Re-enable all gstack skills (undo any profile set)' Makefile && ! grep -q 'currentsaysnone' skills/profile/SKILL.md && echo DOCS_OK EXPECT: DOCS_OK EVIDENCE: MET exit=0 marker-found :: DOCS_OK -
Magic 21st residue is gone from the tracked tree outside history and registries: no
MAGIC_API_KEY,@21st-dev/magic, or the wordmagicas a standalone token (the MCP) in any tracked file exceptCHANGELOG.md,.claude/**,lib/tests/fixtures/**(frozen snapshots) andlib/project-archetypes/**("magic numbers" is prose) and, [gated 2026-09-25] exactly ONE line ofREADME.md(the history sentence the user chose to keep). Positive control: the same search ondevelopstill trips. CHECK: git grep -qiI -e 'MAGIC_API_KEY' develop -- . ':!CHANGELOG.md' ':!.claude' ':!lib/tests/fixtures' || exit 1; git grep -iIl -e 'MAGIC_API_KEY' -e '@21st-dev/magic' -- . ':!CHANGELOG.md' ':!.claude' ':!lib/tests/fixtures' | grep -q . && exit 1; git grep -iIl -e '[^a-zA-Z]magic[^a-zA-Z-]' -- . ':!CHANGELOG.md' ':!.claude' ':!lib/tests/fixtures' ':!lib/project-archetypes' ':!README.md' | grep -q . && exit 1; [ "$(grep -ci 'magic' README.md)" -eq 1 ] && echo RESIDUE_GONE EXPECT: RESIDUE_GONE EVIDENCE: MET exit=0 marker-found :: RESIDUE_GONE -
shellcheck clean on every touched shell file. CHECK: shellcheck lib/profile.sh hooks/statusline.sh lib/tests/profile-default.test.sh lib/tests/profile-set-managed.test.sh install-plugins.sh lib/toggle-external.sh >/dev/null 2>&1 && echo SHELLCHECK_OK EXPECT: SHELLCHECK_OK EVIDENCE: MET exit=0 marker-found :: SHELLCHECK_OK
-
(judgement) No new dependency. LRN-020 honoured:
fullnames the real default profile,resetapplies it and a fresh install applies it when nothing is selected, so no label denotes "nothing applied"; the parenthetical after the name says whether the profile is applied (% match) or merely in force (default — not applied yet). The cross-profile "best guess" scan is replaced by the match of the labelled profile only (one profile scored instead of ten). -
[gated 2026-09-25, revised after challenge]
install-plugins.shapplies the default profile at the very end of the install (a Step 11 AFTER the Step 10link.shrefresh, BEFORE the Install Summary) by callingbash "$REPO/lib/profile.sh" resetONLY when.active-profileis absent, empty or readsnone; the call is guarded (|| warn …, the installer runs underset -e) so a failure never hides the Summary; an existing selection is re-applied withbash "$REPO/lib/profile.sh" set "$SEL"(same guard) because Step 2 re-parks gstack and Step 10'slink.shre-links the design externals on every run — the label never changes, its state comes back; a missinglib/profile.shwarns and skips. Step 8.7 no longer parks the 21st pack unconditionally (that block is removed: a re-run must never re-park what the selected profile or the user enabled); its comments and the Summary line say the design skills follow the profile and the publishing skills stay on demand, with no hard-coded counts. The installer itself is NEVER executed during this run (side effects: npm, claude plugin) —bash -n+ shellcheck only. CHECK: r=$(grep -n 'lib/profile.sh" reset' install-plugins.sh | head -1 | cut -d: -f1); l=$(grep -n 'bash "$REPO/link.sh"' install-plugins.sh | head -1 | cut -d: -f1); s=$(grep -n 'Install Summary' install-plugins.sh | head -1 | cut -d: -f1); [ -n "$r" ] && [ -n "$l" ] && [ -n "$s" ] && [ "$l" -lt "$r" ] && [ "$r" -lt "$s" ] && grep -q 'active-profile' install-plugins.sh && grep -A1 'lib/profile.sh" reset' install-plugins.sh | grep -q '|| *warn' && grep -A1 'lib/profile.sh" set "$SEL"' install-plugins.sh | grep -q '|| *warn' && ! grep -q 'toggle-external.sh" disable 21st' install-plugins.sh && bash -n install-plugins.sh && echo INSTALL_DEFAULT_OK EXPECT: INSTALL_DEFAULT_OK EVIDENCE: MET exit=0 marker-found :: INSTALL_DEFAULT_OK -
[revised after challenge] The citers of the old
current/resetsemantics outside the profile files are patched in the same diff:agents/plugin-advisor.mdno longer expects"custom"fromcurrentnor states thatresetleaves plugin state untouched; thelib/toggle-external.shheader namesresetas the way back to the default profile.cmd_gstack onand SKILL.md no longer claim to "(re-)enable ALL gstack". CHECK: ! grep -q 'or "custom"' agents/plugin-advisor.md && ! grep -q 'Plugin state is NOT touched by reset' agents/plugin-advisor.md && grep -qi 'default profile' lib/toggle-external.sh && ! grep -q 'all gstack skills already enabled' lib/profile.sh && ! grep -q 'all gstack enabled' lib/profile.sh && ! grep -qi 're-enable ALL gstack' skills/profile/SKILL.md && echo CITERS_OK EXPECT: CITERS_OK EVIDENCE: MET exit=0 marker-found :: CITERS_OK
FILE SCOPE
Executor (feater) — the feature:
- lib/profile.sh (DEFAULT_PROFILE, active_profile(), reset, current, gstack off, usage, header)
- hooks/statusline.sh (fallback = default profile)
- lib/tests/profile-default.test.sh (new)
- skills/profile/SKILL.md (docs)
- Makefile (profile-reset help string)
- install-plugins.sh ([gated 2026-09-25] final default-profile step + 8.7 comment + summary line)
- agents/plugin-advisor.md ([revised after challenge] two citers of
current/resetsemantics) - lib/toggle-external.sh ([revised after challenge] one header-comment citer of
reset)
Orchestrator, committed BEFORE dispatch as chore(21st): drop magic MCP residue
(prose only, no logic — the executor's diff starts after it):
- .env.example, .gitleaks.toml, install-plugins.sh (Step 8.7 header comment), plugins.lock.json (21st note), lib/profile.sh (comments + usage NOTE), lib/tests/profile-set-managed.test.sh (header comment), README.md (21st section + MCP-secret section wording).
Out of scope: CHANGELOG.md history, .claude/** registries (append-only),
lib/tests/fixtures/** snapshots, lib/profiles/*.profile contents, the
gstack submodule, ~/.claude/.env (user's file — gated question).