Skip to content

Tier D — Orchestrator core-extraction plan (2026-05-15)

Tier D — Orchestrator core-extraction plan (2026-05-15)

Section titled “Tier D — Orchestrator core-extraction plan (2026-05-15)”

Companion to: crate-structure-audit-2026-05-15.md §4.4
Prereq: Tiers A + B + C landed (all on 2026-05-15). vox-arch-check reports clean.

  • vox-orchestrator is at 65,560 LoC vs max_loc = 70_0007% headroom (~4,440 LoC).
  • The audit’s “vertical-slice” path (agentos/vox-orchestrator-policy) is a dead end: agentos/ contains only 358 LoC across 8 stubs.
  • The correct wedge is C5 from the 2026-05-08 followup design: extract src/orchestrator/ (12.8K LoC) into a new vox-orchestrator-core crate. This is the densest subdir and the primary source of the +13K LoC regrowth.
  • C5 requires co-moving the Orchestrator struct (Rust coherence: impl blocks for a type must live in the defining crate). The minimum co-move set is ~8 sibling modules; total displacement is ~20–25K LoC.
  • Estimated post-split sizes: vox-orchestrator-core ~35K LoC, vox-orchestrator ~32K LoC.
  • Do not start this work until vox-orchestrator Rule 13 fires (>15% LoC growth since last release tag). Until then, dei_shim/ is a lower-risk intermediate extraction (§4).

vox-orchestrator 65,560 LoC (budget: 70,000 — 7% headroom)

Subdir breakdown (descending):

DirLoCNotes
orchestrator/12,825Task dispatch + Orchestrator inherent impls
dei_shim/5,005Research pipeline shim
models/3,448Model registry + selection
a2a/3,167A2A remote-worker protocol
planning/2,870Plan adequacy / continuation
services/2,848Request routing
config/2,673Env-sourced config
preregistration/1,456Agent pre-registration
types/1,426Shared internal types
memory/1,193Memory manager
attention/1,089Attention tracker
session/1,026Session lifecycle
orch_daemon/994Daemon entry point
budget/983Holistic budget manager
queue/837(thin, most queue logic is in vox-orchestrator-queue)
hopper/638Task hopper shim
routing/564Routing helpers
legacy/412Compatibility shims
agentos/358Policy stubs — not an extraction target
context/321Context store helpers
flat files~17Kruntime.rs, catalog.rs, events.rs, usage.rs, handoff.rs, …

The 2026-05-15 audit §4.4 listed two paths for Tier D:

Path 2 (vertical-slice): split agentos/ into vox-orchestrator-policy.

At audit-writing time agentos/ was assumed to hold most of the +13K LoC regrowth. Measurement shows it is 358 lines (8 stub files: policy_runtime.rs, guardrail_kernel.rs, context_budget_manager.rs, risk_scoring.rs, intent_planner.rs, checkpoint_engine.rs, replay_fast_forward.rs, mutation_classifier.rs). Creating a crate boundary for 358 LoC adds manifest overhead and compile-unit fragmentation with near-zero LoC benefit.


3. C5: orchestrator/vox-orchestrator-core

Section titled “3. C5: orchestrator/ → vox-orchestrator-core”

src/orchestrator/ contains the core Orchestrator inherent impl blocks — task dispatch submission, completion, agent lifecycle, scaling, persistence, VCS ops, campaigns, comms, safety, and the integration tests. At 12,825 LoC it is the single densest subdir and accounts for the bulk of the post-reorg regrowth.

Problem: All files in src/orchestrator/ contain impl crate::orchestrator::Orchestrator { … } blocks. Rust’s coherence rules require that inherent impl blocks for a type live in the same crate as the type’s definition. You cannot add inherent methods on ExternalCrate::Orchestrator from a downstream crate.

Consequence: Extracting src/orchestrator/ requires moving the Orchestrator struct definition with it, into vox-orchestrator-core.

src/orchestrator/**/*.rs (excluding tests) imports these sibling modules via crate:::

