LearnNewsExamplesServices
Frontmatter
id11983
titleRemove config-template test fallbacks and legacy env hooks
stateClosed
labels
enhancementairefactoringtestingarchitecture
assigneesneo-gpt
createdAtMay 25, 2026, 6:36 PM
updatedAtMay 25, 2026, 8:05 PM
githubUrlhttps://github.com/neomjs/neo/issues/11983
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 25, 2026, 8:05 PM

Remove config-template test fallbacks and legacy env hooks

Closed v13.0.0/archive-v13-0-0-chunk-13 enhancementairefactoringtestingarchitecture
neo-gpt
neo-gpt commented on May 25, 2026, 6:36 PM

Context

Operator surfaced a concrete config-substrate cleanup gap on 2026-05-25 during the #11982 correction cycle.

Current live evidence:

  • ai/config.template.mjs still contains an idempotent Playwright-worker collision workaround around Neo.ai.Config registration:
    • comment block beginning Idempotent registration: ai/config.template.mjs and the operator-overlay...
    • const instance = Neo.ns('Neo.ai.Config') ?? Neo.setupClass(Config);
  • ai/mcp/server/memory-core/config.template.mjs still defines applyLegacyEnv() with fallback support for SSE_PORT, NEO_CHROMA_EMBEDDING_PROVIDER, NEO_KB_CHROMA_HOST, and NEO_KB_CHROMA_PORT.
  • ai/mcp/server/knowledge-base/config.template.mjs still defines applyLegacyEnv() with fallback support for SSE_PORT and NEO_MEMORY_CORE_DB_PATH.
  • Exact grep also shows many Playwright unit tests import repo-local gitignored config.mjs files directly instead of the tracked templates.

Duplicate sweep:

  • #10823 is the closed predecessor for Phase 1 legacy alias deletion. It removed earlier helper-level aliases, but the current template-level applyLegacyEnv() methods still exist, so this is residual cleanup rather than a duplicate.
  • Live open-issue search for config.template applyLegacyEnv Neo.ai.Config returned no open duplicate.
  • Knowledge Base semantic search was attempted but unavailable because the local embedding endpoint refused connection.

The Problem

The current shape preserves two wrong testing and compatibility escape hatches:

  1. The top-level ai/config.template.mjs masks test pollution by reusing an existing Neo.ai.Config singleton when both ai/config.template.mjs and the operator overlay ai/config.mjs load in the same Playwright worker. That workaround hides the real contract violation: tests must not import the gitignored operator overlay when they need canonical defaults.

  2. Memory Core and Knowledge Base config templates still carry legacy env fallback methods after the config cleanup line already moved to canonical env names. These methods reintroduce alias semantics and keep old names alive inside the source of truth.

Both issues make cloud-deployment config behavior harder to reason about. The template should be the test source of truth; the gitignored overlay is operator-local runtime state, not a unit-test fixture.

The Architectural Reality

  • ai/config.template.mjs owns the top-level Tier-1 AI config singleton Neo.ai.Config.
  • ai/config.mjs is gitignored operator overlay generated from the template by initServerConfigs.mjs; it is not safe test input because it can drift per checkout.
  • ai/mcp/server/memory-core/config.template.mjs and ai/mcp/server/knowledge-base/config.template.mjs are tracked per-server templates and should expose canonical env bindings only.
  • Playwright unit workers reuse process-global Neo namespaces, so importing both a template and a gitignored overlay can collide under unitTestMode. The fix is import discipline, not idempotent singleton reuse.
  • Closed #10823 established the cleanup direction: no released-version compatibility burden for these legacy aliases.

The Fix

  • In ai/config.template.mjs, delete the idempotent registration comment and replace the fallback registration with strict class setup:
    • const instance = Neo.setupClass(Config);
  • Audit Playwright unit tests and fixtures so canonical config defaults come from tracked config.template.mjs, not repo-local gitignored config.mjs overlays.
  • Delete applyLegacyEnv() from both:
    • ai/mcp/server/memory-core/config.template.mjs
    • ai/mcp/server/knowledge-base/config.template.mjs
  • Remove or rewrite tests that assert legacy fallback behavior.
  • Add/adjust regression coverage proving template imports are deterministic and no longer need the Neo.ns(...) ?? collision workaround.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
