gabriel / musehub public
feat patch task/quorum-enforcement #1 / 1
AI Agent gabriel · 146 days ago · May 1, 2026 · Diff

feat: quorum enforcement for governed repos

Repos with governance.json at HEAD now require threshold-many approved reviews from declared quorum members before a proposal can merge.

- musehub_governance.py: load_governance reads governance.json from repo HEAD object store; check_quorum counts member fingerprint approvals - proposals.py merge route: loads governance then blocks with 403 when quorum not met - test_quorum_enforcement.py: 10 TDD tests covering load_governance, check_quorum, and the merge API hook; all green

sha256:83803f8369d519d0147dc9f955d47a4aa18c53589da50b774d0e2cfe13a0d92e sha
+45 ~1 symbols
sha256:7eab2d10015d2ee130ea9775726d0a69c4fe406c40f467cbfa1795043cab9e43 snapshot
+45
symbols added
~1
symbol modified
0
dead code introduced
Semantic Changes 46 symbols
+ check_quorum function async_function check_quorum L60–115
+ AsyncSession import import AsyncSession L24–24
+ annotations import import annotations L18–18
+ auth_db import import auth_db L26–26
+ db import import db L27–27
+ json import import json L20–20
+ logging import import logging L21–21
+ select import import select L23–23
+ load_governance function async_function load_governance L32–57
+ logger variable variable logger L29–29
~ tests/test_quorum_enforcement.py .py 35 symbols added
+ _GOVERNANCE_1OF1 variable variable _GOVERNANCE_1OF1 L42–49
+ _GOVERNANCE_2OF3 variable variable _GOVERNANCE_2OF3 L51–62
+ _MEMBER_FP variable variable _MEMBER_FP L39–39
+ _NONMEMBER_FP variable variable _NONMEMBER_FP L40–40
+ _NOW variable variable _NOW L38–38
+ _PROPOSAL_COUNTER variable variable _PROPOSAL_COUNTER L104–104
+ _make_auth_key function function _make_auth_key L79–89
+ _make_identity function function _make_identity L65–76
+ _make_proposal function function _make_proposal L107–122
+ _make_repo function function _make_repo L92–101
+ _make_review function function _make_review L125–135
+ _sha256 function function _sha256 L30–31
+ AsyncClient import import AsyncClient L21–21
+ AsyncSession import import AsyncSession L22–22
+ _hashlib import import _hashlib L25–25
+ annotations import import annotations L16–16
+ app import import app L24–24
+ compute_identity_id import import compute_identity_id L27–27
+ compute_proposal_id import import compute_proposal_id L27–27
+ compute_repo_id import import compute_repo_id L27–27
+ compute_review_id import import compute_review_id L27–27
+ datetime import import datetime L20–20
+ json import import json L18–18
+ pytest import import pytest L19–19
+ timezone import import timezone L20–20
+ test_check_quorum_2of3_partial_not_met function async_function test_check_quorum_2of3_partial_not_met L344–367
+ test_check_quorum_changes_requested_not_counted function async_function test_check_quorum_changes_requested_not_counted L318–340
+ test_check_quorum_member_approval_counts function async_function test_check_quorum_member_approval_counts L291–314
+ test_check_quorum_no_approvals_not_met function async_function test_check_quorum_no_approvals_not_met L243–261
+ test_check_quorum_nonmember_approval_not_counted function async_function test_check_quorum_nonmember_approval_not_counted L265–287
+ test_load_governance_returns_none_when_no_file function async_function test_load_governance_returns_none_when_no_file L144–156
+ test_load_governance_returns_parsed_json function async_function test_load_governance_returns_parsed_json L160–234
+ test_merge_allowed_when_quorum_met function async_function test_merge_allowed_when_quorum_met L410–457
+ test_merge_blocked_when_quorum_not_met function async_function test_merge_blocked_when_quorum_not_met L376–406
+ test_merge_unaffected_without_governance function async_function test_merge_unaffected_without_governance L461–488
← Older Oldest on task/quorum-enforcement
All commits
Newer → Latest on task/quorum-enforcement

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:83803f8369d519d0147dc9f955d47a4aa18c53589da50b774d0e2cfe13a0d92e --body "your comment"