gabriel / musehub public
feat patch graph task/identity-push-validator #1 / 1
AI Agent gabriel · 156 days ago · Apr 21, 2026 · Diff

feat(graph): IdentityPushValidator — hub-side I1/I2/I3 enforcement at push time

I1: DFS cycle detection — hard error, push rejected I2: multi-source BFS root distance — warning, node annotated as orphaned I3: ordered authorization enforcement - spawns(from→to): from_handle must sign - member_of(m→org): ordered processing, min(quorum, |prior|) existing members must sign bootstrap (0 prior members): self-authorization sufficient partial quorum (|prior| < quorum): all prior members must sign full quorum (|prior| >= quorum): quorum-many prior members must sign 33 TDD tests — all passing.

sha256:450006ff2bb8cb0537f32f9073b31481224056b107525115da6820a43031042d sha
+63 symbols
sha256:ecbfecdb7c1f9f9fd263a61ce9dad503048d3514082aa9023a08fdc91f2eff15 snapshot
+63
symbols added
0
dead code introduced
Semantic Changes 63 symbols
~ musehub/graph/push_validator.py .py 13 symbols added
+ IdentityPushValidator class class IdentityPushValidator L35–142
+ validate method method validate L38–142
+ ValidationResult class class ValidationResult L29–32
+ CycleDetector import import CycleDetector L23–23
+ CycleError import import CycleError L23–23
+ EdgeType import import EdgeType L24–24
+ GraphEdge import import GraphEdge L24–24
+ IdentityDAG import import IdentityDAG L24–24
+ NodeType import import NodeType L24–24
+ RootDistanceIndex import import RootDistanceIndex L25–25
+ annotations import import annotations L19–19
+ dataclass class import dataclass L21–21
+ field import import field L21–21
~ tests/test_identity_push_validator.py .py 50 symbols added
+ TestCombinedScenarios class class TestCombinedScenarios L299–343
+ test_full_graph_gabriel_claudecode_musehub method method test_full_graph_gabriel_claudecode_musehub L300–323
+ test_i1_error_does_not_suppress_i3_errors method method test_i1_error_does_not_suppress_i3_errors L325–334
+ test_warnings_do_not_make_result_invalid method method test_warnings_do_not_make_result_invalid L336–343
+ TestI1Acyclicity class class TestI1Acyclicity L98–146
+ test_cross_edge_type_cycle_rejected method method test_cross_edge_type_cycle_rejected L141–146
+ test_diamond_dag_valid method method test_diamond_dag_valid L124–133
+ test_direct_cycle_rejected method method test_direct_cycle_rejected L111–116
+ test_indirect_cycle_three_nodes_rejected method method test_indirect_cycle_three_nodes_rejected L118–122
+ test_linear_chain_valid method method test_linear_chain_valid L99–102
+ test_member_of_cycle_rejected method method test_member_of_cycle_rejected L135–139
+ test_self_loop_rejected method method test_self_loop_rejected L104–109
+ TestI2RootDistance class class TestI2RootDistance L151–192
+ test_agent_chain_no_warning method method test_agent_chain_no_warning L162–169
+ test_agent_spawned_by_human_no_warning method method test_agent_spawned_by_human_no_warning L156–160
+ test_human_no_warning method method test_human_no_warning L152–154
+ test_nested_org_with_human_root_no_warning method method test_nested_org_with_human_root_no_warning L185–192
+ test_org_with_human_member_no_warning method method test_org_with_human_member_no_warning L175–178
+ test_org_with_no_human_path_warned method method test_org_with_no_human_path_warned L180–183
+ test_orphaned_agent_warned method method test_orphaned_agent_warned L171–173
+ TestI3AuthMemberOf class class TestI3AuthMemberOf L244–294
+ test_first_member_self_authorized_valid method method test_first_member_self_authorized_valid L245–249
+ test_membership_insufficient_signatures_rejected method method test_membership_insufficient_signatures_rejected L262–270
+ test_membership_requires_quorum_of_current_members method method test_membership_requires_quorum_of_current_members L251–260
+ test_no_signatures_rejected method method test_no_signatures_rejected L284–288
+ test_non_member_signature_does_not_count method method test_non_member_signature_does_not_count L272–282
+ test_quorum_1_founder_joins_empty_org_valid method method test_quorum_1_founder_joins_empty_org_valid L290–294
+ TestI3AuthSpawns class class TestI3AuthSpawns L197–239
+ test_agent_spawn_wrong_signer_rejected method method test_agent_spawn_wrong_signer_rejected L232–239
+ test_agent_spawning_agent_authorized_by_original_spawner method method test_agent_spawning_agent_authorized_by_original_spawner L223–230
+ test_extra_signers_ok_as_long_as_spawner_present method method test_extra_signers_ok_as_long_as_spawner_present L218–221
+ test_spawner_signature_absent_rejected method method test_spawner_signature_absent_rejected L203–209
+ test_spawner_signature_present_valid method method test_spawner_signature_present_valid L198–201
+ test_wrong_signer_rejected method method test_wrong_signer_rejected L211–216
+ TestTrivial class class TestTrivial L74–93
+ test_empty_graph_is_valid method method test_empty_graph_is_valid L75–78
+ test_orphaned_agent_warning method method test_orphaned_agent_warning L90–93
+ test_single_human_is_valid method method test_single_human_is_valid L80–82
+ test_single_org_no_members_warning method method test_single_org_no_members_warning L84–88
+ agent function function agent L39–41
+ human function function human L34–36
+ Decimal import import Decimal L22–22
+ IdentityPushValidator import import IdentityPushValidator L26–26
+ ValidationResult import import ValidationResult L26–26
+ annotations import import annotations L20–20
+ pytest import import pytest L24–24
+ member_of function function member_of L58–64
+ org function function org L44–46
+ spawns function function spawns L49–55
+ v function function v L68–69
← Older Oldest on task/identity-push-validator
All commits
Newer → Latest on task/identity-push-validator

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:450006ff2bb8cb0537f32f9073b31481224056b107525115da6820a43031042d --body "your comment"