Skip to content

chore(git-hooks): install the guardrails git hooks as shared lefthook jobs - #9462

Closed
kyle-sexton wants to merge 2 commits into
mainfrom
chore/guardrails-shared-git-hooks
Closed

kyle-sexton wants to merge 2 commits into
mainfrom
chore/guardrails-shared-git-hooks

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

No related issue: rollout of the guardrails git hooks as shared, committed lefthook jobs, following the standards#852 pilot; the installer defects it hits are tracked in #9426.

Summary

Installs the guardrails plugin's three git-hook entries in this repository so every clone gets them from lefthook install, and records the commit subject pattern they enforce:

  • commit-msg-convention (commit-msg): the subject against subject_pattern in .claude/source-control.md.
  • pre-commit-content (pre-commit): secrets and machine-specific paths on added lines.
  • reference-verify (pre-push): CLI flags, /plugin:skill references and deleted paths on pushed lines.

Fix

  • .githooks/guardrails/: plugin-owned copies written by install.mjs copy --scope shared (guardrails 0.55.4, the version plugins/guardrails/ is at on main; each copy matches its source apart from the installer's stamp line), staged 100755 where they carry a shebang.
  • lefthook.yml: the three jobs from the installer's snippets. guardrails-reference-verify is appended to the existing pre-push list with use_stdin: true; the existing check-affected job does not set use_stdin (it runs with </dev/null and judges HEAD, as its comment says), so the one stdin lefthook hands out per hook goes to the guardrails job. New pre-commit and commit-msg sections; this file had no pre-commit lane, so there is no exclude to extend.
  • .github/workflows/pr-require-checks.yml: .githooks/guardrails/ added to the ShellCheck action's exclude (the relocated copies fail SC2218, SC1091 and others because their source paths point at plugin-tree locations; the sources stay linted under plugins/guardrails/), and :(exclude).githooks/guardrails/*-path-patterns.sh to the machine-path check (the two pattern-lib copies self-match, as plugins/guardrails/lib/path-detection/** already does).
  • .claude/hooks/check-affected-pre-push.test.sh: one line outside the hook files. Its lefthook end-to-end case copies lefthook.yml into a fixture repo and pushes through lefthook; without .githooks/ in the fixture the new pre-push job exited 127 and lefthook lets the push through when the merge-base checks pass failed (50 pass, 1 fail). It now copies .githooks/ too: 51 pass, 0 fail.
  • .claude/source-control.md: subject_pattern is the twelve Conventional Commits types ci-status accepts, an optional scope, plus git's own Merge ... and Revert "..." subjects; the intro paragraph now names it among the set keys.
  • The installer's .gitattributes decision (.githooks/** text eol=lf) is left out: * text=auto eol=lf already covers it.
  • Shared-copy and layout checks: scripts/sync-shared-copies.sh --check (520 registered copies match) and scripts/check-cross-plugin-source-drift.sh pass with the copies present; neither scans .githooks/, so no exclusion was needed there.

Verification

Observation runs against this repository's history in report-only mode:

Hook Observation Findings Classification
reference-verify pre-push replay of origin/main~200..origin/main, 236 changed .md/.sh/.ps1 files, 2 min 19 s 2 (--scheduled in plugins/machine-health/CHANGELOG.md and plugins/machine-health/skills/setup/SKILL.md) tool noise: --scheduled is a skill argument inside the quoted prompt of claude -p "/machine-health:audit on-demand --scheduled", read as a flag of a claude on-demand subcommand. Zero skill-reference and stale-path findings. No payload in the range hit the argument-size limit (no Argument list too long in the replay's stderr)
pre-commit-content each of the last 100 non-merge commits replayed into the index (1 to 80 staged files each), 43 s total 0 none. A planted /home/alice/... line in a staged .md was reported, rc 1, so the replay did scan
commit-msg-convention subject_pattern tested against the last 500 subjects on main 0 non-matching none

Also:

  • lefthook validate: All good. actionlint on the workflow: clean.
  • The install commit's pre-commit-content took 70 s over the 10.7k vendored lines; the next commit's took 0.09 s, commit-msg-convention 0.02 s. reference-verify on this branch's push: 16 s.
  • scripts/check-affected.sh passes everything except ShellCheck on the copies: its local ShellCheck mirror does not read the workflow's exclude:, and the pre-push job runs the merge-base copy, so this branch's pushes skip that one job (LEFTHOOK_EXCLUDE=check-affected) and CI judges ShellCheck with the new exclude. Until scripts/check-affected.sh drops .githooks/guardrails/* from its shell list, every refresh of the copies hits the same block.
  • Affected suites run locally, since a draft skips the test and lint lanes: 63 suites (what scripts/affected-tests.sh --allow-unmapped selects, plus scripts/check-affected-gates.test.sh) in 191 s. 60 pass. 3 fail for this machine's environment only: check-script-contract.test.sh needs node_modules/.bin/htmlhint, and ci-test-node-stop-commands.test.sh and run-hygiene-gate.test.sh need PyYAML. affected-tests.sh reports the 12 shell copies as UNMAPPED, so once the PR is ready the plan runs the whole shell corpus (a warning, not a failure).
  • The new excludes, checked locally against the pinned actions (ci-workflows 5e18f3d): the ShellCheck run.sh, given this diff and EXCLUDE=.githooks/guardrails/, checks only the test file and exits 0. The machine-path script with the new exclude list reports no .githooks/ line; before the change it reported machine-path-patterns.sh:41 and hardcoded-path-patterns.sh:37.

Known defects, upstream (#9426): reference-verify skipped .githooks/guardrails/hook-utils.sh (238,555 bytes, a new file sent whole) on this branch's push with Argument list too long and still passed (item 4); the CLI-flag noise above. The copies are not edited in place: they are plugin-owned and a release refresh would overwrite the change.

Related

  • standards#852: the merged pilot this mirrors.
  • #9426: installer defects the rollout hits.
  • dotfiles#1292: removes the user-global checks.*.declined keys and makes repos-sync run lefthook install after clone or fast-forward.

🤖 Generated with Claude Code

kyle-sexton and others added 2 commits October 23, 2026 12:26
… jobs

Commit the guardrails plugin's commit-msg-convention, pre-commit-content
and reference-verify entries under .githooks/guardrails/ (install.mjs copy
--scope shared, guardrails 0.55.4) with their lefthook.yml jobs, and record
the subject_pattern they enforce in .claude/source-control.md.

The check-affected pre-push test copies lefthook.yml into a fixture repo;
it now copies .githooks/ too, so the new pre-push job finds its script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ShellCheck flags the relocated .githooks/guardrails/ copies (their source
directives point at plugin-tree paths), and the two path-pattern copies
self-match the machine-path check, as plugins/guardrails/lib/path-detection/
already does. The sources stay linted under plugins/guardrails/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton

Copy link
Copy Markdown
Member Author

Superseded by #9504: guardrails git hooks reach repositories through a lefthook remotes entry, so per-repo shared copies are no longer used.

@github-actions
github-actions Bot deleted the chore/guardrails-shared-git-hooks branch October 24, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge Hard merge gate: do not merge while applied.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant