build(apm): consume holocron plugins through apm instead of plugin install
Why:
The repo published apm packages but consumed them the old way — `claude plugin install
<name>@holocron`, six plugins enabled per project. Dogfooding stopped one layer short of the
install tooling kyberforge itself ships.
Implementation notes:
- Root apm.yml declares the six packages as dependencies.apm git+path objects against the
holocron remote. Object form over `<name>@holocron` aliases on purpose: an alias first needs
`apm marketplace add`, which writes to ~/.apm/marketplaces.json — user scope, absent on a fresh
clone. Unpinned against the default branch, matching the autoUpdate the native install had.
- apm.lock.yaml is committed; .claude/skills/, .claude/agents/ and apm_modules/ are gitignored
regenerable install output. Committing the deployed skills would add a third mirror of content
ADR-0017 already governs two copies of.
- .mcp.json is generated by apm from plugins/bin/.mcp.json, so the obsidian MCP server survives
the switch.
- .claude/settings.json is reduced to {"hooks": {}}. apm replays the install into a scratch tree
and diffs, so any repo-owned key there is permanent drift that fails apm-audit-ci. Nothing was
lost: enabledPlugins was empty after the uninstall and the only hooks entry was PreToolUse: [].
- tests/run-bats.sh and tests/run-tests.sh exclude apm_modules/. It holds a full copy of every
plugin, and a copied .bats file resolves its helpers against the dependency root rather than
this repo — 334 tests, 167 failures before the exclusion.
Impact:
Skills are now unnamespaced — `git-commits`, not `git:git-commits` — because apm deploys plain
project skills with no plugin to prefix. AGENTS.md, CONTEXT.md and docs/spec/architecture.md are
updated accordingly. Root apm.yml now declares dependencies, which arms apm-audit-ci's
lockfile-exists check for the root manifest. External consumers are unaffected: the marketplace
manifests are untouched and `apm pack --check-clean` stays clean. Project scope only.
ADR: 0018
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
This commit is contained in:
@@ -21,6 +21,13 @@ fi
|
||||
# keeps the loop in this shell so the appends survive. `sort` is still fed
|
||||
# newline-delimited output, exactly as before. Same convention as
|
||||
# tests/run-tests.sh.
|
||||
#
|
||||
# apm_modules/ is excluded because `apm install` materializes a full copy of
|
||||
# every dependency there — including this repo's own plugins, which it consumes
|
||||
# from the holocron remote. Those copies carry their own .bats files whose
|
||||
# relative paths (`$BATS_TEST_DIRNAME/../../../../../../`) resolve to the
|
||||
# dependency's root, not this repo's, so they fail on a missing bats-support
|
||||
# helper. They are the same tests already discovered under plugins/.
|
||||
TEST_FILES=()
|
||||
while IFS= read -r f; do
|
||||
TEST_FILES+=("$f")
|
||||
@@ -29,6 +36,7 @@ done < <(
|
||||
-not -path "*/tests/bats/*" \
|
||||
-not -path "*/test_helper/*" \
|
||||
-not -path "*/.claude/worktrees/*" \
|
||||
-not -path "*/apm_modules/*" \
|
||||
| sort
|
||||
)
|
||||
|
||||
@@ -67,7 +75,7 @@ if [[ -n "$GIT_TOPLEVEL" && "$GIT_TOPLEVEL" == "$REPO_ROOT" ]]; then
|
||||
[[ -n "$f" ]] && EXPECTED_FILES+=("$REPO_ROOT/$f")
|
||||
done < <(
|
||||
git -C "$REPO_ROOT" ls-files -- '*.bats' \
|
||||
| grep -Ev '(^|/)tests/bats/|(^|/)test_helper/|(^|/)\.claude/worktrees/' \
|
||||
| grep -Ev '(^|/)tests/bats/|(^|/)test_helper/|(^|/)\.claude/worktrees/|(^|/)apm_modules/' \
|
||||
| sort || true
|
||||
)
|
||||
else
|
||||
|
||||
@@ -119,6 +119,10 @@ run_bats
|
||||
# /bin/bash 3.2, which has no `mapfile`. Process substitution (not a pipe)
|
||||
# keeps the loop in this shell so the appends survive. `sort` is still fed
|
||||
# newline-delimited output, exactly as before.
|
||||
#
|
||||
# apm_modules/ is excluded for the same reason tests/run-bats.sh excludes it:
|
||||
# `apm install` materializes dependency copies of this repo's own plugins there,
|
||||
# and re-running a dependency's tests re-runs what plugins/ already covers.
|
||||
SCRIPTS=()
|
||||
while IFS= read -r script; do
|
||||
SCRIPTS+=("$script")
|
||||
@@ -126,6 +130,7 @@ done < <(
|
||||
find "$SEARCH_ROOT" -name "test-*.sh" \
|
||||
-not -path "*/.git/*" \
|
||||
-not -path "*/.claude/worktrees/*" \
|
||||
-not -path "*/apm_modules/*" \
|
||||
| sort
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user