Repository navigation
fix(classifier): v1.2.37 narrow protected-ref gating to true target pushes (t_c0f25265) - #64
Open
maximalang wants to merge 3 commits into
Open
maximalang wants to merge 3 commits into
maximalang wants to merge 3 commits into
Conversation
… pushes Root cause (live repro on v1.2.36, card t_c0f25265): the gated category armed on any command line where a push/merge token co-occurred with a protected branch name — including integrating the trunk INTO a feature branch and stage-chained commands where the protected name appeared in an earlier read-only stage. Affected workers deadlocked in evidence_gate_missing on legitimate integration git usage (rr-team train + landing lane, 2026-10-07). Fix: the category now requires an actual protected target — a push whose ref argument resolves to a protected branch (incl. src:dst and refs/heads forms), gh pr merge, or an explicit "merge ... into <protected>" form — with matching scoped to a single shell stage. Read-only probes (merge-base, pr view --json) were already fixed in v1.2.34/36 and keep passing via the FP corpus. Tests: +11 regression cases (5 FP, 6 TP controls) in test_policy.py; version pin updated in test_hardening_v121.py; full suite 924 passed. Versions bumped to 1.2.37 (pyproject, both plugin.yaml, __init__, CHANGELOG).
added 2 commits
October 14, 2026 13:12
…c0f25265) Merge trunk v1.2.46 into fix/classifier-fp-v1237 and finish the FP fix: - release_to_protected_branch now requires a push ref argument that RESOLVES to a protected branch, boundary-anchored ((?<![:\w./-]) / (?![\w./-]), plus :<branch>, :refs/heads/<branch>, refs/heads/<branch> forms). Protected names that are only a path component of a different branch (push origin feature/main-fix) no longer arm the gate. - Matching stays scoped to one shell stage, so an earlier fetch/merge-base/ prose stage cannot arm a later unrelated push (landed on the PR head). - Version 1.2.37 -> 1.2.48 across pyproject/plugin.yaml x2/__init__/uv.lock/ version-guard test + CHANGELOG (1.2.37 collided with open refs and the trunk already released 1.2.46). - tests/test_policy.py: added boundary regression cases (feature/main-fix, mainnet, release-notes, HEAD:feature/main-fix) and TP controls (feature/x:release, HEAD:refs/heads/master, multi-refspec). Evidence: probe matrix fp=0 tp=0 (only force-push stays approval_required via irreversible_data_loss); uv run pytest 956 passed (normal + worker env); version guard collision=false; uv lock --check, compileall, drift-check, build/verify-bundle, uv build all green at 1.2.48. Refs t_c0f25265. No config/evidence_gates changes; no deploy.
- Boundary character class was written as [\w./-:] whose final two members form
the ASCII range 0x2F-0x3A ('/' and ':'), which made '-' a member and pulled
'release-notes' back into the gate. Use an explicit alternation rather than a
trailing ':' inside the class, and require the negative lookahead to reject
':' so 'push origin main:feature/x' (protected ref as SOURCE) is not read as
a protected destination.
- tests/test_policy.py: added the release-notes regression that caught it.
Evidence: pytest 956 passed; probe matrix fp=0 (tp=1 is 'push --force main',
which stays approval_required via irreversible_data_loss, i.e. stricter).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
v1.2.37 —
release_to_protected_branchclassifier narrowing (card t_c0f25265).Root cause (live repro on deployed v1.2.36)
The gated category armed on any single command line where a
push/mergetoken co-occurred with a protected branch name — regardless of direction or
stage boundaries:
git merge origin/main(trunk integrated INTO a feature branch) — deniedwith
evidence_gate_missing, deadlocking rr-team merge-train andlanding-lane workers on 2026-10-07;
stage (fetch/merge-base) next to an unrelated later push;
(
merge-baseandpr view --json mergeablereads were already fixed by thev1.2.34 FP corpus / v1.2.36
merge(?!-base)lookahead; probe confirms theystay read-only.)
Fix
The category now requires an actual protected target:
pushwhose ref argument resolves to a protected branch (incl.src:dstand
refs/heads/<branch>forms),gh pr merge,merge ... into <protected>phrasing,with matching scoped to a single shell stage (
[^;&|\n]), so earlier stagesand prose cannot arm the gate. Serious-risk rules (force-push →
irreversible_data_loss) untouched.Evidence
(must stay gated) in
tests/test_policy.py.git merge origin/maingoesrelease_to_protected_branch→repository_change(allow);git push origin main,push HEAD:main,push ... refs/heads/main,gh pr mergeall stayrelease_to_protected_branch.__init__,version-guard test, CHANGELOG).
Deploy note
After merge, roll v1.2.37 out to profile plugin dirs and verify one
previously denied command class passes live.