Dev Server Module Audit (FN-2214)

April 21, 2026 · View on GitHub

← Docs index

This document audits the two parallel dev-server module families under packages/dashboard/src, identifies production wiring vs disconnected modules, and proposes a concrete consolidation plan.


1) Overview

Fusion currently contains two parallel module families for dashboard dev-server functionality:

  • Legacy family (dev-server-*) — the production path used by API routes and server shutdown.
  • Newer family (devserver-*) — introduced in FN-2183 as an alternative implementation, but not wired into production routes.

Summary table (source files only)

FileLOCStatusProduction importers
dev-server-detect.ts190Activedev-server-routes.ts
dev-server-store.ts234Activedev-server-routes.ts, dev-server-process.ts
dev-server-port-detect.ts250Activedev-server-process.ts
dev-server-process.ts355Activedev-server-routes.ts
dev-server-manager.ts403Orphaned from productionNone (imported only by tests)
dev-server-routes.ts406Active (entrypoint)routes.ts, server.ts
devserver-types.ts41DisconnectedNone (internal to devserver-* family only)
devserver-detect.ts165DisconnectedNone
devserver-persistence.ts100DisconnectedNone
devserver-manager.ts469DisconnectedNone

2) Legacy dev-server-* Family — File-by-File Analysis

2.1 dev-server-detect.ts

Responsibility
Detects candidate dev-server scripts from root/workspace package.json files and ranks them with confidence scoring.

Exports

  • DEV_SERVER_SCRIPT_NAMES — priority-ordered script names: dev, start, serve, web, frontend, preview, storybook.
  • DEV_SCRIPT_NAMES — deprecated alias to DEV_SERVER_SCRIPT_NAMES.
  • FRAMEWORK_INDICATORS — dependency-name indicators used for framework confidence boosts.
  • DetectedScript — candidate record shape.
  • DetectionResult — result wrapper { candidates }.
  • isCandidateScript(name) — helper for script-name inclusion check.
  • detectDevServerScripts(projectRoot) — main detection routine.

Importers

  • Production: dev-server-routes.ts
  • Test-only: __tests__/dev-server-detect.test.ts, __tests__/dev-server-routes.test.ts

Key behavior

  • Reads root package.json, then scans packages/*/package.json and apps/*/package.json via glob.
  • Computes confidence score (0–1) from:
    • script-name priority (getScriptPriorityScore),
    • dependency-based framework indicators,
    • private / missing main heuristics.
  • Sorts by confidence desc, then source, then script name.

Production wiring

  • Used by GET /api/dev-server/detect in dev-server-routes.ts.

2.2 dev-server-store.ts

Responsibility
Persists and normalizes dev-server runtime state/config in .fusion/dev-server.json.

Exports

  • DevServerStatus"starting" | "running" | "stopped" | "failed".
  • DevServerState — process/session state shape.
  • DevServerConfig — persisted user config shape.
  • DEV_SERVER_CONFIG_DEFAULTS — config defaults.
  • DEV_SERVER_LOG_MAX_LINES — ring-buffer cap (500).
  • DEV_SERVER_DEFAULT_STATE() — state defaults.
  • DevServerStore — class-based storage API.
  • loadDevServerStore(projectDir) — singleton loader keyed by resolved project root.
  • resetDevServerStore() — test reset helper.

Importers

  • Production/runtime chain: dev-server-routes.ts, dev-server-process.ts (types)
  • Non-test but not production-wired: dev-server-manager.ts
  • Test-only: __tests__/dev-server-store.test.ts, __tests__/dev-server-process.test.ts, __tests__/dev-server-manager.test.ts, __tests__/dev-server-manager-persistence.test.ts, __tests__/dev-server-routes.test.ts

Key behavior

  • File path is fixed to join(resolve(projectDir), ".fusion", "dev-server.json").
  • Persists object shape { state, config }.
  • Normalizes invalid/malformed values defensively (normalizeState, normalizeConfig).
  • Maintains bounded logHistory ring buffer and writes on every state/config/log mutation.

Production wiring

  • dev-server-routes.ts uses it for config endpoints and status persistence.
  • DevServerProcessManager writes lifecycle/log/URL detection updates through the store.

