From b10011c4d8f1d064c572acdd8b3f7bbe37a2e9ca Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 2 Sep 2026 20:57:19 -0400 Subject: [PATCH 1/3] docs(hooks): record the post-program hook budget accounting The hook-budget convention gains a dated reference-figures section in spawn-equivalents with the harness sha256, and the four plugins that lacked an accounting row (typos-format, eol-normalizer, markdown-format, context-guard) gain one under Requirements. Documentation only. Co-Authored-By: Claude Fable 5.1 --- docs/conventions/hook-budget/README.md | 36 +++++++++++++++++++ .../context-guard/.claude-plugin/plugin.json | 2 +- plugins/context-guard/CHANGELOG.md | 9 +++++ plugins/context-guard/README.md | 18 ++++++++++ .../eol-normalizer/.claude-plugin/plugin.json | 2 +- plugins/eol-normalizer/CHANGELOG.md | 8 +++++ plugins/eol-normalizer/README.md | 14 ++++++++ .../.claude-plugin/plugin.json | 2 +- plugins/markdown-format/CHANGELOG.md | 8 +++++ plugins/markdown-format/README.md | 16 +++++++++ .../typos-format/.claude-plugin/plugin.json | 2 +- plugins/typos-format/CHANGELOG.md | 8 +++++ plugins/typos-format/README.md | 15 ++++++++ 13 files changed, 136 insertions(+), 4 deletions(-) diff --git a/docs/conventions/hook-budget/README.md b/docs/conventions/hook-budget/README.md index a89ee0399c..895d9426ef 100644 --- a/docs/conventions/hook-budget/README.md +++ b/docs/conventions/hook-budget/README.md @@ -36,6 +36,42 @@ three guardrails verifiers) ≈ 1.9 s. #1809's single-writer change removes per- repos without a markdownlint config; in an opted-in repo the per-Write set is unchanged (typos-format still scans in report-only mode), so these figures remain the binding accounting until re-measured. +## Reference figures (2026-09-02, after the hook-performance program) + +The fleet's binding measurement is now the dotfiles fan-out harness +(`common/measure-claude-hook-fanout.sh`, sha256 +`5a254b50a67a9e1b158ce9ff7bd3c7c53f7eade80e55a1b2f8c5075026067178`), which samples 22 events +against the installed plugin cache, times each hook process in-process with `EPOCHREALTIME`, and +interleaves a `bash -c :` spawn floor S with every sample. A run is valid at S at or below 160 ms; +figures below are spawn-equivalents (hook wall divided by the same-run S), which is the number that +survives a change of host, with the reference-host conversion at S = 80 ms beside it. Every hook +stays `type: command` in its plugin's `hooks/hooks.json`; the program removed no check, added no +`async` row, and narrowed no matcher. The eight guardrails per-Bash-call guards and the three +per-Write verifier guards run through one dispatcher process per event; the six formatter plugins +carry one `if: Edit(*.ext)` row per extension so a Write to any other file spawns nothing. + +| Surface (benign payload) | Before (`main` 2026-09-02 morning, S = 33 ms) | After (`main` at `9f07fb5fc`, S = 26 ms, phase 4b not yet installed) | Reference host at S = 80 ms | +| --- | --- | --- | --- | +| PreToolUse `Bash` (`git status --short`), slowest hook | 75.0 | 91.5 | about 7.3 s | +| PreToolUse `Write` (in-repo `.md`), slowest hook | 23.4 | 78.0 | about 6.2 s | +| PostToolUse `Write` (in-repo `.md`), slowest hook | 36.7 (out-of-repo sample; the in-repo pre-program figure is 13,225 ms, about 400 S) | 163.5 | about 13 s | +| PostToolBatch (per turn) | 38.0 | 8.2 | about 0.65 s | +| UserPromptSubmit (per turn) | 29.5 | 6.7 | about 0.54 s | +| Stop, slowest of four (per turn) | 11.4 | 27.2 | about 2.2 s | +| SessionStart `startup`, slowest | 2.7 | 2.9 | about 0.23 s | + +The per-turn rows meet the budget table above; the per-tool-call rows do not, and the "after" +column is worse than "before" on those rows for two stated reasons: the before run's Write samples +lived outside the repository, so every Write and verifier guard early-exited and measured a no-op +(the harness now writes its samples under the measured cwd), and the after run shared its host with +the phase 4b worker's suites (S rose from 18 ms to 26 ms during it). The remaining per-tool-call +cost sits in the guardrails dispatcher, which pays the shared library's telemetry envelope (two +`jq` per guard when `HOOK_TELEMETRY_SINK` is set) and payload reader on every fire; the builtin +versions of both land with the 4b sync and the final run in the program's DEVIATIONS log is the +figure of record for that column. Per-plugin READMEs carry the paired before-and-after figures +for each change (guardrails, context-guard, rate-limit-guard, typos-format, eol-normalizer, +markdown-format). + ## Rules 1. **A plugin adding or widening an always-on hook states its measured share** (method above) in diff --git a/plugins/context-guard/.claude-plugin/plugin.json b/plugins/context-guard/.claude-plugin/plugin.json index 540b5f20b8..a7b7cf83cd 100644 --- a/plugins/context-guard/.claude-plugin/plugin.json +++ b/plugins/context-guard/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "context-guard", - "version": "0.7.34", + "version": "0.7.36", "description": "Per-session context-window observability plus the first shipped consumer: a statusline wrapper tees each session's context_window fields to a per-session snapshot file, a zone resolver classifies usage into smart/acceptable/dumb bands (percentage bands plus window-class token bands, conservative-min combination, zones.json SSOT with shipped defaults), a reader contract fixes how consuming sessions interpret the snapshots, and zone-crossing hooks report once per transition into a worse zone across two channels \u2014 the continuation menu to the operator, who owns that choice, and to the model only the zone determination plus the counter-steer that a zone word is not a decay signal (advisory by default; an optional blocking mode gates new mutating work on a fresh dumb-zone snapshot with handoff-writing exempt), with a PostCompact hook persisting an evidence-degraded marker.", "author": { "name": "Melodic Software", diff --git a/plugins/context-guard/CHANGELOG.md b/plugins/context-guard/CHANGELOG.md index c71b41ae9b..5085559a38 100644 --- a/plugins/context-guard/CHANGELOG.md +++ b/plugins/context-guard/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to the `context-guard` plugin. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.36] + +### Changed + +- **README carries the hook budget accounting rows.** The 0.7.34 process counts for the + PostToolBatch, PreToolUse, PostCompact rows and the zone resolver, and the kept 60-second timeout + rationale, now sit under Requirements, per the hook-budget convention's rule 1. Documentation + only. + ## [0.7.34] ### Changed diff --git a/plugins/context-guard/README.md b/plugins/context-guard/README.md index b92388b46c..35a1eb56fa 100644 --- a/plugins/context-guard/README.md +++ b/plugins/context-guard/README.md @@ -196,6 +196,24 @@ cost is process-spawn bound on `jq` and `date`, and correspondingly less on nati the input path, so this is display latency, not typing latency; `refreshInterval` in your settings governs how often it runs. +### Hook budget accounting + +Per [`docs/conventions/hook-budget/README.md`](../../docs/conventions/hook-budget/README.md), +the PostToolBatch and UserPromptSubmit rows are per-turn hooks and the PreToolUse row is +per-tool-call, all always-on. Measured on Windows 11 under Git Bash, twelve trials against an +interleaved `bash -c :` floor, old and new interleaved in one loop (2026-09-02): + +| Event | Fires | Spawn-equivalents | What changed | +| --- | --- | --- | --- | +| PostToolBatch, steady zone (`zone-crossing-inject.sh`) | 1 | 18.9 before, 10.8 after (0.7.34) | 11 processes to 2: one `jq` reading both payload fields, `dirname` and `tr` pipelines replaced by expansions, `mkdir -p` behind a `-d` guard | +| PreToolUse `Write`/`Edit`, advisory mode (`zone-gate.sh`) | 1 | 2.5 before, 1.4 after (0.7.34) | no process spawned in the default posture | +| PostCompact (`post-compact-mark.sh`) | 1 | 9 processes to 4 (0.7.34) | `date` replaced by printf's clock with a `date` fallback; `mkdir` and `rm` behind existence guards | +| Zone resolver (`scripts/context-zone.sh`, called by the rows above) | per resolve | 9.5 before, 2.3 after (0.7.34) | six processes to one `jq`; a whole steady PostToolBatch fire is 3 processes, down from 15 | + +The two advisory rows keep their 60-second timeout: the 0.4.8 measurement put this script at +22.0 s on Windows with Defender real-time protection, and a timeout caps a stalled hook without +speeding a normal one. + ## Configuration Three `userConfig` options, all hook-scoped: `context_guard_hooks_enabled` (kill switch, default diff --git a/plugins/eol-normalizer/.claude-plugin/plugin.json b/plugins/eol-normalizer/.claude-plugin/plugin.json index 8d98c2ed85..bf62f3298d 100644 --- a/plugins/eol-normalizer/.claude-plugin/plugin.json +++ b/plugins/eol-normalizer/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "eol-normalizer", - "version": "0.6.28", + "version": "0.6.30", "description": "Normalize a written file's working-tree line endings to its .gitattributes eol value on edit \u2014 symmetric CRLF/LF driven by git check-attr, advisory and never blocking.", "author": { "name": "Melodic Software", diff --git a/plugins/eol-normalizer/CHANGELOG.md b/plugins/eol-normalizer/CHANGELOG.md index 7fd30abb3a..5a88e55f30 100644 --- a/plugins/eol-normalizer/CHANGELOG.md +++ b/plugins/eol-normalizer/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to the `eol-normalizer` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.30] + +### Changed + +- **README carries the hook budget accounting row.** The measured 41.0 to 21.5 spawn-equivalents + of 0.6.28 and the residual now sit under Requirements, per the hook-budget convention's rule 1. + Documentation only. + ## [0.6.28] ### Changed diff --git a/plugins/eol-normalizer/README.md b/plugins/eol-normalizer/README.md index 7c11f29335..e058738ab3 100644 --- a/plugins/eol-normalizer/README.md +++ b/plugins/eol-normalizer/README.md @@ -47,6 +47,20 @@ The hook itself runs on Bash 3.2+. Telemetry timing uses `EPOCHREALTIME` (Bash 5.0+); on older bash the telemetry envelope is skipped while normalization still runs. +### Hook budget accounting + +Per [`docs/conventions/hook-budget/README.md`](../../docs/conventions/hook-budget/README.md), +this hook is always-on for every `Write` and `Edit`, so its cost on the path where there is +nothing to rewrite is the figure that counts. Measured on Windows 11 under Git Bash, twelve +interleaved trials against an interleaved `bash -c :` floor (2026-09-02): + +| Event | Fires | Spawn-equivalents | What changed | +| --- | --- | --- | --- | +| PostToolUse `Write`, already-normalized `.md` | 1 | 41.0 before, 21.5 after (0.6.28) | sixteen of twenty-seven processes gone: one `git check-attr` for both attributes, `dirname` and `basename` as parameter expansions, the NUL sniff as one `read`, and no temp file, `cp`, `cmp` or `rm` for a file that needs no rewrite | + +The residual is the shared library's payload reader and telemetry emitter, cut in 0.6.29 by the +vendored `hook-utils.sh` (one batched `realpath`, no jq on the envelope). + ## Install ```shell diff --git a/plugins/markdown-format/.claude-plugin/plugin.json b/plugins/markdown-format/.claude-plugin/plugin.json index 4a96d77bae..9f5739dd2d 100644 --- a/plugins/markdown-format/.claude-plugin/plugin.json +++ b/plugins/markdown-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "markdown-format", - "version": "0.11.38", + "version": "0.11.40", "description": "Auto-format and lint Markdown on edit via markdownlint-cli2 \u2014 only in repos that carry their own markdownlint config.", "author": { "name": "Melodic Software", diff --git a/plugins/markdown-format/CHANGELOG.md b/plugins/markdown-format/CHANGELOG.md index 7063171bd9..91d923ed19 100644 --- a/plugins/markdown-format/CHANGELOG.md +++ b/plugins/markdown-format/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to the `markdown-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.11.40] + +### Changed + +- **README carries the hook budget accounting rows.** The measured 41.6 to 32.0 spawn-equivalents + of 0.11.38, the `if`-row skip for non-Markdown files and the residual now sit under Requirements, + per the hook-budget convention's rule 1. Documentation only. + ## [0.11.38] ### Changed diff --git a/plugins/markdown-format/README.md b/plugins/markdown-format/README.md index f0e5a1a87d..71c77ac83b 100644 --- a/plugins/markdown-format/README.md +++ b/plugins/markdown-format/README.md @@ -137,6 +137,22 @@ key), the gate fails closed and the lint run stays skipped. Declarative rule-only JSONC/YAML configuration is unaffected and lints immediately. Prefer it when executable configuration is unnecessary. +### Hook budget accounting + +Per [`docs/conventions/hook-budget/README.md`](../../docs/conventions/hook-budget/README.md), +this hook is always-on for every `Write` and `Edit` of a `.md` or `.mdc` file (the two `if` +rows in `hooks/hooks.json` keep every other extension from spawning it), so its cost on a clean +Markdown edit is the figure that counts. Measured on Windows 11 under Git Bash, twelve interleaved +trials against an interleaved `bash -c :` floor (2026-09-02): + +| Event | Fires | Spawn-equivalents | What changed | +| --- | --- | --- | --- | +| PostToolUse `Write`, clean `.md` in a repo with a markdownlint config | 1 | 41.6 before, 32.0 after (0.11.38) | seven of twenty-one processes gone: six `dirname` calls and one `basename` are parameter expansions, including inside the config-discovery and risky-config walks | +| PostToolUse `Write`, non-Markdown file | 0 | skipped by the `if` rows | one entry per extension since 0.11.35 | + +The residual is `markdownlint-cli2` itself (one Node process per fire) plus the shared library's +payload reader and telemetry emitter, cut in 0.11.39 by the vendored `hook-utils.sh`. + ## Install ```shell diff --git a/plugins/typos-format/.claude-plugin/plugin.json b/plugins/typos-format/.claude-plugin/plugin.json index 463393ee97..c393994668 100644 --- a/plugins/typos-format/.claude-plugin/plugin.json +++ b/plugins/typos-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "typos-format", - "version": "0.6.35", + "version": "0.6.37", "description": "Spell-check on edit via typos-cli, unconditionally \u2014 report-only by default, honoring the consuming repo's own typos configuration when one is present.", "author": { "name": "Melodic Software", diff --git a/plugins/typos-format/CHANGELOG.md b/plugins/typos-format/CHANGELOG.md index 1388fbba3e..b81e34420e 100644 --- a/plugins/typos-format/CHANGELOG.md +++ b/plugins/typos-format/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to the `typos-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.37] + +### Changed + +- **README carries the hook budget accounting row.** The measured 36.3 to 26.0 spawn-equivalents + of 0.6.35 and the residual now sit under Requirements, per the hook-budget convention's rule 1. + Documentation only. + ## [0.6.35] ### Changed diff --git a/plugins/typos-format/README.md b/plugins/typos-format/README.md index 6b774bfb49..3198b04eb4 100644 --- a/plugins/typos-format/README.md +++ b/plugins/typos-format/README.md @@ -89,6 +89,21 @@ The hook itself runs on Bash 3.2+. Telemetry timing uses `EPOCHREALTIME` (Bash 5.0+); on older bash the telemetry envelope is skipped while typo fixing still runs. +### Hook budget accounting + +Per [`docs/conventions/hook-budget/README.md`](../../docs/conventions/hook-budget/README.md), +this hook is always-on for every `Write`, `Edit` and `NotebookEdit`, so its cost on the path +where `typos` finds nothing is the figure that counts. Measured on Windows 11 under Git Bash, +twelve interleaved trials against an interleaved `bash -c :` floor (2026-09-02): + +| Event | Fires | Spawn-equivalents | What changed | +| --- | --- | --- | --- | +| PostToolUse `Write`, clean `.md` | 1 | 36.3 before, 26.0 after (0.6.35) | three of sixteen processes gone: two `dirname` calls became parameter expansions and the `notebook_path` copy runs only for a payload that carries one | + +The residual is the shared library's payload reader and telemetry emitter, cut in 0.6.36 by the +vendored `hook-utils.sh` (one batched `realpath`, no jq on the envelope), and the `typos` binary +itself. + ## Install ```shell From 93c394c4ca7810cae884812b55f1732edd2f7788 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:40:49 -0400 Subject: [PATCH 2/3] docs(hook-budget): fill the after column from the final run at main 5e3d749cb Co-Authored-By: Claude Fable 5.1 --- docs/conventions/hook-budget/README.md | 41 ++++++++++++++------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/docs/conventions/hook-budget/README.md b/docs/conventions/hook-budget/README.md index 895d9426ef..cdef13d679 100644 --- a/docs/conventions/hook-budget/README.md +++ b/docs/conventions/hook-budget/README.md @@ -50,27 +50,30 @@ stays `type: command` in its plugin's `hooks/hooks.json`; the program removed no per-Write verifier guards run through one dispatcher process per event; the six formatter plugins carry one `if: Edit(*.ext)` row per extension so a Write to any other file spawns nothing. -| Surface (benign payload) | Before (`main` 2026-09-02 morning, S = 33 ms) | After (`main` at `9f07fb5fc`, S = 26 ms, phase 4b not yet installed) | Reference host at S = 80 ms | +| Surface (benign payload) | Before (`main` 2026-09-02 morning, S = 33 ms) | After (`main` at `5e3d749cb`, 2026-09-03, S = 18 ms, quiet host) | After at S = 80 ms | | --- | --- | --- | --- | -| PreToolUse `Bash` (`git status --short`), slowest hook | 75.0 | 91.5 | about 7.3 s | -| PreToolUse `Write` (in-repo `.md`), slowest hook | 23.4 | 78.0 | about 6.2 s | -| PostToolUse `Write` (in-repo `.md`), slowest hook | 36.7 (out-of-repo sample; the in-repo pre-program figure is 13,225 ms, about 400 S) | 163.5 | about 13 s | -| PostToolBatch (per turn) | 38.0 | 8.2 | about 0.65 s | -| UserPromptSubmit (per turn) | 29.5 | 6.7 | about 0.54 s | -| Stop, slowest of four (per turn) | 11.4 | 27.2 | about 2.2 s | -| SessionStart `startup`, slowest | 2.7 | 2.9 | about 0.23 s | +| PreToolUse `Bash` (`git status --short`), slowest hook | 75.0 | 88.8 (1,599 ms) | about 7.1 s | +| PreToolUse `Write` (in-repo `.md`), slowest hook | 23.4 | 75.6 (1,360 ms) | about 6.0 s | +| PostToolUse `Write` (in-repo `.md`), slowest hook | 36.7 (out-of-repo sample; the in-repo pre-program figure is 13,225 ms, about 400 S) | 108.3 (1,949 ms) | about 8.7 s | +| PostToolBatch (per turn) | 38.0 | 15.7 (282 ms) | about 1.3 s | +| UserPromptSubmit (per turn) | 29.5 | 16.5 (297 ms) | about 1.3 s | +| Stop, slowest of four (per turn) | 11.4 | 22.8 (410 ms) | about 1.8 s | +| SessionStart `startup`, slowest | 2.7 | 3.3 (60 ms) | about 0.26 s | -The per-turn rows meet the budget table above; the per-tool-call rows do not, and the "after" -column is worse than "before" on those rows for two stated reasons: the before run's Write samples -lived outside the repository, so every Write and verifier guard early-exited and measured a no-op -(the harness now writes its samples under the measured cwd), and the after run shared its host with -the phase 4b worker's suites (S rose from 18 ms to 26 ms during it). The remaining per-tool-call -cost sits in the guardrails dispatcher, which pays the shared library's telemetry envelope (two -`jq` per guard when `HOOK_TELEMETRY_SINK` is set) and payload reader on every fire; the builtin -versions of both land with the 4b sync and the final run in the program's DEVIATIONS log is the -figure of record for that column. Per-plugin READMEs carry the paired before-and-after figures -for each change (guardrails, context-guard, rate-limit-guard, typos-format, eol-normalizer, -markdown-format). +Read against the budget table above in milliseconds on the measuring host: PostToolBatch, +UserPromptSubmit and Stop meet the 500 ms per-turn ceiling; PreToolUse `Bash`, PreToolUse `Write` +and PostToolUse `Write` sit at 1.4 to 1.9 s against the 1 s typical ceiling and inside the 2 s +worst case, and in the pre-program shape PostToolUse `Write` in a repository was 13.2 s. The +"after" spawn-equivalents read higher than "before" on the Write rows because the before run's +Write samples lived outside the repository, so every Write and verifier guard early-exited and +measured a no-op; the harness now writes its samples under the measured cwd. The remaining +per-tool-call cost is the guardrails dispatcher (1.6 to 3.0 s per fire on this host, eight guards +per Bash call and three per Write, each still sourcing the library and building its telemetry +data), followed by markdown-format's `markdownlint-cli2` Node process. Per-plugin READMEs carry +the paired before-and-after figures for each change (guardrails, context-guard, +rate-limit-guard, typos-format, eol-normalizer, markdown-format). The run's transcript, the +installed versions and shas, the per-file cache compare and every `hooks.json` entry measured are +recorded in the hook-performance program's DEVIATIONS log. ## Rules From fef694794310a9ed91061929590b2ba8d41a2450 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:52:26 -0400 Subject: [PATCH 3/3] docs(hooks): read the reference figures as the convention sums them and add the Edit rows The compliance paragraph now sums PreToolUse and PostToolUse per tool call and states the reference-host reading plainly: no per-tool-call surface meets the budget, and on the reference host no per-turn surface does either; the program shrank the overage. The context-guard table gains the UserPromptSubmit row and states PostCompact in spawn-equivalents. Co-Authored-By: Claude Fable 5.1 --- docs/conventions/hook-budget/README.md | 28 +++++++++++++++++--------- plugins/context-guard/README.md | 3 ++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/conventions/hook-budget/README.md b/docs/conventions/hook-budget/README.md index cdef13d679..f90d74df13 100644 --- a/docs/conventions/hook-budget/README.md +++ b/docs/conventions/hook-budget/README.md @@ -55,21 +55,31 @@ carry one `if: Edit(*.ext)` row per extension so a Write to any other file spawn | PreToolUse `Bash` (`git status --short`), slowest hook | 75.0 | 88.8 (1,599 ms) | about 7.1 s | | PreToolUse `Write` (in-repo `.md`), slowest hook | 23.4 | 75.6 (1,360 ms) | about 6.0 s | | PostToolUse `Write` (in-repo `.md`), slowest hook | 36.7 (out-of-repo sample; the in-repo pre-program figure is 13,225 ms, about 400 S) | 108.3 (1,949 ms) | about 8.7 s | +| PreToolUse `Edit` (in-repo `.md`), slowest hook | 34.8 | 114.6 (2,062 ms) | about 9.2 s | +| PostToolUse `Edit` (in-repo `.md`), slowest hook | 41.6 (out-of-repo sample; the in-repo pre-program figure is 17,192 ms, about 520 S) | 169.3 (3,048 ms) | about 13.5 s | | PostToolBatch (per turn) | 38.0 | 15.7 (282 ms) | about 1.3 s | | UserPromptSubmit (per turn) | 29.5 | 16.5 (297 ms) | about 1.3 s | | Stop, slowest of four (per turn) | 11.4 | 22.8 (410 ms) | about 1.8 s | | SessionStart `startup`, slowest | 2.7 | 3.3 (60 ms) | about 0.26 s | -Read against the budget table above in milliseconds on the measuring host: PostToolBatch, -UserPromptSubmit and Stop meet the 500 ms per-turn ceiling; PreToolUse `Bash`, PreToolUse `Write` -and PostToolUse `Write` sit at 1.4 to 1.9 s against the 1 s typical ceiling and inside the 2 s -worst case, and in the pre-program shape PostToolUse `Write` in a repository was 13.2 s. The -"after" spawn-equivalents read higher than "before" on the Write rows because the before run's -Write samples lived outside the repository, so every Write and verifier guard early-exited and +The budget table above sums PreToolUse and PostToolUse for one tool call and says the Windows +reference-host figures are binding, so the reading is: **no per-tool-call surface meets the +budget, and on the reference host no per-turn surface does either.** On the measuring host at +S = 18 ms an in-repo Markdown Write costs 1,360 plus 1,949 = 3,309 ms and an in-repo Edit 2,062 +plus 3,048 = 5,110 ms, both above the 2 s worst case; a benign Bash call costs 1,599 ms (no +PostToolUse hook fires), above the 1 s typical ceiling and inside the worst case. Scaled to the +80 ms reference host those pairs are about 14.7 s and 22.7 s, and the per-turn rows land at 1.3 to +1.8 s against 500 ms. What the program changed is the size of the overage: in the pre-program shape +the in-repo Write pair was 773 plus 13,225 = 14.0 s and the Edit pair 1,147 plus 17,192 = 18.3 s +on the same host, and PostToolBatch and UserPromptSubmit were 1,254 and 975 ms per turn. The +"after" spawn-equivalents read higher than "before" on the Write and Edit rows because the before +run's samples lived outside the repository, so every Write and verifier guard early-exited and measured a no-op; the harness now writes its samples under the measured cwd. The remaining -per-tool-call cost is the guardrails dispatcher (1.6 to 3.0 s per fire on this host, eight guards -per Bash call and three per Write, each still sourcing the library and building its telemetry -data), followed by markdown-format's `markdownlint-cli2` Node process. Per-plugin READMEs carry +per-tool-call cost is the guardrails dispatcher, 1,360 to 3,048 ms per fire on this host across +the Write, Edit and Bash rows (eight guards per Bash call and three per Write or Edit, each still +sourcing the library and building its telemetry data), followed by markdown-format's +`markdownlint-cli2` Node process; rule 2 stands, and that overage is the guardrails plugin's +remediation work, named in its README. Per-plugin READMEs carry the paired before-and-after figures for each change (guardrails, context-guard, rate-limit-guard, typos-format, eol-normalizer, markdown-format). The run's transcript, the installed versions and shas, the per-file cache compare and every `hooks.json` entry measured are diff --git a/plugins/context-guard/README.md b/plugins/context-guard/README.md index 35a1eb56fa..7232279fbf 100644 --- a/plugins/context-guard/README.md +++ b/plugins/context-guard/README.md @@ -206,8 +206,9 @@ interleaved `bash -c :` floor, old and new interleaved in one loop (2026-09-02): | Event | Fires | Spawn-equivalents | What changed | | --- | --- | --- | --- | | PostToolBatch, steady zone (`zone-crossing-inject.sh`) | 1 | 18.9 before, 10.8 after (0.7.34) | 11 processes to 2: one `jq` reading both payload fields, `dirname` and `tr` pipelines replaced by expansions, `mkdir -p` behind a `-d` guard | +| UserPromptSubmit, steady zone (the same `zone-crossing-inject.sh`) | 1 | 18.4 before, 11.8 after (0.7.34) | same script, same cuts; measured separately because the payload differs | | PreToolUse `Write`/`Edit`, advisory mode (`zone-gate.sh`) | 1 | 2.5 before, 1.4 after (0.7.34) | no process spawned in the default posture | -| PostCompact (`post-compact-mark.sh`) | 1 | 9 processes to 4 (0.7.34) | `date` replaced by printf's clock with a `date` fallback; `mkdir` and `rm` behind existence guards | +| PostCompact (`post-compact-mark.sh`) | 1 | 9.4 before, 5.7 after (0.7.34) | 9 processes to 4: `date` replaced by printf's clock with a `date` fallback; `mkdir` and `rm` behind existence guards | | Zone resolver (`scripts/context-zone.sh`, called by the rows above) | per resolve | 9.5 before, 2.3 after (0.7.34) | six processes to one `jq`; a whole steady PostToolBatch fire is 3 processes, down from 15 | The two advisory rows keep their 60-second timeout: the 0.4.8 measurement put this script at