eb4b945599
ci/woodpecker/push/test Pipeline is pending
kotkan/claude-plugin-inference-arbitrage#10 — a hook file is only counted if it's referenced by .claude-plugin/hooks.json, executable, or has a shebang. hooks/hooks.json itself is always excluded regardless, since it is configuration rather than logic. mask-worktree-audit.py needed no change: it derives script_loc from the already-filtered hooks[] output. Bumps plugin.json to 0.6.2 (fix).
58 lines
2.4 KiB
Bash
Executable File
58 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Asserts bin/plugin-inventory against tests/fixtures/sample-plugin, whose
|
|
# every signal value is known by construction (see the fixture files
|
|
# themselves for what each one is designed to trigger).
|
|
set -euo pipefail
|
|
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
|
|
|
OUT=$(python3 bin/plugin-inventory tests/fixtures/sample-plugin --json)
|
|
fail=0
|
|
|
|
check() {
|
|
local desc="$1" expr="$2"
|
|
if ! python3 -c "
|
|
import json, sys
|
|
d = json.loads('''$OUT''')
|
|
assert ($expr), 'FAILED: $desc'
|
|
"; then
|
|
echo "FAIL: $desc" >&2
|
|
fail=1
|
|
else
|
|
echo "ok: $desc"
|
|
fi
|
|
}
|
|
|
|
check "plugin name resolved from manifest" "d['plugin']['name'] == 'sample-plugin'"
|
|
check "two skills found" "len(d['skills']) == 2"
|
|
check "dupe-a verb_ratio is 0.5 (2 script, 2 judgment)" "d['skills'][0]['verb_ratio'] == 0.5"
|
|
check "dupe-a rule_tables counted" "d['skills'][0]['rule_tables'] == 1"
|
|
check "dupe-b has no rule table" "d['skills'][1]['rule_tables'] == 0"
|
|
check "duplicated command block found across dupe-a and dupe-b" "
|
|
any(b['sig'] == 'git status --short' and sorted(b['skills']) == ['dupe-a', 'dupe-b']
|
|
for b in d['aggregate']['duplicated_command_blocks'])
|
|
"
|
|
check "one agent found" "len(d['agents']) == 1"
|
|
check "fetcher mechanical_tool_share is 0.8 (4 of 5 tools)" "d['agents'][0]['mechanical_tool_share'] == 0.8"
|
|
check "one hook found (README.md/hooks.json excluded, kotkan/claude-plugin-inference-arbitrage#10)" "len(d['hooks']) == 1 and d['hooks'][0]['file'] == 'guard.sh'"
|
|
check "hook LOC matches file" "d['hooks'][0]['loc'] == 8"
|
|
check "README.md not counted toward script_loc" "d['aggregate']['script_loc'] == d['hooks'][0]['loc'] + d['scripts'][0]['loc']"
|
|
check "one bin script found, bash detected" "d['scripts'][0]['lang'] == 'bash' and d['scripts'][0]['loc'] == 3"
|
|
check "hook_prose_drift catches FIXTURE_ENV_VAR/fixture_check restated in dupe-a" "
|
|
any(p['hook'] == 'guard.sh' and p['skill'] == 'dupe-a'
|
|
and {'fixture_env_var', 'fixture_check'} <= set(p['shared_tokens'])
|
|
for p in d['aggregate']['hook_prose_drift'])
|
|
"
|
|
check "hook_prose_drift does NOT fire for dupe-b (no shared identifiers)" "
|
|
not any(p['skill'] == 'dupe-b' for p in d['aggregate']['hook_prose_drift'])
|
|
"
|
|
|
|
# Target resolution: bare name against a nonexistent cache entry fails loudly.
|
|
if python3 bin/plugin-inventory this-plugin-does-not-exist >/dev/null 2>&1; then
|
|
echo "FAIL: unresolvable target should exit non-zero" >&2
|
|
fail=1
|
|
else
|
|
echo "ok: unresolvable target exits non-zero"
|
|
fi
|
|
|
|
exit "$fail"
|