Context
The orchestrator daemon is now the single source of truth for background memory/KB maintenance. Recent migrations removed per-MCP-server primitives in favor of orchestrator-owned scheduling:
- #12139 — removed 9 boot-time auto-* config flags (
autoSummarize, autoStartDatabase, autoStartInference, autoDream, autoGoldenPath, realTimeMemoryParsing, autoIngestFileSystem in memory-core; autoStartDatabase, autoSync in knowledge-base) + 2 MCP tools (manage_database, summarize_sessions).
- #12065 — the orchestrator REM pipeline (dream / summary / golden-path / chroma / kbSync scheduled tasks) became the sole driver of those behaviors.
The Problem
These removals create an asymmetric regression risk in the backlog. With 266 open tickets, some describe behavior whose premise is now obsolete. The canonical example: autoStartInference (NEO_MEM_AUTO_START_INFERENCE) was a config flag whose actual auto-start-inference logic was never implemented — the flag was string-matched in config + a hardcoded = false override, but no behavior was ever wired to it. The orchestrator owns inference lifecycle (mlx/lms continuous tasks).
A fresh agent session assigned a ticket like "implement inference-server auto-start" sees the config is now gone, concludes "even the config is missing — let me re-add it," and re-introduces exactly the per-MCP-instance self-trigger pattern #12139 deliberately deleted. That pattern historically caused duplicate summarizations across multiple harness-spawned MCP instances (Claude Desktop / Codex / Antigravity each spawn N instances per server). The ticket reads as actionable because the cleanup succeeded.
You cannot grep-guarantee a clean backlog across 266 decaying tickets — and the dangerous class is precisely the tickets that describe the behavior without naming the removed flag, so a one-time content audit can't catch them. The safety net must be mechanical at the merge gate: a fresh session can ignore a comment, but it cannot merge past red CI.
The Architectural Reality
ai/scripts/diagnostics/check-retired-primitives.mjs already proves the pattern: a declarative RETIRED_PRIMITIVES table (import-path fragments) that fails CI when a retired module is re-imported under ai/ (ADR 0004 §2.6 Clean-Cut Pattern). It is run by test/playwright/unit/ai/scripts/diagnostics/checkRetiredPrimitives.spec.mjs. Today it covers retired helper modules only (shared/chunkPath.mjs, shared/archivePath.mjs).
The flags live as <name>: leaf(...) declarations in ai/mcp/server/*/config.template.mjs; the tools live as operationId: <name> in ai/mcp/server/*/openapi.yaml (the tool-shape SSOT, from which the derived consistency specs compute expectations — see #12139).
The Fix
Extend the retired-primitive guard with two new categories so re-adding orchestrator-owned config/tools is unmergeable:
- Retired config flags — a
RETIRED_CONFIG_FLAGS table ({name, envVar, owner, ref, reason}) for the 9 removed auto-* flags. Scan every ai/mcp/server/*/config.template.mjs for a re-added <flag>: leaf( declaration.
- Retired MCP tools — a
RETIRED_MCP_TOOLS table for manage_database + summarize_sessions. Scan every ai/mcp/server/*/openapi.yaml for a re-added operationId: <tool>.
On a hit, fail CI with a self-explaining, premise-correcting message, e.g.:
❌ autoStartInference is retired. The orchestrator daemon owns inference lifecycle (mlx/lms continuous tasks) — see #12139 / #12065. Do NOT re-add per-MCP-server config. If a ticket instructed you to implement this, that ticket's premise is obsolete; close/annotate it rather than resurrect the flag.
Prefer extending the existing check-retired-primitives.mjs (three declarative tables + three category-aware matchers) over a parallel script, to keep the guard DRY and discoverable. The existing grep-based scan + escapeRegex + exit-code handling generalize cleanly.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
RETIRED_CONFIG_FLAGS table |
ai/scripts/diagnostics/check-retired-primitives.mjs |
declares the 9 removed auto-* flags + owner + ref |
n/a |
inline JSDoc |
#12139 diff |
RETIRED_MCP_TOOLS table |
ai/scripts/diagnostics/check-retired-primitives.mjs |
declares manage_database + summarize_sessions |
n/a |
inline JSDoc |
#12139 diff |
config.template.mjs scan |
ai/mcp/server/*/config.template.mjs |
fail if a retired flag is re-declared as a leaf( |
n/a |
— |
this ticket |
openapi.yaml scan |
ai/mcp/server/*/openapi.yaml |
fail if a retired tool operationId reappears |
n/a |
— |
this ticket |
| failure message |
guard stdout |
premise-correcting pointer to orchestrator-SSOT + ref |
n/a |
— |
this ticket |
| guard spec |
test/playwright/unit/ai/scripts/diagnostics/checkRetiredPrimitives.spec.mjs |
green on clean tree, red on re-add (both paths) |
n/a |
— |
existing spec |
Decision Record impact
aligned-with ADR 0004 §2.6 (Clean-Cut Pattern) + §5.6 (deprecation-theater anti-pattern) — extends the same mechanical-enforcement layer from retired modules to retired config flags + MCP tools.
Acceptance Criteria
Out of Scope
- A full semantic audit of all 266 open tickets — the guard makes the regression unmergeable regardless of stale ticket prose, which is the higher-leverage fix. A targeted audit of the highest-risk behavior-tickets (e.g. the
inference server cluster) may follow as a separate hygiene pass.
- Runtime behavior — pure build/CI-time guard.
- Auto-closing or auto-annotating the stale backlog tickets (separate concern; the guard protects the substrate regardless).
Avoided Traps
- One-time backlog audit instead of a guard — rejected: 266 tickets decay continuously against a moving architecture; an audit is stale the day after. The dangerous tickets describe behavior without naming the removed flag, so they're un-greppable by name. A mechanical merge-gate is the only durable defense.
- A new parallel checker script — rejected:
check-retired-primitives.mjs already owns this concern; a sibling script fragments the guard surface and the CI wiring.
Related
- #12139 (removed the flags + tools this guard protects)
- #12065 (orchestrator-SSOT REM pipeline — the owner of these behaviors)
- ADR 0004 §2.6 Clean-Cut Pattern +
ai/scripts/diagnostics/check-retired-primitives.mjs (the precedent being extended)
Origin Session ID: 94a91ebc-d325-4d32-a746-4ff8c26c0342
Handoff Retrieval Hints: query_raw_memories("retired config flag CI guard orchestrator SSOT autoStartInference"); commit anchor = #12139 merge (de-auto-trigger).
Context
The orchestrator daemon is now the single source of truth for background memory/KB maintenance. Recent migrations removed per-MCP-server primitives in favor of orchestrator-owned scheduling:
autoSummarize,autoStartDatabase,autoStartInference,autoDream,autoGoldenPath,realTimeMemoryParsing,autoIngestFileSystemin memory-core;autoStartDatabase,autoSyncin knowledge-base) + 2 MCP tools (manage_database,summarize_sessions).The Problem
These removals create an asymmetric regression risk in the backlog. With 266 open tickets, some describe behavior whose premise is now obsolete. The canonical example:
autoStartInference(NEO_MEM_AUTO_START_INFERENCE) was a config flag whose actual auto-start-inference logic was never implemented — the flag was string-matched in config + a hardcoded= falseoverride, but no behavior was ever wired to it. The orchestrator owns inference lifecycle (mlx/lms continuous tasks).A fresh agent session assigned a ticket like "implement inference-server auto-start" sees the config is now gone, concludes "even the config is missing — let me re-add it," and re-introduces exactly the per-MCP-instance self-trigger pattern #12139 deliberately deleted. That pattern historically caused duplicate summarizations across multiple harness-spawned MCP instances (Claude Desktop / Codex / Antigravity each spawn N instances per server). The ticket reads as actionable because the cleanup succeeded.
You cannot grep-guarantee a clean backlog across 266 decaying tickets — and the dangerous class is precisely the tickets that describe the behavior without naming the removed flag, so a one-time content audit can't catch them. The safety net must be mechanical at the merge gate: a fresh session can ignore a comment, but it cannot merge past red CI.
The Architectural Reality
ai/scripts/diagnostics/check-retired-primitives.mjsalready proves the pattern: a declarativeRETIRED_PRIMITIVEStable (import-path fragments) that fails CI when a retired module is re-imported underai/(ADR 0004 §2.6 Clean-Cut Pattern). It is run bytest/playwright/unit/ai/scripts/diagnostics/checkRetiredPrimitives.spec.mjs. Today it covers retired helper modules only (shared/chunkPath.mjs,shared/archivePath.mjs).The flags live as
<name>: leaf(...)declarations inai/mcp/server/*/config.template.mjs; the tools live asoperationId: <name>inai/mcp/server/*/openapi.yaml(the tool-shape SSOT, from which the derived consistency specs compute expectations — see #12139).The Fix
Extend the retired-primitive guard with two new categories so re-adding orchestrator-owned config/tools is unmergeable:
RETIRED_CONFIG_FLAGStable ({name, envVar, owner, ref, reason}) for the 9 removed auto-* flags. Scan everyai/mcp/server/*/config.template.mjsfor a re-added<flag>: leaf(declaration.RETIRED_MCP_TOOLStable formanage_database+summarize_sessions. Scan everyai/mcp/server/*/openapi.yamlfor a re-addedoperationId: <tool>.On a hit, fail CI with a self-explaining, premise-correcting message, e.g.:
Prefer extending the existing
check-retired-primitives.mjs(three declarative tables + three category-aware matchers) over a parallel script, to keep the guard DRY and discoverable. The existing grep-based scan +escapeRegex+ exit-code handling generalize cleanly.Contract Ledger
RETIRED_CONFIG_FLAGStableai/scripts/diagnostics/check-retired-primitives.mjsRETIRED_MCP_TOOLStableai/scripts/diagnostics/check-retired-primitives.mjsmanage_database+summarize_sessionsconfig.template.mjsscanai/mcp/server/*/config.template.mjsleaf(openapi.yamlscanai/mcp/server/*/openapi.yamloperationIdreappearstest/playwright/unit/ai/scripts/diagnostics/checkRetiredPrimitives.spec.mjsDecision Record impact
aligned-with ADR 0004§2.6 (Clean-Cut Pattern) + §5.6 (deprecation-theater anti-pattern) — extends the same mechanical-enforcement layer from retired modules to retired config flags + MCP tools.Acceptance Criteria
RETIRED_CONFIG_FLAGS(9 flags) +RETIRED_MCP_TOOLS(2 tools) declarative tables added tocheck-retired-primitives.mjs.<name>: leaf() in anyai/mcp/server/*/config.template.mjs.operationId: <tool>in anyai/mcp/server/*/openapi.yaml.Out of Scope
inference servercluster) may follow as a separate hygiene pass.Avoided Traps
check-retired-primitives.mjsalready owns this concern; a sibling script fragments the guard surface and the CI wiring.Related
ai/scripts/diagnostics/check-retired-primitives.mjs(the precedent being extended)Origin Session ID: 94a91ebc-d325-4d32-a746-4ff8c26c0342
Handoff Retrieval Hints:
query_raw_memories("retired config flag CI guard orchestrator SSOT autoStartInference"); commit anchor = #12139 merge (de-auto-trigger).