Skip to content

guardrails: hooks ship false-positive over-fires with no per-hook fixtures or shared precision convention (6-issue class: diff-scope, quoted-arg, boolean-intent, stdin, path-branch) #547

Description

@kyle-sexton

Lane: triage · Category: improvement (prevention umbrella) · Source: triage cycle 2026-07-19 — routing #543/#544/#545/#546 surfaced a class with no prevention layer.

Pattern — guardrails hooks recurrently ship false-positive over-fires, each caught in production and hand-filed

Open guardrails-hook false-positive / imprecision issues, one root class, zero prevention:

Note: #544 and #543 were filed ~3s apart by two babysit workers — the same over-fire found twice, independently, in production.

Root cause

Two systemic gaps behind every instance:

  1. No false-positive regression fixtures per hook. Hooks ship with no golden corpus of "commands/edits that MUST stay quiet" alongside "that MUST fire." So an over-fire is only discoverable by a worker tripping it live, then hand-filing — the pipeline pays at production time, repeatedly, for a defect a fixture would catch at hook-authoring time. (Directly analogous to source-control:babysit-prs: one shared authorship/finding/approval classifier + golden fixtures; gate script owns the merge-ready boolean (6-issue class) #534's shared-classifier + golden-fixtures argument for babysit, and quality-net: skill changes ship with zero regression detection — 120 evals.json unexecuted, skill-quality:check uninvoked (staged eval/gate/pass^k umbrella) #530's skill-regression net.)
  2. No shared precision convention. The same imprecision recurs across independent hooks: whole-file instead of diff-scoped (guardrails: cli-flag-verify PostToolUse hook scans whole file, warns on pre-existing lines outside the edited hunk #543/guardrails: cli-flag-verify PostToolUse hook flags pre-existing unrelated lines (not diff-scoped) #544), substring co-occurrence instead of structural match (block-hook-bypass: false-fires when a Bash command contains both an echo token and a redirect (script-stdout capture, or quoted-string arguments) rather than an actual file-authoring bypass #546), quoted-argument blindness (block-hook-bypass: false-fires when a Bash command contains both an echo token and a redirect (script-stdout capture, or quoted-string arguments) rather than an actual file-authoring bypass #546), boolean-intent inversion (guardrails:flag-commit-pr-skill-bypass: advisory false-fires on canonical git commit -F - with inline heredoc Co-Authored-By trailer (requires BOTH markers, contradicting documented "either marker -> stay quiet" intent) #545), unbounded stdin (guardrails: cli-flag-verify.sh still reads fd0 unbounded (last Win32-stall stdin site) #446), path-branch over-broad matching (guardrails: hardcoded-path-check false positives — repo-path branch flags all paths under home; percent-env interpolations flagged #389). Each is a fresh hand-fix with no reusable discipline.

Observed vs expected

  • Observed: guardrails hooks are authored ad hoc; false-positives are found by babysit workers during real passes and filed one at a time; fixing one hook teaches the next nothing.
  • Expected: (a) a per-hook golden-fixture harness (true-positive MUST-fire + false-positive MUST-stay-quiet cases; every filed instance above becomes a fixture), run in CI on any plugins/guardrails/hooks/** change; (b) a documented hook-precision convention — diff-scope PostToolUse:Edit checks to the changed hunk (whole-file only for new files), match structural producers not token co-occurrence, ignore tokens inside quoted args, bound stdin reads, and prefer either/or marker logic where "already-canonical → stay quiet" is the intent. New hooks and the fixes for the members conform to it.

Category

improvement (prevention). Kills a recurring false-positive class + the babysit-worker-time it burns finding them live, instead of N hand-fixes plus indefinite recurrence.

Relations

Members #389 #390 #446 #543 #545 #546 (#544 dup of #543); #534 (same fixtures-as-prevention pattern for the babysit classifier); #530 (skill regression net — behavior-level sibling); #540 (shared dogfood-filing — the #543/#544 concurrent-duplicate is its motivating example); #531/#532 (sibling prevention umbrellas). Decompose candidate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: highSignificant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions