Wire MuseHub org + quorum model onto staging (membership: gabriel, aaronrene)
Wire the MuseHub Org + Quorum Model onto Staging (membership: gabriel, aaronrene)
Background
Almost none of this needs to be built. The identity/quorum architecture already
exists and is fully documented in musehub/templates/musehub/pages/docs_muse_identity.html:
- The
identitydomain plugin (muse/plugins/identity/) already has atype: "human"|"agent"|"org"field onIdentityRecord, aquorum: int | nullthreshold field, andspawns/member_ofrelationship edges withauthorized_bysignature arrays (muse/plugins/identity/records.py). - Every registered identity already has a dedicated
{handle}/identityMuse repo — the canonical source of truth for pubkey/quorum/relationships; Postgres is a rebuildable index, not the other way around. IdentityPushValidator(musehub.graph.push_validator) already enforces I1 (acyclicity, hard error), I2 (root distance, warning), and I3 (authorization/ quorum signatures, hard error) at push time, with the exact bootstrap rule (min(quorum, prior_members)signatures required per new member) and recursive sub-org voting viaQuorumEngine.effective_weight()(musehub.graph.quorum).governance.jsoncommitted to a repo's HEAD already drives quorum enforcement on proposal merges —check_quorum()(musehub/services/musehub_governance.py) is already called from the proposal-merge route (musehub/api/routes/musehub/proposals.py:546-549), resolving handle-based quorum members against each member's identity repo HEAD so key rotation propagates automatically.POST /api/orgs(create org identity + repo, MSign), plus member add/list/ remove, already exist server-side (musehub/api/routes/api/orgs.py).
What's actually missing is the wiring, not the architecture:
- No
muse hub orgCLI command group exists yet — org creation and membership management are only reachable by hand-building raw API calls, with no CLI wrapper mirroring the existingmuse hub attestationpattern. - No org exists on staging today — every repo currently listed is owned by
gabrielalone (muse hub repo list --hub https://staging.musehub.ai). - No
governance.jsonis committed to any of our actual repos — the enforcement mechanism is live and wired, but nothing has ever asked it to enforce anything. - It is not yet verified whether
check_quorum()permits an author to count toward their own proposal's quorum (self-approval) — this is the load- bearing question for the review policy this ticket exists to implement: gabriel, and agents gabriel is directing, self-review; anyone else (starting with aaronrene) needs a formal quorum-satisfying review from an existing org member. If self-approval is not currently permitted bycheck_quorum(), that is either a real gap to close or a deliberate constraint to design around — this plan does not assume either answer.
This is a wiring-and-verification project, not a new-feature build. Every phase below either uses existing, documented primitives directly, or adds the minimum CLI/operational surface needed to actually exercise them.
Goal
- A real org exists on staging MuseHub with founding member
gabrieland second memberaaronrene, created and verified through the actual push/ validation path (IdentityPushValidator), not by hand-editing a database row. governance.jsonis committed to the repos this org should govern (at minimummuseandmusehub), with quorum members/threshold resolved from the org's real identity repo, not hardcoded fingerprints.- The self-review-vs-formal-review policy is verified end-to-end against the real merge path: a gabriel-authored proposal merges without requiring a second reviewer; an aaronrene-authored proposal is blocked until it receives a quorum-satisfying review from an existing org member.
- A
muse hub orgCLI command group exists if it's genuinely missing (Phase 1 confirms this before Phase 2 assumes it). - The existing identity docs page is updated to reference the real, live
staging org as a worked example, replacing or supplementing its currently
hypothetical
graph-lab/acmeexamples.
"Done" means: every deliverable below is checked off, every test ID is green, and a real aaronrene-authored proposal against a governed repo has actually been blocked-then-approved-then-merged on staging, not just simulated in a test fixture.
Non-Goals / Out of Scope
- Redesigning I1/I2/I3,
QuorumEngine, or the HD key-derivation scheme. All of that is settled, documented, working architecture. This plan consumes it. - Governing every repo in the workspace immediately. Phase 4 starts with
museandmusehub— extendinggovernance.jsonto every other repo/ domain is a fast, mechanical follow-up once the pattern is proven on two real repos, not a reason to widen this ticket's scope now. - Building a web GUI org-management page. If one doesn't already exist, it's a reasonable fast-follow (flagged in Open Questions) but not blocking for the CLI/API-level goal here.
- Onboarding anyone beyond gabriel and aaronrene. Scoped explicitly to those two; widening membership is a future, separate action.
Design
Org creation and bootstrap
Per I3's documented bootstrap rule, the founding member of an empty org
self-signs — no quorum to satisfy yet, since there are zero prior members.
gabriel is the founder. aaronrene joining second, with the org's quorum
threshold set to 1, requires min(1, 1) = 1 signature from the existing
member set ({gabriel}) — i.e., gabriel's sign-off admits aaronrene. This is
the existing, documented mechanism; no new logic is needed to model "gabriel
approves who joins."
Self-review vs. formal-review policy — the actual design question
The review policy gabriel described (self-review for gabriel/gabriel-directed
agents; formal quorum review for everyone else) is not naturally expressed
by governance.json's quorum.threshold/members alone if check_quorum()
counts the proposal's own author toward the threshold — a threshold of 1 with
members: ["gabriel"] would then let anyone's proposal merge the moment
gabriel is listed as a member, without requiring gabriel to actually review
anyone else's work. Phase 1 must determine, by reading check_quorum()'s
actual implementation and by testing it directly, whether:
(a) it already excludes the proposal author from counting toward their own quorum (in which case the existing mechanism already implements exactly the policy gabriel described — an aaronrene-authored proposal literally cannot self-satisfy quorum, and a gabriel-authored proposal is a separate question addressed below), or
(b) it does not exclude the author, in which case this plan must either (i) add that exclusion as a small, targeted fix if it's clearly a gap rather than an intentional design choice, or (ii) design the policy a different way (e.g., a separate "self-merge allowed for these handles" governance field, distinct from quorum review).
Either way, gabriel's own proposals need a distinct allowance — "self- review" for the founder isn't quorum-satisfaction, it's an explicit bypass. Whether that bypass already exists (e.g., repo owner can always merge regardless of governance) or needs to be added is also a Phase 1 finding, not an assumption baked into this plan up front.
Governance rollout
governance.json is committed to a repo's main branch HEAD — an ordinary
file, versioned like any other, resolved by load_governance() at merge
time. Rolling it out to muse and musehub is a real commit to each repo,
not a database configuration action — consistent with the workspace's
existing "everything is a versioned artifact" ethos.
Phases
Each phase is fully green before the next begins. Test IDs use the ORG_NN
prefix.
Phase 1 — Audit current behavior (no new code, tests only)
Before building anything, pin down exactly how the existing mechanisms behave today, with tests that exercise the real code paths (not just re-reading source).
ORG_01— Confirm whether amuse hub orgCLI command group exists; if not, this becomes Phase 2's deliverable list, not a re-derivation later.ORG_02— Integration test: doescheck_quorum()count the proposal author toward their own proposal's quorum? Exercise the real function against a constructed governance config and review set — don't infer from reading alone.ORG_03— Integration test: does the existing proposal-merge route allow a repo owner to merge their own proposal regardless ofgovernance.json, or does governance apply uniformly to every author including the owner?ORG_04— ConfirmPOST /api/orgsand the member add/list/remove endpoints work end-to-end against staging with a throwaway test org (not the realgabriel/aaronreneorg yet) — verifying the documented behavior is actually live on staging, not just implemented in a branch that hasn't shipped.
Phase 2 — muse hub org CLI (only if Phase 1 confirms it's missing)
ORG_10—muse hub org create --name <name> --json, wrappingPOST /api/orgs, mirroring the existingmuse hub attestation createpattern (client-side validation before network I/O, standard envelope JSON output).ORG_11—muse hub org member add/list/remove, wrapping the corresponding/api/orgs/{org}/membersendpoints.ORG_12— CLI tests mocking the API layer (same pattern astests/test_mist_read_api_path.py's_hub_apimocking) confirming correct path construction and argument handling, not just a happy-path smoke test.
Phase 3 — Create the real org on staging
ORG_20— Create the actual org (handle TBD — see Open Questions) on staging withgabrielas founding member, verified viaIdentityPushValidator's real bootstrap path (self-sign, zero prior members) — not a direct database insert.ORG_21— Addaaronreneas the second member, verified through the realmin(quorum, prior)signature-count path — confirm the push is rejected if gabriel's signature is missing, and succeeds when present, as a direct regression test against staging (or a staging-equivalent fixture environment if hitting real staging destructively is undesirable — see Risks).ORG_22— Confirm the org's identity repo ({org-handle}/identity) exists and itsidentities//relationships/files match what §"Org creation and bootstrap" describes, read directly viamuse -C {org-handle}/identity log --jsonandmuse cat.
Phase 4 — Governance rollout on muse and musehub
ORG_30— Commitgovernance.jsontomuse'smainbranch with quorum members resolved from the new org (handle-based, per the documented preferred form — never raw fingerprints, since handles track key rotation automatically).ORG_31— Same formusehub.ORG_32— End-to-end regression: open a real (or realistic staging- fixture) proposal authored byaaronreneagainst a governed repo; confirm merge is blocked until a quorum-satisfying review lands; confirm it succeeds once that review is submitted.ORG_33— End-to-end regression: open a proposal authored bygabriel(or an agent gabriel is directing) against the same governed repo; confirm the self-review bypass identified/built in Phase 1 behaves as intended — merge proceeds without requiring a second, independent reviewer.
Phase 5 — Docs and workspace policy
ORG_40— Updatedocs_muse_identity.html's quorum section to reference the real, live staging org as a concrete worked example alongside (or replacing) the current hypotheticalgraph-lab/acmeexamples.ORG_41— Update the workspace's shared.muse/agent.md(or wherever the review-policy convention should live) to state explicitly: proposals authored by gabriel or an agent gabriel is directing may self-review; every other author's proposal requires a quorum-satisfying review from an existing governing-org member before merge.
Acceptance Criteria
- A real org exists on staging with
gabrielandaaronreneas verified members, created through the actual identity-push validation path. governance.jsonis live onmuseandmusehub'smainbranches.- A real (or staging-fixture) aaronrene-authored proposal against a governed repo cannot merge without a quorum-satisfying review, and can merge once one is submitted.
- A real (or staging-fixture) gabriel-authored proposal against the same governed repo merges without requiring a second reviewer.
muse hub orgCLI commands exist and are tested, unless Phase 1 finds they're unnecessary because equivalent functionality already exists somewhere else in the CLI (in which case that finding replaces this criterion, not silently satisfies it).- No test in the suite depends on a specific staging database row surviving between runs — fixtures create and tear down their own throwaway org state where Phase 1's audit tests need real staging interaction.
Risks
- Testing against real staging risk: several phases above call for
verifying behavior against actual staging state (a real org, real
proposals). Mitigation: prefer a disposable, clearly-named throwaway org/
repo for verification passes (Phase 1's
ORG_04) before creating the realgabriel+aaronreneorg in Phase 3, so early mistakes don't have to be unwound on the record that matters. - Self-review-bypass ambiguity risk: this plan explicitly does not
assume how gabriel's self-review bypass works today (owner-always-merges?
author-counts-toward-own-quorum? something else?) — Phase 1's findings
could change Phase 4's exact implementation. That's intentional: guessing
here and discovering the guess was wrong after
governance.jsonis live on real repos is a worse failure mode than spending Phase 1 to find out first. - Documentation drift risk:
docs_muse_identity.htmlis detailed and currently accurate to the underlying code per this plan's own research — Phase 5 must update it to reflect the real org, not let the doc silently become the one part of this effort that stays hypothetical.
Open Questions
- What should the org's handle actually be? (
musehub-core,muse-org, something else?) Needs a decision before Phase 3, not left implicit. - Should the quorum threshold be
1(any single existing member's approval suffices) or higher, now that membership is just gabriel and aaronrene? With two members and threshold=1, aaronrene's own review would already satisfy quorum for someone else's proposal once she's a member — worth deciding deliberately whether that's the intended posture at this membership size, versus reserving quorum>1 for whenever a third member joins. - Does a web-GUI org-management page already exist (the earlier open
musehubissues list mentioned profile/social/release-page work but nothing explicitly for org management) — if genuinely absent, should it be filed as its own follow-up issue now, or deferred until the CLI/API path above is proven? - Once Phase 1 answers the self-review-bypass question, does the answer
belong in
governance.json's schema itself (e.g. an explicitself_merge_allowed: ["gabriel"]field) or in a separate mechanism entirely? This plan intentionally leaves the exact shape open until Phase 1's findings are in.
Implementation Order
Phase 1 → Phase 2 (conditional) → Phase 3 → Phase 4 → Phase 5. Phase 1 is strictly load-bearing for every later phase — Phase 4's governance rollout depends entirely on knowing how self-review actually behaves, which is exactly what Phase 1 exists to determine before any real repo is governed.
Plan-only issue. Each phase's deliverables should be checked off in place as they land — this is operational/wiring work on existing architecture, not a new domain requiring further decomposition into separate staging issues.