2.3 dev-server-port-detect.ts

Responsibility
Extracts localhost preview URLs/ports from process output and probes common fallback ports.

Exports

  • PortDetectionResult{ url, port, source }.
  • FALLBACK_PREVIEW_PORTS — 10 common ports: 5173,3000,4173,6006,8080,4200,4400,8888,4321,4000.
  • detectPortFromLogLine(line) — single-line parser.
  • detectPortFromLogs(lines) — reverse scan from newest log line.
  • probeFallbackPorts(host?, timeoutMs?) — sequential TCP probe of fallback ports.

Importers

  • Production: dev-server-process.ts
  • Test-only: __tests__/dev-server-port-detect.test.ts

Key behavior

  • Reserved dashboard port 4040 is hard-excluded.
  • Strips ANSI color codes before parsing.
  • Dedicated framework parsers for Vite, Next.js, Storybook, Angular (multiple regex patterns each), then generic URL and generic keyword+port fallbacks.
  • probeFallbackPorts normalizes host input and probes in deterministic order.

Production wiring

  • DevServerProcessManager calls detectPortFromLogLine on each output line and schedules probeFallbackPorts after startup delay when no URL is announced.

2.4 dev-server-process.ts

Responsibility
Manages child-process lifecycle for a single dev server (start/stop/restart), log streaming, and URL detection.

Exports

  • DevServerEvent — event union (started, output, stopped, failed, url-detected).
  • DevServerProcessManagerOptions — timeout/probe tuning options.
  • DevServerProcessManagerEventEmitter-based process manager class.

Importers

  • Production/runtime chain: dev-server-routes.ts
  • Non-test but not production-wired: dev-server-manager.ts
  • Test-only: __tests__/dev-server-process.test.ts

Key behavior

  • Uses spawn(command, [], { shell: true, stdio: ["pipe","pipe","pipe"] }).
  • Persists process lifecycle into DevServerStore (startingrunningstopped/failed).
  • Streams stdout/stderr line-by-line into store log ring buffer and emits output events.
  • Detects preview URL from logs via detectPortFromLogLine; if absent, schedules delayed fallback probing.
  • Stop behavior sends SIGTERM, then escalates to SIGKILL after timeout.

Production wiring

  • Instantiated directly inside dev-server-routes.ts runtime map (getRuntime).

2.5 dev-server-manager.ts

Responsibility
Higher-level wrapper around DevServerProcessManager adding snapshot/log abstractions, SSE event buffering, and subscriber fan-out.

Exports

  • FALLBACK_PORTS — fallback port list (matches legacy probe list; excludes 4040).
  • DevServerPersistedLogEntry
  • DevServerPersistedState
  • DevServerStartOptions
  • DevServerSnapshot
  • DevServerUrlDetectedEvent
  • DevServerManagerEvent
  • DevServerManagerOptions
  • DevServerManager — wrapper class with SessionEventBuffer support.
  • loadDevServerManager(rootDir) — singleton loader.
  • shutdownAllDevServerManagers() — shutdown helper.
  • resetDevServerManager() — test reset helper.

Importers

  • Production: None
  • Test-only: __tests__/dev-server-manager.test.ts, __tests__/dev-server-manager-persistence.test.ts

Key behavior

  • Wraps DevServerProcessManager events into higher-level state/log events.
  • Buffers events with SessionEventBuffer (getBufferedEvents(sinceId)) for replay-friendly SSE semantics.
  • Maintains in-memory subscriber set for push delivery.
  • initialize() performs stale PID reconciliation: if persisted running/starting PID is dead, marks state stopped and appends recovery log.

Production wiring

  • Not wired: routes do not instantiate this class; they use DevServerProcessManager directly.

2.6 dev-server-routes.ts

Responsibility
Express router exposing /api/dev-server/* endpoints for detection, config, lifecycle, preview URL override, and SSE log stream.

Exports

  • DevServerRouterOptions — requires projectRoot.
  • createDevServerRouter(options) — router factory.
  • stopAllDevServers() — stop+cleanup hook used by server shutdown.
  • destroyAllDevServerManagers() — test teardown helper (clears route runtime map + store singleton).
  • getActiveProcessManagers() — test introspection helper.

Importers

  • Production: routes.ts, server.ts
  • Test-only: __tests__/dev-server-routes.test.ts, __tests__/dev-server-config-routes.test.ts

Key behavior

  • Maintains per-project runtime map { store, manager } where manager is DevServerProcessManager.
  • Endpoints:
    • GET /detect
    • GET /config, PUT /config
    • GET /status
    • POST /start, POST /stop, POST /restart
    • PUT /preview-url
    • GET /logs/stream (SSE)
  • SSE stream writes raw events/history/heartbeat directly; no SessionEventBuffer replay path.

Production wiring

  • Mounted in routes.ts via router.use("/dev-server", createDevServerRouter(...)).
  • Server shutdown in server.ts calls stopAllDevServers() on HTTP server close.

3) Newer devserver-* Family — File-by-File Analysis

3.1 devserver-types.ts

Responsibility
Defines branded IDs and strongly typed multi-server session/config/log models.

Exports

  • DevServerId — branded string type.
  • createDevServerId(id) — branding helper.
  • DevServerStatus — includes "stopping" in addition to stopped/starting/running/failed.
  • DevServerConfig
  • DevServerRuntime
  • DevServerLogEntry
  • DevServerSession
  • MAX_LOG_ENTRIES (500)
  • DevServerSessionMap

Importers

  • Production: None (only imported by disconnected family files)
  • Test-only: __tests__/devserver-types.test.ts, __tests__/devserver-detect.test.ts, __tests__/devserver-manager.test.ts

Key behavior

  • Provides cleaner type boundary than inline legacy store types.
  • Adds explicit stopping transitional status.

Connection status

  • Zero production imports.

3.2 devserver-detect.ts

Responsibility
Alternative script detector that scans root/apps/packages package manifests and returns executable command entries.

Exports

  • DetectedCommand
  • PRIORITY_SCRIPTSdev,start,web,frontend,serve,storybook
  • FRAMEWORK_PATTERNS — regex map for command-string framework detection.
  • detectFramework(scriptCommand)
  • detectDevServerCommands(projectRoot)

Importers

  • Production: None
  • Test-only: __tests__/devserver-detect.test.ts

Key behavior

  • Reads package JSON using execAsync(node -e ...) and then JSON parses stdout.
  • Discovers workspace manifests by directory traversal of apps/* and packages/*.
  • Dedupes by cwd::scriptName and sorts by priority script index, then directory depth, then cwd.

Connection status

  • Zero production imports.

3.3 devserver-persistence.ts

Responsibility
Alternative persistence layer for multi-config dev servers.

Exports

  • projectDevServerFile(projectDir) — path resolver for .fusion/devserver.json.
  • loadDevServerConfigs(projectDir)
  • saveDevServerConfigs(projectDir, configs)
  • reconstructSessions(configs)
  • type PersistenceData

Importers

  • Production: None
  • Test-only: __tests__/devserver-detect.test.ts

Key behavior

  • Persists { configs: DevServerConfig[] } instead of { state, config }.
  • Parses optional env object safely, brands IDs via createDevServerId.
  • Save operation is intentionally graceful no-op on write failure.

Connection status

  • Zero production imports.

3.4 devserver-manager.ts

Responsibility
Alternative multi-server runtime manager with typed events, inline URL detection, and inline port probing.

Exports

  • DevServerManagerEvents — typed event map (log, status, preview, exit).
  • DevServerManager — multi-session process manager.
  • getDevServerManager(projectRoot) — singleton getter.
  • destroyDevServerManager(projectRoot)
  • destroyAllDevServerManagers()

Importers

  • Production: None
  • Test-only: __tests__/devserver-manager.test.ts

Key behavior

  • Supports multiple concurrent server sessions keyed by DevServerId.
  • Parses command strings with custom quote-aware parseCommand() split.
  • Detects URLs from output via inline localhost regex and probes COMMON_DEV_PORTS (6 ports).
  • Uses Windows-aware terminate/kill paths (process.kill(pid) on Windows; SIGTERM/SIGKILL elsewhere).
  • Explicit stopping state and stop timeout escalation.

Connection status

  • Zero production imports.

4) Overlapping Responsibilities

ConcernLegacy file(s)Newer file(s)Overlap description
Script detectiondev-server-detect.tsdevserver-detect.tsBoth scan package manifests for likely dev scripts.
Config persistencedev-server-store.tsdevserver-persistence.tsBoth persist dev-server configuration under .fusion/ JSON files.
Process managementdev-server-process.ts + dev-server-manager.tsdevserver-manager.tsBoth families manage child processes, lifecycle transitions, logs, and URL detection/probing.
Port detectiondev-server-port-detect.tsInline in devserver-manager.tsBoth parse localhost URL/port from logs and probe fallback ports.
Type definitionsInline in dev-server-store.tsdevserver-types.tsBoth define runtime/session/config/status concepts.

Specific differences

Script detection

  • Legacy (dev-server-detect.ts)
    • 7 script names (dev,start,serve,web,frontend,preview,storybook).
    • Confidence scoring (priority boost + dependency-based framework indicators + private/main heuristic).
    • Uses glob workspace discovery.
  • Newer (devserver-detect.ts)
    • 6 script names (dev,start,web,frontend,serve,storybook).
    • Framework detection from script-command regex only.
    • Sorts by PRIORITY_SCRIPTS index + directory depth.
    • Reads package.json via spawned node -e command (execAsync).

Persistence

  • Legacy (dev-server-store.ts)
    • File: .fusion/dev-server.json
    • Shape: { state, config }
    • Class API: DevServerStore
  • Newer (devserver-persistence.ts)
    • File: .fusion/devserver.json
    • Shape: { configs: DevServerConfig[] }
    • Function API: loadDevServerConfigs / saveDevServerConfigs

Process management

  • Legacy
    • DevServerProcessManager: single server per instance; delegates detection to dev-server-port-detect.ts.
    • DevServerManager: adds buffering/subscribers/stale PID recovery, but is not route-wired.
    • Routes instantiate DevServerProcessManager directly.
  • Newer (devserver-manager.ts)
    • Multi-server sessions, typed event contract, built-in parsing/probing, stopping status.
    • Includes Windows-specific stop/kill handling.

Port detection

  • Legacy (dev-server-port-detect.ts)
    • Dedicated detection module.
    • Framework-specific parsers for Vite/Next/Storybook/Angular plus generic URL/keyword fallbacks.
    • Probes 10 fallback ports (FALLBACK_PREVIEW_PORTS).
  • Newer (devserver-manager.ts)
    • Inline regex: https?://(localhost|127\.0\.0\.1)(?::(\d+))?
    • Probes 6 common ports (COMMON_DEV_PORTS).

5) Production Import Graph

routes.ts ──→ dev-server-routes.ts ──→ dev-server-detect.ts
                                  ├──→ dev-server-store.ts
                                  └──→ dev-server-process.ts ──→ dev-server-port-detect.ts
                                                               └──→ dev-server-store.ts (type import)

server.ts ──→ dev-server-routes.ts (stopAllDevServers)

dev-server-manager.ts ──→ dev-server-process.ts
                       ├──→ dev-server-store.ts
                       └──→ sse-buffer.ts
  ⚠ Not imported by routes.ts; exercised only via dedicated tests

devserver-types.ts ──→ devserver-manager.ts, devserver-persistence.ts (internal only)
devserver-detect.ts ──→ (no production importers)
devserver-persistence.ts ──→ devserver-types.ts (internal only)
devserver-manager.ts ──→ devserver-types.ts (internal only)
  ⚠ Entire `devserver-*` family has ZERO production imports

Verified production wiring points:

  • packages/dashboard/src/routes.ts:54 imports createDevServerRouter; routes.ts:17299 mounts /dev-server.
  • packages/dashboard/src/server.ts:45 imports stopAllDevServers; server.ts:827 calls it during server close cleanup.

6) Test Coverage Summary

  • Legacy family tests: 8 files, 1911 LOC total
    • dev-server-detect.test.ts (187)
    • dev-server-store.test.ts (338)
    • dev-server-port-detect.test.ts (241)
    • dev-server-process.test.ts (239)
    • dev-server-manager.test.ts (173)
    • dev-server-manager-persistence.test.ts (131)
    • dev-server-routes.test.ts (493)
    • dev-server-config-routes.test.ts (109)
  • Newer family tests: 3 files, 620 LOC total
    • devserver-types.test.ts (125)
    • devserver-detect.test.ts (140)
    • devserver-manager.test.ts (355)

Notes on legacy manager coverage:

  • dev-server-manager.ts is directly tested by:
    • dev-server-manager.test.ts
    • dev-server-manager-persistence.test.ts
  • Route-level behavior (including SSE and config persistence) is tested in:
    • dev-server-routes.test.ts
    • dev-server-config-routes.test.ts

7) Consolidation Plan

FileRecommendationRationale
dev-server-routes.tsKeepSole production entry point and API contract owner.
dev-server-detect.tsKeepAlready route-integrated; richer scoring and dependency-based framework heuristics.
dev-server-store.tsKeepExisting persisted contract (.fusion/dev-server.json) and route/process integration.
dev-server-port-detect.tsKeepDedicated parsing/probing module with broader detection behavior and explicit 4040 exclusion.
dev-server-process.tsKeepCore runtime manager used directly by routes.
dev-server-manager.tsRemove or integrateNot production-wired; useful capabilities (buffering + stale PID recovery) should be migrated before deletion if needed.
devserver-types.tsAdopt ideas (possibly as dev-server-types.ts)Branded IDs and explicit stopping status are cleaner than ad-hoc inline type evolution.
devserver-detect.tsRemoveDuplicates detection concern with narrower heuristics and no production wiring.
devserver-persistence.tsRemoveCompeting persistence path (devserver.json) conflicts with current persisted contract.
devserver-manager.tsCherry-pick patterns, then removeMulti-server/session abstractions and typed events are valuable, but module is disconnected from runtime.

8) Risks & Invariants

Risks to address during consolidation

  • Persistence path divergence:
    • Legacy: .fusion/dev-server.json
    • Newer: .fusion/devserver.json
    • Consolidation must not silently flip active persistence format.
  • SSE buffering mismatch:
    • dev-server-manager.ts has SessionEventBuffer replay support.
    • dev-server-routes.ts SSE stream is direct writes + heartbeat only.
    • If manager wrapper is removed, either preserve buffering elsewhere or explicitly accept behavior change.
  • Stale PID recovery gap:
    • Present in DevServerManager.initialize() (legacy manager wrapper).
    • Not present in route path that uses DevServerProcessManager directly.
  • Test cleanup coupling:
    • Removing disconnected devserver-* files requires removing their 3 dedicated tests.
    • dev-server-manager.ts behavior is covered directly by dev-server-manager.test.ts and dev-server-manager-persistence.test.ts, and related route/SSE behavior is covered in dev-server-routes.test.ts / dev-server-config-routes.test.ts.
    • Any removal/integration of dev-server-manager.ts requires replacing equivalent buffering/recovery coverage in whichever layer keeps that behavior.

Invariants that must be preserved

  • /api/dev-server/* routes and response shapes remain stable.
  • .fusion/dev-server.json format remains backward-compatible.
  • Port 4040 is never used as fallback preview suggestion.
  • stopAllDevServers() remains callable from server.ts shutdown lifecycle.

9) Implementation Checklist for Follow-up Task

Removal / consolidation actions

  • Remove devserver-types.ts, devserver-detect.ts, devserver-persistence.ts, devserver-manager.ts
  • Remove devserver-types.test.ts, devserver-detect.test.ts, devserver-manager.test.ts
  • Decide fate of dev-server-manager.ts (remove, integrate SSE buffering into routes, or wire into routes)
  • Remove/replace associated manager tests if dev-server-manager.ts is removed
  • If adopting branded types, introduce dev-server-types.ts and migrate legacy inline type usage
  • Run full test suite and verify no regressions
  • Verify no imports remain to removed files

Validation checks

  • Documented ownership for all 10 source files remains accurate after refactor
  • Production import graph matches actual import statements
  • Route API contract and persisted storage invariants are unchanged
  • No references to deleted devserver-* modules remain in source or tests