Priority: HIGH (operator-directed, 2026-08-08) — the debt is measured to be actively compounding: PR #16675 added two fresh ai/ → src/ai/fleet import edges today (see The Problem). Every week of deferral raises the relocation cost.
Context
Operator challenge (2026-08-08, verbatim core): "src/ai/fleet is pure debt... neo has the body => src folder => frontend realm and core, meant to run as ESM inside browsers. and there is the brain => ai folder => nodejs scripts... we have apps/agentos as the home for the FM frontend. we did NOT name it fleet on purpose, since it will get enhanced to an agent harness (v14 project home), as well as showing diagnostics for the agent os... right now, the neo body contains mcp server definitions inside the fleet folder, and this just feels wrong."
The steward verification sweep (same day) confirmed the debt and sharpened its class; the design disposition is on public record as a post-fold delta note on D#16652 (DC_kwDODSospM4BEcpX): a module can be plane-clean and category-wrong. These six files pass D#16652's converged closure doctrine (pure, store-free, genuinely dual-consumed — a guard would derive them shared and stay green) and are still misplaced on the axis that doctrine deliberately does not govern: what the code IS (@neo-opus-grace's axis distinction, D#16652 fold). The engine tree (src/ — what browsers execute as the framework) is carrying Agent-OS product vocabulary.
The Problem
Inventory (measured 2026-08-08, session-verified):
src/ai/fleet/mcpServers.mjs 191 loc MCP catalog + sparse-override validation + REMOTE_MCP_CREDENTIAL_ENV_VAR
src/ai/fleet/fleetCockpitStatus.mjs 287 loc cockpit status envelope constructors + source registry
src/ai/fleet/harnessTypes.mjs 52 loc harness-type registry (defineAgent validation + picker labels)
src/ai/fleet/fleetWireMethods.mjs 72 loc the bridge wire-method contract list
src/ai/fleet/installFleetBridge.mjs 148 loc browser boot glue (apps/agentos/app.mjs installs it)
src/ai/fleet/createFleetRegistryBridge.mjs 38 loc browser bridge factory
788 loc
- All six are transitively dual-consumed: browser side via
apps/agentos/app.mjs boot + view modules + two apps/agentos/config/ thin re-export fronts; node side via 7+ ai/services/fleet/* + ai/scripts/fleet/* importers.
- The accretion is live: PR #16675 (open, 2026-08-08) adds
import {REMOTE_MCP_CREDENTIAL_ENV_VAR} from '../../../src/ai/fleet/mcpServers.mjs' into ai/mcp/client/Client.mjs + ai/mcp/client/config.mjs. The author did the right thing under the current layout — importing the one authority beats duplicating a credential env-var name. The layout makes correct behavior grow the debt: a credential env-var name for the Brain's canonical MCP client now lives in the Body engine tree.
- The app side already signals the correct ownership:
apps/agentos/config/mcpServers.mjs + config/harnessTypes.mjs exist purely as re-export fronts "so app views keep their conventional config import path" — the product surface already wants this vocabulary as app config.
- The v14 trajectory (operator, same challenge):
apps/agentos is deliberately named for what it becomes — the agent-harness project home + Agent OS diagnostics surface. Its vocabulary belongs to it, not to the engine namespace every framework consumer reads.
The Architectural Reality
- Realm doctrine (ADR 0018, two hemispheres):
src/ = Body engine (browser ESM); ai/ = Brain (Node). src/ai/* has one legitimate citizen class: the extended-NL Body-side organs that RUN in the App-Worker (WriteGuard, LockRegistry, TransactionService, client/* — the #13056 in-heap half). The fleet/ subfolder is not that class; it is FM product contract vocabulary that rode in on the folder name.
- The boundary that must not invert (D#16652 fold, measured):
src → ai = 0 (lint-checkable), ai → src = 325. This ticket REDUCES the ai→src edge count and touches the src→ai invariant not at all.
- The proven parity pattern: this repo already solves same-vocabulary-two-surfaces without shared imports —
ai/scripts/lint/lint-config-template-ssot.mjs (config-leaf-parity snapshot) and ai/scripts/lint/lint-openapi-service-parity.mjs. Drift = red CI, authority stays single.
- Operable-cold (the #14560 product principle): the cockpit renders labels/pickers/state names with the fleet server down (#15284's banner). A wire-only contract would break this; the app-side render vocabulary must stay importable in the browser.
- The wire already exists:
FleetControlBridge over the authenticated fleet HTTP ingress (#15320, single-viewer) serves the full catalog at runtime; the browser needs local vocabulary, not local authority.
The Fix
Dissolve src/ai/fleet/ entirely. Realm assignments (exact filenames finalized in the PR under structural-pre-flight; both targets have exact sibling precedents):
- Authority →
ai/services/fleet/ (48-file owning folder, structure-map-verified): the MCP catalog + sparse-override validation + REMOTE_MCP_CREDENTIAL_ENV_VAR, the harness-type registry (validation half), the status-envelope constructors, and the wire-method list's validating side. The services that validate the vocabulary own it.
- Render vocabulary →
apps/agentos/config/: the existing thin fronts become the real files — labels, picker entries, state names ONLY; zero validation logic. This is the operable-cold local surface and the v14-trajectory home.
- Browser boot glue →
apps/agentos/: installFleetBridge + createFleetRegistryBridge are FM-product boot modules booted by apps/agentos/app.mjs; they move to the app that boots them (exact placement per structural-pre-flight; their unit specs move along).
- Parity lint binds every dual vocabulary (catalog keys/labels/defaults, harness types, wire methods, status states) in the proven snapshot style: one authority, one render copy, drift is red.
- All importers updated (~25 sites measured across
ai/, apps/, test/). PR #16675 coordination: whichever merges first, the other rebases one import path — no serialization, coordinated with @neo-gpt via A2A.
Contract Ledger Matrix
| Target Surface |
Source of Authority (today → after) |
Proposed Behavior |
Fallback |
Docs |
Evidence |
MCP_SERVERS catalog + sparse-override validation + REMOTE_MCP_CREDENTIAL_ENV_VAR |
src/ai/fleet/mcpServers.mjs → ai/services/fleet/ module |
Values byte-identical; node importers repoint; browser reads labels from apps/agentos/config/ |
none needed (mechanical move) |
JSDoc names the parity contract on both sides |
parity snapshot + unit scope green |
| Harness-type registry |
src/ai/fleet/harnessTypes.mjs → split per above |
defineAgent/configureAgent validate Brain-side; pickers render app-side |
none |
same |
same |
| Cockpit status envelopes |
src/ai/fleet/fleetCockpitStatus.mjs → constructors Brain-side; state-name vocabulary app-side |
Wire carries instances (already does); app consumers (sourceHealth, nameSlot) read app-side vocabulary |
none |
same |
cockpit boots live + cold |
| Wire-method contract list |
src/ai/fleet/fleetWireMethods.mjs → authority Brain-side; browser stub list app-side |
dispatchFleetRequest validates against authority; bridge builds proxies from app-side list; parity lint binds the two |
none |
same |
parity lint red-proven once |
| Bridge boot glue |
src/ai/fleet/installFleetBridge.mjs + createFleetRegistryBridge.mjs → apps/agentos/ |
Unchanged behavior; specs move |
none |
same |
unit scope green |
Decision Record impact
aligned-with ADR 0018 (two-hemisphere realm doctrine). Informs D#16652's pending Decision Record: the category axis (what code is) is distinct from the executability axis (where a process runs) — recorded there at DC_kwDODSospM4BEcpX. This ticket is deliberately not a graduation of D#16652 (independent premise: operator directive + measured accretion; scope disjoint from the barrel/plane fold).
Acceptance Criteria
Out of Scope
- The D#16652 host/cloud SDK barrel split (Option B) — different axis, its own Decision Record, its own cut.
- #16645 (devFleetServer env re-derivation beside the leaves) — adjacent ADR-0019 cleanup, separately claimed.
- Any CHANGE to vocabulary content (labels, defaults, keys) — this is relocation, byte-identical.
- The v14 diagnostics/harness surfaces the operator pictures for
apps/agentos — this ticket clears their ground, nothing more.
Avoided Traps
apps/ as authority — ai/ services importing from apps/ inverts ownership (services outlive UIs); rejected.
- A new
shared/ tree — D#16652's A-row lesson: a second importable place is a second thing to import wrongly; and inventing a third realm has zero sibling precedent. Rejected.
- Wire-only (no local vocabulary) — breaks operable-cold (#14560 product principle, #15284's banner). Rejected.
- Keep
src/ai/fleet + add a guard — the G-closure doctrine would derive these files shared and stay green forever; the category error would be legalized, and the engine tree would keep accreting product vocabulary behind a green guard. Rejected — this is the exact failure mode the D#16652 delta note warns the Decision Record about.
- The npm-boundary argument — self-falsified during verification (
.npmignore ships ai/ too); deliberately NOT load-bearing here, recorded so no successor re-derives it.
Creation-gate record
Live latest-open sweep: latest 20 open issues checked 2026-08-08T11:42Z — no equivalent (nearest neighbor #16645, adjacent-distinct, linked). Local archive grep: mentions only, no relocation ticket. A2A in-flight sweep: Memory Core unavailable at create time (container flap); equivalence: this claim's earliest durable timestamps are 11:24Z (D#16652 delta note announcing "ticket follows the standard gates") + 11:25Z (all-agents broadcast) — any competing claim post-dates both and resolves via first-claim-timestamp-wins. Structure-map gate: ai/services/fleet (48 files) confirmed owning folder; app-side siblings are the existing apps/agentos/config/ fronts.
Related
- #14560 (FM cockpit epic — steward context) · #13015 (FM service spine)
- PR #16675 (the live accretion example; coordination, not blockage)
- #16645 (adjacent devFleetServer config cleanup, same file neighborhood)
- D#16652 (the plane doctrine this aligns beside; delta note
DC_kwDODSospM4BEcpX)
Origin Session ID: b0aa9931-78c8-4723-bd11-683b99bd3a36
Retrieval Hint: "src/ai/fleet dissolution parity lint realm placement category axis"
Priority: HIGH (operator-directed, 2026-08-08) — the debt is measured to be actively compounding: PR #16675 added two fresh
ai/ → src/ai/fleetimport edges today (see The Problem). Every week of deferral raises the relocation cost.Context
Operator challenge (2026-08-08, verbatim core): "src/ai/fleet is pure debt... neo has the body => src folder => frontend realm and core, meant to run as ESM inside browsers. and there is the brain => ai folder => nodejs scripts... we have apps/agentos as the home for the FM frontend. we did NOT name it fleet on purpose, since it will get enhanced to an agent harness (v14 project home), as well as showing diagnostics for the agent os... right now, the neo body contains mcp server definitions inside the fleet folder, and this just feels wrong."
The steward verification sweep (same day) confirmed the debt and sharpened its class; the design disposition is on public record as a post-fold delta note on D#16652 (
DC_kwDODSospM4BEcpX): a module can be plane-clean and category-wrong. These six files pass D#16652's converged closure doctrine (pure, store-free, genuinely dual-consumed — a guard would derive themsharedand stay green) and are still misplaced on the axis that doctrine deliberately does not govern: what the code IS (@neo-opus-grace's axis distinction, D#16652 fold). The engine tree (src/— what browsers execute as the framework) is carrying Agent-OS product vocabulary.The Problem
Inventory (measured 2026-08-08, session-verified):
src/ai/fleet/mcpServers.mjs 191 loc MCP catalog + sparse-override validation + REMOTE_MCP_CREDENTIAL_ENV_VAR src/ai/fleet/fleetCockpitStatus.mjs 287 loc cockpit status envelope constructors + source registry src/ai/fleet/harnessTypes.mjs 52 loc harness-type registry (defineAgent validation + picker labels) src/ai/fleet/fleetWireMethods.mjs 72 loc the bridge wire-method contract list src/ai/fleet/installFleetBridge.mjs 148 loc browser boot glue (apps/agentos/app.mjs installs it) src/ai/fleet/createFleetRegistryBridge.mjs 38 loc browser bridge factory 788 locapps/agentos/app.mjsboot + view modules + twoapps/agentos/config/thin re-export fronts; node side via 7+ai/services/fleet/*+ai/scripts/fleet/*importers.import {REMOTE_MCP_CREDENTIAL_ENV_VAR} from '../../../src/ai/fleet/mcpServers.mjs'intoai/mcp/client/Client.mjs+ai/mcp/client/config.mjs. The author did the right thing under the current layout — importing the one authority beats duplicating a credential env-var name. The layout makes correct behavior grow the debt: a credential env-var name for the Brain's canonical MCP client now lives in the Body engine tree.apps/agentos/config/mcpServers.mjs+config/harnessTypes.mjsexist purely as re-export fronts "so app views keep their conventional config import path" — the product surface already wants this vocabulary as app config.apps/agentosis deliberately named for what it becomes — the agent-harness project home + Agent OS diagnostics surface. Its vocabulary belongs to it, not to the engine namespace every framework consumer reads.The Architectural Reality
src/= Body engine (browser ESM);ai/= Brain (Node).src/ai/*has one legitimate citizen class: the extended-NL Body-side organs that RUN in the App-Worker (WriteGuard,LockRegistry,TransactionService,client/*— the #13056 in-heap half). Thefleet/subfolder is not that class; it is FM product contract vocabulary that rode in on the folder name.src → ai = 0(lint-checkable),ai → src = 325. This ticket REDUCES the ai→src edge count and touches the src→ai invariant not at all.ai/scripts/lint/lint-config-template-ssot.mjs(config-leaf-parity snapshot) andai/scripts/lint/lint-openapi-service-parity.mjs. Drift = red CI, authority stays single.FleetControlBridgeover the authenticated fleet HTTP ingress (#15320, single-viewer) serves the full catalog at runtime; the browser needs local vocabulary, not local authority.The Fix
Dissolve
src/ai/fleet/entirely. Realm assignments (exact filenames finalized in the PR understructural-pre-flight; both targets have exact sibling precedents):ai/services/fleet/(48-file owning folder, structure-map-verified): the MCP catalog + sparse-override validation +REMOTE_MCP_CREDENTIAL_ENV_VAR, the harness-type registry (validation half), the status-envelope constructors, and the wire-method list's validating side. The services that validate the vocabulary own it.apps/agentos/config/: the existing thin fronts become the real files — labels, picker entries, state names ONLY; zero validation logic. This is the operable-cold local surface and the v14-trajectory home.apps/agentos/:installFleetBridge+createFleetRegistryBridgeare FM-product boot modules booted byapps/agentos/app.mjs; they move to the app that boots them (exact placement per structural-pre-flight; their unit specs move along).ai/,apps/,test/). PR #16675 coordination: whichever merges first, the other rebases one import path — no serialization, coordinated with @neo-gpt via A2A.Contract Ledger Matrix
MCP_SERVERScatalog + sparse-override validation +REMOTE_MCP_CREDENTIAL_ENV_VARsrc/ai/fleet/mcpServers.mjs→ai/services/fleet/moduleapps/agentos/config/src/ai/fleet/harnessTypes.mjs→ split per abovedefineAgent/configureAgentvalidate Brain-side; pickers render app-sidesrc/ai/fleet/fleetCockpitStatus.mjs→ constructors Brain-side; state-name vocabulary app-sidesourceHealth,nameSlot) read app-side vocabularysrc/ai/fleet/fleetWireMethods.mjs→ authority Brain-side; browser stub list app-sidedispatchFleetRequestvalidates against authority; bridge builds proxies from app-side list; parity lint binds the twosrc/ai/fleet/installFleetBridge.mjs+createFleetRegistryBridge.mjs→apps/agentos/Decision Record impact
aligned-with ADR 0018(two-hemisphere realm doctrine). Informs D#16652's pending Decision Record: the category axis (what code is) is distinct from the executability axis (where a process runs) — recorded there atDC_kwDODSospM4BEcpX. This ticket is deliberately not a graduation of D#16652 (independent premise: operator directive + measured accretion; scope disjoint from the barrel/plane fold).Acceptance Criteria
src/ai/fleet/no longer exists;grep -rn "src/ai/fleet" src/ apps/ ai/ test/ buildScripts/→ 0 hits (archived content exempt).src/ai/contains only the extended-NL Body-side organs (WriteGuard, LockRegistry, TransactionService, client/*, admission helpers) — zero FM product vocabulary.ai/services/fleet/with JSDoc naming the parity contract; render vocabulary underapps/agentos/config/with zero validation logic.Out of Scope
apps/agentos— this ticket clears their ground, nothing more.Avoided Traps
apps/as authority —ai/services importing fromapps/inverts ownership (services outlive UIs); rejected.shared/tree — D#16652's A-row lesson: a second importable place is a second thing to import wrongly; and inventing a third realm has zero sibling precedent. Rejected.src/ai/fleet+ add a guard — the G-closure doctrine would derive these filessharedand stay green forever; the category error would be legalized, and the engine tree would keep accreting product vocabulary behind a green guard. Rejected — this is the exact failure mode the D#16652 delta note warns the Decision Record about..npmignoreshipsai/too); deliberately NOT load-bearing here, recorded so no successor re-derives it.Creation-gate record
Live latest-open sweep: latest 20 open issues checked 2026-08-08T11:42Z — no equivalent (nearest neighbor #16645, adjacent-distinct, linked). Local archive grep: mentions only, no relocation ticket. A2A in-flight sweep: Memory Core unavailable at create time (container flap); equivalence: this claim's earliest durable timestamps are 11:24Z (D#16652 delta note announcing "ticket follows the standard gates") + 11:25Z (all-agents broadcast) — any competing claim post-dates both and resolves via first-claim-timestamp-wins. Structure-map gate:
ai/services/fleet(48 files) confirmed owning folder; app-side siblings are the existingapps/agentos/config/fronts.Related
DC_kwDODSospM4BEcpX)Origin Session ID: b0aa9931-78c8-4723-bd11-683b99bd3a36 Retrieval Hint: "src/ai/fleet dissolution parity lint realm placement category axis"