You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix(merge-guard): unify branch_set + mass_target onto injective netstring _canonical_join SSOT (issue 1136)
#1136 is a delimiter-class canonical-identity collision, not a single-delimiter
bug: mass_target's identity was non-injective at two git-legal delimiters (the
refspec comma AND the remote/refspec boundary), letting two distinct destructive
sets share one identity (a cross-set under-block).
Replace the hand-rolled delimiter joins in both destructive-set identity encoders
with one pure netstring/length-prefix primitive, `_canonical_join(items)` = the
`len:value` framing, injective by construction and content-agnostic:
- branch_set = _canonical_join(sorted(set(names)))
- mass_target = _canonical_join([flags_part, remote, *sorted(set(refspecs))])
The structural delimiters are eliminated (subsumed by framing), closing the whole
delimiter class at once. The \x00implicit sentinel stays unchanged (its NUL keeps
it disjoint from a real remote literally named "implicit" under framing). Refspecs
are now deduped (a duplicate ref is the same destructive target).
Over-block is closed by construction: mint and read derive the identity from the
same _canonical_join via the one extract_command_context SSOT, so a faithful click
self-matches. No mint/read call site is split.
Format-pinned tests updated to be format-following (assert against _canonical_join
calls, not hardcoded literals); format-agnostic distinctness/reorder/absence
asserts left intact. Doc-drift comment in merge_guard_pre corrected; stale
encoding prose in the shared-hook docstrings brought in line with the framing.
* chore(release): bump plugin version to 4.5.7
Canonical-identity SSOT fix (issue 1136) — merge_guard mass_target + branch_set
delimiter-class collision closed via the shared injective netstring _canonical_join.
* test(merge-guard): #1136 canonical-join SSOT SACROSANCT cert — injectivity proof + closure + over-block corpus
52-row bidirectional certification for the canonical-identity SSOT (issue 1136):
- Injectivity by exhibited inverse: a total constructive left-inverse decode
round-trips every edge (empty list/item, embedded colon/digits/NUL, multi-digit
lengths, netstring-looking content) plus a 5000-random property test — bounds the
shared-helper concentration hazard by construction, not by sampling.
- Closure: base (9256c93, baked in-test via git-show+exec) COLLIDES -> HEAD
REFUSES for BOTH the comma AND the boundary witnesses, at the identity level AND
the real mint->execute gate (a 2-set token no longer authorizes the 3-set).
- Over-block primary corpus (the cardinal direction): faithful mass/branch deletes
mint and self-match; reorder and dedup still match.
- Doubled surface base-vs-HEAD, sentinel isolation, the dedup behavior row, and the
colon force-delete edge.
Full suite: 11114 passed / 11 skipped / 0 failed / 0 errors (python 3.12.7).
* test(merge-guard): harden #1136 cert non-vacuity — self-contained base-through-gate row + HASH_3 control
Self-critical cert review strengthenings on #1136's core claim (both were
empirically confirmed, not fixing a hole — the pre-registered vacuity suspects
were falsified):
- Add `hash-in-remote` (the HASH_3 form `git push "origin#a" --delete b c`) to the
over-block self-match corpus — the missing mintable + self-authorizing control
that proves the # cross-set DENY is a WRONG-SET denial, not an unmintable-always-
deny artifact.
- New test_base_encoder_through_real_gate_cross_authorizes: patches the baked base
encoder into the one SSOT and asserts the collision CROSS-AUTHORIZES at the real
mint->execute gate for BOTH witnesses — making the closure non-vacuity SELF-
CONTAINED (no longer relying on an out-of-file monkeypatch).
Cert 52 -> 54 rows. Full suite 11116 passed / 11 skipped / 0 failed / 0 errors.
* ci(merge-guard): make baked-base cert files CI-portable under shallow clone
The #1136 and (pre-existing) #1129-R2 certification files load a base classifier
via `git show <base-sha>:...` at module load. CI's actions/checkout does a shallow
clone (fetch-depth 1) lacking those base commits, so `git show` failed and BOTH
files aborted collection — taking the whole suite down (0 tests run). Surfaced by
CI + the Copilot review.
Two complementary fixes (defense-in-depth), modeled on the existing
test_merge_guard_1118_recert.py precedent:
- .github/workflows/tests.yml: fetch-depth: 0 on checkout, so CI has full history
and every baked-base non-vacuity differential actually RUNS in CI.
- Both cert files: _load_classifier returns None on git-show failure (collection
succeeds), the module-level base symbols are None-safe, and a @requires_history
skip gates ONLY the base-vs-HEAD differential rows — the HEAD-side closure/REFUSE
assertions and absolute invariants stay unguarded so a fix-revert is still caught
even under a shallow clone.
No behavioral assertion altered (R2 cert: guards only). Full suite 11119 passed /
11 skipped / 0 failed / 0 errors.
0 commit comments