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)

Measurement duality (ADR-0056)

Two numbers, two tools, both enforced in CI:

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)

  1. Close K6, regenerate baseline, run the full-suite Phase-K gate. K6 merged; baseline at 83; full-suite gate = the pre-push hook run.
  2. Follow-ups queued: relocate orchestrator/prolog_worker.py → infra/ (obsoletes a KNOWN_VIOLATIONS waiver); the (TESTING, ARCHITECTURE) routing-subject gap (pre-existing — performance routes die at stage 2; subject choice is a design decision for Mohamed).
  3. The mechanical pass (817 modules) + Phases 0–4 of the 52 — multi-week; starts only on explicit go.

Related: Architecture · Blockers · Decisions · Upcoming work