perf(hook-utils): drop buffer_stdin startup subshells, repo_root tr, and emit_tel jq - #3732
Merged
Merged
Conversation
…and emit_tel jq
buffer_stdin resolved timeout and slice through $( ) and process substitution.
GNU Bash forks a subshell for both even when the body is builtins only; those
two wrappers ran in distinct pids. The _to helpers write into caller variables
with printf -v instead.
hook::repo_root piped git through tr -d '\r'. The payload path already strips
CR in-shell; repo_root now does the same, so the census is 1 git instead of
git+tr.
hook::json_str_object_to builds compact string-field objects byte-identical to
jq -nc --arg. The seven always-on Bash-guard emit_tel builders use it, so a
wired HOOK_TELEMETRY_SINK no longer spends one jq per guard on
{tool,subject,form}.
Synced to all 17 carrying plugins; versions bumped for delivery.
Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
kyle-sexton
marked this pull request as ready for review
September 4, 2026 22:21
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Main shipped the same patch numbers this PR used for the hook-utils delivery. Keep main's notes under its headings and place the Phase 1 note under a new higher version so changelog-parity and --check-bump still hold. Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
…ions Main shipped the same patch numbers as the previous rematch, plus a guardrails 0.32.0 minor. Keep every heading from main and from this branch's earlier bumps (including claude-ops 0.41.14) and place the Phase 1 hook-utils note under a new higher version so --check-bump and --check-preserved both hold. Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
The print-form timeout wrapper takes no arguments; passing "$@" in the BASHPID pin made SC2120/SC2119 fire on the existing no-arg calls. printf -v destinations need an empty initializer for SC2154. grep -q quiet matches in this file trip the grep -P portability token, so the sites carry a portability-ok reason. Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
kyle-sexton
enabled auto-merge (squash)
September 5, 2026 02:50
kyle-sexton
pushed a commit
that referenced
this pull request
Sep 5, 2026
…eview-cf00b1 Resolves the context-guard CHANGELOG conflict. Both sides independently claimed 0.7.41: main's #3732 shipped the vendored hook-utils.sh buffer_stdin/repo_root change under that version, and this branch's 027d11a claimed it for the marker-write skip. Main's 0.7.41 is already released, so it keeps the version it shipped under and this branch's entry moves up to 0.7.42, with plugin.json bumped to match. Both entries survive, per the branch's own stated convention that each merge places this entry above the newer one under its own version. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VPLatLkg4329L8eyfxhuMa
kyle-sexton
added a commit
that referenced
this pull request
Sep 5, 2026
…er (#3736) No related issue: the defect was found by an in-session fleet audit that had no tracking issue; the audit's findings on other lanes are tracked in #3685, #3721 and #3727. ## Summary `zone-crossing-inject.sh` fires once per `UserPromptSubmit` and once per `PostToolBatch`, so a three-batch turn that stays in one zone fired four times and rewrote both state markers four times to the values they already held. The armed-rank gate already suppressed the extra notices, so this was wasted I/O rather than duplicate injection. Alongside it, `hooks.json` lacked its documented top-level `description`. ## Fix - Each marker is written only when its raw on-disk bytes differ from the new value. The comparand is the read before normalization, so a legacy-format marker is still rewritten in the current format and an absent marker still latches on the first fire. Write ordering, the fail-open posture and the `.zone` rollback on a failed `.armed` write are unchanged; the rollback now fires only when this call was the one that moved `.zone`. - A new contract-test case (12c) pins the skip. Every existing assertion reads stdout, which is identical whether the markers were rewritten or skipped, so a revert to unconditional writes would have passed all 58. The new case backdates both markers to 2000-01-01 and a reference file to 2000-01-02, fires on an unchanged zone, and asserts neither marker is newer than the reference, with a positive control that a mismatched marker is still rewritten. `bash -nt` keeps it free of any `stat(1)` dialect, and mtimes are not subject to root's permission bypass, which is why it is not a chmod test. - `hooks.json` gains a top-level `description`. - `context-guard` bumps to 0.7.42 with a CHANGELOG entry. Main shipped 0.7.39 in #3718, 0.7.40 in #3727 and 0.7.41 in #3732 while this branch was open; each merge placed this entry above the newer one under its own version, so consumers on any of them still receive this change. **Withdrawn in review.** The draft also dropped the four `hooks.json` timeouts from 60 to 10, reasoning from the hooks reference's 30-second `UserPromptSubmit` default and a 30 ms quiet-host measurement. The Codex review on `5acee106` pointed at the 0.4.8 CHANGELOG entry and the README paragraph that own that value: on Windows 11 / Git Bash with Defender real-time protection, `zone-crossing-inject.sh` measured 22.0 s, and a 10-second cap was the exact defect 0.4.8 fixed, cancelling the advisory on essentially every fire while still charging the full wall time. Nothing on this branch re-measured that profile, so `3db2c457` restores all four rows to 60 and the CHANGELOG entry says why they stay. Five files: `zone-crossing-inject.sh`, `zone-crossing-inject.test.sh`, `hooks.json`, `plugin.json`, `CHANGELOG.md`, all under `plugins/context-guard/`. The interview Brief that scoped this lived in `docs/topics/prompt-hooks-review/` on the branch and is pruned before merge per the topic-docs convention; its substance is this body, and the audit's measured baseline is routed to #3685. ## Verification - `shellcheck` clean on the changed script and the test, plain and with the repo `.shellcheckrc`; `check-shell-portability.sh origin/main` clean on both. - `plugins/context-guard/hooks/zone-crossing-inject.test.sh`: 58 pass, 0 fail at every head through `3db2c457`; 63 pass, 0 fail on `860d66d6` with case 12c. Against `origin/main`'s hook the suite reads 61 pass, 2 fail, the two failures being exactly the skip assertions. The first attempt at the fix failed one case (`0.7.1-format marker not normalized`): comparing against the normalized read skipped the rewrite of a legacy marker. Fixed by comparing against the raw read. - `scripts/affected-tests.sh --run`: all selected suites pass at every head (26 before the first merge, 27 on `f7cb502f`, 2 on the pruned head `511b549f` once the Brief stopped driving reference-based selection, 2 on `fcc3f8cd`, all selected on `5acee106`, 2 on `3db2c457`, 3 on `860d66d6`), zero `FAIL` lines. A mid-merge run had reported three failures in guardrails, session-flow and source-control; on a clean `origin/main` worktree the guardrails suite passes 213/0 and the session-flow failure reproduces identically, and this branch touches none of those plugins. - On `fcc3f8cd`, after merging the #3727 squash: the three context-guard suites pass 18/58/25, and main's new `scripts/check-killswitch-hoist.sh` reports 15 of 15 guards clean. - On `5acee106`, after merging the #3732 squash (resolved by the babysit lane, see its comment on this PR): the three context-guard suites pass 18/58/25 again, `scripts/sync-hook-utils.sh --check` reports all 17 copies matching, and the diff against main is still exactly the files above. - On `3db2c457`: the three context-guard suites pass 18/58/25, markdownlint clean on the CHANGELOG, `hooks.json` parses and every `timeout` reads 60 again. - `scripts/check-changelog-parity.sh` `--check-bump origin/main`, `--check-order`, `--check-preserved origin/main`: all exit 0 on every head. - `scripts/check-contract-slice-prune.sh --check-diff origin/main`: passes on `511b549f`. This was the one failing sub-gate of 56 on the lint lane at `f7cb502f` (`contract-slice-diff`); every other hygiene sub-gate was already green there. - Review lanes on `5acee106`: security-review reported no findings; the Claude review lane found no blocking issue and raised the missing skip test, addressed in `860d66d6`; the Codex review raised the timeout finding above, addressed in `3db2c457`. ## Related - #3685: per-tool-call overhead thread; the audit's measurement caveats on the hook-budget convention are posted there as evidence. - #3718: shipped context-guard 0.7.39 (zone-gate deny-reason text). - #3721: `block-hook-bypass` corpus sweep (PreToolUse lane). - #3727: kill-switch hoist, PreToolUse half, with `scripts/check-killswitch-hoist.sh`. Landed first and took context-guard 0.7.40. - #3732: vendored `hook-utils.sh` startup-subshell trim. Landed second and took context-guard 0.7.41, so this PR's entry sits above it as 0.7.42. - Interview ledger: `.work/prompt-hooks-review/interview-checklist.md` (untracked, memory tier). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01ECoW7mi7Zod61utjdyWtRE --------- Co-authored-by: Claude <noreply@anthropic.com>
kyle-sexton
pushed a commit
that referenced
this pull request
Sep 5, 2026
Harness re-run after merging main (#3732 changed the library startup), plus direct cold-cache, warm, and execve probes of cli-flag-verify: 980 ms cold, ~120 ms warm, 88 failed execve per warm run, all the env PATH walk for bash behind five #!/usr/bin/env execs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019DaWEB8Daq1xAXy2Xj1Pme
kyle-sexton
added a commit
that referenced
this pull request
Sep 5, 2026
… cache hits in-process (#3747) No related issue: the verifier-lane performance fix was routed to this lane by the operator through the prompt-hooks session (relayed 2026-09-04, confirmed 2026-09-05) and tracked in the topic's contract slice rather than an issue. ## Summary The three guardrails PostToolUse verifiers were the most expensive hooks on a markdown write. `skill-reference-verify` spent 468 of its 643 ms in a loop that spawned two `jq` and two `tr` per plugin manifest (74 manifests, 296 processes) to build an index one process builds in 5 ms. `cli-flag-verify` spawned the bundled verifier for every candidate even on a warm 24 h cache, where the verifier's whole job is to read one file and match one pattern; each spawn also paid the `#!/usr/bin/env` PATH walk for `bash`. This PR is the first of three from the hook-logging-pipeline topic (the PostToolUse kill-switch hoist and the per-session pipeline follow as separate PRs, each opened after the previous merges). ## Fix 1. **`skill-reference-verify.sh`**: `build_plugin_index` reads every manifest in one `jq -r` emitting `<manifest>\x1e<name>\x1e<paths>` (raw fields on non-whitespace separators, so a nameless manifest keeps its empty field in place and a declared path arrives byte-identical); manifests jq could not parse, and any behind a parse error in the batch, take the per-manifest read the batch replaced, so a malformed sibling changes nothing for the others. 2. **`cli-flag-verify.sh`**: a second pre-gate exits before the fragment pipeline when the content names none of the scanned bins (the `-` gate alone passed every hyphenated paragraph); cache hits are answered in-process (one lazy `find` indexes the fresh cache files on the first candidate whose bin is installed; the cached `--help` text is matched with `=~`), and the verifier is spawned only on a miss. 3. **`lib/verification/cli-flag-cache.sh`** (new): the cache directory, key, freshness window and flag-match pattern, defined once and sourced by both the hook and the verifier. Review of the first cut found the hook's hand-copied pattern had dropped the `[` terminator, so `--flag[=VALUE]` was known cold and unknown warm; one definition is the fix for that class. 4. **`verify-cli-flag.sh`**: `[[ -d ]]` before `mkdir -p`; the 24 h freshness test compares against a reference file touched to that timestamp (one POSIX `touch -t` in place of `find | grep`, `find` kept for Bash before 5.0); the flag match is `=~` over the cached text instead of `printf | grep -E`. 5. guardrails 0.32.1 to 0.32.2 with the CHANGELOG entry carrying the before and after numbers (ADR 0003 rule 2). ## Verification Measured on this Linux host with the topic's harness (N = 15) and direct probes; the raw tables live in the topic's memory slice, the distilled rows in FINDINGS.md on the branch: | Row | Before | After | | --- | --- | --- | | `skill-reference-verify`, `.md` citing a skill | 642.9 ms (334.8 S) | 63.8 ms (33.8 S) | | index loop, isolated (74 manifests) | 468.5 ms | 5.2 ms | | `cli-flag-verify`, warm cache | 118.9 to 135.8 ms | 55.1 to 79.2 ms | | `execve` per warm run (strace) | 152, 88 failed | 34, 11 failed | Every new suite case was written first and run against the unmodified hooks (`git stash` of the three scripts): 2 failures in the skill-reference suite and 3 in the cli-flag suite on the committed hooks, 0 after; the review-round cases (`--color[=WHEN]` on a warm cache, a nameless manifest, a backslash in a declared path) likewise fail on the first cut and pass on the head. Suites: `skill-reference-verify.test.sh` 133/133, `cli-flag-verify.test.sh` 92/92 (was 123 and 70). `scripts/affected-tests.sh --run`: all 26 selected suites pass. `shellcheck -x` clean on the four scripts and both suites. `scripts/check-changelog-parity.sh --check-bump origin/main` exit 0. A fresh-context code review at high effort ran on the first cut; all six of its findings were verified by reproduction and are fixed in the head commit. The topic's contract slice (`docs/topics/hook-logging-pipeline/`) rides this branch and is pruned in the final commit before the ready flip, per the topic-docs convention; the Brief and the phases this PR ships are below. <details> <summary>Brief (TLDR, Goal, corrections) and Phases 0 and 1 of the plan</summary> ### TLDR Design the logging and telemetry pipeline for the marketplace's hooks, and settle the upstream decisions that determine what it instruments. Evidence base is FINDINGS.md, a measured read-only audit of the 26 wired `PostToolUse` rows plus a doc-alignment pass. Interview complete: five rounds, 21 questions, 19 answered and 2 deferred with named arbiters. Register gate clean. ### Goal Observability across every hook event, defaulting to off, costing effectively nothing when off and as close to nothing as measurable when on, with no surface left as a black box and every toggle reachable by Claude on the operator's behalf rather than by hand. ### The verifier-lane allocation (confirmed after the interview closed) The three PostToolUse verifiers on a markdown write citing a skill and CLI commands cost about 825 ms (peer measurement, corroborated at 601 to 622 ms for the dominant guard alone). Four patch shapes, each measured by the prompt-hooks lane and re-measured here before landing: the batched index; the bin-name pre-gate; the in-parent cache read; the three cache-path spawns in the verifier. Read ADR-0003 before touching any of the three; it was written about exactly these guards. ### Phase 0: Baseline measurements [DONE] Re-measure before touching anything (ADR-0003 rule 1). PR #3732 changed the library's startup path after the handoff figures were taken, so every number is re-captured. Harness at N = 15; cold cache for `cli-flag-verify` with the directory cleared; PATH tax by `strace -f -e trace=execve`; distilled figures into FINDINGS.md under "Re-measurement 2026-09-05". ### Phase 1: Verifier-lane fix (PR A) [DOING] Four patch shapes, each with a repro-first test per `hook-precision`. Timing assertions live in the harness rows recorded in FINDINGS.md; the suites assert structure (spawn counts through PATH shims, equivalence), which is stable on shared CI runners. 1a the batched index with a fixture of three manifest shapes and a one-invocation assertion; 1b the bin-name pre-gate with a zero-`sed` case on hyphenated prose; 1c the in-parent cache read with a zero-verifier-spawn case on a warm cache and identical findings; 1d the verifier's own cache path with the `--save-dev` versus `--save-developer` boundary cold and warm. Harness re-run; before and after in FINDINGS.md and the CHANGELOG entry; guardrails patch bump above `origin/main`; `scripts/affected-tests.sh --run`; shellcheck; PR as draft with the body contract; prune commit before the ready flip. Sanity check: harness "with refs" row for `skill-reference-verify` under 100 ms; the guardrails suites exit 0 with the shim-counter cases; `scripts/affected-tests.sh --run` exit 0; `scripts/check-changelog-parity.sh --check-bump origin/main` exit 0. </details> ## Related - Refs #3685, the hook-budget convention's spawn-dominated versus work-dominated split, which this topic's measurements bear on (`markdown-format` at 343 ms is Node startup, not spawns) and which this PR does not change - Refs #3719 and PR #3727, the PreToolUse half of the kill-switch hoist; the PostToolUse half is the next PR from this branch's topic - `docs/adr/0003-verification-guards-earn-default-on-by-measured-precision.md`, rule 1 (measure before shipping) and rule 2 (report the number in the PR) - `docs/conventions/hook-precision/README.md`, the repro-first discipline every new case follows - `lib/hook-utils.sh` and its 17 vendored copies are untouched 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019DaWEB8Daq1xAXy2Xj1Pme --- _Generated by [Claude Code](https://claude.ai/code/session_019DaWEB8Daq1xAXy2Xj1Pme)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
kyle-sexton
added a commit
that referenced
this pull request
Sep 7, 2026
…ners (#3878) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> No linked issue ## Summary Drop leftover process creations on the hottest Bash paths in this marketplace: the shared hook library every always-on hook sources, the always-on formatter Write/Edit paths (typos, ruff, biome, bash, powershell, go, actionlint, eol, markdown), the always-on desktop-notification Notification path, always-on guardrails verifiers, and CI scanners that used to spawn once per file, per plugin, or per allowlist entry. ## Fix GNU Bash runs command substitution in a subshell even for builtins (Command Substitution, [Bash Reference Manual](https://www.gnu.org/software/bash/manual/html_node/Command-Execution-Environment.html); [Greg's Wiki](https://mywiki.wooledge.org/CommandSubstitution)). Cygwin's `fork` is a non-copy-on-write Win32 `CreateProcess` ([Cygwin User's Guide, Process Creation](https://ftp.cygwin.com/cygwin-ug-net/highlights.html)): "fork will almost certainly always be inefficient under Win32." ### Shared hook library (`lib/hook-utils.sh`, synced to 17 carriers, patch bump) Same `_to` / in-process pattern as #3838, #3732, and #3678: - `hook::json_escape_to` deletes residual C0 bytes with parameter expansion instead of `printf | tr -d` - `hook::emit_channels` writes through `_to` instead of `$(hook::json_escape …)` - Fractional `read -t` landed in bash-4.0-alpha (CHANGES). `hook::read_supports_fractional_timeout` is `BASH_VERSINFO`; no TMPDIR probe file - `hook::notice_once` reads the marker with `read`, creates the directory only when missing, and prunes stale markers once per process - `hook::bash_parse_segments` walks `${cmd:i:1}` instead of `read -N1` from a process substitution, and `$'…'` bodies decode through `ansi_c_decode_to` (`printf -v`) - `hook::repo_root_to` / `hook::repo_relative_path_to` write in this shell so callers skip a leftover capture around git or builtins-only work Isolation `$(source …)` forks are unchanged (#3685). ### typos-format (always-on Write|Edit|NotebookEdit) - Basename via `${FILE##*/}` (plus a backslash trim), not `basename(1)` - `repo_root_to` / `repo_relative_path_to` instead of capture subshells - Directory existence check instead of `$(cd && pwd)` - `command -v typos` is no longer captured; the later exec looks the name up on PATH ### Remaining always-on formatters (ruff, biome, bash, powershell, go, actionlint, eol, markdown) Same leftover class as typos-format, now applied to every always-on formatter that still captured `_to` helpers or spawned `basename` / leftover `cd && pwd`: - `FILE_BASE` is `${FILE##*/}` (and a backslash trim) - `repo_root_to` / `repo_relative_path_to` write in-process - `$(cd && pwd)` canonicalize is an existence check on the path git already answered (ruff, biome, bash-format EditorConfig walk) - Nested `$(normalize_path "$(physical_path …)")` in powershell-format uses the `_to` forms - `command -v ruff|biome|goimports` is no longer captured - markdown-format keeps physical `pwd -P` containment and config discovery; leftover helper-capture and membership dirname on the root-resolution path are gone ### desktop-notification (always-on Notification) - Field extract fuses into `hook::buffer_stdin_to` so completeness and `.notification_type` / `.message` share one jq process - C0 stripping is parameter expansion, not `printf | tr` - `repo_root_to` writes in-process; OSC 9 / BEL use `printf -v`; `terminalSequence` uses `json_escape_jq_to` - `uname` stays so tests can PATH-stub Darwin; git for `repo_root` stays ### guardrails verifiers (always-on PostToolUse / PreToolUse) - `skill-reference-verify`, `stale-path-verify`, and `cli-flag-verify` call `repo_root_to` / `repo_relative_path_to` in-process - `hardcoded-path-check` and `secret-pattern-detection` use `normalize_path_to` instead of leftover `$(hook::normalize_path)` captures - Isolation `$(source …)` forks are unchanged (#3685) ### CI scanners - Orphaned-fixture scan: one `*.test.*` index, cached `evals.json` `files[]`, in-shell ERE escape. Unquoted `\\` matches one backslash (a quoted `'\\'` arm is two chars and leaves `\b` as a word boundary) - Purged-em-dash scan: one `git ls-files -z` with every `:(glob)` pathspec; in-process component-wise attribution so `*` cannot cross `/`. `--list` stdout is byte-identical to origin/main - Cross-plugin source drift: one `find plugins` plus one `sha256sum` of 2+ cluster paths. Discover stdout is byte-identical to origin/main - Discriminating-test-skips / silent-skips: one awk per corpus (`FNR` + `FILENAME`; mawk has no `ENDFILE`) - Hook-exec-form: one jq over every `hooks.json` and one over every `plugin.json` (`input_filename` attributes rows). Unreadable `hooks.json` still fails closed via per-file fallback; unreadable manifests are still skipped Hook-specific leftover-fork work already in flight (#3873, #3872, #3871, #3870, #3869, #3851, #3849, #3779, #3880, #3886) is out of scope here. ## Verification Independent census re-derived spawn counts from `84adf87b` vs `cdb93f61` without inheriting implementer figures. Kernel census `strace -f -e trace=clone,clone3,fork,vfork,execve`; counter over duration; 3 identical trials. **always-on formatters** (this revision vs `84adf87b`): | Hook | clones before | clones after | execve before | execve after | |---|---|---|---|---| | ruff-format no-config skip | 14 | 10 | 4 | 4 | | powershell-format no-settings skip | 23 | 16 | 7 | 7 | | bash-format no-EditorConfig (ShellCheck finding) | 17 | 13 | 6 (1 `basename`) | 5 (0 `basename`) | **guardrails** (this revision): | Hook | clones before | clones after | execve | |---|---|---|---| | skill-reference-verify Write, no skill refs | 18 | 17 | 8 unchanged | | secret-pattern-detection clean Write | 10 | 8 | 4 unchanged | Secret-pattern absolute counts are with `CLAUDE_PLUGIN_ROOT` set (Claude Code always sets it). Without that env the leftover `PLUGIN_ROOT=$(cd … && pwd)` fallback adds one clone on both sides (11→9); the drop of 2 is the same. **CI scanners** (successful execve, exclude ENOENT; earlier commits on this PR): | Gate | origin/main or prior HEAD | HEAD | |---|---|---| | purged-em-dashes `--list` | 478 | 9 | | cross-plugin-source-drift `--check` | 181 | 4 | | discriminating-test-skips | 316 (awk 312) | 5 (awk 1) | | silent-skips | 120 (awk 118) | 4 (awk 2) | | hook-exec-form `--check` | 196 execve, jq 96, tr 96, clones 292 | 7 execve, jq 2, tr 0, clones 9 | `--list` / discover stdout for the two listing gates is byte-identical to origin/main. **Local `scripts/affected-tests.sh --run`:** 153 shell suites passed or were skipped; 14 NOT RUN python/mjs ecosystems (exit 3, expected on this runner). No `FAIL`. Including: `lib/hook-utils.test.sh` PASS=323; bash-format PASS=54; eol-normalizer PASS=54; markdown-format PASS=174; powershell-format PASS=17; cli-flag-verify PASS=92; hardcoded-path-check PASS=118; secret-pattern-detection PASS=86; skill-reference-verify PASS=140; stale-path-verify PASS=108. ruff/biome/go/actionlint behavioral cases skipped here (binaries absent); skip-path and source pins still ran. `session-event-log.test.sh` PASS=53 isolated under the fan-out. **CI on `cdb93f61`:** lint, hook-utils, test-linux (0–3), test-windows, changes, ci-status, and managed-files-guard all succeeded. https://github.com/melodic-software/claude-code-plugins/actions/runs/34066676378 https://github.com/melodic-software/claude-code-plugins/actions/runs/34066676488 ## Related Refs #3838, #3732, #3678, #1979, #3488, #2891. Same leftover-fork class as open PRs #3849 / #3851 / #3869 / #3873 / #3872 / #3871 / #3870 / #3779 / #3880 / #3886 (those stay hook-specific). N/A for a dedicated issue. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-fdfdc962-be1b-4c9c-9833-3aec57852330?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-fdfdc962-be1b-4c9c-9833-3aec57852330&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No linked issue
Summary
Phase 1 of a measurement-first shell-script performance pass: cut remaining process creations on the always-on hook hot path in
lib/hook-utils.sh(17 plugin copies) and stop spendingjqon wired-sink{tool,subject,form}telemetry.Fix
Discovery ranked remaining waste after the hook-performance program (#3623). Guardrails already measured and rejected dispatcher
repo_rootpriming, per-guarddirnamereplacement, and merginghardcoded-path-checkgit probes. This PR takes the three leftover cuts that had a drift-immune counter and a matching repo pattern:hook::buffer_stdintimeout/slice wrappers. GNU Bash runs command substitution and process substitution in a subshell even for builtins. The suite already documented those two startup forks._tohelpers write into caller variables withprintf -v.hook::repo_rootgit | tr. Same in-shell CR stripbuffer_stdinalready uses (${root//$'\\r'/}).hook::json_str_object_to+ seven always-on Bash-guardemit_telbuilders. Compact{tool,subject,form}is now builtin and byte-identical tojq -nc --arg …. The envelope was already builtin (perf(hook-utils): build the telemetry envelope and read file_path with builtins #3678). Unwired default path is unchanged (zero telemetry spawns).Carrying plugin versions are bumped so consumers receive the synced copies. After merging
maintwice, those versions were re-bumped past the numbersmainshipped in the meantime, and every earlier heading this branch introduced (including claude-ops0.41.14) is kept so--check-preservedholds.Phase 2 (not in this PR): context-guard resolver in-process; skill/stale-path grep short-circuit;
affected-tests.shmanifest cache.Verification
Headline counters on this Linux host (wall-clock refused as binding; Windows Git Bash remains the consumer cost model):
buffer_stdintimeout/slice$$≠$BASHPID)$$=$BASHPID)hook::repo_rootspawns=2 [1 git 1 tr]spawns=1 [1 git]emit_teldata objectspawns=1 [1 jq]spawns=0{"tool":"Bash","subject":"git status --short","form":""}cmp)bash lib/hook-utils.test.sh: PASS=286 FAIL=0.Critical guard contracts: block-no-verify 238, block-dangerous-git 479, block-hook-bypass 576, block-noncanonical-commit 213, block-convention-violation 70, block-windows-drive-tmp 214, block-exported-msys-pathconv 127, run-guards 66 — all FAIL=0.
scripts/affected-tests.sh --run: 142 shell suites passed; 9 selected non-shell suites named as NOT RUN (CI lanes). Zero FAIL lines.Post-merge gates vs
origin/main:sync-hook-utils.sh --check/--check-bump,check-changelog-parity.sh --check/--check-bump/--check-preserved/--check-order,check-shell-portability.sh, andshellcheck -x lib/hook-utils.test.shall OK. Re-ranhook-utils.test.sh(286/0) on the merge.Related
Refs #3623, #1403, #3678. Follows
docs/conventions/hook-budget/README.md(budget never relaxes) andplugins/performance/reference/harness-integrity.md(spawn count over two-pass wall-clock).