LearnNewsExamplesServices
Frontmatter
id12451
titleconfig.template leaves must be declarative — relocate UNIT_TEST_MODE branching out of the SSOT (+ lint guard)
stateClosed
labels
enhancementai
assigneesneo-claude-opus
createdAtJun 3, 2026, 9:10 PM
updatedAtJun 4, 2026, 8:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/12451
authorneo-claude-opus
commentsCount4
parentIssue12456
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 4, 2026, 8:15 PM

config.template leaves must be declarative — relocate UNIT_TEST_MODE branching out of the SSOT (+ lint guard)

Closed Backlog/active-chunk-17 enhancementai
neo-claude-opus
neo-claude-opus commented on Jun 3, 2026, 9:10 PM

Surfaced by @tobiu (2026-06-03) while challenging the #12420 resolveAiDataRoot over-engineering — the same root antipattern recurs across the config templates, pre-dating #12420.

The antipattern

config.template.mjs is the declarative config SSOT — each value is leaf(default, envVarName, type), where the env override is a string-literal arg the config system resolves. But several leaves embed imperative process.env.UNIT_TEST_MODE === 'true' ? test : prod branching in the default expression — env-resolution logic that belongs at the env/test layer, not baked into the canonical config. Same root as resolveAiDataRoot (#12420): imperative env-resolution leaking into the declarative SSOT.

Instances (V-B-A grep)

  • ai/config.template.mjs:313engines.chroma.database (the lone inline process.env read in that file) — from #12335/#12397 (eccfe225e).
  • ai/mcp/server/memory-core/config.template.mjs:133graph (:memory: vs sqlite).
  • ai/mcp/server/memory-core/config.template.mjs:148,149memory/session collection names.
  • ai/mcp/server/memory-core/config.mjs:122,137,138 — the gitignored overlay copies.

Reshape

  • Config leaves go declarative: e.g. database: leaf(CHROMA_PRODUCTION_DATABASE, 'NEO_CHROMA_DATABASE', 'string').
  • The single test chokepoint test/playwright/playwright.config.unit.mjs:8 (already sets UNIT_TEST_MODE=true) sets the test overrides beside it (NEO_CHROMA_DATABASE=neo-unit-test, NEO_MEMORY_DB_PATH=:memory:, …).
  • The shared SSOT constants (chromaTestIsolation.mjs) stay — they're legit (consumed by the purge script, ChromaManager, specs). The import is not the problem; the inline branch is.

Safety is preserved (evidence it's removable)

The "by construction" test-isolation does not depend on the config branch — it's independently enforced at runtime:

  • ChromaManager.mjs:114 — refuses CHROMA_PRODUCTION_DATABASE under UNIT_TEST_MODE (fails loud, never pollutes prod).
  • dropChromaTestDatabase — refuses to drop prod.

So the inline config branch is largely redundant with the runtime guard; removing it does not regress the orphan-prevention motivation (the 1,281-orphan incident behind #12335).

Wrinkle (not a one-liner)

The test-*-${Date.now()}-${Math.random()} collection-name leaves need per-run/per-worker uniqueness → the dynamic generation must move to the test bootstrap (computed per worker), not a static env value. The chroma DATABASE (static neo-unit-test) is the clean case; the dynamic names are the harder sub-case.

The mechanical guard (the real friction→gold)

A lint banning inline process.env. reads inside config.template.mjs / config.mjs leaf defaults (env access only via the leaf's env-var-name arg) would have caught both this AND resolveAiDataRoot (#12420) at PR time — un-mergeable, not "review harder." Validate false-positive surface during implementation; this is the same class of fix as the #12442 premise gate but mechanically enforceable.

Related

  • Sibling instance: #12420 (resolveAiDataRoot) — REQUEST_CHANGES posted.
  • Recurring "wrong-shape merges" theme: #12442 (pr-review premise gate) → subs #12447–#12449.

Origin: @tobiu-surfaced, session e886ae3e-13c0-4a94-9713-f8316e2342d0.

tobiu referenced in commit a460136 - "feat(ai): lint banning inline process.env in config.template leaves (#12451) (#12472) on Jun 4, 2026, 10:13 AM
tobiu referenced in commit 3104248 - "refactor(ai): make config.template chroma database leaf declarative (#12480) (#12481) on Jun 4, 2026, 12:47 PM
tobiu closed this issue on Jun 4, 2026, 8:15 PM