Parent
Source: handoff-inbox item 20260723-014618-guardrails-hpp-win-repo-pattern-gaps (Finding 1), producer work-laptop (Windows/PowerShell), guardrails 0.12.1. Prior art: #918/#932 (pattern broadening), standards#250 (upstream mirror).
What to build
The Windows repo-checkout pattern body HPP_WIN_REPO_BODY (and the same shape in HPP_WIN_USER_BODY / HPP_ESCAPED_WIN_REPO_BODY) currently inverts detection:
- The final
(/|\\?) group requires a trailing separator after the child segment, so a real bare value at end of line — root = C:/Dev/GitHub — does NOT match (false negative on exactly the shape the guard exists to catch).
- The segment class
[^/\\$%<{~]+ permits spaces/hyphens/parentheses, so prose can satisfy the trailing-separator requirement by greedily consuming words until a later / appears. Reproduced: # C:/Projects/melodic - personal melodic-software repos (reference/reading only here) matches as C:/Projects/melodic - personal melodic-software repos (reference/ — a false positive reported as "Windows repo path detected".
Net: the hook blocks the wrong line while the actual violations pass clean.
The lib's own design comment states intent as "a match needs at least one child segment past the root" — but the trailing-separator implementation actually requires a child segment PLUS a separator (effectively a grandchild boundary), and the prose-safety rationale for it ("the segment class permits spaces") is defeated by the greedy-span false positive above. Fix the pattern to implement the documented intent:
- Exclude whitespace from the child-segment character class (e.g.
[^/\\$%<{~[:space:]]+), which kills the prose false positive on its own.
- Replace the mandatory trailing separator with a right boundary that also accepts end-of-line/whitespace (POSIX ERE, no lookarounds — e.g. make the trailing group
(/|\\{1,2}|$|[[:space:]]) or equivalent), so a bare X:/<root>/<child> value at EOL matches. A bare root itself (C:/Dev, C:\Users\Alice) must still NOT match — the child-segment requirement stays.
- Sweep the sibling bodies in the same file for the same shape (
HPP_WIN_USER_BODY, HPP_ESCAPED_WIN_REPO_BODY; assess HPP_MACOS_USER_BODY/HPP_LINUX_USER_BODY which share the trailing-/ + space-permitting class) and keep the file's design comments truthful about the new boundary semantics.
- Keep the cheap pre-filter gate in
hardcoded-path-patterns.sh a strict superset of the detailed patterns (widening the body must not out-run the gate).
Distribution constraint: machine-path-patterns.sh is a managed synced component from melodic-software/standards (components/path-detection/machine-path-patterns.sh, currently in sync). The pattern change must land in BOTH: a standards PR (precedent: standards#250) and the matching local copy here, byte-identical, or the next sync bot run reverts the fix.
Acceptance criteria
Blocked by
None — can start immediately.
Parent
Source: handoff-inbox item
20260723-014618-guardrails-hpp-win-repo-pattern-gaps(Finding 1), producer work-laptop (Windows/PowerShell), guardrails 0.12.1. Prior art: #918/#932 (pattern broadening), standards#250 (upstream mirror).What to build
The Windows repo-checkout pattern body
HPP_WIN_REPO_BODY(and the same shape inHPP_WIN_USER_BODY/HPP_ESCAPED_WIN_REPO_BODY) currently inverts detection:(/|\\?)group requires a trailing separator after the child segment, so a real bare value at end of line —root = C:/Dev/GitHub— does NOT match (false negative on exactly the shape the guard exists to catch).[^/\\$%<{~]+permits spaces/hyphens/parentheses, so prose can satisfy the trailing-separator requirement by greedily consuming words until a later/appears. Reproduced:# C:/Projects/melodic - personal melodic-software repos (reference/reading only here)matches asC:/Projects/melodic - personal melodic-software repos (reference/— a false positive reported as "Windows repo path detected".Net: the hook blocks the wrong line while the actual violations pass clean.
The lib's own design comment states intent as "a match needs at least one child segment past the root" — but the trailing-separator implementation actually requires a child segment PLUS a separator (effectively a grandchild boundary), and the prose-safety rationale for it ("the segment class permits spaces") is defeated by the greedy-span false positive above. Fix the pattern to implement the documented intent:
[^/\\$%<{~[:space:]]+), which kills the prose false positive on its own.(/|\\{1,2}|$|[[:space:]])or equivalent), so a bareX:/<root>/<child>value at EOL matches. A bare root itself (C:/Dev,C:\Users\Alice) must still NOT match — the child-segment requirement stays.HPP_WIN_USER_BODY,HPP_ESCAPED_WIN_REPO_BODY; assessHPP_MACOS_USER_BODY/HPP_LINUX_USER_BODYwhich share the trailing-/+ space-permitting class) and keep the file's design comments truthful about the new boundary semantics.hardcoded-path-patterns.sha strict superset of the detailed patterns (widening the body must not out-run the gate).Distribution constraint:
machine-path-patterns.shis a managed synced component frommelodic-software/standards(components/path-detection/machine-path-patterns.sh, currently in sync). The pattern change must land in BOTH: a standards PR (precedent: standards#250) and the matching local copy here, byte-identical, or the next sync bot run reverts the fix.Acceptance criteria
root = C:/Dev/GitHubandroot = C:/Projects/melodic(bare value, EOL, no trailing slash) are flagged byHPP_WIN_REPO_BODY# C:/Projects/melodic - personal melodic-software repos (reference/reading only here)does not produce a greedy prose-span match (flagging only a path token itself is acceptable)C:/Dev,C:\Users\Alicealone) still do not matchALICE~1)hardcoded-path-check.test.shfor both observed lines; full suite passesBlocked by
None — can start immediately.