Context
config.template.mjs files across all three config tiers (Memory Core, Knowledge Base, Tier 1 ai/config.template.mjs) read process env vars with inconsistent prefix discipline. Some are correctly NEO_-prefixed (e.g., NEO_MC_PRIMARY, NEO_OLLAMA_HOST, NEO_VECTOR_DIMENSION); others use bare global-namespace names (e.g., AUTO_SUMMARIZE, TRANSPORT, MEMORY_COLLECTION_NAME).
This ticket is a Phase 1.6 cleanup under Epic #10822 — bring Neo-specific env vars to the canonical NEO_ prefix; preserve third-party-canonical names where they exist (GitHub, Gemini, OIDC/OAuth conventions).
The Problem
Bare global-namespace env vars create real pipeline-conflict risk. In CI runners, container envs, multi-tenant deployments, or operator shells with parallel stacks, names like AUTO_SUMMARIZE, TRANSPORT, GRAPH_DECAY_FACTOR, MEMORY_COLLECTION_NAME are likely to collide with other tools' env vars. The pattern is structurally equivalent to global vars in JavaScript: ergonomic in isolation, dangerous at scale.
The codebase already has the right convention for ~80% of Neo-specific vars (NEO_ prefix); the remaining ~20% are the inconsistency.
The Architectural Reality
Empirical audit via grep -nE 'process\.env\.[A-Z_]+' ai/mcp/server/memory-core/config.template.mjs ai/mcp/server/knowledge-base/config.template.mjs ai/config.template.mjs:
Already correctly NEO_-prefixed (no change):
NEO_MC_PRIMARY, NEO_MEM_AUTO_START_DATABASE, NEO_MEM_AUTO_START_INFERENCE
NEO_MODEL_PROVIDER, NEO_OLLAMA_*, NEO_OPENAI_COMPATIBLE_*
NEO_VECTOR_DIMENSION, NEO_CHROMA_UNIFIED, NEO_CHROMA_HOST, NEO_CHROMA_PORT
NEO_RLAIF_PATH, NEO_GUIDE_GAP_WEIGHT_THRESHOLD
NEO_CONCEPT_DISCOVERY_PR_SCAN_LIMIT, NEO_CONCEPT_DISCOVERY_MIN_SOURCE_LENGTH
NEO_MAILBOX_DEFAULT_REPLY_POLICY, NEO_LAZY_EDGES_QUEUE_PATH
NEO_PUBLIC_URL, MCP_HTTP_PORT (operator-facing per #10808)
Third-party-canonical (preserve as-is — leave alone):
GH_TOKEN (GitHub canonical)
GEMINI_API_KEY (Google API canonical)
NEO_OAUTH_CLIENT_ID, NEO_OAUTH_CLIENT_SECRET (OAuth standard)
NEO_AUTH_HOST, NEO_AUTH_PORT, NEO_AUTH_REALM, NEO_AUTH_ISSUER_URL, NEO_AUTH_TRUST_PROXY_IDENTITY (Keycloak/OIDC adjacent)
Neo-specific without NEO_ prefix (TARGET — rename):
Memory Core (ai/mcp/server/memory-core/config.template.mjs):
| Current |
Renamed to |
AUTO_SUMMARIZE |
NEO_AUTO_SUMMARIZE |
AUTO_DREAM |
NEO_AUTO_DREAM |
AUTO_GOLDEN_PATH |
NEO_AUTO_GOLDEN_PATH |
REAL_TIME_MEMORY_PARSING |
NEO_REAL_TIME_MEMORY_PARSING |
AUTO_INGEST_FS |
NEO_AUTO_INGEST_FS |
TRANSPORT |
NEO_TRANSPORT |
MEMORY_COLLECTION_NAME |
NEO_MEMORY_COLLECTION_NAME |
SESSION_COLLECTION_NAME |
NEO_SESSION_COLLECTION_NAME |
GRAPH_COLLECTION_NAME |
NEO_GRAPH_COLLECTION_NAME |
GRAPH_DECAY_FACTOR |
NEO_GRAPH_DECAY_FACTOR |
Knowledge Base (ai/mcp/server/knowledge-base/config.template.mjs):
| Current |
Renamed to |
AUTO_SYNC |
NEO_AUTO_SYNC |
TRANSPORT |
NEO_TRANSPORT (same as MC; one canonical name) |
Tier 1 (ai/config.template.mjs):
| Current |
Renamed to |
TRANSPORT |
NEO_TRANSPORT (same canonical name) |
Total: 13 occurrences across 3 files, 11 distinct new env-var names (TRANSPORT collapses to the single NEO_TRANSPORT across MC + KB + Tier 1).
The Fix
Hard-cut migration per env-var-rename-rule.md (codified in #10826). Single PR atomically:
- Rename in all three
config.template.mjs files
- Rename in their gitignored
config.mjs counterparts (operator-side; documented in PR body for operator action)
- Update
.env.example if present (or add NEO_ prefixed examples)
- Update
learn/agentos/DeploymentCookbook.md env-var inventory table
- Search-and-replace any documentation references (
grep -r AUTO_SUMMARIZE learn/, etc.)
- No deprecation chains; no fallback aliases; one-shot
Acceptance Criteria
Out of Scope
- Renaming third-party-canonical names (GH_TOKEN, GEMINI_API_KEY, NEO_AUTH_*, ONEO_AUTH_*) — these follow upstream conventions; leave alone
- Renaming operator-facing names that already shipped per #10808 (MCP_HTTP_PORT, NEO_PUBLIC_URL) — already correct
- KB-specific env vars under
kbFaq* block (NEO_KB_FAQ_*) — already correctly prefixed
Avoided Traps / Gold Standards Rejected
- Backward-compat alias period — explicitly forbidden per #10826 hard-cut rule. Engine-class deployments don't have thousands of users to protect across release windows; aliases are wrong-shape.
- Per-tier domain-prefix (e.g.,
NEO_MC_AUTO_SUMMARIZE vs NEO_KB_AUTO_SYNC vs NEO_TRANSPORT) — over-namespaces. Some vars naturally belong to one MCP server (NEO_AUTO_SUMMARIZE → MC only); others span (NEO_TRANSPORT applies to all MCP transports). Per-var domain-prefix decided case-by-case based on actual scope, not a blanket rule.
Related
- Sub-issue under Epic #10822 (Config substrate cleanup)
- Follows #10826 hard-cut sunset rule for env-var renames
- Pairs with #10842 (applyEnv priority inversion fix) — the canonical env-resolution helper Gemini is implementing will use these renamed vars
Origin Session ID: 8b31fd62-6a53-40b5-aae2-c5288f8ced09
Retrieval Hint: "Neo env var prefix consistency NEO_ MC KB Tier 1 config.template.mjs hard-cut rename pipeline conflict"
Context
config.template.mjsfiles across all three config tiers (Memory Core, Knowledge Base, Tier 1ai/config.template.mjs) read process env vars with inconsistent prefix discipline. Some are correctlyNEO_-prefixed (e.g.,NEO_MC_PRIMARY,NEO_OLLAMA_HOST,NEO_VECTOR_DIMENSION); others use bare global-namespace names (e.g.,AUTO_SUMMARIZE,TRANSPORT,MEMORY_COLLECTION_NAME).This ticket is a Phase 1.6 cleanup under Epic #10822 — bring Neo-specific env vars to the canonical
NEO_prefix; preserve third-party-canonical names where they exist (GitHub, Gemini, OIDC/OAuth conventions).The Problem
Bare global-namespace env vars create real pipeline-conflict risk. In CI runners, container envs, multi-tenant deployments, or operator shells with parallel stacks, names like
AUTO_SUMMARIZE,TRANSPORT,GRAPH_DECAY_FACTOR,MEMORY_COLLECTION_NAMEare likely to collide with other tools' env vars. The pattern is structurally equivalent to global vars in JavaScript: ergonomic in isolation, dangerous at scale.The codebase already has the right convention for ~80% of Neo-specific vars (
NEO_prefix); the remaining ~20% are the inconsistency.The Architectural Reality
Empirical audit via
grep -nE 'process\.env\.[A-Z_]+' ai/mcp/server/memory-core/config.template.mjs ai/mcp/server/knowledge-base/config.template.mjs ai/config.template.mjs:Already correctly
NEO_-prefixed (no change):NEO_MC_PRIMARY,NEO_MEM_AUTO_START_DATABASE,NEO_MEM_AUTO_START_INFERENCENEO_MODEL_PROVIDER,NEO_OLLAMA_*,NEO_OPENAI_COMPATIBLE_*NEO_VECTOR_DIMENSION,NEO_CHROMA_UNIFIED,NEO_CHROMA_HOST,NEO_CHROMA_PORTNEO_RLAIF_PATH,NEO_GUIDE_GAP_WEIGHT_THRESHOLDNEO_CONCEPT_DISCOVERY_PR_SCAN_LIMIT,NEO_CONCEPT_DISCOVERY_MIN_SOURCE_LENGTHNEO_MAILBOX_DEFAULT_REPLY_POLICY,NEO_LAZY_EDGES_QUEUE_PATHNEO_PUBLIC_URL,MCP_HTTP_PORT(operator-facing per #10808)Third-party-canonical (preserve as-is — leave alone):
GH_TOKEN(GitHub canonical)GEMINI_API_KEY(Google API canonical)NEO_OAUTH_CLIENT_ID,NEO_OAUTH_CLIENT_SECRET(OAuth standard)NEO_AUTH_HOST,NEO_AUTH_PORT,NEO_AUTH_REALM,NEO_AUTH_ISSUER_URL,NEO_AUTH_TRUST_PROXY_IDENTITY(Keycloak/OIDC adjacent)Neo-specific without
NEO_prefix (TARGET — rename):Memory Core (
ai/mcp/server/memory-core/config.template.mjs):AUTO_SUMMARIZENEO_AUTO_SUMMARIZEAUTO_DREAMNEO_AUTO_DREAMAUTO_GOLDEN_PATHNEO_AUTO_GOLDEN_PATHREAL_TIME_MEMORY_PARSINGNEO_REAL_TIME_MEMORY_PARSINGAUTO_INGEST_FSNEO_AUTO_INGEST_FSTRANSPORTNEO_TRANSPORTMEMORY_COLLECTION_NAMENEO_MEMORY_COLLECTION_NAMESESSION_COLLECTION_NAMENEO_SESSION_COLLECTION_NAMEGRAPH_COLLECTION_NAMENEO_GRAPH_COLLECTION_NAMEGRAPH_DECAY_FACTORNEO_GRAPH_DECAY_FACTORKnowledge Base (
ai/mcp/server/knowledge-base/config.template.mjs):AUTO_SYNCNEO_AUTO_SYNCTRANSPORTNEO_TRANSPORT(same as MC; one canonical name)Tier 1 (
ai/config.template.mjs):TRANSPORTNEO_TRANSPORT(same canonical name)Total: 13 occurrences across 3 files, 11 distinct new env-var names (TRANSPORT collapses to the single
NEO_TRANSPORTacross MC + KB + Tier 1).The Fix
Hard-cut migration per
env-var-rename-rule.md(codified in #10826). Single PR atomically:config.template.mjsfilesconfig.mjscounterparts (operator-side; documented in PR body for operator action).env.exampleif present (or add NEO_ prefixed examples)learn/agentos/DeploymentCookbook.mdenv-var inventory tablegrep -r AUTO_SUMMARIZE learn/, etc.)Acceptance Criteria
config.template.mjsuseNEO_prefixlearn/agentos/DeploymentCookbook.mdenv-var inventory table updated with renamed namesgrep -rE "process\.env\.(AUTO_SUMMARIZE|AUTO_DREAM|AUTO_GOLDEN_PATH|REAL_TIME_MEMORY_PARSING|AUTO_INGEST_FS|TRANSPORT|MEMORY_COLLECTION_NAME|SESSION_COLLECTION_NAME|GRAPH_COLLECTION_NAME|GRAPH_DECAY_FACTOR|AUTO_SYNC)" ai/ src/ buildScripts/returns zero results post-PRcp .env .env.bak; sed -i '' 's/^AUTO_SUMMARIZE=/NEO_AUTO_SUMMARIZE=/; ...' .envOut of Scope
kbFaq*block (NEO_KB_FAQ_*) — already correctly prefixedAvoided Traps / Gold Standards Rejected
NEO_MC_AUTO_SUMMARIZEvsNEO_KB_AUTO_SYNCvsNEO_TRANSPORT) — over-namespaces. Some vars naturally belong to one MCP server (NEO_AUTO_SUMMARIZE → MC only); others span (NEO_TRANSPORT applies to all MCP transports). Per-var domain-prefix decided case-by-case based on actual scope, not a blanket rule.Related
Origin Session ID: 8b31fd62-6a53-40b5-aae2-c5288f8ced09 Retrieval Hint: "Neo env var prefix consistency NEO_ MC KB Tier 1 config.template.mjs hard-cut rename pipeline conflict"