Architecture migration 2026-09 — target design & status
Source artifacts:
~/workspace/orchestrata-review-2026-09-17/(review, target design, migration map/plan, cycle resolutions — reconciled and revised 2026-09-21). This page is the wiki-of-record digest.
Why (measured, verified independently on master)
The 2026-09-17 adversarial review measured the disease; every checkable
claim reproduced on master within ±1 module: 868 modules / ~235K LOC, 3
dispatch engines / 4 Postman construction sites, 3 tool frameworks
(agents/tool_registry.py at exactly 2,164 LOC), providers+llm+drivers
split, 2 AST frameworks, DI with exactly 1 production call site
(gateway/server.py:471), CXPPacket defined in L2 (cxp/_packet_impl.py)
so L0 vocabulary imports concrete cxp/postman/orchestrator. Traceability
bimodal (~55% overall, ~0% on the newest specs); the Prolog query layer
behind code_intel/trace_intel was down.
The target design (clean-sheet orchestrata.*)
The one rule: Down only. Sideways through orchestrata.core protocols
only. No upward imports, no same-layer concrete imports, no
TYPE_CHECKING/lazy-import hiding of cycles; concrete wiring happens once,
in the L4 composition root.
| Layer | Meaning | Subsystems |
|---|---|---|
| L0 Vocabulary | types, protocols, enums, errors, entities — zero behavior | core (incl. CXPPacket) |
| L1 Infrastructure | domain-agnostic technical capability | infra, di |
| L2 Communication | packet codec + broker | cxp, postman |
| L3 Domain services | work units | agents, governance, knowledge_graph, semantic_graph, providers, tools |
| L4 Orchestration | coordinates L3; the ONLY concrete-import site | kernel, orchestrator, session, memory, context |
| L5 Interface | external surface | gateway, cli, plugin, integrations |
| Islands | self-contained satellites, never imported by the runtime | verification, harness, factory, refactor, domaingen, openspec, ast |
Key mechanisms: protocol-mediated sideways access via a DI container with
fail-fast resolve_all() at boot; a single composition root
(kernel/bootstrap.py); the dependency matrix is mechanically checkable
(target: 0 violations).
The revised migration plan (2026-09-21 revision)
- Preconditions (all DONE): janus provisioning fix
(
scripts/_janus_patched/BUILDING.md— GCC≥14 strictness workaround); measurement baseline pinned; blocking CI ratchet landed. - Phase K first (keystone): 5 misplaced-module relocations + Cycle 2
(
corepurity /CXPPacket→ core) BEFORE any mechanical move — they clear most Phase-3 UP violations in advance. - Then the mechanical pass (817 clean modules, libcst codemod +
git mv- expiring shims), then the 52 cross-boundary refactors in topological
order (Phases 0–4), with per-phase gates: ruff/black,
--strict0, ratchet non-increasing, affected tests, full suite.
- expiring shims), then the 52 cross-boundary refactors in topological
order (Phases 0–4), with per-phase gates: ruff/black,
- Rollback: one commit per module move; one branch per phase; every phase independently revertable; no long-lived fork.
- Sizing: ≈8–12 weeks, 1 engineer.
Measurement duality (ADR-0056)
Two numbers, two tools, both enforced in CI:
- Runtime gate —
scripts/architecture_checker.py --strict(top-level imports): 0 violations; 68–69 accepted function-scoped (RULED D7). - Static ratchet —
scripts/architecture_static_check.py(every edge incl. TYPE_CHECKING + function-scoped, plus Tarjan SCC): baseline pinned inscripts/architecture_static_baseline.json; the blockingarchitecture-ratchetCI job fails on any increase. The baseline JSON is the authoritative debt ledger — the review's 141/10-cycle figures were a deleted-branch snapshot.
Status — 2026-09-21 (executed via agent swarm, worktree-per-item)
| Item | State | Result |
|---|---|---|
| Preconditions | ✅ merged | janus build recipe; static checker + baseline; architecture-ratchet CI job |
K1 orchestrator/prolog_bridge.py → infra/ |
✅ merged | new L1 infra package (ADR-0054) |
K2 orchestrator/redis_state.py → infra/ |
✅ merged | |
K3 kernel/volk_registry.py → agents/ |
✅ merged | ADR-0055; volk_health (L0) purified |
K4 memory/embedding.py → infra |
❎ dropped | zero violations under current LAYER_ASSIGNMENTS (memory is L2) |
K5 session/context.py consumers → protocol |
✅ merged | new L0 SessionManagerProtocol; constructor injection |
K6 CXPPacket → core.packet (Cycle 2) |
✅ merged (580cd371) |
move+shim → core purge → 200-file codemod → unshim; serialization bytes byte-identical (msgpack sha256 pinned), characterization 3368 tests identical; old cxp.packet paths deleted (cxp.exceptions keeps a permanent compat re-export for exception identity) |
Static debt: 100 → 83 on master. Cycles: 6 SCCs / 18 modules (Cycle-2's
keystone SCC moved with the code). core is now pure — the target
dependency graph's keystone is in. Phase K is code-complete; the full-suite
closure gate runs as the pre-push hook's escalated suite.
Test-run economics (Mohamed's ruling 2026-09-21: "no test that passes must
run twice"): the affected-test selector's three escalate-to-full bugs are
fixed (deleted-file via range-base snapshot; zero-coverage → untested, not
full; fixture-aware conftest), generated-index staleness is content-age not
checkout-age, untested changed files fail-closed (write the test), and the
pre-push hook skips + self-stamps on content-identical source. A full run
happens only when the honest blast radius IS the whole suite (env profile or
root-conftest bootstrap changes) — scripts/affected_tests.py computes the
proof on every push.
Convergence note (2026-09-21 evening): origin/master's parallel
sessions 269–270 (18 commits, remediation phases 0–2) merged at 53e20bd5.
Their device-agnostic CPU embedder fixtures superseded a gpu-lane stopgap
(reverted; 22/22 embedder tests pass on CPU). The CHANGEME_ sentinel guard
landed in all three config homes (kernel cli_main, code_intel,
postman cli).
Fixes wave landed alongside (all on master): Prolog query-layer repair
(library(json)→library(http/json) fallback for Guix swipl 9.3.8 — the
orphaned review patch rescued and merged); KG relationship canonicalization
(REL_CONTAINS/CALLS/IMPORTS single source + identity drift-lock test);
CHANGEME_ config-sentinel guard; stale pipeline-CLI fail-fast test repaired
(routing fix 9fbed221 proven intentional); all 5 generated_* suites
regenerated with backward-compatible pins; 3 PEP 649/749 lazy-annotation
NameErrors fixed (ADR-0057). Session suite 2405/2405 green.
Next (needs go/no-go)
Close K6, regenerate baseline, run the full-suite Phase-K gate.K6 merged; baseline at 83; full-suite gate = the pre-push hook run.- Follow-ups queued: relocate
orchestrator/prolog_worker.py→infra/(obsoletes a KNOWN_VIOLATIONS waiver); the(TESTING, ARCHITECTURE)routing-subject gap (pre-existing —performanceroutes die at stage 2; subject choice is a design decision for Mohamed). - The mechanical pass (817 modules) + Phases 0–4 of the 52 — multi-week; starts only on explicit go.
Related: Architecture · Blockers · Decisions · Upcoming work