chore: drop the flat content mirror and native install support (ADR-0024)

apm becomes the only supported install path. The flat mirror at each plugin
root existed solely so Claude Code's native `claude plugin install` could
convention-scan plugin content (ADR-0017). With no native consumers, it cost
~20,000 tracked lines plus ~2,100 lines of sync tooling and ~88s of every
push to guard content apm never reads — and its only automated gate,
`claude plugin validate --strict`, passes on a plugin with zero content, so
it could not detect the defect ADR-0017 was created to fix.

Removes the mirror (213 files), the six per-plugin manifest pairs,
sync-plugin-content.sh, its 1,289-line test, the orphaned
marketplace-plugins.sh, and the check-plugin-content-sync and
validate-plugins pre-push hooks. The root `marketplace:` block and
.claude-plugin/ catalogue stay: apm's own marketplace consumers read that
same file, so `<name>@holocron` short names keep working.

tests/run-bats.sh now excludes .claude/skills/. apm installs from .apm/,
which carries the tests/ dirs the mirror stripped, so deployed .bats files
would otherwise be discovered and double-run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
This commit is contained in:
2026-09-14 16:59:42 +00:00
parent 0dffff3c21
commit 718c79af70
245 changed files with 298 additions and 22602 deletions

View File

@@ -28,6 +28,13 @@ fi
# 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/.
#
# .claude/skills/ is excluded for the same reason, one install step later. apm
# deploys skills there straight from each plugin's `.apm/` tree, `tests/` dirs
# and all, so every `<skill>/tests/*.bats` file under plugins/ also lands at
# .claude/skills/<name>/tests/ and would be discovered and run a second time.
# (It used to be invisible here: the generated flat mirror apm installed from
# stripped `tests/` out. The mirror is gone, so the exclusion is explicit.)
TEST_FILES=()
while IFS= read -r f; do
TEST_FILES+=("$f")
@@ -37,6 +44,7 @@ done < <(
-not -path "*/test_helper/*" \
-not -path "*/.claude/worktrees/*" \
-not -path "*/apm_modules/*" \
-not -path "*/.claude/skills/*" \
| sort
)
@@ -75,7 +83,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/|(^|/)apm_modules/' \
| grep -Ev '(^|/)tests/bats/|(^|/)test_helper/|(^|/)\.claude/worktrees/|(^|/)apm_modules/|(^|/)\.claude/skills/' \
| sort || true
)
else
@@ -120,9 +128,8 @@ fi
# flushed in stable sorted order once every job has finished.
#
# Dispatch and throttling is scripts/lib/batch-run.sh's batch_run -- shared
# with scripts/sync-plugin-content.sh and tests/run-tests.sh so a batching bug
# fix only needs to land once; see that file for why this is batched rather
# than a rolling `wait -n` pool.
# with tests/run-tests.sh so a batching bug fix only needs to land once; see
# that file for why this is batched rather than a rolling `wait -n` pool.
SCRATCH_ROOT="$(mktemp -d)"
trap 'rm -rf "$SCRATCH_ROOT"' EXIT
# Repo-root-relative -- see tests/run-tests.sh for why `../scripts/...` does not

View File

@@ -156,9 +156,8 @@ done < <(
# write back into the live repo tree -- verified before adding this), so they
# run concurrently in fixed-size batches instead of one at a time. Dispatch and
# throttling is scripts/lib/batch-run.sh's batch_run -- shared with
# scripts/sync-plugin-content.sh and tests/run-bats.sh so a batching bug fix
# only needs to land once; see that file for why this is batched rather than a
# rolling `wait -n` pool.
# tests/run-bats.sh so a batching bug fix only needs to land once; see that
# file for why this is batched rather than a rolling `wait -n` pool.
SCRATCH_ROOT="$(mktemp -d)"
trap 'rm -rf "$SCRATCH_ROOT"' EXIT
# The source= path below is repo-root-relative, matching scripts/install.sh:5 --

View File

@@ -10,8 +10,7 @@ pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
# Same `exit 77` (automake convention; run-tests.sh renders it as SKIPPED) guard
# tests/test-vale-wrap.sh and tests/test-sync-plugin-content.sh use for a missing
# binary. Without it this suite reported 5 genuine failures on a machine with no
# tests/test-vale-wrap.sh uses for a missing binary. Without it this suite reported 5 genuine failures on a machine with no
# vale, none of which were regressions.
#
# The suite SKIPPING while the script it tests HARD-FAILS is deliberate, not an

View File

@@ -513,12 +513,12 @@ else
fi
# --- 10f. A skip reason printed on STDERR, with no `SKIP:` prefix, still lands ---
# There is no house format: three suites print `SKIP: <reason>` on stdout and
# tests/test-sync-plugin-content.sh prints `apm not installed -- skipping (...)`
# on stderr. batch-run.sh folds stderr into the same log, so both are reachable,
# but only a fallback chain finds the second one. Without this case the reason
# extraction could be narrowed to the `SKIP:` prefix and the apm suite would fail
# the gate with no indication of what to install.
# There is no house format: suites print `SKIP: <reason>` on stdout, while an
# unprefixed reason on stderr (`<tool> not installed -- skipping (...)`) is
# equally valid. batch-run.sh folds stderr into the same log, so both are
# reachable, but only a fallback chain finds the second one. Without this case
# the reason extraction could be narrowed to the `SKIP:` prefix and such a suite
# would fail the gate with no indication of what to install.
echo ""
echo "--- a stderr skip reason with no SKIP: prefix is still reported ---"
DIR10F="$(make_fake_repo)"

File diff suppressed because it is too large Load Diff

View File

@@ -460,11 +460,11 @@ fi
# - tests/*.sh — the runners and every regression test
# - plugins/*/.apm/**/*.sh — the scripts plugins ship to users
# - providers/**/*.sh — the scripts install.sh deploys to user machines
# plugins/*/skills/** is deliberately NOT scanned: it is the generated mirror of
# .apm/, so scanning both double-reports every finding, and mirror-vs-source
# drift is already sync-plugin-content.sh --check's job. Scanning .apm/ is what
# closed the gap where skill-audit's vale-wrap.sh was covered but agent-audit's
# byte-identical copy of it was not.
# .apm/ is the only plugin content scanned, and it is the only plugin content
# there is: the generated flat plugins/*/skills/** mirror was deleted with
# native plugin-install support, so there is no second copy to double-report.
# Scanning .apm/ is what closed the gap where skill-audit's vale-wrap.sh was
# covered but agent-audit's byte-identical copy of it was not.
# providers/**/*.sh was excluded until issue #96: statusline-command.sh seeded
# `parts=()` empty and expanded it unguarded, a real latent hazard rather than a
# false positive, in a file this case did not own. That expansion is now guarded,