Skip to content

guardrails: PowerShell commands with no git commit are blocked fail-closed on {} or () grouping #1415

Description

@kyle-sexton

Reproduced first-hand, twice, in one session

block-noncanonical-commit.sh blocks PowerShell commands that contain no git commit at all,
when the command carries {} or () grouping. Both of these were blocked while driving PR merges:

BLOCKED: this PowerShell git command cannot be parsed with confidence — blocked (fail-closed).
Remove the obfuscating construct (backtick, --%, subexpression, or {}/() grouping).

The commands that tripped it:

git fetch origin --prune 2>&1 | Select-Object -Last 5; git rev-list --left-right --count A...B; git merge-base A B | ForEach-Object { git log --oneline -1 $_ }
$r = ... ; foreach ($t in $p.reviewThreads.nodes) { if (-not $t.isResolved) { ... } }

Neither contains git commit. The second contains no git subcommand the guard cares about at all —
it is a GraphQL result loop that happens to sit in the same pipeline as a git status.

The same shape was independently reported by the L5 lane of the context-engineering pass against
block-no-verify.sh as well, on & 'script.ps1' and Get-ChildItem | ForEach-Object {...}.

Why this is worth fixing rather than living with

The guard is fail-closed by design, which is right for a commit guard. But the fail-closed
branch currently triggers on the presence of a grouping construct anywhere in the command line,
rather than on an unparseable git commit invocation. In PowerShell, {} and () are ordinary
control flow and subexpression syntax — foreach, if, ForEach-Object, $(...) — so the guard
denies a large fraction of legitimate non-commit PowerShell.

The cost is not only friction. A guard that blocks routine commands trains its users to reach for
the other shell to get work done, which is exactly the bypass the guard exists to prevent.

Suggested direction

Gate the fail-closed branch on the command actually containing a git commit invocation
(git commit, git -C … commit, an alias resolving to one) before applying the
unparseable-construct test. A command with no commit in it is out of the guard's stated scope and
should exit 0 regardless of its syntax.

Both guards need the same treatment: block-noncanonical-commit.sh and block-no-verify.sh.

Related

Refs #1403 — the guardrails performance work; PR #1385 explicitly did not address this false
positive, and the fresh-context verification recorded it as "ignored, neither fixed nor worsened".

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.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions