LearnNewsExamplesServices
Frontmatter
id13482
titleOrchestrator-supervise the local dev-server (no tab-spawn on restart)
stateClosed
labels
enhancementdeveloper-experienceaiarchitecture
assigneesneo-gpt
createdAtJun 19, 2026, 12:07 AM
updatedAtJun 19, 2026, 2:10 AM
githubUrlhttps://github.com/neomjs/neo/issues/13482
authorneo-opus-vega
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 19, 2026, 2:10 AM

Orchestrator-supervise the local dev-server (no tab-spawn on restart)

Closed v13.1.0/archive-v13-1-0-chunk-3 enhancementdeveloper-experienceaiarchitecture
neo-opus-vega
neo-opus-vega commented on Jun 19, 2026, 12:07 AM

Context

Operator-observed (2026-06-18): frequent new browser tabs spawning during local dev. Root cause located: the webpack dev-server is started via npm run server-start (= webpack serve … --open) and/or the gitignored VS Code .claude/launch.json neo-dev-server config — and the --open flag opens a browser tab on every (re)start. The local orchestrator (ai/daemons/orchestrator/) already supervises chroma / wake / embed daemons, but it does not supervise the dev-server, so it's hand-started and re-opens a tab each time.

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 dev-server / tab-spawn ticket. A2A in-flight sweep: latest 20 messages; no competing [lane-claim].

The Problem

No orchestrator supervision of the local dev-server means (a) manual start/restart toil, and (b) a browser tab spawned per (re)start via --open — which accumulates during long local dev / agent sessions (the observed "tabs keep appearing"). This is a local-dev-loop stability/self-healing gap, not a cloud concern.

The Architectural Reality

  • ai/daemons/orchestrator/taskDefinitions.mjs buildTaskDefinitions() already defines supervised daemons (chroma, bridgeDaemon (= the wake daemon), embedDaemon, …), each shaped {label, command, args, pidFileName, expectedCommand, [singletonPort], [livenessProbe]}. Orchestrator.poll() + continuousTasks own liveness + restart.
  • package.json server-start = webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs --open (port 8080). The --open is the tab-spawner.
  • .claude/launch.json (gitignored, operator-local) runs the same webpack serve on 8080 — restarts there also re-open.

The Fix

Add a devServer continuous task to buildTaskDefinitions():

  • runs webpack serve -c ./buildScripts/webpack/webpack.server.config.mjs without --open (port 8080),
  • livenessProbe against :8080 + singletonPort: 8080 so it never double-spawns over a manually-started dev-server,
  • gated LOCAL-only via a new aiConfig.orchestrator.devServer.{enabled,port,livenessProbeTimeoutMs} leaf (default active only in local/dev deploymentMode; the cloud orchestrator never launches a dev-server).
  • Leave server-start's manual --open intact for explicit manual use (or add a server-start-headless alias for the no-open invocation).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
devServer orchestrator task taskDefinitions.mjs + Orchestrator continuousTasks Supervise webpack serve :8080, no --open, restart-on-death singletonPort: 8080 defers if a dev-server already listens (manual start) Inline task JSDoc Unit test: task-def shape + args contain no --open
aiConfig.orchestrator.devServer.{enabled,port,livenessProbeTimeoutMs} ai/config.template.mjs (ADR 0019 leaf) LOCAL-only gate (off under cloud deploymentMode); livenessProbeTimeoutMs (default 1000) bounds the TCP singleton probe Absent leaf → conservative local default / fail-loud per ADR 0019 config.template JSDoc + Tier-1 config.template.spec snapshot ai:lint-config-template-ssot + spec assert

Ledger reconciled to shipped reality (PR #13490): the leaf ships {enabled, port, livenessProbeTimeoutMs} — the livenessProbeTimeoutMs field is additive beyond the original {enabled, port} scoping.

Decision Record impact

none — aligned-with the orchestrator's existing daemon-supervision design + ADR 0019 (the config leaf).

Acceptance Criteria

  • The local orchestrator supervises the dev-server (:8080), auto-restarting it on death.
  • The orchestrator-launched dev-server does not pass --open → no browser tab spawned on (re)start.
  • LOCAL-only: the task is gated to local/dev deploymentMode (cloud orchestrator never launches a dev-server) via an aiConfig.orchestrator.devServer leaf.
  • Singleton-safe: does not double-spawn if a dev-server already listens on :8080.
  • Unit coverage for the task definition (args lack --open; LOCAL-only gating).

Out of Scope

  • Cloud / deploy-plane web serving.
  • Changing server-start's manual --open behavior (explicit manual open stays available).
  • The gitignored .claude/launch.json (operator-local).

Avoided Traps

  • Running the dev-server in the cloud orchestrator (LOCAL-only gate).
  • Double-spawning over a manually-started dev-server (singletonPort).
  • Stripping --open from server-start itself (manual users may want it).

Related

  • Refs #13012 (Agent Harness — the local orchestrator powers the harness dev loop).
  • Sibling stability ticket filed alongside: orchestrator-supervised Neural Link Bridge.

Origin Session ID: d1903453-9b2d-4f5d-bb5a-cf51ac2f7538

Handoff Retrieval Hints: query_raw_memories("orchestrator dev-server webpack serve --open browser tab spawn local taskDefinitions devServer"). Anchors: ai/daemons/orchestrator/taskDefinitions.mjs, package.json server-start, .claude/launch.json.

Authored by Claude Opus 4.8 (Claude Code), @neo-opus-vega (Vega), at @tobiu's request.