Context
Operator-observed (2026-06-18): the Neural Link Bridge is not part of the local orchestrator — the operator starts it manually each session (npm run ai:server-neural-link → ai/mcp/server/neural-link/run-bridge.mjs, port 8081). The orchestrator (ai/daemons/orchestrator/) supervises chroma / wake / embed daemons but not the NL bridge.
Release classification: post-release (local-dev orchestrator stability/self-healing; boardless — not a v13 release gate).
Live latest-open sweep: checked latest 25 open issues on 2026-06-18; no equivalent orchestrator NL-bridge supervision ticket. A2A in-flight sweep: latest 20 messages; no competing [lane-claim].
The Problem
Manual NL-bridge start is forgotten-start friction (Neural Link tools silently fail until the bridge is up) plus no auto-restart on crash. The bridge is the NL transport (Brain↔Body possession surface); its absence breaks inspection / possession with a non-obvious failure mode.
The Architectural Reality
package.json ai:server-neural-link = node ./ai/mcp/server/neural-link/run-bridge.mjs (port 8081) — the manual start path.
taskDefinitions.mjs has no run-bridge task. The bridgeDaemon task there is the wake daemon (a frozen lane-taxonomy name kept verbatim across the wake-daemon rename — see the in-code comment), not the NL bridge. So nothing in the orchestrator supervises the NL Bridge today.
- The NL bridge on
:8081 is shared infra — multiple Neo clones + the ConnectionService.spawnBridge path can target the same port. Supervision MUST be singleton-safe (cf. the chroma task's singletonPort reap-duplicate discipline). Managing/killing the shared :8081 bridge is operator-authority territory, so the task must never stomp a running or peer-clone bridge.
The Fix
Add a neuralLinkBridge continuous task to buildTaskDefinitions():
- runs
node ai/mcp/server/neural-link/run-bridge.mjs (port 8081),
livenessProbe against :8081 + singletonPort: 8081 so it never spawns a second bridge if one is already listening (manual or peer-clone),
- gated LOCAL-only via a new
aiConfig.orchestrator.localOnly.neuralLinkBridgeEnabled leaf (cloud has its own NL topology); orchestrator-side probe timeout via aiConfig.orchestrator.neuralLinkBridge.livenessProbeTimeoutMs. The bridge port is owned by the NL config SSOT (ai/mcp/server/neural-link/config.mjs, NEO_NL_PORT) — the orchestrator consumes it (neuralLinkConfig.port), never re-defines it.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
neuralLinkBridge orchestrator task |
taskDefinitions.mjs + Orchestrator continuousTasks |
Supervise run-bridge.mjs :8081, restart-on-death |
singletonPort: 8081 defers if a bridge already listens (manual / peer-clone) — never double-spawns shared infra |
Inline task JSDoc |
Unit test: task-def shape + singleton gating |
aiConfig.orchestrator.localOnly.neuralLinkBridgeEnabled |
ai/config.template.mjs (ADR 0019 leaf) |
LOCAL-only gate (off under cloud deploymentMode); lives under localOnly, mirroring chromaDaemonEnabled / bridgeDaemonEnabled |
Absent leaf → conservative local default / fail-loud per ADR 0019 |
config.template JSDoc |
ai:lint-config-template-ssot |
aiConfig.orchestrator.neuralLinkBridge.livenessProbeTimeoutMs |
ai/config.template.mjs (ADR 0019 leaf) |
Orchestrator-side TCP liveness-probe timeout (default 1000ms). Bridge port NOT here — owned by ai/mcp/server/neural-link/config.mjs (NEO_NL_PORT), consumed via neuralLinkConfig.port |
Absent leaf → conservative default |
config.template JSDoc |
config.template.spec inline assertion |
Ledger reconciled to shipped reality (PR #13489, Grace's Required Action): the enabled gate lives under orchestrator.localOnly.neuralLinkBridgeEnabled (not neuralLinkBridge.enabled), and the bridge port is not duplicated in the orchestrator config — it stays owned by the NL config SSOT (NEO_NL_PORT). The orchestrator-side neuralLinkBridge leaf carries only livenessProbeTimeoutMs. This is a cleaner shape than the original {enabled,port} scoping.
Decision Record impact
none — aligned-with the orchestrator's daemon-supervision design + ADR 0019 (the config leaf).
Acceptance Criteria
Out of Scope
- Cloud NL topology.
- The wake daemon (the separate
bridgeDaemon task).
ConnectionService.spawnBridge (the in-service spawn path stays as-is).
#13056 (extended-NL coordination — H3-deferred; this is plain bridge supervision).
Avoided Traps
- Conflating with the wake daemon (
bridgeDaemon is the wake daemon — frozen name).
- Stomping the shared
:8081 bridge — singleton-safe, operator-authority infra.
- Running it in the cloud orchestrator (LOCAL-only gate).
Related
Refs #13012 (Agent Harness — NL is the possession transport the harness rides).
- Sibling stability ticket filed alongside: orchestrator-supervised local dev-server.
Origin Session ID: d1903453-9b2d-4f5d-bb5a-cf51ac2f7538
Handoff Retrieval Hints: query_raw_memories("orchestrator supervise neural link bridge run-bridge 8081 singletonPort shared infra local taskDefinitions"). Anchors: ai/daemons/orchestrator/taskDefinitions.mjs, package.json ai:server-neural-link, ai/mcp/server/neural-link/run-bridge.mjs.
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-vega (Vega), at @tobiu's request.
Context
Operator-observed (2026-06-18): the Neural Link Bridge is not part of the local orchestrator — the operator starts it manually each session (
npm run ai:server-neural-link→ai/mcp/server/neural-link/run-bridge.mjs, port 8081). The orchestrator (ai/daemons/orchestrator/) supervises chroma / wake / embed daemons but not the NL bridge.Release classification: post-release(local-dev orchestrator stability/self-healing; boardless — not a v13 release gate).Live latest-open sweep: checked latest 25 open issues on 2026-06-18; no equivalent orchestrator NL-bridge supervision ticket. A2A in-flight sweep: latest 20 messages; no competing
[lane-claim].The Problem
Manual NL-bridge start is forgotten-start friction (Neural Link tools silently fail until the bridge is up) plus no auto-restart on crash. The bridge is the NL transport (Brain↔Body possession surface); its absence breaks inspection / possession with a non-obvious failure mode.
The Architectural Reality
package.jsonai:server-neural-link=node ./ai/mcp/server/neural-link/run-bridge.mjs(port 8081) — the manual start path.taskDefinitions.mjshas no run-bridge task. ThebridgeDaemontask there is the wake daemon (a frozen lane-taxonomy name kept verbatim across the wake-daemon rename — see the in-code comment), not the NL bridge. So nothing in the orchestrator supervises the NL Bridge today.:8081is shared infra — multiple Neo clones + theConnectionService.spawnBridgepath can target the same port. Supervision MUST be singleton-safe (cf. thechromatask'ssingletonPortreap-duplicate discipline). Managing/killing the shared:8081bridge is operator-authority territory, so the task must never stomp a running or peer-clone bridge.The Fix
Add a
neuralLinkBridgecontinuous task tobuildTaskDefinitions():node ai/mcp/server/neural-link/run-bridge.mjs(port 8081),livenessProbeagainst:8081+singletonPort: 8081so it never spawns a second bridge if one is already listening (manual or peer-clone),aiConfig.orchestrator.localOnly.neuralLinkBridgeEnabledleaf (cloud has its own NL topology); orchestrator-side probe timeout viaaiConfig.orchestrator.neuralLinkBridge.livenessProbeTimeoutMs. The bridge port is owned by the NL config SSOT (ai/mcp/server/neural-link/config.mjs,NEO_NL_PORT) — the orchestrator consumes it (neuralLinkConfig.port), never re-defines it.Contract Ledger
neuralLinkBridgeorchestrator tasktaskDefinitions.mjs+OrchestratorcontinuousTasksrun-bridge.mjs:8081, restart-on-deathsingletonPort: 8081defers if a bridge already listens (manual / peer-clone) — never double-spawns shared infraaiConfig.orchestrator.localOnly.neuralLinkBridgeEnabledai/config.template.mjs(ADR 0019 leaf)deploymentMode); lives underlocalOnly, mirroringchromaDaemonEnabled/bridgeDaemonEnabledai:lint-config-template-ssotaiConfig.orchestrator.neuralLinkBridge.livenessProbeTimeoutMsai/config.template.mjs(ADR 0019 leaf)ai/mcp/server/neural-link/config.mjs(NEO_NL_PORT), consumed vianeuralLinkConfig.portconfig.template.specinline assertionLedger reconciled to shipped reality (PR #13489, Grace's Required Action): the
enabledgate lives underorchestrator.localOnly.neuralLinkBridgeEnabled(notneuralLinkBridge.enabled), and the bridge port is not duplicated in the orchestrator config — it stays owned by the NL config SSOT (NEO_NL_PORT). The orchestrator-sideneuralLinkBridgeleaf carries onlylivenessProbeTimeoutMs. This is a cleaner shape than the original{enabled,port}scoping.Decision Record impact
none— aligned-with the orchestrator's daemon-supervision design + ADR 0019 (the config leaf).Acceptance Criteria
run-bridge.mjs,:8081), auto-restarting on death.:8081already has a listener (manual or peer-clone) — uses thechroma-stylesingletonPortdiscipline.aiConfig.orchestrator.localOnly.neuralLinkBridgeEnabled(cloud orchestrator never launches it).bridgeDaemontask (distinct lane, frozen name).Out of Scope
bridgeDaemontask).ConnectionService.spawnBridge(the in-service spawn path stays as-is).#13056(extended-NL coordination — H3-deferred; this is plain bridge supervision).Avoided Traps
bridgeDaemonis the wake daemon — frozen name).:8081bridge — singleton-safe, operator-authority infra.Related
Refs #13012(Agent Harness — NL is the possession transport the harness rides).Origin Session ID: d1903453-9b2d-4f5d-bb5a-cf51ac2f7538
Handoff Retrieval Hints:
query_raw_memories("orchestrator supervise neural link bridge run-bridge 8081 singletonPort shared infra local taskDefinitions"). Anchors:ai/daemons/orchestrator/taskDefinitions.mjs,package.jsonai:server-neural-link,ai/mcp/server/neural-link/run-bridge.mjs.Authored by Claude Opus 4.8 (Claude Code), @neo-opus-vega (Vega), at @tobiu's request.