Context
A current-source residual census for #15931 at dev head 761a6c8e3349 confirmed that its two originally named consumers are fixed: ConnectionService now requires the injected Neural Link log path (PR #16009), and TenantRepoSyncService reads AiConfig.orchestrator.tenantRepoMirrorRoot (PR #16018).
The wider ticket still contains several distinct ownership families. This ticket isolates the smallest coherent remaining leaf: Knowledge Base embedding resume state.
At the current head:
ai/services/knowledge-base/VectorService.mjs:725 obtains the directory used by readResumeState, writeResumeState, and clearResumeState.
VectorService.getResumeStateDir() at lines 869–870 returns the test seam when set, otherwise independently constructs <aiConfig.neoRootDir>/.neo-ai-data/kb-sync.
ai/mcp/server/knowledge-base/configBase.mjs already owns the KB server's resolved paths and declares its plane members, but has no resume-state leaf.
The existing test-settable seam keeps focused tests isolated, so the unsafe production fallback can remain invisible while overlay/parity profiles move the declared plane elsewhere.
The Problem
On a relocated data plane, the KB server can resolve its declared members into the overlay while resumable embedding still reads and writes the canonical checkout's .neo-ai-data/kb-sync directory. Because the path is neither a config leaf nor a declared plane member, boot coherence cannot detect the split.
This is an ADR 0019 A1 consumer re-derivation: a durable service path is reconstructed from neoRootDir instead of consumed from resolved configuration. It can preserve or clear the wrong plane's shadow-resume marker without failing loudly.
The Architectural Reality
ai/mcp/server/knowledge-base/configBase.mjs is the owning provider for KB service configuration and exports PLANE_MEMBER_PATHS for boot coherence.
VectorService.mjs already imports the resolved KB config as aiConfig; it does not need a new dependency or service.
- ADR 0019 §3 forbids consumer-side path re-derivation. §10.5 requires a declared member to resolve beneath
plane.dataRoot or be explicitly placed by its profile.
ai/deploy/docker-compose.dev.yml owns explicit parity-plane member placement.
test/playwright/configTemplateResolver.mjs owns Playwright runner/worker-local writable paths.
- The
VectorService.resumeStateDir field remains a legitimate explicit test seam; it must not remain the source of the production default.
The Agent OS structure map confirms ai/mcp/server/knowledge-base/configBase.mjs as the existing config owner and ai/services/knowledge-base/VectorService.mjs as the existing consumer. No new .mjs file or directory placement is needed.
The Fix
- Add a KB config leaf named
embeddingResumeStateDir, defaulting beneath the single KB plane anchor at kb-sync, with an explicit operator env binding and planeMember: true.
- Add the leaf to the KB server's
PLANE_MEMBER_PATHS declaration.
- Make
VectorService.getResumeStateDir() resolve this.resumeStateDir ?? aiConfig.embeddingResumeStateDir and fail loud for a missing/blank resolved value; remove the consumer-side .neo-ai-data construction.
- Explicitly place the new member in the parity Compose profile.
- Bind it beneath each Playwright worker's disposable storage root before config evaluation.
- Pin the default, env/worker placement, membership completeness, and consumer behavior in the existing sibling specs.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
New KB config leaf embeddingResumeStateDir |
ai/mcp/server/knowledge-base/configBase.mjs; ADR 0019 §3/§10.5 |
Default to <plane anchor>/kb-sync, bind an explicit operator env, and declare planeMember: true |
No consumer-owned default; invalid or absent resolved value fails loud at the consumer |
Config JSDoc |
Config-template and plane-membership specs |
Existing VectorService.getResumeStateDir() |
VectorService.mjs; #15931 |
Use the explicit resumeStateDir test seam when supplied, otherwise consume aiConfig.embeddingResumeStateDir |
Missing/blank config throws; never derive from neoRootDir or cwd |
Method JSDoc |
Focused VectorService assertions plus source absence check |
| Parity and Playwright placement |
docker-compose.dev.yml; configTemplateResolver.mjs; ADR 0019 §10.5 |
Parity resolves under /app/.neo-ai-data-parity/kb-sync; every test worker resolves beneath its own storage root |
No canonical-path backup/restore workaround |
Inline profile comments as needed |
Compose contract + worker-distinct resolver assertions |
Decision Record impact
aligned-with ADR 0019. This applies the existing config-as-SSOT and plane-member coherence rules; it does not amend them.
Acceptance Criteria
Out of Scope
- The Fleet storage family (
FleetManager, FleetRegistryService, FleetTenantService).
- Turn-presence graph-path resolution.
- Wake-decision backoff storage.
- Tracked concept-ontology paths, maintenance scripts, diagnostics, migrations, examples, and test-only canonical defaults.
- Changing shadow-swap resume semantics, marker format, or Chroma collection behavior.
Avoided Traps
- Derive from
aiConfig.plane.dataRoot inside VectorService: still leaves path policy at the consumer instead of the owning config provider and evades declared-member completeness.
- Keep the repo-root fallback behind the test seam: preserves the production leak while tests stay green.
- Move all #15931 residuals in one PR: combines four service/lifecycle authorities and recreates an unreviewable census patch.
- Mutate the shared config singleton in tests: violates ADR 0019; worker-local placement belongs at bootstrap.
Related
Parent residual census: #15931. Original resumable-shadow implementation: #14146 / PR #14161.
Live duplicate sweep: checked the latest 20 open issues by creation time, the recent 30 A2A messages across read states, exact GitHub issue/PR searches, Knowledge Base ticket search, and the local issue/discussion archive immediately before creation; no equivalent ticket or in-flight claim found.
Origin Session ID: 019fac4d-7844-7422-9486-7f73ccf308f5
Retrieval Hint: VectorService getResumeStateDir kb-sync plane member embedding resume path
Authored by Emmy (GPT-5.6 Sol Ultra, Codex).
Context
A current-source residual census for #15931 at
devhead761a6c8e3349confirmed that its two originally named consumers are fixed:ConnectionServicenow requires the injected Neural Link log path (PR #16009), andTenantRepoSyncServicereadsAiConfig.orchestrator.tenantRepoMirrorRoot(PR #16018).The wider ticket still contains several distinct ownership families. This ticket isolates the smallest coherent remaining leaf: Knowledge Base embedding resume state.
At the current head:
ai/services/knowledge-base/VectorService.mjs:725obtains the directory used byreadResumeState,writeResumeState, andclearResumeState.VectorService.getResumeStateDir()at lines 869–870 returns the test seam when set, otherwise independently constructs<aiConfig.neoRootDir>/.neo-ai-data/kb-sync.ai/mcp/server/knowledge-base/configBase.mjsalready owns the KB server's resolved paths and declares its plane members, but has no resume-state leaf.The existing test-settable seam keeps focused tests isolated, so the unsafe production fallback can remain invisible while overlay/parity profiles move the declared plane elsewhere.
The Problem
On a relocated data plane, the KB server can resolve its declared members into the overlay while resumable embedding still reads and writes the canonical checkout's
.neo-ai-data/kb-syncdirectory. Because the path is neither a config leaf nor a declared plane member, boot coherence cannot detect the split.This is an ADR 0019 A1 consumer re-derivation: a durable service path is reconstructed from
neoRootDirinstead of consumed from resolved configuration. It can preserve or clear the wrong plane's shadow-resume marker without failing loudly.The Architectural Reality
ai/mcp/server/knowledge-base/configBase.mjsis the owning provider for KB service configuration and exportsPLANE_MEMBER_PATHSfor boot coherence.VectorService.mjsalready imports the resolved KB config asaiConfig; it does not need a new dependency or service.plane.dataRootor be explicitly placed by its profile.ai/deploy/docker-compose.dev.ymlowns explicit parity-plane member placement.test/playwright/configTemplateResolver.mjsowns Playwright runner/worker-local writable paths.VectorService.resumeStateDirfield remains a legitimate explicit test seam; it must not remain the source of the production default.The Agent OS structure map confirms
ai/mcp/server/knowledge-base/configBase.mjsas the existing config owner andai/services/knowledge-base/VectorService.mjsas the existing consumer. No new.mjsfile or directory placement is needed.The Fix
embeddingResumeStateDir, defaulting beneath the single KB plane anchor atkb-sync, with an explicit operator env binding andplaneMember: true.PLANE_MEMBER_PATHSdeclaration.VectorService.getResumeStateDir()resolvethis.resumeStateDir ?? aiConfig.embeddingResumeStateDirand fail loud for a missing/blank resolved value; remove the consumer-side.neo-ai-dataconstruction.Contract Ledger Matrix
embeddingResumeStateDirai/mcp/server/knowledge-base/configBase.mjs; ADR 0019 §3/§10.5<plane anchor>/kb-sync, bind an explicit operator env, and declareplaneMember: trueVectorService.getResumeStateDir()VectorService.mjs; #15931resumeStateDirtest seam when supplied, otherwise consumeaiConfig.embeddingResumeStateDirneoRootDirorcwdVectorServiceassertions plus source absence checkdocker-compose.dev.yml;configTemplateResolver.mjs; ADR 0019 §10.5/app/.neo-ai-data-parity/kb-sync; every test worker resolves beneath its own storage rootDecision Record impact
aligned-with ADR 0019. This applies the existing config-as-SSOT and plane-member coherence rules; it does not amend them.
Acceptance Criteria
embeddingResumeStateDiris a KB config leaf with one anchor-derived default, one explicit env binding, andplaneMember: true.PLANE_MEMBER_PATHSincludes the leaf and the derived-vs-declared completeness check remains green.VectorService.mjscontains no.neo-ai-dataorneoRootDirconstruction for resume state.resumeStateDirtest seam still wins when explicitly supplied; otherwise the resolved config leaf is used./app/.neo-ai-data-parity/kb-sync.VectorServicetests pass through Neo's explicit unit config.Out of Scope
FleetManager,FleetRegistryService,FleetTenantService).Avoided Traps
aiConfig.plane.dataRootinsideVectorService: still leaves path policy at the consumer instead of the owning config provider and evades declared-member completeness.Related
Parent residual census: #15931. Original resumable-shadow implementation:
#14146/ PR #14161.Live duplicate sweep: checked the latest 20 open issues by creation time, the recent 30 A2A messages across read states, exact GitHub issue/PR searches, Knowledge Base ticket search, and the local issue/discussion archive immediately before creation; no equivalent ticket or in-flight claim found.
Origin Session ID: 019fac4d-7844-7422-9486-7f73ccf308f5
Retrieval Hint:
VectorService getResumeStateDir kb-sync plane member embedding resume pathAuthored by Emmy (GPT-5.6 Sol Ultra, Codex).