LearnNewsExamplesServices
Frontmatter
id16174
titleKB resume markers bypass the resolved data plane
stateClosed
labels
bugaiarchitecture
assigneesneo-gpt-emmy
createdAtJul 30, 2026, 2:53 PM
updatedAtJul 30, 2026, 3:38 PM
githubUrlhttps://github.com/neomjs/neo/issues/16174
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 30, 2026, 3:38 PM

KB resume markers bypass the resolved data plane

Closed Backlog/active-chunk-11 bugaiarchitecture
neo-gpt-emmy
neo-gpt-emmy commented on Jul 30, 2026, 2:53 PM

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

  1. 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.
  2. Add the leaf to the KB server's PLANE_MEMBER_PATHS declaration.
  3. 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.
  4. Explicitly place the new member in the parity Compose profile.
  5. Bind it beneath each Playwright worker's disposable storage root before config evaluation.
  6. 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

  • embeddingResumeStateDir is a KB config leaf with one anchor-derived default, one explicit env binding, and planeMember: true.
  • KB PLANE_MEMBER_PATHS includes the leaf and the derived-vs-declared completeness check remains green.
  • VectorService.mjs contains no .neo-ai-data or neoRootDir construction for resume state.
  • The existing resumeStateDir test seam still wins when explicitly supplied; otherwise the resolved config leaf is used.
  • A missing or blank resolved config value fails loud rather than falling back to the canonical checkout.
  • The parity Compose profile places the member under /app/.neo-ai-data-parity/kb-sync.
  • Playwright runner and worker scopes place the member beneath their disposable storage roots, with distinct worker paths proven.
  • Focused KB config, plane-coherence, resolver, and VectorService tests pass through Neo's explicit unit config.
  • AiConfig mutation lint remains green; tests do not mutate the shared config singleton.

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).

tobiu referenced in commit 1e7ed23 - "feat(ai): declare KB resume state as a plane member (#16174) (#16177)" on Jul 30, 2026, 3:38 PM
tobiu closed this issue on Jul 30, 2026, 3:38 PM