ai/config.template.mjs class registration Operator directive + Neo unitTestMode namespace discipline Strict Neo.setupClass(Config); duplicate imports should fail loudly instead of silently reusing stale singleton state None PR body notes test import contract Unit/import audit
Playwright unit config imports Operator directive: tests use templates only Tests needing canonical defaults import tracked config.template.mjs, never repo-local gitignored config.mjs Synthetic temp config.mjs files may exist only inside tests for config-copy tooling, not as runtime config imports Test comments where needed rg "config.mjs" test/playwright/unit/ai reduced to allowed tooling fixtures only
MC/KB applyLegacyEnv() #10823 cleanup direction + operator directive Delete template-level legacy env fallback hooks None; canonical env names only PR body migration note if needed Unit coverage no longer references legacy env vars

Decision Record Impact

Aligned with the accepted #10822 / #10823 config hard-cut direction. No ADR amendment expected.

Acceptance Criteria

  • ai/config.template.mjs no longer contains the idempotent registration comment or Neo.ns('Neo.ai.Config') ?? Neo.setupClass(Config).
  • Top-level config template exports through strict Neo.setupClass(Config) registration.
  • Playwright unit tests that need canonical config defaults import tracked config.template.mjs, not repo-local gitignored config.mjs overlays.
  • Any remaining config.mjs mentions in unit tests are limited to synthetic temp files or tests whose subject is config-file copying/migration, not runtime default consumption.
  • applyLegacyEnv() is deleted from ai/mcp/server/memory-core/config.template.mjs.
  • applyLegacyEnv() is deleted from ai/mcp/server/knowledge-base/config.template.mjs.
  • Legacy env fallback assertions for SSE_PORT, NEO_CHROMA_EMBEDDING_PROVIDER, NEO_KB_CHROMA_HOST, NEO_KB_CHROMA_PORT, and NEO_MEMORY_CORE_DB_PATH are removed or rewritten to canonical-name expectations.
  • Focused unit coverage passes for the changed config templates and affected tests.
  • rg "applyLegacyEnv|NEO_KB_CHROMA_HOST|NEO_KB_CHROMA_PORT|NEO_CHROMA_EMBEDDING_PROVIDER|SSE_PORT|NEO_MEMORY_CORE_DB_PATH" ai/mcp/server/{memory-core,knowledge-base}/config.template.mjs test/playwright/unit/ai shows no remaining legacy fallback contract except historical issue/discussion resources.

Out Of Scope

  • Deleting gitignored runtime config.mjs overlays from operator checkouts.
  • Changing production services that intentionally import their runtime config.mjs overlay.
  • Reworking the entire three-tier config architecture.
  • Cleaning unrelated config templates such as GitHub Workflow or Neural Link unless they directly block the ACs above.

Avoided Traps

  • Do not replace Neo.ns(...) ?? Neo.setupClass(...) with another collision-suppression helper. The collision is the signal that tests imported the wrong config layer.
  • Do not preserve legacy env aliases for backwards compatibility. This is unreleased v13 Agent OS substrate and #10823 already established the hard-cut direction.
  • Do not broaden this into a cloud-deployment config epic. This is a narrow residual cleanup ticket.

Related

  • Predecessor cleanup: #10823
  • Parent config cleanup direction: #10822
  • Operator-surfaced during #11982 correction cycle.

Retrieval Hint: "ai config template strict setupClass tests use config.template only delete applyLegacyEnv memory-core knowledge-base"

tobiu referenced in commit f733ff5 - "fix(ai): remove config-template legacy fallbacks (#11983) (#11984) on May 25, 2026, 8:05 PM
tobiu closed this issue on May 25, 2026, 8:05 PM