You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
test(guardrails): verify the commit-msg hook under Windows IDE git and prove parity with the local gate #9778
Needs a Windows host and a person: the MinGit failure (git bundled with Visual Studio or SSMS, no bash.exe) and the operator's local commit-msg gate exist only on the operator's Windows machine.
Outcome
The sh-entry hook runs under Windows IDE-bundled git, and the plugin hook matches the local gate it replaces.
Done when
With Visual Studio's or SSMS's bundled git, a commit in a repository with the hook installed rejects a non-conforming subject and accepts a conforming one; the git version and result are reported on this issue.
The config-hook lane is checked with that git, or the report states it is below the 2.54 floor and the docs cover that case.
The plugin guard passes behavior-equivalent test cases for the local guard it replaces (the operator retires the local copy then, outside this repo).
Released for re-triage under the owner's 2026-10-26 rule: a person is involved only for "1. A change in original intent/vision 2. Something comes up during implementation ... that alters intent/vision or the primary design 3. If there is a HIGH/CRITICAL security issue". None applies here, so the hold label came off and intake triage runs again now.
To hold this issue again, add needs-human (or status: needs-decision) and name which of the three applies.
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Medium
Uncertainty: Knowable
Flags: none
Blocked by: none
I read this as a verification task. It needs three checks. First, the sh-entry commit-msg hook must reject a bad subject and accept a good one under Visual Studio or SSMS bundled git. Second, the config-hook lane must be checked against the 2.54 floor with that git, or the report must say it falls below the floor. Third, the plugin guard must pass behavior-equivalent cases for the local guard it replaces.
The Windows-host items need a person on a Windows machine, so a host run covers them. The parity test cases can be checked without that host. The dependencies #9774, #9775 and #9776 are not in the open list, so nothing open blocks this. I found no duplicate.
Not admitted to the issue lane yet: blocker #9775 is not closed by a listed human or a merge; blocker #9776 is not closed by a listed human or a merge.
This records a re-fire of an earlier refusal, not a new refusal. The lanes kill switch stopped run 41280047418, the work-resolve-issue run that agent-ready started, before it did any work; that run ended at 2026-11-01T06:32:15Z. work-unblock has now removed and added agent-ready back to start a fresh run. A kill-switch refusal is no fault in this issue or the lanes, so it never counts against later re-fires; after limits.limit-stops-per-issue of them since a person last added agent-ready or a run last reported, work-unblock waits longer before each one, up to 24 hours.
The work-resolve-issue lane stopped on this issue (host-only): the run reports the work needs a host run the lane cannot make.
It added host-run and removed agent-ready: an agent run on a host builds it, and it waits on no decision from a person.
In the run's words:
host-only: every done-when item needs the operator's Windows machine. Items 1 and 2 need a commit made with Visual Studio's or SSMS's bundled git (MinGit, no bash.exe), with its git version reported on the issue. Item 3 needs behavior-equivalent test cases for the operator's local commit-msg guard, which lives only on that machine and is not in this repository (plugins/guardrails/retirements.yaml lists only the plugin's own retired hooks). The issue body says itself that it 'Needs a Windows host and a person'. This Linux CI lane has no such host, so it made no change.
What the run says it did not do:
Commit test with Visual Studio's or SSMS's bundled git, with the git version reported on the issue: needs the operator's Windows host
Config-hook lane check with that git, or a report that it is below the 2.54 floor: needs the same host
Behavior-equivalent tests against the operator's local commit-msg guard: that guard's source is not in this repository
Intake triage did not triage this issue after 2 dispatches, so the sweep no longer dispatches it and labeled it needs-triage for a maintainer. Triage it by hand, and read the runs for why intake did not:
Host run. I ran a read-only probe of the operator's Windows desktop for IDE-bundled git, plus a differential parity run of the plugin's commit-msg-convention.sh against the only surviving local commit-msg gate.
Claude Code 2.1.316. All probes were read-only toward Windows: no installs, nothing elevated.
Done when 1 and 2 (IDE-bundled git): BLOCKED, owner step
vswhere -all -products * lists two products: Visual Studio Community 2026 (18.10.12210.168) and SQL Server Management Studio 21 (21.6.36603.0).
A recursive search of both install trees finds no git.exe, sh.exe or bash.exe.
So this host has no Visual Studio or SSMS bundled git to test with.
The only git on the Windows PATH is Git for Windows 2.55.0.windows.3. That is above the 2.54 config-hook floor, but it is not the IDE git these items ask for.
Owner step (an install, which this run may not do):
Open Visual Studio Installer.
Click Modify on Visual Studio Community 2026, open Individual components, tick Git for Windows, and apply.
If SSMS 21's installer offers the same component, add it there as well.
Comment on this issue when it is installed.
An agent then reruns both checks on that git:
commit with a non-conforming subject (rejected) and a conforming one (accepted), with the hook installed through install.mjs config-hook;
git hook list commit-msg, or a below-floor report.
Done when 3 (parity with the local gate): partly shown; the target gate was not found
Which local gate.#5948 describes the local gate as follows:
a per-repo allowlist keyed by the canonical clone name from git rev-parse --git-common-dir;
one POSIX ERE subject_pattern per repo;
a one-off env-var bypass.
Where I looked, and found nothing:
WSL ~/.claude, ~/.config and ~/.local/bin;
the Windows user profile (.config, .githooks, bin, .claude\hooks, .local\bin);
global and system git config: no core.hooksPath, no hook.*, no init.templateDir;
dotfiles history: a pickaxe search for git-common-dir and subject_pattern finds only copies of this plugin's own hooks (added in d8ab23e, removed in b3a3613).
The only local commit-msg gate in dotfiles history is the global core.hooksPath hook from melodic-software/dotfiles@d5f8e06. It was reverted 11 minutes later in aa6c9ef (2026-06-21), so it is already retired.
Differential run on that hook. I ran 69 subjects through each hook on Linux sh, in a throwaway repo:
Plugin pattern
Same result
Different
The repo's tracked subject_pattern
63
6
The old hook's own regex
65
4
The 2 extra differences under the tracked pattern come from the pattern, not the hook logic: the tracked pattern adds the security type and allows nested parentheses in a scope.
I then ran the 4 logic differences end to end through git commit:
A leading blank line and an empty message behave the same in both hooks, because git normalises or refuses the message first.
Two cases remain, and in both the plugin is stricter on purpose. The existing suite already pins both:
Revert the thing (no quotes) fails: commit-msg-convention.test.sh line 110.
-m "#123 fix thing" fails: line 92.
The #5948 gate's other behaviours map to the plugin as follows:
Local gate behaviour
Plugin equivalent
Covered by
Per-repo opt-in pattern
The git-ignored docs/conventions/source-control.local.yaml personal layer
Tests at lines 139–147
Env-var bypass
Not carried over: the plugin's only skip is checks.skipmissing
install-commit-msg.md "Skipping and removing"
I opened no PR: the existing suite already covers every case where the two hooks differ.
Still open for item 3. Owner or laptop lane: say whether the #5948 per-repo gate still exists on the laptop. If it does, port its cases into commit-msg-convention.test.sh. If it does not, item 3 can be ticked on the evidence above.
Host run. I reran done-when items 1 and 2 on the operator's Windows desktop, after the owner added the Git for Windows component to Visual Studio Community 2026, using the git that component installed. (agent)
Claude Code 2.1.316. Nothing on Windows was installed, uninstalled or elevated by this run. The probe used a throwaway repository and a throwaway global config (GIT_CONFIG_GLOBAL and XDG_CONFIG_HOME pointed into a temp directory). Afterwards, git config --global --get-regexp '^includeif\.' on the real global config shows no line from this probe.
What the VS 2026 Git component is on this host
vswhere -all -products * -requires Microsoft.VisualStudio.Component.Git -property installationPath now returns C:\Program Files\Microsoft Visual Studio\18\Community. The earlier run returned nothing.
A recursive search of that VS tree for git.exe, sh.exe and bash.exe finds none.
The VS installer log for this change shows the component's GitV2 package (catalog version 2.55.0.5, type Exe) running the Git for Windows installer (Git-2.55.0.5-64-bit.exe /VERYSILENT ... /o:PathOption=Cmd) into C:\Program Files\Git. The same log shows the superseded GitV2 2.55.0.4 package uninstalled first. The installer log ends Installation process succeeded at 14:37:32 local time, the same timestamp as C:\Program Files\Git\unins000.dat.
C:\Program Files\Git\cmd\git.exe --version reports git version 2.56.0.windows.4; the earlier run saw 2.55.0.windows.3. The downloaded installer failed the catalog's SHA256 check and passed Authenticode. That points to the download link serving a newer signed build than the catalog named, but this run did not confirm it.
C:\Program Files\Git\bin\bash.exe and usr\bin\sh.exe both exist. git var GIT_SHELL_PATH reports C:/Program Files/Git/usr/bin/sh.exe.
Finding: on this host, VS 2026's Git component installs full Git for Windows, bash included, into Program Files\Git. It installs no VS-private MinGit. So the "IDE git without bash.exe" case does not happen through VS 2026 here, and the hook can only be tested with the full Git for Windows that the component installs. The earlier run found no bundled git under SSMS 21's install tree. Whether SSMS's installer offers a Git component, which would be the remaining route to a no-bash MinGit, was not checked.
Item 1: commit with the IDE-installed git: PASS
I ran Windows node v24.21.0 with C:\Program Files\Git\cmd first on PATH, so the installer's git calls resolved to C:\Program Files\Git\cmd\git.exe (2.56.0.windows.4). I used a throwaway repository holding this repo's tracked docs/conventions/source-control.yaml.
install.mjs config-hook --include-if 'gitdir/i:<temp>/repo/' returned installed for commit-msg-convention and one include-if decision.
I applied that decision with git config --global --add into the throwaway global config.
The rerun returned unchanged and decisions: []. No git-too-old decision was returned.
The include file holds [hook "guardrails-commit-msg-convention"], event = commit-msg, command = "sh \"<temp>/xdg/git/checks/guardrails/commit-msg-convention.sh\"".
Results:
Commit
Subject
Exit
Result
Non-conforming
added convention file
1
Rejected: guardrails: the commit subject does not match the team convention., then the subject and subject_pattern in docs/conventions/source-control.yaml. Commit count stayed at 0.
git hook list commit-msg printed guardrails-commit-msg-convention and exited 0. Git 2.56 is above the 2.54 floor.
install.mjs verify reported ok commit-msg-convention. Its exit code was 1 only because the other three entries (pre-commit-content, pre-push-content, reference-verify) report missing: config-hook installs only the commit-msg entry, as install-commit-msg.md states.
Status
Items 1 and 2 are met on the git that VS 2026's Git component installs on this host.
MinGit without bash was not tested: VS 2026's component on this host installs no MinGit, and SSMS's installer was not checked.
Item 2: PASS: git hook list commit-msg lists guardrails-commit-msg-convention on that git (above the 2.54 floor).
Item 3 is moot and dropped: there is no local commit-msg gate left to match. Checked this session on the laptop WSL host: no global core.hooksPath, no hook.* config, no ~/.githooks or ~/.config/git/hooks, and the only hook file that matches git-common-dir is a chezmoi-apply gate, not a commit gate. The desk check and dotfiles history (the one global commit-msg hook, reverted in dotfiles aa6c9ef) are in the earlier host-run record. The same reasoning dropped test(guardrails): measure the identity-domain guard on the operator's command corpus and prove parity with the local guard #9750's criterion 3.
Finding kept here, no new issue: Visual Studio 2026's Git component installs full Git for Windows (with bash) into Program Files\Git, so the IDE-git-without-bash case does not occur through VS 2026.
Activity
kyle-sexton commentedon Oct 26, 2026
Released for re-triage under the owner's 2026-10-26 rule: a person is involved only for "1. A change in original intent/vision 2. Something comes up during implementation ... that alters intent/vision or the primary design 3. If there is a HIGH/CRITICAL security issue". None applies here, so the hold label came off and intake triage runs again now.
To hold this issue again, add
needs-human(orstatus: needs-decision) and name which of the three applies.github-actions commentedon Oct 26, 2026
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Medium
Uncertainty: Knowable
Flags: none
Blocked by: none
I read this as a verification task. It needs three checks. First, the sh-entry commit-msg hook must reject a bad subject and accept a good one under Visual Studio or SSMS bundled git. Second, the config-hook lane must be checked against the 2.54 floor with that git, or the report must say it falls below the floor. Third, the plugin guard must pass behavior-equivalent cases for the local guard it replaces.
The Windows-host items need a person on a Windows machine, so a host run covers them. The parity test cases can be checked without that host. The dependencies #9774, #9775 and #9776 are not in the open list, so nothing open blocks this. I found no duplicate.
Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 26, 2026
Not admitted to the issue lane yet: blocker #9775 is not closed by a listed human or a merge; blocker #9776 is not closed by a listed human or a merge.
2 remaining items
melodic-automation-lanes commentedon Nov 1, 2026
This records a re-fire of an earlier refusal, not a new refusal. The lanes kill switch stopped run 41280047418, the work-resolve-issue run that
agent-readystarted, before it did any work; that run ended at 2026-11-01T06:32:15Z. work-unblock has now removed and addedagent-readyback to start a fresh run. A kill-switch refusal is no fault in this issue or the lanes, so it never counts against later re-fires; after limits.limit-stops-per-issue of them since a person last addedagent-readyor a run last reported, work-unblock waits longer before each one, up to 24 hours.github-actions commentedon Nov 1, 2026
github-actions commentedon Nov 1, 2026
melodic-automation-lanes commentedon Nov 1, 2026
The work-resolve-issue lane stopped on this issue (
host-only): the run reports the work needs a host run the lane cannot make.It added
host-runand removedagent-ready: an agent run on a host builds it, and it waits on no decision from a person.In the run's words:
What the run says it did not do:
Run: https://github.com/melodic-software/claude-code-plugins/actions/runs/41281450341
To hand it back to the lane, remove
host-runand addagent-readyagain.github-actions commentedon Nov 1, 2026
Intake triage did not triage this issue after 2 dispatches, so the sweep no longer dispatches it and labeled it needs-triage for a maintainer. Triage it by hand, and read the runs for why intake did not:
kyle-sexton commentedon Nov 2, 2026
Claim. Backlog HITL host-run worker is taking this now.
kyle-sexton commentedon Nov 2, 2026
Host run. I ran a read-only probe of the operator's Windows desktop for IDE-bundled git, plus a differential parity run of the plugin's
commit-msg-convention.shagainst the only surviving local commit-msg gate.Claude Code 2.1.316. All probes were read-only toward Windows: no installs, nothing elevated.
Done when 1 and 2 (IDE-bundled git): BLOCKED, owner step
vswhere -all -products *lists two products: Visual Studio Community 2026 (18.10.12210.168) and SQL Server Management Studio 21 (21.6.36603.0).vswhere -requires Microsoft.VisualStudio.Component.Gitreturns nothing.git.exe,sh.exeorbash.exe.Owner step (an install, which this run may not do):
An agent then reruns both checks on that git:
install.mjs config-hook;git hook list commit-msg, or a below-floor report.Done when 3 (parity with the local gate): partly shown; the target gate was not found
Which local gate. #5948 describes the local gate as follows:
git rev-parse --git-common-dir;subject_patternper repo;Where I looked, and found nothing:
~/.claude,~/.configand~/.local/bin;.config,.githooks,bin,.claude\hooks,.local\bin);core.hooksPath, nohook.*, noinit.templateDir;git-common-dirandsubject_patternfinds only copies of this plugin's own hooks (added in d8ab23e, removed in b3a3613).The only local commit-msg gate in dotfiles history is the global
core.hooksPathhook from melodic-software/dotfiles@d5f8e06. It was reverted 11 minutes later in aa6c9ef (2026-06-21), so it is already retired.Differential run on that hook. I ran 69 subjects through each hook on Linux
sh, in a throwaway repo:subject_patternThe 2 extra differences under the tracked pattern come from the pattern, not the hook logic: the tracked pattern adds the
securitytype and allows nested parentheses in a scope.I then ran the 4 logic differences end to end through
git commit:Revert the thing(no quotes) fails:commit-msg-convention.test.shline 110.-m "#123 fix thing"fails: line 92.The #5948 gate's other behaviours map to the plugin as follows:
docs/conventions/source-control.local.yamlpersonal layerchecks.skipmissinginstall-commit-msg.md"Skipping and removing"I opened no PR: the existing suite already covers every case where the two hooks differ.
Still open for item 3. Owner or laptop lane: say whether the #5948 per-repo gate still exists on the laptop. If it does, port its cases into
commit-msg-convention.test.sh. If it does not, item 3 can be ticked on the evidence above.Target labels: add none; remove none.
kyle-sexton commentedon Nov 2, 2026
Host run. I reran done-when items 1 and 2 on the operator's Windows desktop, after the owner added the Git for Windows component to Visual Studio Community 2026, using the git that component installed. (agent)
Claude Code 2.1.316. Nothing on Windows was installed, uninstalled or elevated by this run. The probe used a throwaway repository and a throwaway global config (
GIT_CONFIG_GLOBALandXDG_CONFIG_HOMEpointed into a temp directory). Afterwards,git config --global --get-regexp '^includeif\.'on the real global config shows no line from this probe.What the VS 2026 Git component is on this host
vswhere -all -products * -requires Microsoft.VisualStudio.Component.Git -property installationPathnow returnsC:\Program Files\Microsoft Visual Studio\18\Community. The earlier run returned nothing.git.exe,sh.exeandbash.exefinds none.GitV2package (catalog version 2.55.0.5, type Exe) running the Git for Windows installer (Git-2.55.0.5-64-bit.exe /VERYSILENT ... /o:PathOption=Cmd) intoC:\Program Files\Git. The same log shows the supersededGitV22.55.0.4 package uninstalled first. The installer log endsInstallation process succeededat 14:37:32 local time, the same timestamp asC:\Program Files\Git\unins000.dat.C:\Program Files\Git\cmd\git.exe --versionreportsgit version 2.56.0.windows.4; the earlier run saw 2.55.0.windows.3. The downloaded installer failed the catalog's SHA256 check and passed Authenticode. That points to the download link serving a newer signed build than the catalog named, but this run did not confirm it.C:\Program Files\Git\bin\bash.exeandusr\bin\sh.exeboth exist.git var GIT_SHELL_PATHreportsC:/Program Files/Git/usr/bin/sh.exe.Finding: on this host, VS 2026's Git component installs full Git for Windows, bash included, into
Program Files\Git. It installs no VS-private MinGit. So the "IDE git withoutbash.exe" case does not happen through VS 2026 here, and the hook can only be tested with the full Git for Windows that the component installs. The earlier run found no bundled git under SSMS 21's install tree. Whether SSMS's installer offers a Git component, which would be the remaining route to a no-bash MinGit, was not checked.Item 1: commit with the IDE-installed git: PASS
I ran Windows
nodev24.21.0 withC:\Program Files\Git\cmdfirst on PATH, so the installer'sgitcalls resolved toC:\Program Files\Git\cmd\git.exe(2.56.0.windows.4). I used a throwaway repository holding this repo's trackeddocs/conventions/source-control.yaml.install.mjs config-hook --include-if 'gitdir/i:<temp>/repo/'returnedinstalledforcommit-msg-conventionand oneinclude-ifdecision.git config --global --addinto the throwaway global config.unchangedanddecisions: []. Nogit-too-olddecision was returned.[hook "guardrails-commit-msg-convention"],event = commit-msg,command = "sh \"<temp>/xdg/git/checks/guardrails/commit-msg-convention.sh\"".Results:
added convention fileguardrails: the commit subject does not match the team convention., then the subject andsubject_pattern in docs/conventions/source-control.yaml. Commit count stayed at 0.chore: add convention file[main (root-commit) dbc94a5] chore: add convention fileItem 2: config-hook lane with that git: PASS
git hook list commit-msgprintedguardrails-commit-msg-conventionand exited 0. Git 2.56 is above the 2.54 floor.install.mjs verifyreportedok commit-msg-convention. Its exit code was 1 only because the other three entries (pre-commit-content,pre-push-content,reference-verify) reportmissing:config-hookinstalls only the commit-msg entry, asinstall-commit-msg.mdstates.Status
Target labels: add none; remove none.
kyle-sexton commentedon Nov 2, 2026
Done. (agent; not an owner decision; under the owner's standing direction s1, 2026-11-02)
git version 2.56.0.windows.4, a non-conforming subject rejected, a conforming one accepted.git hook list commit-msglistsguardrails-commit-msg-conventionon that git (above the 2.54 floor).core.hooksPath, nohook.*config, no~/.githooksor~/.config/git/hooks, and the only hook file that matchesgit-common-diris a chezmoi-apply gate, not a commit gate. The desk check and dotfiles history (the one global commit-msg hook, reverted in dotfiles aa6c9ef) are in the earlier host-run record. The same reasoning dropped test(guardrails): measure the identity-domain guard on the operator's command corpus and prove parity with the local guard #9750's criterion 3.Finding kept here, no new issue: Visual Studio 2026's Git component installs full Git for Windows (with bash) into
Program Files\Git, so the IDE-git-without-bash case does not occur through VS 2026.