Summary
Child of #3508. This issue was originally filed against guardrails with shell-oriented criteria. Both were wrong — the hook is disk-hygiene's and it is Python. Corrected below. A fix is already in flight, so this is close to a verify-and-close.
The hook
|
|
| Plugin |
disk-hygiene |
| Hook |
plugins/disk-hygiene/skills/clean/scripts/guard_launch_monitor.py |
| Launcher |
plugins/disk-hygiene/hooks/run-python-hook.sh |
| Registration |
plugins/disk-hygiene/hooks/hooks.json, Stop event |
| Configured timeout |
20 s |
| Timeouts in window |
52 |
| Average recorded duration |
31.8 s |
Root cause and status
The cost was launcher overhead, not the hook body. run-python-hook.sh re-derived its Python interpreter on every invocation: a sed read of a 3,500-line file, dirname, and an entire extra Python process spawned only to evaluate a sys.version_info >= MIN_PYTHON predicate. Four process spawns per warm call, of which one was the actual work.
Fixed on branch perf/disk-hygiene-guard-hook-spawns (4 spawns -> 1), measured with an interleaved A/B, 24 pairs alternating within one run so the host's ~6x drift hits both arms equally:
BEFORE p50 = 5446 ms p95 = 16991 ms
AFTER p50 = 1418 ms p95 = 7874 ms median paired ratio 3.71x
AFTER min = 124 ms
This hook is fixed as a side effect because it shares that launcher.
The bar it must still meet
docs/conventions/hook-budget/README.md sets the per-turn ceiling for the whole always-on Stop set at <= 500 ms parallel wall — shared with #3512 (claude-ops) and #3515 (autonomy). At AFTER p50 = 1418 ms this hook alone is still ~3x that ceiling, though the remaining wall-clock is dominated by the one irreducible interpreter spawn (AFTER min = 124 ms shows the floor when the host is briefly uncontended).
The convention also notes that interpreter choice is a budget decision — a Python Stop hook spends roughly a third of the whole per-turn budget on interpreter startup alone on the reference host.
Acceptance criteria
Close as covered once that PR lands unless the re-measurement shows the per-turn set still over budget.
Note
Criteria in the original body ("collapse jq calls", "replace grep/sed with bash builtins") were written for a shell hook and do not apply to a Python one. The launcher they would apply to is already fixed.
Summary
Child of #3508. This issue was originally filed against
guardrailswith shell-oriented criteria. Both were wrong — the hook isdisk-hygiene's and it is Python. Corrected below. A fix is already in flight, so this is close to a verify-and-close.The hook
disk-hygieneplugins/disk-hygiene/skills/clean/scripts/guard_launch_monitor.pyplugins/disk-hygiene/hooks/run-python-hook.shplugins/disk-hygiene/hooks/hooks.json,StopeventRoot cause and status
The cost was launcher overhead, not the hook body.
run-python-hook.shre-derived its Python interpreter on every invocation: asedread of a 3,500-line file,dirname, and an entire extra Python process spawned only to evaluate asys.version_info >= MIN_PYTHONpredicate. Four process spawns per warm call, of which one was the actual work.Fixed on branch
perf/disk-hygiene-guard-hook-spawns(4 spawns -> 1), measured with an interleaved A/B, 24 pairs alternating within one run so the host's ~6x drift hits both arms equally:This hook is fixed as a side effect because it shares that launcher.
The bar it must still meet
docs/conventions/hook-budget/README.mdsets the per-turn ceiling for the whole always-on Stop set at <= 500 ms parallel wall — shared with #3512 (claude-ops) and #3515 (autonomy). AtAFTER p50 = 1418 msthis hook alone is still ~3x that ceiling, though the remaining wall-clock is dominated by the one irreducible interpreter spawn (AFTER min = 124 msshows the floor when the host is briefly uncontended).The convention also notes that interpreter choice is a budget decision — a Python
Stophook spends roughly a third of the whole per-turn budget on interpreter startup alone on the reference host.Acceptance criteria
perf/disk-hygiene-guard-hook-spawnslands.disk-hygieneREADME per hook-budget Rule 1.scripts/affected-tests.sh --run.Close as covered once that PR lands unless the re-measurement shows the per-turn set still over budget.
Note
Criteria in the original body ("collapse
jqcalls", "replacegrep/sedwith bash builtins") were written for a shell hook and do not apply to a Python one. The launcher they would apply to is already fixed.