0046 Modular Org Runtime Merge
ADR-0046: Modular org layout with runtime registry merge
- Date: 2026-06-26
- Status: accepted
- Deciders: Gerald Dagher (owner), cx-architect
- Amends: RFC-0004 storage decision only
Problem
RFC-0004 consolidated five fragmented registries into a single specialists/unified-registry.json. That fixed validation and orchestration wiring, but the monolith is now ~4.6k lines: hard to review in PRs, impossible to assign squad ownership, and it encodes only one organizational level (macro groups). Product work needs a finer squad layer (e.g. Product Management squad with PM flavor overlays collaborating with UX Research and Design squads under Product Group).
Direct reads of the JSON file appear in ~100 call sites (rg 'specialists/unified-registry.json' audit, 2026-06-26). Edits require whole-file merges and invite silent cross-team drift.
Decision
-
Modular sources on disk under
specialists/org/:groups/*.json— macro groups (kind: group) with group-level decision rights andsquads[]teams/*.json— functional squads (kind: squad) withgroupId,roles[],collaborators[],specialists[]specialists/*.json— one file percx-*withteamId(squad) andgroupId(denormalized)contracts/*.json,policies/*.json— one entity per file
-
Runtime merge —
lib/registry/loader.mjsassembleRegistry(rootDir)walks the tree, merges.cx/org/overlay, validates, and caches by directory mtime. No committed monolithic JSON is the source of truth. -
Assembled registry v3 — in-memory shape matches v2 (
teams,specialists,contracts,policies) withversion: 3. Theteamsmap contains both groups and squads discriminated bykind. Specialistteamfield references the squad id. -
Pilot squad split — Product Group splits into five squads; other macro groups start as one squad each until refined.
Orchestration, fences, contracts, Oracle, and MCP read through loadRegistry() only. Validation invariants from RFC-0004 are preserved; group entries skip the "must have direct specialists" rule when they declare squads[].
Rationale
Modular files match how skills already live (skills/** with inventory snapshot). Runtime merge avoids dual-write drift between a compiled artifact and sources. Two-level org models real collaboration (squads) without losing macro decision rights (groups). Keeping the assembled object shape minimizes consumer churn.
Consequences
- Positive: Per-squad PRs; squad charters and collaborators are first-class; loader is the single read path.
- Negative: One-time migration of ~100 direct JSON readers; validator gains group/squad branches.
- Neutral: Contract
teamBoundarycontinues to reference group ids; routing addsgroupId+squadIdonteamRouting.
Migration
- Run
node scripts/migrate-org-modular.mjsto emitspecialists/org/**from the legacy monolith. - Switch
loadRegistry()toassembleRegistry(). - Delete
specialists/unified-registry.json; retainscripts/migrate-org-modular.mjsfor reference. - Update docs/guides/concepts/teams.md and architecture docs.
Evidence
- Loader audit:
lib/registry/loader.mjs(pre-change) read onlyspecialists/unified-registry.json. - Team/specialist counts: 6 macro groups, 29 specialists (2026-06-26).
- Tests:
tests/registry-runtime-merge.test.mjs,tests/registry-loader.test.mjs.