walk_hooks: stop counting hooks/README.md and hooks.json as script_loc
ci/woodpecker/push/test Pipeline is pending
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).
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "inference-arbitrage",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "Audits a Claude Code plugin's definitions and usage transcripts to find steps that should be a deterministic script instead of raw LLM inference, and files the well-evidenced ones as issues on the target repo.",
|
||||
"author": {
|
||||
"name": "oleks"
|
||||
|
||||
+12
-1
@@ -267,7 +267,13 @@ def walk_agents(plugin_path, catalog):
|
||||
|
||||
def walk_hooks(plugin_path):
|
||||
"""Returns (hooks, texts) — texts maps hook filename -> file content, kept
|
||||
out of the JSON output but needed by build_aggregate for drift detection."""
|
||||
out of the JSON output but needed by build_aggregate for drift detection.
|
||||
|
||||
Only files that look like actual hook scripts are counted: referenced by
|
||||
hooks.json, executable, or shebang'd. `hooks.json` itself is always
|
||||
excluded — it is configuration, not logic — and anything else that fails
|
||||
all three checks (READMEs, notes) is prose, not shipped executable
|
||||
volume (kotkan/claude-plugin-inference-arbitrage#10)."""
|
||||
hooks = []
|
||||
texts = {}
|
||||
hooks_dir = os.path.join(plugin_path, "hooks")
|
||||
@@ -289,9 +295,14 @@ def walk_hooks(plugin_path):
|
||||
except (json.JSONDecodeError, OSError):
|
||||
pass
|
||||
for fname in sorted(os.listdir(hooks_dir)):
|
||||
if fname == "hooks.json":
|
||||
continue
|
||||
fpath = os.path.join(hooks_dir, fname)
|
||||
if not os.path.isfile(fpath):
|
||||
continue
|
||||
if fname not in events_by_file and not os.access(fpath, os.X_OK) \
|
||||
and detect_lang(fpath) == "unknown":
|
||||
continue
|
||||
with open(fpath, encoding="utf-8", errors="ignore") as f:
|
||||
content = f.read()
|
||||
texts[fname] = content
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# hooks
|
||||
|
||||
Fixture doc, not a hook. Must never be counted in `script_loc` or appear in
|
||||
`hooks[]` (kotkan/claude-plugin-inference-arbitrage#10).
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"hooks": {}
|
||||
}
|
||||
@@ -33,8 +33,9 @@ check "duplicated command block found across dupe-a and dupe-b" "
|
||||
"
|
||||
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" "len(d['hooks']) == 1 and d['hooks'][0]['file'] == 'guard.sh'"
|
||||
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'
|
||||
|
||||
Reference in New Issue
Block a user