LearnNewsExamplesServices
Frontmatter
id12515
titleB3 cleanup: orchestrator AiConfig reads fail loud
stateClosed
labels
enhancementairefactoringarchitecture
assigneesneo-gpt
createdAtJun 4, 2026, 5:01 PM
updatedAtJun 4, 2026, 8:22 PM
githubUrlhttps://github.com/neomjs/neo/issues/12515
authorneo-gpt
commentsCount0
parentIssue12461
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 4, 2026, 8:22 PM

B3 cleanup: orchestrator AiConfig reads fail loud

Closed v13.0.0/archive-v13-0-0-chunk-16 enhancementairefactoringarchitecture
neo-gpt
neo-gpt commented on Jun 4, 2026, 5:01 PM

Context

During intake on #12461, the current origin/dev evidence showed the original B3 census is no longer a direct implementation target: the KB source-class leaf closed via #12467 / PR #12469, and ProtoSource is already covered by #12504 / PR #12505. The remaining orchestrator cluster is still present and is narrow enough for a one-PR leaf.

Verification run before filing:

  • git grep -n -E '(aiConfig|AiConfig)[^\\n]*\\?\\.' origin/dev -- 'ai/*.mjs' 'ai/**/*.mjs'
  • git grep -n -E 'sourcePaths\\?\\.' origin/dev -- 'ai/*.mjs' 'ai/**/*.mjs'
  • gh issue list --state all --search "B3 AiConfig orchestrator" --json number,title,state,assignees,labels,url --limit 30
  • gh issue list --state all --search "12461 orchestrator AiConfig" --json number,title,state,assignees,labels,url --limit 30
  • gh pr list --state all --search "orchestrator AiConfig optional OR orchestrator B3 OR 12461" --json number,title,state,mergeStateStatus,reviewDecision,headRefName,baseRefName,mergedAt,url --limit 30
  • ask_knowledge_base(query='existing ticket B3 AiConfig optional chaining orchestrator #12461', type='ticket')

The Problem

ADR 0019 classifies B3 as defensive ?. on AiConfig reads. The sanctioned pattern is to read resolved Provider leaves at the use site and let genuinely missing config paths fail loud. The current orchestrator code still contains optional-chain defenses on declared config subtrees, which preserves the old read-then-defend habit and weakens the SSOT contract that #12461 is trying to retire.

The Architectural Reality

ai/config.template.mjs declares the relevant Provider-owned paths:

  • engines.chroma.port: ai/config.template.mjs:284-288
  • orchestrator.chroma.maxRuntimeMs: ai/config.template.mjs:380-381
  • orchestrator.swarmHeartbeat.{targetSource,targets}: ai/config.template.mjs:402-430
  • orchestrator.devSyncRoots: ai/config.template.mjs:468-474
  • orchestrator.mlx.{enabled,model,port}: ai/config.template.mjs:513-517
  • orchestrator.lms.{enabled,model,port}: ai/config.template.mjs:539-542
  • openAiCompatible.host: ai/config.template.mjs:177-179

The current defensive read sites are in:

  • ai/daemons/orchestrator/Orchestrator.mjs:389
  • ai/daemons/orchestrator/Orchestrator.mjs:406-407
  • ai/daemons/orchestrator/Orchestrator.mjs:447-455
  • ai/daemons/orchestrator/Orchestrator.mjs:511
  • ai/daemons/orchestrator/Orchestrator.mjs:602
  • ai/daemons/orchestrator/Orchestrator.mjs:620
  • ai/daemons/orchestrator/Orchestrator.mjs:660
  • ai/daemons/orchestrator/daemon.mjs:185-188

The Fix

Replace optional-chain defenses on the declared orchestrator AiConfig subtrees with direct Provider reads at the use site.

Expected examples:

  • AiConfig.orchestrator.swarmHeartbeat?.targets -> AiConfig.orchestrator.swarmHeartbeat.targets
  • AiConfig.orchestrator.mlx?.enabled -> AiConfig.orchestrator.mlx.enabled
  • AiConfig.engines.chroma?.port -> AiConfig.engines.chroma.port
  • AiConfig.orchestrator?.devSyncRoots -> AiConfig.orchestrator.devSyncRoots