crate::affinity crate::attention crate::budget
crate::bulletin crate::catalog crate::config
crate::context crate::groups crate::locks
crate::models crate::oplog crate::orchestrator
crate::planning crate::queue crate::scope
crate::services crate::snapshot crate::socrates
crate::topology crate::types

Not all of these need to co-move — some can be extracted as vox-orchestrator-core dependencies instead. The break-even question is: does the module have its own Orchestrator impl blocks, or is it a pure utility consumed by those blocks?

ModuleLoCCan stay in vox-orchestrator as a dep?Notes
types/1,426No — must move. Used by the Orchestrator struct fields.
config/2,673No — must move. OrchestratorConfig is in Orchestrator::new.
budget/983No — must move. BudgetManager is a struct field.
locks/~400No — must move. FileLockManager is a struct field.
bulletin/~200No — must move. BulletinBoard is a struct field.
scope/~150No — must move. ScopeGuard used by task dispatch.
groups/~180No — must move. AffinityGroupRegistry is a struct field.
affinity/~250No — must move. FileAffinityMap is a struct field.
context/321No — must move. ContextStore is a struct field.
snapshot/~150Possibly, if accessed via trait.
oplog/~300Possibly, if accessed via trait.
attention/1,089Possibly, if accessed via a dyn AttentionSink.
planning/2,870Likely must move (plan adequacy checks are in completion handlers).
services/2,848Likely must move (routing is called in task dispatch).
catalog/853Likely must move (catalog refresh is an impl block).
models/3,448Likely must move (model selection called in dispatch).
socrates/~546Possibly, via trait injection.
topology/~200Small — probably must move.
queue/837Already thin; most logic in vox-orchestrator-queue.

Estimated minimum co-move set: types + config + budget + locks + bulletin + scope + groups + affinity + context ≈ ~6,600 LoC. With planning + services + catalog + models (likely must move), the co-move set grows to ~17K LoC.

CratePost-split LoCBudget
vox-orchestrator-core~35,000suggest max_loc = 40_000
vox-orchestrator~32,000suggest max_loc = 35_000 (down from 70K)

The split roughly halves both crates and leaves vox-orchestrator holding: orch_daemon/, dei_shim/, a2a/, runtime.rs, preregistration/, session/, hopper/, routing/, legacy/, and the integration glue.


If C5 is too large to scope right now, dei_shim/ (5,005 LoC) is a viable intermediate:

  • It is the research pipeline shim (vox dei, MENS pipeline dispatch, pipeline.rs at 930 LoC).
  • Its main consumer is orch_daemon/dei_dispatch.rs (323 LoC).
  • Probable dep set: vox-orchestrator types, vox-db, vox-ml-cli, vox-compiler.
  • If it can accept Orchestrator via a thin trait (5–10 methods: task_submit, attention_report, etc.), it becomes extractable without moving the struct.
  • Estimated gain: −5K LoC from vox-orchestrator, buying ~3 more months of headroom at the observed growth rate.

Recommended: do dei_shim/ extraction only if Rule 13 fires before C5 is staffed, as a holding action.


Prerequisite: Rule 13 must confirm vox-orchestrator has grown >15% since last release tag before starting. If the budget is still comfortable, defer.

For each module in the co-move candidate list (§3.3), run:

Terminal window
grep -rn "crate::<module>" crates/vox-orchestrator/src/orchestrator/ --include="*.rs" | wc -l

Classify each as: must-move / trait-injectable / stays-as-dep. Produce a final co-move manifest and target sizes. Update this doc with the findings.

D2 — Create vox-orchestrator-core skeleton (2h)

Section titled “D2 — Create vox-orchestrator-core skeleton (2h)”
crates/vox-orchestrator-core/
Cargo.toml (name = "vox-orchestrator-core", layer = 3, max_loc = 40_000)
src/
lib.rs
  • Add to Cargo.toml workspace members (via glob, no manual edit needed).
  • Add to layers.toml and where-things-live.md.
  • Add workspace-hack dep.
  • Add to hakari traversal-excludes if it ends up smaller than 2K LoC (it won’t — skip).

