test_quorum_naming_collision.py
python
sha256:4461d2674257c5b59a460e0ec23d3680462662e9837ef25b675489d2e42cb994
fix: resolve "I3" naming collision between push_validator.p…
Sonnet 5
minor
⚠ breaking
2 days ago
| 1 | """musehub#227 — "I3" must not name two different, non-reconciled mechanisms. |
| 2 | |
| 3 | Background: musehub/graph/push_validator.py's I3 (per-edge signature |
| 4 | authorization, actually enforced at push time — hard error) and |
| 5 | musehub/graph/quorum.py's I3 (recursive weighted-vote quorum tallying, |
| 6 | never called by anything outside its own module/tests — see musehub#225) |
| 7 | both claimed the "I3" label with genuinely different meanings. Resolution: |
| 8 | push_validator.py's definition is the real, enforced I3 (it's wired into |
| 9 | wire_push); quorum.py's mechanism is renamed away from "I3" entirely, |
| 10 | without deleting it (deletion is musehub#225's call, not this ticket's). |
| 11 | |
| 12 | musehub/services/musehub_governance.py::check_quorum (proposal-review |
| 13 | approval counting) was never actually confused with either — it shares |
| 14 | the English word "quorum" but no number/label — confirmed by audit, no |
| 15 | change needed there, so no test for it below. |
| 16 | """ |
| 17 | from __future__ import annotations |
| 18 | |
| 19 | import re |
| 20 | |
| 21 | |
| 22 | def _claims_label(doc: str, label: str) -> bool: |
| 23 | """Return True if *doc* uses *label* as an invariant-naming claim — |
| 24 | i.e. a line starting with the label immediately followed by a |
| 25 | separator (matching this codebase's own convention, e.g. |
| 26 | "I3 Authorization — hard error" or "I3 Quorum soundness —") — as |
| 27 | opposed to merely mentioning the label in explanatory prose (e.g. |
| 28 | "the actual push-time invariant labeled \"I3\" is ...", which is fine |
| 29 | and expected in a docstring that explains why a collision was |
| 30 | resolved). |
| 31 | """ |
| 32 | pattern = re.compile(rf"^{re.escape(label)}\b.*[—:]", re.MULTILINE) |
| 33 | return bool(pattern.search(doc)) |
| 34 | |
| 35 | |
| 36 | def test_push_validator_module_docstring_claims_i3_authorization() -> None: |
| 37 | """push_validator.py is the one enforced mechanism — it keeps the I3 label.""" |
| 38 | from musehub.graph import push_validator |
| 39 | |
| 40 | doc = push_validator.__doc__ or "" |
| 41 | assert _claims_label(doc, "I3") |
| 42 | assert "Authorization" in doc |
| 43 | |
| 44 | |
| 45 | def test_quorum_module_no_longer_claims_i3() -> None: |
| 46 | """quorum.py's recursive vote-tallying mechanism must not claim to be I3 |
| 47 | — that label belongs to push_validator.py's (different, enforced) |
| 48 | mechanism. musehub#225 decides whether this code is kept or deleted; |
| 49 | this test only asserts it no longer misuses the "I3" name while it exists. |
| 50 | Mentioning "I3" in explanatory prose (e.g. "the actual I3 is defined |
| 51 | elsewhere") is fine — claiming it as this module's own label is not. |
| 52 | """ |
| 53 | from musehub.graph import quorum |
| 54 | |
| 55 | doc = quorum.__doc__ or "" |
| 56 | assert not _claims_label(doc, "I3"), ( |
| 57 | f"quorum.py's module docstring still claims 'I3' as its own label " |
| 58 | f"— that label is reserved for push_validator.py's enforced " |
| 59 | f"authorization mechanism (musehub#227). Got: {doc!r}" |
| 60 | ) |
| 61 | |
| 62 | |
| 63 | def test_quorum_and_push_validator_docstrings_do_not_both_claim_i3() -> None: |
| 64 | """Belt-and-suspenders: whatever these two modules claim, they must not |
| 65 | both claim the same invariant label for different mechanisms.""" |
| 66 | from musehub.graph import push_validator, quorum |
| 67 | |
| 68 | push_claims_i3 = _claims_label(push_validator.__doc__ or "", "I3") |
| 69 | quorum_claims_i3 = _claims_label(quorum.__doc__ or "", "I3") |
| 70 | assert not (push_claims_i3 and quorum_claims_i3), ( |
| 71 | "Both push_validator.py and quorum.py claim 'I3' as their own " |
| 72 | "label — exactly the naming collision musehub#227 reports." |
| 73 | ) |
File History
1 commit
sha256:4461d2674257c5b59a460e0ec23d3680462662e9837ef25b675489d2e42cb994
fix: resolve "I3" naming collision between push_validator.p…
Sonnet 5
minor
⚠
2 days ago