ci: re-pin gitleaks composite, extend the Windows lane, wire unwired suites - #5316
Conversation
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
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
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. |
|
Claude finished @kyle-sexton's task in 1m 50s —— View job Code review complete
SummaryReviewed all 8 changed files ( 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:
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 finished @kyle-sexton's task in 1m 50s —— View job Security review complete
No security issues found. Details:
|
There was a problem hiding this comment.
💡 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".
…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 finished @kyle-sexton's task in 3m 35s —— View job Code review complete
SummaryReviewed the full diff ( This head adds one commit beyond what the prior code-review and security-review passes already covered on
I also re-verified the wiring the earlier reviews already checked, to confirm this new commit didn't disturb it: 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 finished @kyle-sexton's task in 2m 8s —— View job Security review complete
No security issues found. This head ( New commit since the last review ( Everything else in the diff (gitleaks composite re-pin to
|
#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>
…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>
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/,.gitleaksignoreandscripts/gitleaks-*:.github/and is dropped (claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323).$/#4130, fix(ci): contract-only ci-status reads a stale failure during a re-run #4670, ci: every Dependabot PR touching plugins/** fails the changelog-parity bump gate, because Dependabot cannot bump a manifest or write a changelog entry #4144, claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323), and the gitleaks comment no longer implies a red dispatch.Fix
aa6a6230dlintjob:melodic-software/ci-workflows/.github/actions/gitleaks@35880dcb(v0.30.1) withscan-mode: gitandlog-optsunset. 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..gitleaksignorekeeps the two04f4bcd5fingerprints (reachable from main) and drops the five for commits no origin ref reaches.fafdab6af,bf21ed285,b748b5dd4,b2b689b52test-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 onwindows-2025; the skill-visibility step added byb748b5dd4is dropped byb2b689b52.430e0d953ci.yml: outside-node runner on the UNMAPPED fallback,check-prerequisite-probes.test.shas a hard-failingtest-linuxstep, wider shell filter.747b59154comment-only changes in workflows.c2e18d24a.github/requirements-ci-animation.txt(hash-locked) installed withrequirements-ci.txtin one--require-hashescommand, plusANIMATION_REQUIRE_DEPS=1. The install stays (measured below).85ee97b36comment-only: the gitleaks step comment says a manual dispatch scans every ref present in the clone; thetest-windows.ymlcomment names claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323.dee4d13fasilent-revert-canary.yml: "Resolve the pushed range" sourcesscripts/lib/changed-files.shand callschanged_files::verify_basein place of the inlinegit rev-parse --verify --quiet "<ref>^{commit}". The fallback (warn, scan the head commit) is unchanged. Applies the scripts group's request (c).2a619570aci.yml: the "Install locked plugin test toolchains" step diffs thename==versionpins ofplugins/animation/requirements.txtagainst.github/requirements-ci-animation.txtand fails when they differ (Codex review: Dependabot's/.githubentry would bump only the CI copy).Verification
Static checks, on head
85ee97b36:git merge origin/main(earlier, into5ca5fe296): clean, no conflicts, none of its commits in the group's paths.actionlintand onlinezizmor --persona=regular: no findings.bash scripts/check-lane-coverage.sh --check: all 5 lanes reachable fromci-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 onlysilent-revert-canary.yml, re-run:actionlintover every workflow,zizmor --offline --persona=regularon the canary,check-lane-coverage.sh --check(66 gate steps fed, 2 opted out) andcheck-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 onlyci.yml(the pin check): equal pins pass and a one-sidednumpyedit 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 --checkandcheck-shell-portability.sh origin/mainare clean.The migrated step body was run in a scratch repository against five
beforevalues. 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 (headdee4d13fa), succeeded in every step; its emptybeforetakes the commit-mode branch, so it proves thesourceline 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 ownlintrun, 36579146249 (head5ca5fe296,pull_request): "Scan for secrets" success, 8 commits scanned (<base>..HEAD), no leaks found. The run on the newest head85ee97b36, 36582778889, is green (ci-statussuccess) and its scan of 20 commits found no leaks. Thecidispatch below, whose--allscan 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-onlyrefs/remotes/pr/*refs that a CI clone does not hold (correction posted on #3599).Windows lane, two dispatches of
test-windows.ymlon this branch (the only run of these steps on a real Windows host):AssertionError: 'unreadable' != 'read'; the record wasbash exited 1 sourcing the lib: no stderrforplugins/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 attest-windows.yml:205).timeout-minutes: 20, which stays unchanged. Per step:Run.Exitset): 11 passed, 0 failed, 0 skipped.SKIP (host: cygpath rewrites ...)lines, plus the uncounted symlink-escape skip.clauderan on Git Bash.node --test lib/exec-bash.resolver.test.mjs): 1 pass, 0 fail.plugins/guardrails/hooks/exec-bash.test.sh: passed (stdin, exit 2, Git Bash resolution, hooks.json shape, 8 dispatcher rows).cidispatch 36577675603 (headc2e18d24a), which measures the animation install and the gitleaks step:lintsuccess; "Scan for secrets" scanned 3192 commits, no leaks found.test-linuxlegs 0, 1 and 3 green. Leg 2 red only onplugins/planning/tests/interview-defenses.test.sh(SKILL.md frontmatter is unchangeddigest check). That is outside this group's paths and the suite failed the same way at the branch's base; a snapshot of origin/main9ef496019passes 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'sANIMATION_REQUIRE_DEPS=1request stands.Related
.work/audit/REPORT.mdfindings for gitleaks scans every branch, so one false positive on any branch turns hygiene red on every PR #3599, ci: no runner for the Node suites outside the four sub-projects, or for Pester, on either the PR or push path #3703, Adopt exec-form hook rows fleet-wide once upstream #90495 is ruled out on Windows #3686, Five suites fail only on a Windows Git Bash host; give them the host-skip pattern or fix them #3683, hooks: missing external tools are not surfaced to the user; add a model-invocable fleet-wide prerequisites check (no auto-install) #4240, docs-hygiene: no drift test between scripts/check-docs-naming.sh and the emitted gate template #4139, ci: drop the zizmor self-repository ignores and take the auto-fix once actionlint understands$/#4130, fix(ci): contract-only ci-status reads a stale failure during a re-run #4670, ci: every Dependabot PR touching plugins/** fails the changelog-parity bump gate, because Dependabot cannot bump a manifest or write a changelog entry #4144, animation: inkstats undercounts the final hold of a rotoscope work dir #4594.$/#4130, fix(ci): contract-only ci-status reads a stale failure during a re-run #4670, ci: every Dependabot PR touching plugins/** fails the changelog-parity bump gate, because Dependabot cannot bump a manifest or write a changelog entry #4144, animation: inkstats undercounts the final hold of a rotoscope work dir #4594, claude-ops: audit-skill-visibility reads managed scope as unreadable on windows-2025 (bash exited 1 sourcing managed-scope.sh) #5323, scripts: gate entry protocol (mode dispatch, base-ref validation, exit-code policy) is re-derived per gate (deepening candidate) #3413 (the owning groups finish those).f2f421f7b:GITHUB_TOKENlabel does not re-runci-status, and the phrase appears in 63 PR bodies (22 merged). The lane half went to source-control..gitleaksignorelines): already applied inaa6a6230d; both commits are unreachable from origin/main.ANIMATION_REQUIRE_DEPS=1): already applied inc2e18d24a, measured above.430e0d953as a hard-failing step like its fourscripts/libneighbours; withoutcontinue-on-errorthe lane-coverage gate would report an unfed gate, and it passes. (b) scripts: gate entry protocol (mode dispatch, base-ref validation, exit-code policy) is re-derived per gate (deepening candidate) #3413: already commented, follow-up scripts: migrate the remaining seven gates to gate-entry dispatch and exit mapping #5321. (c) the canary predicate: applied indee4d13fa.Refs: #4094, unmerged draft) for items 5, 6, 8, 9 and 10 to 12.ANIMATION_REQUIRE_DEPSmust exit 1 instead of skipping), playbooks (hygiene.md residue-dissolve note), claude-config (claude-config/unhobble: durable state, gate-aware strip plan, sourced carve-out, decide composition #4094).🤖 Generated with Claude Code
https://claude.ai/code/session_01EugXnFddtpHcY5gTuyEirB