Skip to content

ci: re-pin gitleaks composite, extend the Windows lane, wire unwired suites - #5316

Merged
kyle-sexton merged 13 commits into
mainfrom
fix/audit-ci
Sep 29, 2026
Merged

kyle-sexton merged 13 commits into
mainfrom
fix/audit-ci

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3599

Summary

Fixes from the 2026-09-29 audit of the Cursor agent's PRs that touch CI (group "ci"), one commit per change, all under .github/, .gitleaksignore and scripts/gitleaks-*:

Fix

  • aa6a6230d lint job: melodic-software/ci-workflows/.github/actions/gitleaks@35880dcb (v0.30.1) with scan-mode: git and log-opts unset. A pull request scans its own commits (<base>..HEAD), a push scans main's full history, a dispatch scans every ref present in the clone. Only this step moves; the other composites stay at v0.27.1. .gitleaksignore keeps the two 04f4bcd5 fingerprints (reachable from main) and drops the five for commits no origin ref reaches.
  • fafdab6af, bf21ed285, b748b5dd4, b2b689b52 test-windows.yml: the kindle-dedrm step fails the lane on a failing test; the launcher steps and the markdown-format and cloud-bootstrap suites run on windows-2025; the skill-visibility step added by b748b5dd4 is dropped by b2b689b52.
  • 430e0d953 ci.yml: outside-node runner on the UNMAPPED fallback, check-prerequisite-probes.test.sh as a hard-failing test-linux step, wider shell filter.
  • 747b59154 comment-only changes in workflows.
  • c2e18d24a .github/requirements-ci-animation.txt (hash-locked) installed with requirements-ci.txt in one --require-hashes command, plus ANIMATION_REQUIRE_DEPS=1. The install stays (measured below).
  • 85ee97b36 comment-only: the gitleaks step comment says a manual dispatch scans every ref present in the clone; the test-windows.yml comment names claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323.
  • dee4d13fa silent-revert-canary.yml: "Resolve the pushed range" sources scripts/lib/changed-files.sh and calls changed_files::verify_base in place of the inline git rev-parse --verify --quiet "<ref>^{commit}". The fallback (warn, scan the head commit) is unchanged. Applies the scripts group's request (c).
  • 2a619570a ci.yml: the "Install locked plugin test toolchains" step diffs the name==version pins of plugins/animation/requirements.txt against .github/requirements-ci-animation.txt and fails when they differ (Codex review: Dependabot's /.github entry would bump only the CI copy).
  • Requests received from other groups: the animation, architecture, scripts (a, b) and claude-config requests were already met by the commits above or by issue operations; playbooks became a decision packet and hook-launcher was not triggered. Each outcome is under Related.

Verification

Static checks, on head 85ee97b36:

  • git merge origin/main (earlier, into 5ca5fe296): clean, no conflicts, none of its commits in the group's paths.
  • actionlint and online zizmor --persona=regular: no findings.
  • bash scripts/check-lane-coverage.sh --check: all 5 lanes reachable from ci-status.needs, 66 gate steps fed to the aggregator, 2 opted out.
  • bash scripts/check-lane-coverage.test.sh: PASS=40 FAIL=0.
  • bash scripts/check-docs-only-gate.sh --check: passes.
  • bash scripts/check-changelog-parity.sh --check --check-order: passes.
  • bash scripts/validate-plugins.sh: all manifests and the catalog validated. No plugin files changed, so no version bumps or changelog entries.

On head dee4d13fa, which changes only silent-revert-canary.yml, re-run: actionlint over every workflow, zizmor --offline --persona=regular on the canary, check-lane-coverage.sh --check (66 gate steps fed, 2 opted out) and check-shell-portability.sh origin/main: all clean. The checks above were not re-run; the commit changes no other file.

On head 2a619570a, which changes only ci.yml (the pin check): equal pins pass and a one-sided numpy edit fails when the step's diff is run locally; actionlint, zizmor --offline --persona=regular, check-lane-coverage.sh --check (66 gate steps fed, 2 opted out), check-lane-coverage.test.sh (PASS=40), check-docs-only-gate.sh --check and check-shell-portability.sh origin/main are clean.

The migrated step body was run in a scratch repository against five before values. A valid parent sha took range mode with no warning; 40 zeros, an empty value, an unknown sha and a non-ref each took commit mode with one warning. A dispatch of the canary on this branch, 36589890903 (head dee4d13fa), succeeded in every step; its empty before takes the commit-mode branch, so it proves the source line works on the runner and the scratch run covers the rest.

#3599 acceptance criterion 1 (hygiene passes on a PR that does not touch resolve-convention-home.sh): met. This PR's own lint run, 36579146249 (head 5ca5fe296, pull_request): "Scan for secrets" success, 8 commits scanned (<base>..HEAD), no leaks found. The run on the newest head 85ee97b36, 36582778889, is green (ci-status success) and its scan of 20 commits found no leaks. The ci dispatch below, whose --all scan ran in a CI clone, scanned 3192 commits and also found no leaks, so a manual dispatch does not go red on other refs. The 8 findings a local all-refs scan reports come from local-only refs/remotes/pr/* refs that a CI clone does not hold (correction posted on #3599).

Windows lane, two dispatches of test-windows.yml on this branch (the only run of these steps on a real Windows host):

  • 36528002813, red. Step "Test the skill-visibility audit on Windows" failed with 2 failures, both AssertionError: 'unreadable' != 'read'; the record was bash exited 1 sourcing the lib: no stderr for plugins/claude-ops/lib/managed-scope.sh. The cause is in a claude-ops script, not in .github/, so the step was dropped (b2b689b52) instead of committed red, and the defect is filed as claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323 (before this it lived only in the comment at test-windows.yml:205).
  • 36529242934, green, about 10.5 minutes (06:04:46 to 06:15:19) against timeout-minutes: 20, which stays unchanged. Per step:
    • kindle-dedrm Pester (Run.Exit set): 11 passed, 0 failed, 0 skipped.
    • markdown-format: PASS=168 FAIL=0 SKIPPED=4. The host probe fired: four counted SKIP (host: cygpath rewrites ...) lines, plus the uncounted symlink-escape skip.
    • cloud-bootstrap-plugins: PASS=79 FAIL=0, no probe skip; the stubbed claude ran on Git Bash.
    • exec-form launcher, resolver test (node --test lib/exec-bash.resolver.test.mjs): 1 pass, 0 fail.
    • exec-form launcher, plugins/guardrails/hooks/exec-bash.test.sh: passed (stdin, exit 2, Git Bash resolution, hooks.json shape, 8 dispatcher rows).

ci dispatch 36577675603 (head c2e18d24a), which measures the animation install and the gitleaks step:

  • lint success; "Scan for secrets" scanned 3192 commits, no leaks found.
  • test-linux legs 0, 1 and 3 green. Leg 2 red only on plugins/planning/tests/interview-defenses.test.sh (SKILL.md frontmatter is unchanged digest check). That is outside this group's paths and the suite failed the same way at the branch's base; a snapshot of origin/main 9ef496019 passes it (PASS=154 FAIL=0), so the next base merge clears it.
  • Install locked plugin test toolchains: 11 to 14 s per leg with the animation wheels, against 6 to 8 s per leg on today's main push runs 36580419086 and 36580578535 (one 15 s sample). Leg wall time: 162 to 281 s against 141 to 288 s on those runs, so the install adds about 5 s and the wall-time spread is main's own run-to-run spread. No leg is more than 60 s slower, so the install stays, and the animation group's ANIMATION_REQUIRE_DEPS=1 request stands.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB

kyle-sexton and others added 9 commits September 29, 2026 01:32
Run the shared gitleaks composite at v0.30.1 in the lint job and delete
scripts/gitleaks-scoped-scan.sh with its test. With log-opts unset the
composite scans a pull request's own commits (<base>..HEAD), the full
history on a push, and every ref on a manual dispatch, so a finding on
another branch no longer fails a pull request and main gets its history
scan back. Only this step moves; the other composites stay at v0.27.1.

The full-history scan reaches 04f4bcd, which holds the deleted test's
fixture keys, so its two fingerprints return to .gitleaksignore. The five
fingerprints for 7cd6ae4 and f8ae237 come out: no origin ref reaches
either commit.

Refs #3599

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
Invoke-Pester -Path <dir> -Output Detailed exits 0 with failing tests, so the
kindle-dedrm step could not turn the lane red. Run it from a configuration
with Run.Exit set, which exits with the failure count.

Refs #3703

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
Every bash-scripted hook now starts through node exec-bash.mjs, which finds
a real Git Bash, refuses the System32 WSL relay and spawns bash without a
shell. That resolution and spawn only happen on NT, and no Windows step ran
either test. Add the resolver test under the real node.exe and the
guardrails launcher test, which pipes stdin through node exec-bash.mjs to a
recording script and reads every hooks.json row for the node exec form.

Refs #3686

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
markdown-format, cloud-bootstrap plugin accounting and the skill-visibility
audit each probe the host and print a counted SKIP line when they cannot pin
their cases. None ran on a Windows host in CI, so the causes asserted for their
Windows behaviour came from Linux runs alone. Each now has its own step, and the
job comment names the probes so the log can be read for whether one fired.

Refs #3683
Refs #3703
Refs #3686

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
…s-2025

The first dispatch of the lane ran audit_skill_visibility.test.sh red: two
managed-scope unit tests report "bash exited 1 sourcing the lib" for
plugins/claude-ops/lib/managed-scope.sh. The cause is in the audit engine or its
tests, not in the workflow, and a red step also skipped every later step, so
the step leaves the branch until the suite passes on Windows. The job comment
records it as not yet on the lane.

Refs #3683

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
…obe suite, widen the shell filter

- The UNMAPPED fallback ran only run-plugin-tests.sh; leg 3 now also runs
  run-outside-node-suites.sh, as the push path does, so a diff the selector
  cannot map still covers repo-analysis and video-digestion.
- Add scripts/check-prerequisite-probes.test.sh to the leg-2 explicit-suite
  block: run-plugin-tests.sh does not discover scripts/.
- Add the generate-file-name-gate skill tree and .claude/docs-hygiene.json
  to the shell filter group in ci.yml and test-windows.yml, so a change to
  the template or its config runs the docs-naming drift test.

Refs #3703, #4240, #4139

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
…ns and remedies

Refs #4130, #4670, #4144.

The zizmor self-repository comment drops the Claim/Basis/Recheck lines that
restated the paragraph before them and hardcoded actionlint and ci-workflows
pins; the paragraph now ends with the tracker reference. The ci-status
stale-failure comment keeps the mechanism and points at the docs section for
the operator remedy, whose premise is unverified. The Dependabot release
comment cites the GitHub docs page for the GITHUB_TOKEN behavior, states the
operational consequence, and ties the recheck to #4144.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
… suites run

test_inkstats.py and test_woodcut_marks.py self-skip when numpy or cv2 is
missing, and requirements-ci.txt has neither, so CI reported them green
without running them. A separate generated lockfile carries the two pins
and their closure as Linux x64 cp314 wheels; lint-2 and the Windows lane
read only requirements-ci.txt and do not install them. test-linux installs
both files in one --require-hashes command and sets ANIMATION_REQUIRE_DEPS
so a missing import fails the run instead of skipping.

Refs #4594

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
kyle-sexton and others added 2 commits September 29, 2026 10:27
The lint comment implied a dispatch reports findings on other branches. The
dispatch that ran on this branch scanned every ref the CI clone holds and found
nothing; only a local clone that also carries closed pull request heads reports
findings there. The test-windows comment names the tracker for the dropped
skill-visibility step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
The push-range step hand-rolled `git rev-parse --verify --quiet
"<ref>^{commit}"`, the predicate scripts/lib/changed-files.sh already
owns as changed_files::verify_base. The step keeps its own policy: an
unusable `before` falls back to the head commit with a warning, so it
consumes only the helper's status.

Checked by running the step body against a valid sha, 40 zeros, an empty
value, an unknown sha and a non-ref. The first takes range mode, the
other four take commit mode with the warning. actionlint and zizmor
report nothing.

Refs #3413

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB
@kyle-sexton
kyle-sexton marked this pull request as ready for review September 29, 2026 15:38
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 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-29T15:43:55.642354Z 29c47ea 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 29, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 50s —— View job


Code review complete

  • Gather context (PR body, diff, changed files)
  • Review changed files for correctness/maintainability
  • Post inline findings (if any)
  • Post summary

Summary

Reviewed all 8 changed files (ci.yml, test-windows.yml, dependabot-plugin-release.yml, silent-revert-canary.yml, .gitleaksignore, .github/requirements-ci-animation.txt, and the two deleted scripts/gitleaks-scoped-scan* files) against the criteria for this lane: correctness and maintainability, scoped to the diff.

I traced each of the changes back into the working tree to confirm they wire together correctly rather than just reading the diff in isolation:

  • Gitleaks re-pin (aa6a623): the new composite step (ci.yml:367-378) matches the deleted script's documented event-scoped behavior; .gitleaksignore fingerprints correctly track only commits reachable from history (04f4bcd5), and no remaining reference to the deleted scripts/gitleaks-scoped-scan*.sh exists anywhere else in the repo.
  • silent-revert-canary.yml (dee4d13): changed_files::verify_base in scripts/lib/changed-files.sh:66-68 is byte-for-byte the same predicate (git rev-parse --verify --quiet "<ref>^{commit}") the inline check it replaces used, so the fallback behavior (warn + scan head commit) is unchanged. source scripts/lib/changed-files.sh runs under set -uo pipefail (no -e), consistent with the rest of the step.
  • test-windows.yml additions: lib/exec-bash.resolver.test.mjs and plugins/guardrails/hooks/exec-bash.test.sh both exist at the referenced paths; the Pester config change (Run.Exit = $true) correctly makes Invoke-Pester propagate a non-zero exit on failing tests, fixing the described false-green.
  • ci.yml wiring: scripts/check-prerequisite-probes.test.sh exists and the new step (ci.yml:1919-1925) matches the hard-fail, LEG=2-gated pattern of its neighboring shared-lib test steps (no stray continue-on-error). The shell-filter additions (plugins/docs-hygiene/skills/generate-file-name-gate/**, .claude/docs-hygiene.json) both exist and are read by scripts/check-docs-naming.test.sh, so the filter category placement is correct.
  • Animation deps (c2e18d2): numpy==2.5.3 / opencv-python-headless==5.0.0.93 in the new requirements-ci-animation.txt match plugins/animation/requirements.txt exactly, as the file's own header requires. ANIMATION_REQUIRE_DEPS: '1' is set exactly once, scoped to the test-linux "Run plugin contract tests" step, so lint-2 and the Windows lane (which don't install these wheels) are unaffected — plugins/animation/scripts/animation.test.sh already implements the fail-vs-skip branch on that var.
  • Comment-only commits (747b591, 85ee97b): no logic changes; the removed "Claim/Basis/Recheck" blocks are replaced with tracker references as described.

No correctness or maintainability issues found that meet this lane's high-signal bar (nothing a linter/formatter would catch, no pre-existing-line issues, no speculative "add more tests" nits). The PR's own extensive verification section (dispatch runs, static checks) is author-claimed and I did not independently re-run it; the checks above are what I verified directly by reading the resulting files.

@claude

claude Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 50s —— View job


Security review complete

  • Gather context (PR diff, changed files)
  • Check skip gate
  • Review gitleaks composite re-pin and .gitleaksignore changes
  • Review ci.yml changes (UNMAPPED fallback, prerequisite-probe wiring, shell filter)
  • Review test-windows.yml changes (new steps running on windows-2025)
  • Review silent-revert-canary.yml change (shared base-ref predicate)
  • Review dependabot-plugin-release.yml change
  • Review deleted scoped-scan scripts for residual references
  • Check instruction-surface deletions against protected classes
  • Post findings

No security issues found. Details:

  • Gitleaks re-pin (.github/workflows/ci.yml, aa6a623): the local scripts/gitleaks-scoped-scan.sh fork is deleted and the step now calls the shared, SHA-pinned melodic-software/ci-workflows/.github/actions/gitleaks@35880dcb (v0.30.1). Supply-chain pin scrutiny is zizmor's advisory lane, out of scope here. Functionally this is a reduction in custom bash (curl | tar install, hand-rolled range resolution) in favor of the vendored composite — smaller custom attack surface, not larger.
  • .gitleaksignore (diff): the five entries removed name commits unreachable from any origin ref (dead config); the two added name 04f4bcd5's test-fixture keys, which the now-full-history push scan can reach. This is a coverage increase (push previously scanned only the pushed range/one commit; the composite now scans HEAD full history on push) with fixture-only findings suppressed, not a broadening of what's ignored beyond known non-secrets.
  • silent-revert-canary.yml (source scripts/lib/changed-files.sh / changed_files::verify_base): confirmed changed_files::verify_base() in scripts/lib/changed-files.sh is git rev-parse --verify --quiet "${1}^{commit}" — byte-identical to the inline check it replaces, so no weakening of the base-ref validation this fallback logic depends on. Trigger stays push/workflow_dispatch with permissions: contents: read; values still arrive via env:, never interpolated into the script body.
  • ci.yml / test-windows.yml wiring (UNMAPPED fallback running run-outside-node-suites.sh, check-prerequisite-probes.test.sh as a hard-failing step, widened shell-filter globs, new Windows steps for the exec-form launcher and the markdown-format/cloud-bootstrap-plugins suites): all additive test-runner wiring over existing, already-trusted repo scripts. No new untrusted-input handling, no permissions: block changed in any of the four touched workflow files, no new secrets exposure.
  • Comment-only edits (ci.yml zizmor/ci-status comments, dependabot-plugin-release.yml): prose pointing at trackers/docs instead of restating pins; the actual zizmor: ignore[self-repository] directives and permissions: blocks are untouched.
  • Instruction-surface lens: no CLAUDE.md/AGENTS.md/rules file/skill or agent body/hook allow-or-block-list is in this diff's file set, so the deleted/reworded comments here aren't standing instructions in that sense — they're operator-facing rationale, not an enforced rule or guardrail.
  • Confirmed no dangling references to the deleted scripts/gitleaks-scoped-scan.sh/.test.sh remain anywhere in the tree.

@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: 29c47ea45b

ℹ️ 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 .github/requirements-ci-animation.txt
…gin's

Dependabot's /.github pip entry bumps .github/requirements-ci-animation.txt
but cannot reach plugins/animation/requirements.txt, so a one-sided bump
would merge with CI testing versions the plugin does not pin. Compare the
two pin sets before the install and fail with a message naming both files.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

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


Code review complete

  • Gather context (PR body, diff, changed files)
  • Review changed files for correctness/maintainability
  • Post inline findings (if any)
  • Post summary

Summary

Reviewed the full diff (gh pr diff 5316, base origin/main) at head 2a61957, the 8 changed files. This lane is scoped to correctness and maintainability; security findings are left to the separate claude-security-review lane per this repo's REVIEW.md.

This head adds one commit beyond what the prior code-review and security-review passes already covered on 29c47ea: 2a61957 adds a drift gate in ci.yml's "Install locked plugin test toolchains" step — it diffs the numpy/opencv-python-headless pins in the new .github/requirements-ci-animation.txt against plugins/animation/requirements.txt and fails the step if they differ. This is exactly the enforcement Codex's earlier review comment on .github/requirements-ci-animation.txt:4 asked for (a Dependabot bump landing in one file without the other). I traced the mechanics and they hold up:

  • The grep -oE '^[A-Za-z0-9._-]+==[^ ]+' | sort extraction correctly normalizes both files' name==version pairs despite the animation file's \-continued, hash-annotated lines (numpy==2.5.3 \) versus the plugin file's plain lines (numpy==2.5.3) — verified against the actual file contents.
  • No continue-on-error/set +e around it, and GitHub Actions' default bash -eo pipefail step shell means the || { ...; exit 1; } is the only path that can survive a mismatch, so a real drift fails the step rather than warning.
  • plugins/animation/requirements.txt currently pins the same numpy==2.5.3 / opencv-python-headless==5.0.0.93 the new file lists, so the gate passes today as expected.

I also re-verified the wiring the earlier reviews already checked, to confirm this new commit didn't disturb it: scripts/check-prerequisite-probes.test.sh, scripts/run-outside-node-suites.sh, lib/exec-bash.resolver.test.mjs, plugins/guardrails/hooks/exec-bash.test.sh, plugins/markdown-format/hooks/markdown-format.test.sh, and .claude/hooks/cloud-bootstrap-plugins.test.sh all exist at their referenced paths, changed_files::verify_base in scripts/lib/changed-files.sh is still the byte-identical predicate the canary's inline check used, and the widened shell-filter glob (plugins/docs-hygiene/skills/generate-file-name-gate/**) covers a directory that does contain .sh files (scripts/emit-gate.sh, scripts/emit-gate.test.sh), so the category placement is correct in both ci.yml and test-windows.yml.

No correctness or maintainability findings meeting this lane's high-signal bar. Nothing new since the prior two reviews on this branch introduces a defect, and the one new commit is a clean, narrowly-scoped fix for the one open suggestion from Codex's review. The PR body's dispatch runs and static-check output are author-claimed; I did not re-run them myself.

@claude

claude Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 8s —— View job


Security review complete

  • Gather context (PR diff, changed files)
  • Check skip gate
  • Review gitleaks composite re-pin and .gitleaksignore changes
  • Review ci.yml changes (UNMAPPED fallback, prerequisite-probe wiring, shell filter, new animation-pin gate)
  • Review test-windows.yml changes
  • Review silent-revert-canary.yml change
  • Review dependabot-plugin-release.yml change
  • Review deleted scoped-scan scripts for residual references
  • Check instruction-surface deletions against protected classes
  • Post findings

No security issues found. This head (2a61957) adds one new commit on top of 29c47ea, which a prior security review on this PR already cleared; I re-read the full PR diff against origin/main rather than relying on that clearance, since it applied to a different head.

New commit since the last review (2a61957): adds a diff <(grep ...) <(grep ...) check comparing plugins/animation/requirements.txt against .github/requirements-ci-animation.txt before install, failing the step when the pins disagree. This is a direct response to the Codex reviewer's P2 comment on this PR (Dependabot could bump one file without the other). Both operands are repo-tracked files, no untrusted input reaches the diff/grep invocation, and the subsequent install still goes through pip install --require-hashes, so this only tightens an existing hash-locked install — no new injection surface or weakened check.

Everything else in the diff (gitleaks composite re-pin to melodic-software/ci-workflows/.github/actions/gitleaks@35880dcb, .gitleaksignore fingerprint changes, silent-revert-canary.yml's shared changed_files::verify_base predicate, the new Windows-lane steps, the ci.yml UNMAPPED-fallback and prerequisite-probe wiring, the shell-filter glob additions, and the comment-only edits in ci.yml/dependabot-plugin-release.yml) is unchanged from what the prior review on this PR already covered and cleared — re-confirmed here by re-reading each hunk:

  • No permissions: block changed in any of the four touched workflow files.
  • No dangling references remain anywhere in the tree to the deleted scripts/gitleaks-scoped-scan.sh / .test.sh.
  • changed_files::verify_base() in scripts/lib/changed-files.sh is still byte-identical (git rev-parse --verify --quiet "<ref>^{commit}") to the inline check it replaced, so the canary's fallback (warn + scan head commit) is unweakened.
  • No CLAUDE.md/AGENTS.md/rules file/skill or agent body/hook allow-or-block-list is in this diff's file set, so the instruction-surface lens (protected-class check on removed/reworded workflow comments) finds nothing to flag: these are operator-facing rationale comments, not enforced rules.
  • GitHub Actions hardening proper (trigger types, action pins, expression-injection surfaces in run: blocks) is zizmor's advisory lane per this skill's boundary and is not re-reported here; the PR's own verification section notes a clean zizmor --persona=regular run.

@kyle-sexton
kyle-sexton merged commit 9f0b2cf into main Sep 29, 2026
26 checks passed
@kyle-sexton
kyle-sexton deleted the fix/audit-ci branch September 29, 2026 16:44
kyle-sexton added a commit that referenced this pull request Sep 30, 2026
#5339)

Refs: #4582
Refs: #4222
Refs: #4109
Refs: #3413
Refs: #3708
Refs: #4144
Refs: #4586
Refs: #4608
Refs: #3605
Refs: #4683
Refs: #4112

## Summary

Fixes from the audit of the unattended Cursor agent's PRs, mostly in
`scripts/`, plus changes other audit groups asked for in these paths.
The only plugin change is the shared `html-escape.mjs` sync into
`review`, which bumps review to 0.33.8.

- Publisher/portability token alignment gate (#4582) passed with zero
active tokens, its test could not fail, and a padded line read as drift.
- Exec-form gate remedy text still taught shell form; the owner decided
fix-forward on #3708 (2026-09-29).
- `GE_DISCOVERY` in `scripts/lib/gate-entry.sh` was dead API, gate-entry
adoption scope was unstated, and the ADR baseline header said "never add
a pair" while it holds four (#3413, #4109).
- The "no hand-rolled base-ref predicate" guard matched one spelling
only; two scripts still hand-rolled it.
- The detector eval-coverage scanner (#4222) lost wrapper-prefixed emit
calls silently, and its header named RE2 while jq uses Oniguruma. The
mutation audit of its jq walk left 15 surviving mutants with no recorded
disposition, and the shfmt version floor had no test.
- The all-skills verb-contract gate (#4586) never checked a skill: since
#4219 the checker refuses a skill directory, and the gate swallowed the
exit 2 and printed PASS.
- A plugin could be bumped with nothing but `plugin.json` and
`CHANGELOG.md` changed (#5162 did it to ten plugins).
- The pr-explainer page validator let resource-loading CSS through
inside `<style>` (#3605).
- Smaller gaps: the code-metrics prose gate failed on a rewrapped
paragraph, the Dependabot bundle note missed a bundle rebuilt in the
working tree (#4144), the guardrails PowerShell differential corpus
lacked the #4683 shapes, and no check enforced #4112's third-person
descriptions.

## Fix

- `check-publisher-token-alignment.sh`: env overrides
`PUBLISHER_TOKEN_ORG_FILE` / `PUBLISHER_TOKEN_PORT_FILE`; exits 2 when
the ACTIVE marker is missing or either token set is empty. A missing
token file now exits 2 instead of 1, matching the check-script contract
that reserves 1 for findings
(`scripts/check-publisher-token-alignment.sh:11-14`). Both files are now
read through `scripts/lib/read-list.sh`, so surrounding whitespace is
trimmed on both sides. The test runs fixtures for pass, padded lines,
drift, renamed marker, comment-only section, empty org file, missing
file and the real files.
- `check-hook-exec-form.sh`: header and REMEDY text only, leading with
the node launcher route. No gate logic, allowlist or exit code changed.
- `lib/gate-entry.sh`: dead `GE_DISCOVERY` removed, adoption scope
stated. `adr-numbers-baseline.txt` header reworded.
- `lib/gate-entry.test.sh`: guard widened to the class of base-ref
predicates; `ai-slop-report.sh` and `dependabot-plugin-bump.sh` migrated
to the shared predicate. The allowlist entry for
`gitleaks-scoped-scan.sh` is deleted, since #5316 removed that script.
- `check-detector-eval-coverage.sh`: wrapper-prefixed and
forwarder-with-word emit calls are reported UNRESOLVED instead of
dropped; regex-engine note corrected from RE2 to Oniguruma: locally, jq
1.8.2 evaluates the lookbehind `test("(?<=a)b")` as true on `"xab"` and
false on `"xcb"`, and RE2 has no lookbehind. The test diff only adds
assertions (`git diff --numstat origin/main`: 278 added, 0 deleted). The
test pins the walk over case patterns, offsets and replacements, five
cases pin the survivors that reach behavior, and a stub `shfmt`
reporting v3.12.0 must exit 2.
- `check-all-skills-verb-contract.sh`: runs the checker in its root
form, once per `plugins/*/skills` root in parallel. It exits 2 when the
checker exits anything but 0 or 1, or when the pass/fail rollup does not
add up to the skills on disk, and it attributes check-25 lines to their
skill. The one live mismatch it finds,
`docs-hygiene:audit-encapsulation`, sits in the new
`scripts/verb-contract-baseline.txt`, which fails on a stale row. New
`check-all-skills-verb-contract.test.sh` runs the real checker on
fixtures and stubs a crashing and an undercounting checker.
- `check-changelog-parity.sh --check-bump`: a new BUMP WITHOUT CHANGE
failure for a bumped plugin whose only changes are `plugin.json` and
`CHANGELOG.md`. A deliberate re-release goes in the new, empty
`scripts/changelog-no-op-bumps.txt` as `<plugin>@<version>`. Tests cover
the failure, a sanctioned and a mismatched opt-out, a synced-file bump,
one identical sync entry across two carriers (the hook-launcher shape),
and the `No change: repeats` pointer form. Existing bump fixtures now
ship a file change.
- `lib/html-escape.mjs` (synced to `plugins/review/lib/`): inside
`<style>`, `url(`, `@import`, `expression(` and any backslash escape
fail the page. Style text ends where a browser ends it: `</style`
followed by whitespace, `/` or `>`, or end of input for an unclosed
element. The header and `validateRenderedPage` comments no longer claim
the marker proves provenance. `lib/html-escape.test.sh` adds hostile CSS
cases (including closes with `</style x>`, `</style/>` and no close
tag), a restamped safe page (passes) and a restamped hostile page (fails
on structure alone), and renames the stale-digest case. review 0.33.8
with a CHANGELOG entry.
- `check-code-metrics-skill-prose.py`: whitespace runs collapse on both
sides before the substring test; the two wrapped phrases use one space.
Tests: a rewrapped paragraph passes, a rewrapped wrong value fails.
- `dependabot-plugin-bump.sh`: the bundle note also counts uncommitted
and untracked files under the plugin. It compares against `HEAD`, not
the merge base, so a pull-request merge commit does not pull in base
changes. Fixtures cover a modified and an untracked dist file, and a
clean tree.
- `guardrails-ps-differential-corpus.jsonl`: re-harvested. It adds 53
payloads and drops none: the #4683 table shapes with their push, `commit
--no-verify` and `Set-Content` forms, and the CRLF commit here-strings
that must stay allowed. The hand-written section is unchanged.
- New `check-skill-description-voice.sh` (+ test, registered in
`check-script-contract.test.sh`): fails a description carrying
`you`/`your`/`yours`/`yourself`/`yourselves` outside a quoted trigger
phrase. A folded or literal block-scalar description (`>-`, `|`) is read
from its continuation lines. It has `--all`, `<base-ref>` and `--paths`
modes, dispatched in the script itself and listed as such in
`scripts/lib/gate-entry.sh`. Not wired into CI.

## Verification

Run in the worktree after merging `origin/main`:

- `scripts/check-all-skills-verb-contract.sh`: PASS, 307 skills, 1
baselined, in 3 min 11 s on 24 cores. It also passes in a `--depth 1`
clone of this branch (307 skills, about 13 CPU-minutes, so roughly 3 to
4 minutes on lint-2's 4 vCPUs). Before this PR every checker call exited
2. The new suite: 11 pass; 8 of the 11 fail against the old gate. The CI
step has not yet run on this PR, because the draft run skipped it. It
runs once the PR is flipped to ready.
- `scripts/check-changelog-parity.test.sh`: 98 pass, 0 fail. The new
`--check-bump`, replayed on #5162's merge, flags the ten bump-only
plugins. The last 25 first-parent merges on main pass, and so do all 54
open PRs that touch a plugin manifest, each checked against its merge
base with main. `--check-bump origin/main`, `--check --check-order`:
pass.
- `lib/html-escape.test.sh`: pass. `sync-html-escape.sh --check` and
`--check-bump origin/main`: pass.
- `scripts/check-publisher-token-alignment.test.sh`: 14 pass (the
padded-line case fails against the old script).
- `scripts/check-detector-eval-coverage.test.sh`: 172 pass.
`scripts/dependabot-plugin-bump.test.sh`: 10 pass (the two dist cases
fail against the old script).
`scripts/check-code-metrics-skill-prose.test.sh`: 5 pass.
- `scripts/check-guardrails-ps-differential.test.sh`: 21 pass.
`check-guardrails-ps-differential.sh origin/main`: 666 commands, no
refusal lost.
- `scripts/check-skill-description-voice.test.sh`: 13 pass. `--all`
reports three descriptions: provenance audit and setup ("Tells you"),
testing setup ("from your answers").
- `scripts/lib/gate-entry.test.sh`: 23 pass.
`scripts/check-script-contract.test.sh`: 45 pass.
`scripts/check-lane-coverage.sh --check`,
`scripts/check-shell-portability.sh --all`: pass. shellcheck, shfmt and
ruff check are clean on changed files.
- `scripts/affected-tests.sh --run`: 284 shell suites selected, 283
pass. The one failure is `scripts/hook-census.test.sh` ("strace is
missing or cannot trace here"), which is this machine's environment and
not this change. The non-shell suites it lists as NOT RUN include
`scripts/test_check_code_metrics_skill_prose.py`, which ran above.

## Related

Audit findings in `.work/audit/REPORT.md`: #4582, #4222, #4109, #3413,
#3708.

Issue-only items in this group, with no code here: #4288 (reopened with
a decision packet), #4008 (stranded work at `refs/pull/5127/head`),
#4608 (changelog parity fork-count measurement), #3694 (no action).
#4222 was reopened because its 15 surviving mutants had no disposition.
This PR records each one and pins the ones that reach behavior, and the
issue stays open until the PR merges.

Applied requests from other audit groups: core-docs (#4582 whitespace
trim and decision record), code-metrics (prose-gate wrapping), miro
(#4144 bundle note), ci (verb-contract gate and test; shfmt floor test),
claude-memory and docs-hygiene (bump without change), hook-launcher
(one-line carrier entry confirmed and pinned), claude-config
(pointer-form test), review (#3605 CSS validation), guardrails (#4683
corpus), prototype (#4112 description scan), decisions-docs (#4222 and
#4109 owner packets).

Owner decisions opened, not implemented:
- #4222: confirm the shfmt rewrite at priority low.
- #4109: accept or renumber the 0039 ADR pair.
- #5427: how a shared-library sync bumps its carriers
(desktop-notification, biome-format, hook-launcher requests).

Not taken here:
- The hook-utils notice wording and the jq notice class
(markdown-format, actionlint): both need a `lib/hook-utils.sh` sync that
bumps 18 carriers, so they should ride the next sync of that file.
- The options-docs generator wording: superseded by conventions.
- The improvement cap-baseline row: it must land in the same change as
the trim.
- typos-format and planning: optional requests.
- The claude-ops bare-placeholder warning: the argument-hint convention
has no such rule yet.

Still needed from others:
- ci group: add `ci.yml` steps for
`check-all-skills-verb-contract.test.sh`,
`check-skill-description-voice.test.sh`, and the five
`scripts/*.test.sh` suites with no `.github` reference
(`check-publisher-token-alignment`, `check-queue-front-matter`,
`check-script-contract`, `gen-hook-event-registry`,
`plugin-validate-report`). Today these run only when `affected-tests`
selects them on a pull request.
- docs-hygiene: fix the `audit-encapsulation` description and delete its
baseline row in the same change.
- Plugin owners: fix the three provenance and testing descriptions.

Earlier cross-group notes: tracker (README pre-flight table rows); ci
(wire `check-prerequisite-probes.test.sh`, the #3413 follow-up,
`silent-revert-canary.yml:97`); decisions-docs (#4658 reopen);
hook-launcher (do not edit `check-hook-exec-form.sh`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Sep 30, 2026
…5340)

No related issue: audit follow-up for the guardrails plugin. Every issue
it touches is already closed and several are being reopened by hand, so
no closing keyword is used.

## Summary

An audit of the 499 PRs an unattended agent opened between 2026-09-27
and 2026-09-29 found guardrails defects in six groups: guard gaps that
let a destructive command through, tests that no longer test what they
claim, a non-atomic cache, an undeclared Node requirement, README and
CHANGELOG statements that were wrong, and an unratified performance
claim in PLAN.md. This PR fixes what does not need the owner, and leaves
the owner-reserved questions alone (see Related). Guardrails goes 0.41.9
to 0.42.0.

## Fix

- `block-windows-drive-tmp`: a drive-root `\tmp` is refused on a
usertemp host; `curl`/`wget` short-flag clusters, `--output-dir` and an
option after a bare `-O` are judged; the usertemp mount fallback needs
`usertemp` on the `/tmp` mount's own line. The suite feeds commands on
stdin, so the 9 `/usr/bin` writer cases that were skipped now run.
- `block-root-delete-target` (PowerShell): a delete after LF, CRLF or a
bare CR, or inside a scriptblock, grouping or `$( )`, is judged;
`$env:NAME\subpath` no longer refused as a bare variable (`$env:TEMP`,
`$env:TEMP\`, `$env:TEMP\*` still are).
- PowerShell classifier: one untrusted-reduction flag instead of two, CR
scan skipped when the command has no CR, sink-budget tests rebuilt so
they exercise budget exhaustion.
- `stale-path-verify` and `skill-reference-verify`: a partly written
cache is a miss and is rebuilt; no extra process on the hook path.
- `wsl` regression rows added to the `block-hook-bypass`,
`block-noncanonical-commit` and `block-convention-violation` suites.
- Node on PATH is declared in the README, checked by `/guardrails:setup
check`, and listed in `prerequisites.json`; setup's apply text follows
the reconfiguration convention.
- README: `wsl` since-version, six re-parsing guards, PowerShell
no-token over-blocks, plugin-scoped GitHub MCP matcher, contributor
to-do and tracker asides removed. PLAN.md: the "no further process can
be removed" floor is scoped to the PostToolUse cold path and the goal is
marked a draft.
- CHANGELOG: five released entries corrected in place (0.41.7, 0.40.0,
0.38.11, 0.38.1, 0.37.3), no heading removed. They are named in the new
0.42.0 entry.
- From other groups' requests (extending the 0.42.0 entry, no second
bump):
- README: the exec-form dispatcher rows are dated to 0.41.3 (they said
0.41.0), and each fire is stated as two processes, node and then the
bash it spawns, with the candidate order left to the header of
`hooks/exec-bash.mjs` (hook-launcher).
- `/guardrails:setup check` probes the bash `hooks/exec-bash.mjs`
resolves, not the Bash tool's own bash (hook-launcher).
- PLAN.md says its census rows and floor line were measured under shell
form and not re-measured under exec form, and that no hook or skill
reads it (hook-launcher).
- `exec-bash.test.sh` accepts the first bash on `PATH` (a Homebrew bash)
as well as `/bin/bash` and `/usr/bin/bash`, and the plugin's resolver
test gains the PATH-first cases from `lib/exec-bash.resolver.test.mjs`
(hook-launcher).

## Verification

- `git merge origin/main`: two conflicts, the plugin version and the
CHANGELOG head, resolved by keeping 0.42.0 above the 0.41.9 entry that
#5309 added on main.
- `scripts/check-changelog-parity.sh --check --check-order`: pass.
`--check-preserved origin/main`: all 225 headings preserved.
- `scripts/validate-plugins.sh`: all manifests and the catalog validate.
- `scripts/affected-tests.sh --run --jobs 8`: every guardrails suite
passes (block-windows-drive-tmp, block-root-delete-target,
block-dangerous-git, block-hook-bypass, block-noncanonical-commit,
run-guards, stale-path-verify, skill-reference-verify, setup and the
rest). Three suites fail on this host for missing tools, unrelated to
the change: `scripts/check-html-assets.test.sh` and
`scripts/check-script-contract.test.sh` (htmlhint not installed),
`scripts/hook-census.test.sh` (strace not installed). 25 Node and Python
suites are selected but belong to other lanes.
- `scripts/check-guardrails-ps-differential.sh origin/main`: 613
commands, 0 cells where main refuses and this branch does not. The
scratch under-block differentials for block-windows-drive-tmp (6648
cells, 0 lost) and block-root-delete-target (15823 payloads; the 31
cells that differ are `$env:NAME\subpath` spellings Bash also allows,
plus one backtick-before-CR-CR-LF read as PowerShell reads it) are
recorded in the task notes.
- Baseline differential runs at the two earlier commits and at main: 0
cells lost in all three. Substitution-cap cost on WSL2 Linux: 2000
unquoted `$(:)` took a median 6038 ms; the same 2000 inside single
quotes or a heredoc body took 140 ms, level with a 137 ms control with
no substitution text. No Windows measurement was taken.
- No Windows host and no strace here: Windows behavior is proven by the
test-windows lane after the ready flip, and the spawn ceilings by CI's
ratchet step.
- Cross-group pass, on head `c3111b8d6` after merging origin/main
`0589e13f4` (clean):
- `exec-bash.test.sh` and `exec-bash.resolver.test.sh` pass. With a bash
symlink first on `PATH` outside `/bin` and `/usr/bin`, the old pin fails
(`FAIL: bash was not a real path`) and the new one passes.
- `check-changelog-parity.sh --check`, `--check-order`,
`--check-preserved origin/main` (226 headings) and `--check-bump
origin/main` pass.
- `validate-plugins.sh`, `sync-exec-bash.sh --check` (21 copies) and
`check-skill.sh` on the setup skill (PASS, 0 errors) pass. So do
`coverage-manifest.test.sh` (17 checks), `check-skill-portability.sh`
and `check-shell-portability.sh`. markdownlint, typos and shellcheck are
clean on the changed files.
- `scripts/affected-tests.sh --run --jobs 8` against origin/main: 287
selected suites pass. The same three as before fail on this host for
missing tools: `check-html-assets.test.sh` and
`check-script-contract.test.sh` (htmlhint), and `hook-census.test.sh`
(strace).
- PR #4715's disclosed "`git reset --hard` + nested here-string" bypass:
12 PowerShell nested here-string payloads carrying `git reset --hard`
exit 2 from `block-dangerous-git.sh` on this branch and on main, so no
issue was filed. One Bash probe exits 0 on both: a `-c` operand built
from a command substitution, which is the README's declared `$(…)`
residual.
- Ready pass, on head `600ec5b3c` after merging origin/main `a82943beb`
(clean; main's 7 new commits touch no guardrails path):
- Security review of the PR diff: no findings. Every guard change adds
refusals or matches the Bash lane. Probes still refuse `$env:TEMP\..`,
`${env:TEMP}\.`, a stray `)` or `}` before a delete, a delete after a
keyword block, unclosed levels, and a delete after a JSON `\r` or
`\u000d`. A raw control byte in the payload is invalid JSON, so the CR
re-read keeps the command as first read.
- `check-changelog-parity.sh` (`--check`, `--check-order`,
`--check-preserved origin/main`, `--check-bump origin/main`),
`validate-plugins.sh`, `sync-exec-bash.sh --check`, shellcheck,
markdownlint and typos on the changed files: pass. `exec-bash.test.sh`
and the node resolver test pass.
- `scripts/affected-tests.sh --run --jobs 8 origin/main`: the same three
suites fail for missing tools (htmlhint, strace).
`audit-coverage.test.sh` and `cant-fail-scan.test.sh` also failed in the
8-job run; both pass run alone on this head and on a snapshot of
`a82943beb`, and this PR does not touch their paths.

## Related

Audit: `.work/audit/REPORT.md` (local, not committed). Refs #3683 #3686
#3951 #4118 #4236 #4242 #4247 #4251 #4261 #4390 #4516 #4527 #4528 #4651
#4678 #4679 #4681 #4682 #4683 #4685.

Left for the owner, not implemented here:
- #4390: reopened with a decision packet on the cache design, plus an
addendum on PLAN.md's Done-when (ratify the ceilings, k × S, or
re-measure on Windows first) and `async` keep-or-reverse.
- #4684: reopened with a decision packet on the substitution cap against
the hook-precision rule.
- #5341: a new decision issue for block-root-delete-target scope
(launcher grammar, second PowerShell parser).
- #4118, #4681 and #4683: reopened with ratify-or-reverse packets,
because #4766, #4755 and #5036 took decisions reserved for the owner and
were merged by `app/cursor`. #3683 gets the same packet for #4845's
host-skip call.
- #4679: a packet on whether hook-observability condition 3 admits a
once-per-(session, agent) latch, or the admission is recorded as an
owner-approved exception.
- #3951: a packet on whether to build the heredoc-aware fix now in its
own PR, since the owner's 2026-09-28 comment closing #4811 said more
guard logic is not justified now.

Operator-only steps stay open on #3683, #4236, #4261, #4527, #4678,
#4679 and #4684 (Windows-host measurements and runs, and one interactive
render check).

Found and declared, not fixed: `env -f x rm -rf /` exits 0; PowerShell
`$r = Remove-Item ...`, comma-list and here-string forms remain gaps in
block-root-delete-target. An unmeasured Windows `RUN_GUARDS_PROFILE`
cost stays on #4236.

Cross-group requests:
- claude-ops: `audit_skill_visibility.test.sh` skips its whole
`--installed` contract on any Git Bash host (apply `host_path` to the
`--installed` argument or narrow the probe; correct the CHANGELOG
guess).
- claude-config: `unhobble/SKILL.md` (~L382) and
`unhobble/evals/evals.json` restate the block-hook-bypass exit-code
claim with no verification record.
- planning: `planning/skills/setup/SKILL.md` (~L158) has an unwrapped
line in the apply bullet.
- conventions: `docs/conventions/hook-observability/README.md` condition
3 needs to say whether a once-per-(session, agent) latch counts as a
state transition.
- scripts: add the shapes from the PowerShell differential findings to
`scripts/guardrails-ps-differential-corpus.jsonl`.
- hook-launcher: #5309 (0.41.9) landed the PATH lookup and the visible
notice for an unresolvable bash in `exec-bash.mjs`. Still open: a
missing node needs a launcher design that does not depend on node
(#3708). The README wording and the PLAN.md census note are now in this
PR.
- scripts: the 12 nested here-string `git reset --hard` payloads above
are candidates for the same corpus.

Cross-group requests received, checked against origin/main `0589e13f4`:
- hook-launcher:
- The README exec-form version and two-process shape, the PLAN.md
annotation, the relaxed launcher test pin, the PATH-first resolver cases
and the setup bash probe: applied (see Fix).
- Node declaration: already done here (README Requirements, setup check
item 3, `prerequisites.json`).
- Five owner decisions: #4390 already had its packet. #3683 was already
reopened and now has a ratify-or-reverse packet. #4118, #4681 and #4683
are now reopened with packets. #3686 belongs to hook-launcher.
- ci:
  - #4527 already carries the per-suite questions.
- The `\tmp\x` downgrade follow-up is not filed, because bca5f57 in
this PR restores the block assertion: the helper no longer downgrades a
backslash-led `\tmp`, and the quoted spellings expect 2.
- #3683: #5316's windows-2025 run shows `cloud-bootstrap-plugins`
PASS=79 with no probe skip, so its probe needs no rework. The results,
and #4845's causes marked as hypotheses, are on #3683.
- tracker:
  - #3951 not implemented: owner decision (packet above).
- #4235 not delivered by this PR; it needs its own dispatch. The owner's
comment closing #4817 asks for "a design scoped to #4235", which belongs
in its own PR: its `ps-command.sh` changes overlap this PR's classifier
edits and need the token-subset differential. The tracker posts the
scope comments.
  - #4678: reopened with Windows operator steps (not run here).
- #4679's render confirmation: already an open item with the exact
steps.
- The #4715 bypass: probed, not reproducible (see Verification). Its
payloads go to the scripts group rather than this PR, because the corpus
lives in `scripts/`.
- conventions:
- The setup apply bullet already carries main's scope-matching caveat 2.
- #4679: the condition-3 packet is posted. The wording goes to
conventions after the owner answers.
- source-control: commented on #4247 with #5317's widened matcher.
- performance: PLAN.md is already relabelled and #4390 already carries
both labels. The Done-when and `async` questions are posted as an
addendum.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

gitleaks scans every branch, so one false positive on any branch turns hygiene red on every PR

1 participant