For each module in the co-move manifest:

  1. git mv crates/vox-orchestrator/src/<mod> crates/vox-orchestrator-core/src/<mod>
  2. Rewrite use crate::<mod>use crate::<mod> (stays crate:: within vox-orchestrator-core).
  3. Update vox-orchestrator/src/lib.rs to pub use vox_orchestrator_core::<mod>; for any type that’s in the public API.
  4. Add vox-orchestrator-core = { path = … } to vox-orchestrator/Cargo.toml.
  1. git mv crates/vox-orchestrator/src/orchestrator crates/vox-orchestrator-core/src/orchestrator
  2. Fix all crate:: refs within orchestrator/ (they now point to vox-orchestrator-core root — should still resolve after D3 moved the deps).
  3. Move the Orchestrator struct definition from vox-orchestrator/src/lib.rs to vox-orchestrator-core/src/lib.rs.
  4. Re-export in vox-orchestrator/src/lib.rs: pub use vox_orchestrator_core::Orchestrator;
  5. Fix any remaining compilation errors.
  • vox-orchestrator/src/runtime.rs and orch_daemon/ create Orchestrator instances — they now import from vox-orchestrator-core. Verify Orchestrator::new is accessible.
  • vox-clivox-orchestrator inversion: the known inversion does not change (still vox-clivox-orchestrator). The build-time benefit comes from vox-orchestrator now being thinner.
  • Integration tests in src/orchestrator/tests/ stay with the struct in vox-orchestrator-core.
  • cargo test -p vox-orchestrator-core must pass.
  • cargo test -p vox-orchestrator must pass.
  • cargo run -p vox-arch-check must report clean.
  • Update layers.toml: add vox-orchestrator-core entry, lower vox-orchestrator max_loc from 70K to 35K.
  • Update where-things-live.md: add vox-orchestrator-core row in L3 section.
  • Update this plan doc: mark complete, record actual post-split LoC counts.

  • vox-arch-check Rule 13 has fired for vox-orchestrator (>15% LoC growth since last tag), OR headroom has dropped below 5% (~3,500 LoC).
  • D1 dep audit is complete and the co-move manifest is finalized.
  • No other active large PR touches vox-orchestrator/src/ (merge conflicts would be severe).
  • CI is green on main before branching.

RiskLikelihoodImpactMitigation
Orchestrator struct has hidden dependencies not caught in D1MediumHigh — compile failure mid-D4D1 must use cargo check iteration, not grep alone
Re-export changes break the vox-clivox-orchestrator inversionLowMedium — arch-check flags itVerify known_inversions in layers.toml still covers the edge
dei_shim/ has transitive dep on Orchestrator impl methods (not just the type)MediumMedium — blocks dei_shim interim optionCheck with cargo check -p vox-orchestrator-core excluding dei_shim
Integration tests in orchestrator/tests/ require types from vox-orchestrator (post-split)MediumLow — test-only fixMove to vox-orchestrator tests/ as integration test using both crates
Merge conflicts if MENS/mesh work lands while Tier D is in progressHighHighCoordinate with MENS Mn-T1 timeline; Tier D should not overlap

Terminal window
# Total LoC
(Get-ChildItem crates/vox-orchestrator/src -Recurse -Filter *.rs | Get-Content | Measure-Object -Line).Lines
# Per-subdir
Get-ChildItem crates/vox-orchestrator/src -Directory | ForEach-Object {
$loc = (Get-ChildItem "$($_.FullName)" -Recurse -Filter *.rs | Get-Content | Measure-Object -Line).Lines
"$loc $($_.Name)"
} | Sort-Object { [int]($_ -split '\s+')[0] } -Descending
# agentos/ specifically
(Get-ChildItem crates/vox-orchestrator/src/agentos -Recurse -Filter *.rs | Get-Content | Measure-Object -Line).Lines