LearnNewsExamplesServices
Frontmatter
id10991
titleMigrate knowledge-base services to flat SDK boundary
stateClosed
labels
enhancementairefactoringarchitecture
assigneesneo-gemini-3-1-pro
createdAtMay 8, 2026, 10:48 PM
updatedAtMay 15, 2026, 2:47 PM
githubUrlhttps://github.com/neomjs/neo/issues/10991
authorneo-opus-4-7
commentsCount1
parentIssue10986
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 8, 2026, 11:51 PM

Migrate knowledge-base services to flat SDK boundary

Closedenhancementairefactoringarchitecture
neo-opus-4-7
neo-opus-4-7 commented on May 8, 2026, 10:48 PM

Context

Filed 2026-05-08 as M6 sub-issue 1 (knowledge-base) — first per-server SDK migration in the M6 epic #10986 sequence (KB → GH-WF → NL → MC). Selected as #1 because:

  • Smallest cloud-native server (10 services in source dir; 8 SDK-exported via ai/services.mjs aliases)
  • Validates the migration shape before tackling more complex servers (memory-core has 13+ services + lifecycle/ + managers/ subdirs)

Per parent M6 epic #10986 §The Fix and learn/agentos/v13-path.md §3 D4: services move from ai/mcp/server/knowledge-base/services/*.mjsai/services/knowledge-base/*.mjs. ai/services.mjs becomes a re-export aggregator with stable <Server>_<ServiceName> alias contracts (consumer-side unchanged). M2 BaseServer substrate (#10965) provides the extension contract; per-server Server.mjs gets its getDependentServices() override updated to import from the new SDK paths.

The Problem

KB services currently live under ai/mcp/server/knowledge-base/services/ — 10 files, 8 of which are exposed via ai/services.mjs's aliasing layer (KB_DatabaseService, KB_LifecycleService, KB_DocumentService, KB_HealthService, KB_RecorderService, KB_QueryService, KB_SearchService, KB_ChromaManager). Operator scripts, daemons, integration tests, and the KB server's own bootstrap path consume them through the prefix-namespaced re-export layer.

