Skip to content

perf(shell): cut remaining N+1 Git and CLI spawns - #544

Merged
kyle-sexton merged 12 commits into
mainfrom
cursor/bash-spawn-census-cba6
Sep 7, 2026
Merged

perf(shell): cut remaining N+1 Git and CLI spawns#544
kyle-sexton merged 12 commits into
mainfrom
cursor/bash-spawn-census-cba6

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

No related issue: remaining Bash spawn N+1 after #316/#361, ranked by spawn census rather than file size.

Summary

Measurement-first Bash performance pass, following the fleet performance@melodic-software plugin (spawn count over wall clock, stable PATH shim, interleaved repeats) and the patterns already landed in #320/#358/#361.

distribution/sync-manifest.sh is already a Node wrapper; this change does not touch it.

Highest-impact remaining subjects on this repo, in order:

  1. check-exec-bit.sh: 133 → 4 process spawns (git 131 → 2) against 65 shebang-looking blobs.
  2. scan-comment-hygiene.sh: 81 → 3 (awk 77 → 0) — one awk per git-grep hit.
  3. check-machine-specific-paths.sh: 10 → 1 (git 5 → 1, head 5 → 0).
  4. scan-workflow-files.sh: yq 11 → 1 on the success path (CI glob is 11 workflow files).
  5. check-plugin-baseline.sh --compare: jq 5 → 3.
  6. cloud-bootstrap warm path: 5 Claude list CLIs → 2.
  7. setup.sh plugin stage (fleet+repo, warm): 4 Claude list CLIs + N grep → 2 (same list-once shape as cloud-bootstrap).
  8. check-claude-settings-targets.sh --file: jq 3 → 2 on the success path.
  9. check-heading-cites.sh: drop the identity cat when EXCLUDE is empty.

Host qualification (bash -c true, n=20): spread 1.66× (measurable). Headline metric is still the drift-immune spawn counter.

Fix

  • exec-bit: one git grep --cached -z -nIE '^#!' (line 1 ≡ byte-0 shebang) plus one git ls-files --stage -z with exact-recorded-path mode lookup. POSIX awk join (bash 3.2: no declare -A). Combined -z -n emits path NUL lineno NUL text LF (git 2.43 byte dump; git-grep(1) only mentions pathname delimiting). The 100644 shebang case fails closed; a contract test pins that record via tr '\0' '|'.
  • comment-hygiene: chp::scan_text matches the comment-start pattern in-process for newline-free content (the local-lane git-grep hit shape). Multi-line callers still use one awk.
  • machine-specific-paths: one combined git grep -E over the five OS/repo bodies; classify hits in-process so per-OS labels and the 20-line cap stay without a second grep or head.
  • heading-cites: split the corpus pipeline so an empty EXCLUDE does not spawn cat.
  • check-plugin-baseline compare_settings: one tagged jq pass, matching compare_catalog and the perf(distribution): validate the manifest in two yq passes, not 274 #320 yq consolidation.
  • cloud-bootstrap: list marketplaces and plugins once; record installs locally; re-list marketplaces only when this session registered a new one. Materialized .claude/cloud-bootstrap.sh stays byte-identical to the component.
  • setup.sh plugin stage: share one marketplace list and one plugin list across fleet+repo; in-process membership instead of grep -qxF per entry; record new installs so the second source does not re-query. Toolchain tracks (apt/dotnet/nvm) are unchanged.
  • settings-targets: one jq policy pass on the success path; jq empty on the candidate runs only when that pass fails, so parse errors stay exit 2 and policy misses stay exit 1.
  • pin-comment: one yq eval --no-doc over every existing workflow argument on the success path (filename operator; without --no-doc, --- document separators are misread as records). Mike Farah yq 4.53.3 multi-file eval still stops at the first parse error and has no try/catch, so a failed batch falls back to per-file pcc::scan_text and still reports every file.

