Skip to content

feat(setup): offer an optional committed default plugin set - #1196

Merged
potiuk merged 16 commits into
apache:mainfrom
potiuk:feat/committed-default-set
Sep 10, 2026
Merged

feat(setup): offer an optional committed default plugin set#1196
potiuk merged 16 commits into
apache:mainfrom
potiuk:feat/committed-default-set

Conversation

@potiuk

@potiuk potiuk commented Sep 10, 2026

Copy link
Copy Markdown
Member

Stacked on #1195. Until that merges this PR also shows its commits; the 16 commits from docs(design) onward are this one's.

A marketplace install is per-machine and commits nothing, so every contributor installs Magpie by hand. A project can instead commit a small .claude/settings.json block naming the marketplace and a three-plugin floor — magpie-setup, magpie-utilities, magpie-agent-guard — so anyone who clones and trusts the repo arrives ready. That block was documented but nothing ever wrote it.

setup now offers to, once, opt-in, defaulting to no, Claude Code only (Codex can only default-install all ten families; Gemini has no workspace-extension mechanism). Committing the block is optional and is not a prerequisite — the plugins work in the repo either way, and declining leaves a complete install. verify reports a block that falls behind the floor as drift, and reports an absent one informationally, never as a fault. uninstall removes only the three entries it added.

Everything here is prose in skill files: a family plugin ships no tools/, so nothing may depend on a helper existing on the adopter's machine. Behaviour is covered by four new skill-evals suites (14 cases).

A caveat reviewers should know about that evidence. The eval harness's documented automated mode, --cli "claude -p" from the repo root, is unsound in two ways I measured: that CLI has file tools and can read the fixtures' own expected.json, and even with every tool disabled it absorbs project context from its working directory. A skill section stubbed to one sentence scored full marks under the documented command. These suites were validated with tools disabled and the runner invoked from outside the repository — 14/14 green, and failing as expected against stubbed sections. The harness issue itself is not fixed here; it affects all 75 suites and deserves its own change.

Subsystems B (per-skill first-run wizard) and C (wizard screenshots) are designed in docs/designs/ but not implemented.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv

… first-run wizard

Design for three subsystems, delivered in order. A: setup offers, once
and opt-in, to commit the default-set block and scaffold the config
store — both optional, Claude Code only. B: every non-setup skill
declares its required config and a missing file hands off to a wizard.
C: the docs and screenshots.

Records why 'sync the block on every plugin install' is not
implementable — no code runs on plugin install or upgrade on most
harnesses — and why a fixed floor makes it unnecessary.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Six tasks, each test-first against the skill-evals harness: the Step M5
offer and harness gate, the merge rules, the verify staleness check, the
uninstall removal, the docs, and the spec-loop acceptance criteria.

Records the constraint that shaped the approach: a family-plugin install
ships .claude-plugin/ and skills/ only, so nothing here may depend on a
Python helper existing on the adopter's machine. The agent performs the
merge itself from prose rules, and the eval suite is what tests them.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Claude Code only, opt-in, defaulting to no. Both repo-side artefacts —
the enabledPlugins floor and the config store — are offered in one
question, and declining leaves a finished install.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
The output spec restated the decision rules, so a model could answer
every field without reading Step M5 — three of four cases passed against
the pre-change install.md. It now states the JSON contract only.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
The schema block rendered artefacts_offered as a literal array holding
both members in order — the expected answer for two cases. It now shows
a placeholder; the allowed members and their ordering stay in prose.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Only extraKnownMarketplaces and enabledPlugins are touched; an existing
apache-magpie definition is left alone; floor members are added and
nothing is removed; a malformed file is reported, never rewritten.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
…outcomes

The merge rules said 'add missing floor members' without naming them,
so the three entries reached the model only through the eval's output
spec — both a leak and a gap, since the runner extracts that subsection
alone. The spec's field definitions now say what each field reports,
not what the skill decides.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
'The keys the merge left untouched' turned on whether a managed key
happened to need an edit, so a settings file whose apache-magpie
definition was already pinned reported that key as preserved.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
…written

An agent reading only the merge rules had to infer that creating a fresh
settings file means populating enabledPlugins with the floor. The git add
line also read unconditionally, including on the refuse path where
nothing was written.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
An absent block is reported informationally and is never a fault — the
committed set is optional. A block missing floor members is drift, with
a repair offer.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
case-3-stale's report named the absent floor member outright, so the
missing list could be copied from the input. case-2-current listed
exactly the floor, so 'everything looks fine' reached the right answer
without knowing what the floor is.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
… glyphs

Read literally, the stale rule made all three floor entries 'missing'
when no block exists at all. The section also reported in prose while
every other check drives the recap through the glyph column; absent and
current now map to the non-fault glyph.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Other plugins in enabledPlugins survive, other marketplaces survive, and
the settings file is never deleted — it belongs to the project, the same
convention that preserves .apache-magpie-overrides/ by default.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Says plainly in both places that committing the block is optional and
that the plugins work in the repo either way.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
Written against what shipped rather than what the plan predicted: the
fixed floor, the single combined Claude-Code-only offer, absent-is-never
-a-fault, and the docs' optionality statement.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
The directory was added with no route to it — docs/index.md's navigation
table gained no row, so the design and its plan were discoverable only by
knowing the path. Adds the row and a README that says what a design is
for and how it differs from a spec-loop spec.

Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_01M7zttXzAM1wbTdBAjJCECv
@potiuk
potiuk marked this pull request as ready for review September 10, 2026 18:23
@potiuk
potiuk force-pushed the feat/committed-default-set branch from f38bfba to 87a7ab4 Compare September 10, 2026 18:23
@potiuk
potiuk merged commit d844af5 into apache:main Sep 10, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant