Skip to content

fix(git-guards): update test fixtures + strip boolean global git opts#257

Open
JacobPEvans wants to merge 8 commits intomainfrom
fix/issue-256-stale-guard-test-fixtures
Open

fix(git-guards): update test fixtures + strip boolean global git opts#257
JacobPEvans wants to merge 8 commits intomainfrom
fix/issue-256-stale-guard-test-fixtures

Conversation

@JacobPEvans
Copy link
Copy Markdown
Owner

@JacobPEvans JacobPEvans commented Apr 26, 2026

Closes #256

Summary

After the March 2026 policy tightening (all force-pushes now denied, not just to main), three categories of test failures needed fixing:

  1. Stale fixtures: tests expected ask for force-push to feature branches — now deny
  2. BLOCKED_ON_MAIN false positives: commit-based tests ran on main branch in CI (detached HEAD), triggering the main-branch guard before hook-bypass detection could run
  3. Global option bypass: git --no-pager push --force silently allowed because --no-pager was left in subcommand after the extraction loop broke, defeating the ^push anchor

Changes

  • git-permission-guard.py: Extend extraction loop to strip boolean global options (--no-pager, --bare, -p/-P, --paginate, --no-replace-objects) so ^-anchored DENY patterns fire correctly when global options precede the subcommand
  • test_permission_guard.py: Update force-push fixture from askdeny for feature branches; add regression test for git --no-pager push --force
  • test_shlex_valueerror.py: Update fixture reflecting that --no-pager is now stripped by loop so -c core.hooksPath is caught directly (deny), not via shlex fallback (silent_allow)
  • anchor + hooksPath precision: Force-push regex uses ^push\s+.* to avoid matching commit messages; hooksPath key extraction anchored to key portion only

Test Plan

  • All tests pass locally across test_permission_guard.py, test_shlex_valueerror.py, test_gh_guard.py
  • CI: all 6 checks pass (validate ×2, Analyze ×2, CodeQL, AI Merge Gate)

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request tightens the security policy by moving force-push commands from a confirmation-required list to a strictly denied list across all branches. It also refines the logic for detecting core.hooksPath bypasses via the -c flag. Review feedback suggests improving the force-push regex to handle flags placed after the remote or branch and using a more robust regex for configuration key matching to avoid manual string manipulation.

Comment thread git-guards/scripts/git-permission-guard.py Outdated
Comment thread git-guards/scripts/git-permission-guard.py Outdated
@JacobPEvans JacobPEvans marked this pull request as ready for review April 27, 2026 12:12
Copilot AI review requested due to automatic review settings April 27, 2026 12:12
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the git permission guard and its test fixtures to align with the tightened BLOCKED_ON_MAIN/force-push policy so CI stops failing due to stale expectations.

Changes:

  • Deny force-pushes via DENY_GIT_ONLY and remove force-push from ASK_GIT.
  • Tighten -c core.hooksPath fallback parsing to inspect only the config key (reducing false positives).
  • Update test_permission_guard.py fixtures to reflect the tightened behavior and avoid main-branch-dependent commands.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
git-guards/scripts/git-permission-guard.py Adjusts force-push classification and refines fallback core.hooksPath detection.
git-guards/scripts/test_permission_guard.py Updates expected decisions/commands to match current guard policy and make tests branch-agnostic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread git-guards/scripts/git-permission-guard.py Outdated
Comment thread git-guards/scripts/test_permission_guard.py Outdated
- Prefix force-push pattern with ^ to prevent false positives from
  commit messages containing "push --force"
- Add .* between push and force flag to match deferred-flag forms
  like `git push origin main --force`
- Replace split("=")[0] + simple match with anchored regex for
  core.hooksPath detection in fallback tokenizer
- Update stale test comment to reflect all-branch deny policy
@JacobPEvans JacobPEvans requested a review from Copilot April 29, 2026 05:16
@JacobPEvans JacobPEvans changed the title 🤖 Fix #256: stale guard test fixtures for BLOCKED_ON_MAIN tightening fix(git-guards): fix stale test fixtures for force-push and hooksPath guards Apr 29, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread git-guards/scripts/test_permission_guard.py
JacobPEvans added a commit that referenced this pull request Apr 29, 2026
* chore(git-standards): forbid emoji in commits and PR titles

Adds an explicit "Commit & PR Title Style" section to the pr-standards
skill (loaded on demand whenever an agent drafts a PR), and a one-line
cross-reference bullet in git-workflow-standards.

Companion to the soul.md flip in ai-assistant-instructions. Together
these eliminate the gap that caused recent automated AI-fix PRs (#263,
#257) to land with `🤖` prefixes — soul.md was endorsing gitmoji and
neither plugin skill said otherwise.

Applies to human, AI-assisted, and bot-authored PRs alike. Conventional-
commit prefixes carry the signal.

(claude)

* fix(git-standards): clarify emoji-ban scope and conventional-commit phrasing

Addresses copilot review feedback (threads VOoy, VOpG, VOpT) on PR #266.

Changes:
- Rename section header from "Commit & PR Title Style" to
  "Commit, PR Title & PR Description Style" (header now matches body scope)
- Split rule into two parts: emoji ban (commits + titles + descriptions
  + release notes) and conventional-commit prefix requirement (commit
  subjects + PR titles only)
- Replace ambiguous "Use conventional-commit prefixes only" with "are
  required at the start of commit subjects and PR titles only" — the
  original "only" was meant to scope where prefixes apply, but read as
  if the prefix should be the entire message
- Add release notes to the ban for parity with the soul.md update in
  ai-assistant-instructions PR #604

(claude)
…ith --no-pager

Add --no-pager, --bare, -p, -P, --paginate, --no-replace-objects to the
global option extraction loop so they are stripped before ^-anchored DENY
patterns are applied.

Previously the loop only stripped -C and -c, so `git --no-pager push --force`
left `--no-pager` at the start of subcommand, defeating the `^push` anchor and
silently allowing the force-push.

Adds regression test: git --no-pager push --force origin feature/my-branch → deny.

(claude)
…pping

The test expected silent_allow for git --no-pager -c core.hooksPath=/dev/null
because the old loop broke on --no-pager and left the -c option unprocessed.

Now that --no-pager is stripped by the loop, the following -c core.hooksPath
option is extracted directly (no shlex fallback needed), so the correct
outcome is deny. Updated the fixture and its comment accordingly.

(claude)
@JacobPEvans JacobPEvans changed the title fix(git-guards): fix stale test fixtures for force-push and hooksPath guards fix(git-guards): allow writes to bare-repo siblings Apr 29, 2026
@JacobPEvans JacobPEvans changed the title fix(git-guards): allow writes to bare-repo siblings fix(git-guards): update test fixtures + strip boolean global git opts Apr 29, 2026
The comment listed examples that the regex itself enumerates. Reframe to
explain WHY (no argument = different parse pattern from -C/-c).

(claude)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate Claude Code Plugin failing 74/100 runs — stale guard test fixtures

2 participants