Left unchanged after census (already at floor, tiny corpus, or I/O-dominated): sync-manifest Node engine, setup.sh apt/dotnet/nvm, private-repo-inventory (tiny TOML), repin::ahead_of (release-time, small N).

Verification

  • bash harness/shell/run-tests.sh — previously 19 passed, 0 failed, 16 skipped on the earlier commits; this revision adds spawn-census coverage in pin-comment-convention.test.sh.
  • comment-hygiene.test.sh: 8 single-line scans awk=0; multi-line fixture awk=1
  • local-lane-guards.test.sh: exec-bit 8-file git shim (grep=1, ls-files=1, cat-file=0); 100644 shebang fails closed; git grep -z -n layout bad.sh|1|#!/usr/bin/env bash; machine-paths git=1 head=0; comment-hygiene driver awk=0; start-of-line Linux home still labeled
  • check-plugin-baseline.test.sh: --compare jq=3
  • cloud-bootstrap.test.sh: warm path marketplace-list=1, plugin-list=1; copies identical
  • setup.test.sh: fleet+repo warm path marketplace-list=1, plugin-list=1, marketplace-add=0, plugin-install=2 (beta+gamma); bash -n and stamp-after-wait contracts unchanged
  • check-claude-settings-targets.test.sh: --file success-path jq=2; malformed candidate still exits 2
  • pin-comment-convention.test.sh: 8 conforming files yq=1; parse-error fallback still reports a later missing-comment (batch + per-file yq=4)
subject before after
check-exec-bit.sh 133 (git=131) 4 (git=2)
scan-comment-hygiene.sh 81 (awk=77) 3 (awk=0)
check-machine-specific-paths.sh 10 (git=5 head=5) 1 (git=1)
scan-workflow-files.sh (CI glob, success) 11 yq 1 yq
--compare identical fleet list 10 (jq=5) 6 (jq=3)
check-heading-cites.sh 8 (incl. cat=1) 7 (cat=0)
setup.sh plugin stage (fleet+repo, warm) 4 Claude list CLIs + N grep 2 (grep=0)
check-claude-settings-targets.sh --file 3 jq 2 jq

Grounding: GNU/Git cat-file --batch / ls-files --stage / grep (batch vs per-object); Google Shell Style Guide “builtin vs external” and no UUOC; this repo’s #320/#361 spawn-census method; performance plugin harness-integrity (stable PATH, fail closed, commit before verify); yq file operators.

Related

Open in Web Open in Cursor 

cursoragent and others added 3 commits September 6, 2026 21:26
…at-file

Spawn census on this repo (65 shebang-looking blobs) counted 131 git
invocations per run: one ls-files --stage and one cat-file blob per
candidate. One git grep -z -n plus one ls-files --stage, with exact-path
mode lookup, cuts that to two git spawns (133 -> 4 total). Line 1 matching
^#! is the POSIX-text equivalent of the previous byte-0 cat-file check.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
compare_settings parsed the same pair three times (missing plugins, extra
plugins, marketplace diffs). One tagged jq pass matches compare_catalog
and the earlier manifest yq consolidation. --compare jq spawns 5 -> 3.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
… path

install_plugins_from listed marketplaces and plugins per source, then
inventory listed marketplaces again (five CLI round-trips every session).
Share the listings, record installs locally, and re-list marketplaces
only when this session registered a new one.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review September 6, 2026 21:28
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T21:31:02.989189Z 1aa4c31 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 7m 35s —— View job


Code review complete

  • Gather context (PR body, diff, CLAUDE.md rules)
  • Skip-gate check (open, not draft, non-trivial, no prior review from this lane)
  • Review changed files for correctness/maintainability
  • Post inline findings
  • Post summary

Findings

1 high-severity correctness issue, posted inline on check-exec-bit.sh#L58-L65:

