Why:1929ffdandb9c7762preserved every constant, hook ID and error string, but two don't-re-litigate notes were lost. Both were guard-rails — they fired from preloaded context, before the mistake. Restoring the sentence to an on-demand spec doc restores the text without restoring the function, since an on-demand file is opened after a plan is formed, not before. Implementation notes: placed by when each note must fire, not by what it is about. - "Do not expect `apm pack` to refresh the .github/plugin/marketplace.json mirror" now lives in the DRIFT failure message of the script and hook that already catch that exact mistake. It costs no preloaded tokens, fires at the moment of the error, and cannot be missed. No test asserts on that message; --check and shellcheck both pass. - Plugin self-containment has no gate that fires on it, so it goes in architecture.md's Plugin model beside "self-contained plugin units", stated as the constraint it is rather than a description, with the two consequences that make it load-bearing: the duplicated Vale styles (ADR-0014) and ADR-0020's constants copied into three validators. Impact: the every-session set is unchanged — neither note returns to AGENTS.md.
71 lines
3.4 KiB
Bash
Executable File
71 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# .claude-plugin/marketplace.json is apm's compiled Claude marketplace output (see
|
|
# apm.yml's marketplace.outputs.claude). GitHub Copilot CLI's manifest lookup accepts
|
|
# that same file at .claude-plugin/marketplace.json directly, but also has a legacy
|
|
# convention path at .github/plugin/marketplace.json (see
|
|
# plugins/kyberforge/docs/research/docs/github-copilot-plugins/marketplace.md) -- and
|
|
# that path is a mirror of the Claude output, not a separate apm
|
|
# output profile (apm only ships "claude" and "codex" mappers; codex writes a
|
|
# differently-shaped file to .agents/plugins/marketplace.json, not this path). This
|
|
# script keeps that legacy mirror byte-identical to .claude-plugin/marketplace.json
|
|
# instead of letting it silently drift (see issue #90 comment thread).
|
|
|
|
# Hard error, not a `|| pwd` fallback. Every path this script touches hangs off
|
|
# REPO_ROOT, and both of its exits-0 paths are "the files agree" or "neither file
|
|
# exists" -- so a REPO_ROOT pointing somewhere that is not this repo reports "no
|
|
# drift" over a tree it never looked at. Run `--check` from an empty directory
|
|
# outside any worktree and the fallback made that the literal outcome: rev-parse
|
|
# failed, REPO_ROOT became $PWD, neither file was there, exit 0. Refusing to guess
|
|
# is the only answer that cannot be silently wrong; the `-f "$DST"` branch below
|
|
# covers a genuinely stale mirror, which is a different condition.
|
|
if ! REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || [[ -z "$REPO_ROOT" ]]; then
|
|
echo "Error: not inside a git worktree -- cannot locate the repository root, and guessing \$PWD would let --check report \"no drift\" over a tree it never inspected. Run this from within the repository." >&2
|
|
exit 1
|
|
fi
|
|
SRC="$REPO_ROOT/.claude-plugin/marketplace.json"
|
|
DST="$REPO_ROOT/.github/plugin/marketplace.json"
|
|
|
|
usage() {
|
|
echo "Usage: $0 [--check]" >&2
|
|
exit 1
|
|
}
|
|
|
|
CHECK=0
|
|
if [[ "${1:-}" == "--check" ]]; then
|
|
CHECK=1
|
|
shift
|
|
fi
|
|
[[ $# -eq 0 ]] || usage
|
|
|
|
if [[ ! -f "$SRC" ]]; then
|
|
# A missing source with a surviving mirror is drift, not absence: the mirror
|
|
# can only be stale (nothing is left for it to be byte-identical to), which is
|
|
# precisely the silent divergence this script exists to prevent. Exiting 0
|
|
# here would report "no drift" over a mirror of a file that no longer exists.
|
|
# (An unresolvable REPO_ROOT is handled above and is a hard error; this branch
|
|
# is only about a source file that is genuinely gone from a real worktree.)
|
|
# scripts/sync-plugin-content.sh --check --all already errors on the same
|
|
# condition ("requires .../marketplace.json"); this matches it.
|
|
# Neither file present stays a genuine no-op: nothing to mirror, nothing stale.
|
|
if [[ "$CHECK" -eq 1 && -f "$DST" ]]; then
|
|
echo "DRIFT $DST: mirror exists but .claude-plugin/marketplace.json does not" >&2
|
|
echo "Fix: restore .claude-plugin/marketplace.json (apm's compiled Claude marketplace output), or delete $DST" >&2
|
|
exit 1
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$CHECK" -eq 1 ]]; then
|
|
if [[ ! -f "$DST" ]] || ! diff -q "$SRC" "$DST" >/dev/null 2>&1; then
|
|
echo "DRIFT $DST: out of sync with .claude-plugin/marketplace.json" >&2
|
|
echo "Fix: bash scripts/sync-marketplace-mirror.sh -- apm ships no output profile targeting this path, so \`apm pack\` does not refresh it. Expecting it to is exactly the drift this script and its pre-push hook exist to prevent." >&2
|
|
exit 1
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$DST")"
|
|
cp "$SRC" "$DST"
|