Preserve legitimate leaf-value semantics. For example, orchestrator.swarmHeartbeat.targets is a declared nullable leaf, so consumer logic may still normalize an empty/null leaf value after the direct subtree read. The prohibited part is defending against the declared subtree itself being absent.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
AiConfig.orchestrator.swarmHeartbeat.{targets,targetSource} consumers ADR 0019 B3; ai/config.template.mjs:402-430 Orchestrator reads the declared subtree directly. Nullable leaf values keep existing consumer semantics; missing subtree fails loud. Source JSDoc/comments only if wording currently implies defensive fallback. Focused orchestrator unit coverage plus git grep proving no remaining orchestrator swarmHeartbeat?. reads.
AiConfig.orchestrator.mlx / AiConfig.orchestrator.lms consumers ADR 0019 B3; ai/config.template.mjs:513-542 Orchestrator reads enabled, model, and port directly from declared Provider subtrees. No subtree fallback; invalid/missing config fails loud. Source comments only if needed. Focused orchestrator unit coverage plus git grep proving no remaining `orchestrator.(mlx
AiConfig.engines.chroma.port, AiConfig.orchestrator.chroma.maxRuntimeMs, AiConfig.orchestrator.devSyncRoots, AiConfig.openAiCompatible.host consumers ADR 0019 B3; ai/config.template.mjs:284-288, :380-381, :468-474, :177-179 Orchestrator and daemon read declared config leaves directly. No hidden subtree fallback; call-site logic for task state remains unchanged. Source comments only if needed. Focused orchestrator unit coverage plus git grep proving no remaining defensive reads on these declared subtrees.

Decision Record Impact

Aligned with ADR 0019. This ticket does not amend or supersede ADR 0019; it is a cleanup leaf that applies ADR 0019's B3 sanctioned form to the orchestrator cluster.

Acceptance Criteria

  • The orchestrator cluster no longer contains defensive optional chains on declared AiConfig subtrees in ai/daemons/orchestrator/Orchestrator.mjs or ai/daemons/orchestrator/daemon.mjs.
  • Legitimate nullable leaf handling is preserved. A null swarmHeartbeat.targets leaf still falls through to resolver semantics; the subtree read itself is direct.
  • Focused unit coverage is added or updated for the changed orchestrator behavior without mutating the shared AiConfig singleton.
  • Verification includes a targeted unit command, git diff --check, and a git grep proof for the orchestrator B3 patterns removed by this ticket.
  • The implementation PR resolves this ticket and references parent #12461.

Out of Scope

  • KB source classes: already closed by #12467 / PR #12469.
  • ProtoSource: covered by #12504 / PR #12505.
  • Memory Core, graph extraction, GitLab workflow, BaseServer, or shared vector clusters from the broader #12461 census.
  • B5 / C1 restructuring of TaskDefinitions.mjs or other pass-through config architecture.
  • Changing learn/tree.json or public Learn navigation.

Avoided Traps

  • Do not implement against the whole #12461 umbrella in one PR; it explicitly calls for cluster-sized cleanup leaves.
  • Do not remove meaningful nullable leaf semantics while removing subtree defense.
  • Do not import Neo/AiConfig into non-entrypoint helpers as part of this B3 leaf; C1/B5 cleanup is a separate shape.
  • Do not add hidden defaults such as || {} or ?? <literal> to compensate for removed ?. defenses.

Related

Parent: #12461

Epic: #12456

Prior resolved leaf: #12467 / PR #12469

Sibling in flight: #12504 / PR #12505

Retrieval Hint: query_raw_memories("AiConfig ADR 0019 B3 orchestrator optional chain #12461") or query_documents(query='B3 AiConfig orchestrator optional chain', type='ticket').

tobiu referenced in commit 7bd33de - "fix(orchestrator): fail loud on AiConfig subtree reads (#12515) (#12516) on Jun 4, 2026, 8:22 PM
tobiu closed this issue on Jun 4, 2026, 8:22 PM