The new shebang-detection loop assumes git grep -z -n NUL-delimits every field (path\0lineno\0text), but git-grep(1) documents -z as delimiting only the pathnamelineno and matched text stay :-joined and \n-terminated (path\0lineno:text\n). Tracing the byte layout by hand, read -r -d '' lineno either reads across into the next record (multi-candidate case, garbled lineno, never "1") or hits EOF and breaks before the path is recorded (single-candidate case). Either way shebang_paths ends up empty whenever a real shebang file exists, so the gate always falls through to "All shebang files are mode 100755" and exits 0 — silently defeating the check this PR is centered on. This would also flip the pre-existing local-lane-guards.test.sh:49-58 regression test ("exec-bit fails a 100644 shebang") from pass to fail. Full reasoning and a suggested fix direction are in the inline comment.

Note: I could not execute git grep -z ... directly in this review sandbox to get an empirical byte dump (those invocations were blocked), so this is derived from the documented -z semantics plus hand-tracing the parser against the included test — worth an explicit test run before merge to confirm.

No other issues found. The check-plugin-baseline.sh jq consolidation and the cloud-bootstrap.sh list-once/cache-locally change both check out: output format is preserved in the former, and .claude/cloud-bootstrap.sh is byte-identical to components/cloud-bootstrap/cloud-bootstrap.sh at HEAD (the working-tree diff between those two files I saw locally is pre-existing uncommitted drift in this checkout, unrelated to this PR's commits).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1aa4c31b56

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread components/local-lane-guards/check-exec-bit.sh Outdated
Stock macOS bash 3.2 has no associative arrays. Replace declare -A with a
POSIX awk join on the batched ls-files records (same awk dependency as
heading-cites). Spawn census stays git=2; total still 4 (mktemp -d + awk).

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
Comment thread components/local-lane-guards/check-exec-bit.sh
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

cursoragent and others added 8 commits September 6, 2026 21:41
The local-lane driver already prefilters to one candidate comment per
call, then chp::scan_text spawned awk to re-extract comment lines. Match
the comment-start pattern in-process for newline-free content so a tree
scan no longer pays one awk per hit. Multi-line callers still use one awk.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
PATH-prefix assignments on a shell function persist, and command -v can
see a leftover census shim. command -p pins the standard awk so the
counter cannot double-count a wrapper.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
Five per-OS git greps each walked the index. One combined -E union plus
in-process classification keeps the per-OS labels and the 20-line cap
without a second grep or a display-only head.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
An empty EXCLUDE used to pipe ls-files through cat. Split the pipeline
so the exclude grep is the only extra stage when a consumer sets one.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
git-grep(1) documents -z as delimiting pathnames, which a review read
as path NUL lineno:text LF. Combined -z -n actually emits path NUL
lineno NUL text LF (git 2.43 byte dump; the 100644 shebang case already
fails closed). Pipe through tr so the two NULs are visible to assert_eq.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
…rm path

install_plugins_from listed the Claude plugin CLI twice (once per source)
and spawned grep -qxF per entry. Share one marketplace list and one plugin
list across fleet+repo, record new installs in-process, and skip with the
same membership idiom cloud-bootstrap already uses.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
check_one ran jq empty then jq -e per candidate. The success path now
does one policy pass; jq empty on the candidate runs only when that pass
fails, so parse errors stay exit 2 and policy misses stay exit 1.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
CI scans 11 workflow files, each previously one yq. One eval --no-doc over
the glob matches per-file records (filename operator; --- separators would
be misread as hits). Multi-file eval still stops at the first parse error
and has no try/catch (yq 4.53.3), so a failed batch falls back per-file.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
@kyle-sexton
kyle-sexton merged commit 29fa4c8 into main Sep 7, 2026
84 checks passed
@kyle-sexton
kyle-sexton deleted the cursor/bash-spawn-census-cba6 branch September 7, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(distribution): sync-manifest.sh spends 276 process spawns on Git index and control-character checks

2 participants