The friction (per parent epic #10986 framing): the on-disk shape conflates "service implementation" with "MCP transport endpoint" — services are owned by the server-specific dir rather than by the SDK boundary. This sub-issue normalizes KB to the existing ai/services/ConceptService.mjs flat-shape precedent.

The Architectural Reality

Current state (verified 2026-05-08 via ls ai/mcp/server/knowledge-base/services/ + grep on ai/services.mjs):

File SDK alias (ai/services.mjs) SDK-exported
ChromaManager.mjs KB_ChromaManager
DatabaseLifecycleService.mjs KB_LifecycleService
DatabaseService.mjs KB_DatabaseService
DocumentService.mjs KB_DocumentService
HealthService.mjs KB_HealthService
KBRecorderService.mjs KB_RecorderService
QueryService.mjs KB_QueryService
SearchService.mjs KB_SearchService
VectorService.mjs (not exported — internal helper to ChromaManager)
toolService.mjs (not exported — MCP tool router)

M2 BaseServer substrate (#10965): getDependentServices() override at ai/mcp/server/knowledge-base/Server.mjs:59 resolves service dependencies. Migration updates this override's import paths.

makeSafe() Zod-wrapping (ai/services.mjs:210-216): wraps 7 of 8 SDK-exported services with operation Zod schemas. Migration preserves the wrapping; only import paths change above the wrap.

Existing flat-shape precedent: ai/services/ConceptService.mjs (Concept Ontology) demonstrates the target shape — flat, owned by SDK boundary, not coupled to any MCP server's directory tree.

The Fix

Per-file moves (10 files):

Source path Destination path
ai/mcp/server/knowledge-base/services/ChromaManager.mjs ai/services/knowledge-base/ChromaManager.mjs
ai/mcp/server/knowledge-base/services/DatabaseLifecycleService.mjs ai/services/knowledge-base/DatabaseLifecycleService.mjs
ai/mcp/server/knowledge-base/services/DatabaseService.mjs ai/services/knowledge-base/DatabaseService.mjs
ai/mcp/server/knowledge-base/services/DocumentService.mjs ai/services/knowledge-base/DocumentService.mjs
ai/mcp/server/knowledge-base/services/HealthService.mjs ai/services/knowledge-base/HealthService.mjs
ai/mcp/server/knowledge-base/services/KBRecorderService.mjs ai/services/knowledge-base/KBRecorderService.mjs
ai/mcp/server/knowledge-base/services/QueryService.mjs ai/services/knowledge-base/QueryService.mjs
ai/mcp/server/knowledge-base/services/SearchService.mjs ai/services/knowledge-base/SearchService.mjs
ai/mcp/server/knowledge-base/services/VectorService.mjs ai/services/knowledge-base/VectorService.mjs
ai/mcp/server/knowledge-base/services/toolService.mjs ai/services/knowledge-base/toolService.mjs

Then:

  1. Update ai/services.mjs import paths (lines 28-35) — alias names (KB_*) preserved; only import paths change.
  2. Update ai/mcp/server/knowledge-base/Server.mjs getDependentServices() override and any other internal references to the old service paths.
  3. Update KB config.mjs / openapi.yaml if they reference service paths.
  4. Update internal cross-references between KB services (e.g., if VectorService imports ChromaManager, both at new paths).
  5. Remove the now-empty ai/mcp/server/knowledge-base/services/ directory.
  6. Verify operator scripts (ai:summarize-sessions, ai:run-sandman, ai:backup, ai:defrag-*) work unchanged via the preserved KB_* aliases.

Class names UNCHANGED. Service file names UNCHANGED. Only physical locations change.

Neo class-system compatibility note: Neo enforces filepath-to-className matching at setupClass time (per #10965 review correction). KB services appear to be factory-singletons (not Neo classes), so this is likely N/A — but verify during implementation. If any KB service does use Neo.setupClass() with a className matching the old path, the className must be updated alongside the path move.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
ai/services/knowledge-base/<ServiceName>.mjs paths This sub-issue + parent epic #10986 Flat SDK location for KB services None — physical move Brief note in learn/agentos/ post-M6-epic ls ai/services/knowledge-base/ confirms move; old ai/mcp/server/knowledge-base/services/ removed
ai/services.mjs KB_* re-export aliases This sub-issue Continue exposing all 8 currently-aliased services; only import paths change above the alias Aliases preserved → consumer code unchanged JSDoc on ai/services.mjs Operator scripts + tests run unchanged post-migration
KB Server.getDependentServices() override M2 BaseServer extension contract (#10965) Returns service instances imported from new SDK paths Migration touches imports only; method signature unchanged KB Server.mjs JSDoc Per-server unit specs pass
KB unit + integration coverage Existing test substrate Continue working post-migration with no AC delta Test fixture imports updated alongside service moves n/a All 21 KB unit specs pass (per #10973 baseline) + integration row green

Acceptance Criteria

  • AC1: All 10 KB service files moved from ai/mcp/server/knowledge-base/services/ to ai/services/knowledge-base/. Old directory removed.
  • AC2: ai/services.mjs continues exporting all 8 currently-aliased KB services (KB_DatabaseService, KB_LifecycleService, KB_DocumentService, KB_HealthService, KB_RecorderService, KB_QueryService, KB_SearchService, KB_ChromaManager); only import paths change.
  • AC3: ai/mcp/server/knowledge-base/Server.mjs getDependentServices() override updated to import from new SDK paths.
  • AC4: Operator scripts + daemons + tests consume KB services unchanged (no code changes required at consumer sites; aliases hold).
  • AC5: Internal cross-references between KB services updated (e.g., if VectorService imports ChromaManager, both at new paths).
  • AC6: All 21 KB unit specs pass post-migration (per #10973 PR2 evidence baseline).
  • AC7: Integration row green post-migration on the PR.
  • AC8: Healthcheck JSON shape unchanged (snapshot diff captured in PR evidence).
  • AC9: Neo class-system compatibility: if any KB service uses Neo.setupClass() with a className matching the old path, className updated to the new path (likely N/A — KB services appear factory-singleton-shape, not Neo classes — verify during implementation).
  • AC10: PR description includes a brief diff summary table (file count moved, alias-preserved count, consumer-side breakage delta — should be zero).

Out of Scope

  • makeSafe() Zod schema reshape — wrapping pattern preserved as-is; this sub-issue does not reshape the SDK contract surface.
  • Removing or renaming KB services — physical move only. Service names + class names + alias names unchanged.
  • Touching ai/mcp/server/shared/services/* — shared cross-cutting services (DestructiveOperationGuard, AuthService, TransportService, etc.) stay at the shared boundary, unaffected by this sub-issue.
  • Other Tier-1 servers — github-workflow, neural-link, memory-core migrations are separate sub-issues filed per parent epic #10986 sequencing.
  • <Server>_<ServiceName> namespace prefix collapse — preserved through M6 per parent epic Out of Scope; future ticket may reshape.
  • VectorService / toolService SDK exposure — internal-only. Migration moves them physically but does NOT expose them externally via new aliases.
  • ai/services.mjs re-organization — this sub-issue updates KB import paths only; broader SDK-aggregator restructuring (e.g., per-server sub-modules) is future scope.

Avoided Traps / Gold Standards Rejected

  • Rejected: only move SDK-exported services, leave internal helpers in old location. Splits KB services across two top-level dirs categorized by export-status; creates ongoing cognitive cost for KB authors deciding "is this internal or SDK?". Move all 10 to keep the directory unified.
  • Rejected: rename KB_* aliases to drop the prefix during migration. Breaks every operator script, daemon, and test consumer in lockstep with this PR. Reshape is future-ticket scope per parent epic.
  • Rejected: refactor the makeSafe Zod wrapping pattern alongside the move. Increases PR risk; breaks "do one thing well per PR". makeSafe stays as-is; future tickets can reshape.
  • Rejected: collapse VectorService into ChromaManager during migration. Architectural reshape, not a migration. Separate ticket if desired.
  • Rejected: add new external SDK exports for VectorService / toolService. They're internal for a reason (VectorService is a ChromaManager helper; toolService is the MCP tool-routing surface). External exposure should be a deliberate decision, not a side-effect of physical move.
  • Rejected: gradual migration via indirection layer. A re-export shim under the old paths pointing to the new ones adds complexity; clean cut-over (move files + update imports in same PR) is simpler and safer for a 10-file scope.
  • Rejected: parallel cadence with sibling M6 sub-issues (GH-WF / NL / MC). Per parent epic #10986 Avoided Traps: each migration touches ai/services.mjs import paths — concurrent PRs would merge-conflict at that file. Linear sequencing keeps the SDK aggregator under single-edit lock.

Related

  • Parent epic: #10986 — Migrate Tier-1 MCP services to flat SDK boundary (M6)
  • Predecessor milestone (cleared M6's gate): #10965 — M2 BaseServer common base class (CLOSED)
  • Sibling sub-issues (to be filed): github-workflow, neural-link, memory-core
  • Sibling SDK work: #10103 — SDK-layer config-file migration (config-file dual of M6's services migration)
  • Strategic anchor: learn/agentos/v13-path.md §3 D4 + §4 M6
  • M2 per-server migration precedent: #10973 — knowledge-base migration to BaseServer (analogous earlier per-server migration; this M6 sub-issue follows the same single-PR per-server pattern). The same Server.mjs that received the M2 BaseServer extension hooks now receives M6's getDependentServices() import-path update.

Origin Session ID: 33ed57b5-10ed-491d-8b8f-ce5f1223ec38

Retrieval Hint: query_raw_memories(query="M6 SDK migration knowledge-base services flat shape ai/services/knowledge-base KB_ aliases")

tobiu closed this issue on May 8, 2026, 11:51 PM
tobiu referenced in commit bd2def8 - "refactor(knowledge-base): migrate KB services to flat SDK boundary (#10991) (#10995) on May 8, 2026, 11:51 PM
tobiu referenced in commit dc43731 - "refactor(github-workflow): migrate services to flat SDK boundary (#10993) (#10997) on May 9, 2026, 12:35 AM