LearnNewsExamplesServices
Frontmatter
id11074
titleExtract WakeSubstrateCoordinatorService as M4 per-task coordinator (fold bridge-daemon into orchestrator)
stateClosed
labels
enhancementaiarchitecturemodel-experience
assignees[]
createdAtMay 10, 2026, 12:55 AM
updatedAtMay 12, 2026, 4:08 AM
githubUrlhttps://github.com/neomjs/neo/issues/11074
authorneo-opus-4-7
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 10, 2026, 5:45 PM

Extract WakeSubstrateCoordinatorService as M4 per-task coordinator (fold bridge-daemon into orchestrator)

Closedenhancementaiarchitecturemodel-experience
neo-opus-4-7
neo-opus-4-7 commented on May 10, 2026, 12:55 AM

Context

Operator confirmed 2026-05-10: "of course we want heartbeat and bridge daemon inside our new orchestrator!" — supersedes the originally-out-of-scope framing in v13-path.md:94 (which said "bridge-daemon's specialized HTTP/osascript-driven domain stays separate"). Fold direction is in-scope.

Operator further surfaced 2026-05-10: "sunset wakeups => KILL harness, restart, start a fresh session. important for nightshift mode... I challenge it should be in scope." This ticket includes sunset-wake handling in the fold scope.

Sibling-precedent shape: #11062 (BackupCoordinatorService) + HeartbeatCoordinatorService (filed in same batch).

The Problem

Bridge-daemon currently runs as a separate persistent-process daemon (ai/scripts/bridge-daemon.mjs):

  • Operator must keep terminal open OR install launchd plist (anti-pattern per #11066/#11067 retraction)
  • Tail-syncs SQLite GraphLog every ~2-3s for low-latency wake delivery
  • Coalesces wake events per WAKE_SUBSCRIPTION
  • Delivers via osascript (Antigravity / Claude Code / Codex Desktop) or tmux
  • (Subprocess) Sunset detection + recovery dispatch via checkSunsetted.mjs + resumeHarness.mjs

Folding into orchestrator unifies persistent-process management — operator runs one daemon (orchestrator), no separate bridge process.

Architectural Reality

Bridge-daemon's work split:

Concern Substrate
GraphLog tail-sync SQLite polling (getLastSyncId, getGraphLogEntries)
Wake-event coalescing Per-subscription coalescing window
osascript / tmux delivery Operating-system-specific (macOS osascript)
Sunset detection Subprocess checkSunsetted.mjs
Sunset recovery Subprocess resumeHarness.mjs (KILL harness, spawn fresh session)
Idle-out nudge Subprocess idleOutNudge.mjs
All-agent-idle trio-wake Subprocess trioWakeCooldown.mjs

Folding shape: WakeSubstrateCoordinatorService.getDueTask() returns trigger when pending wake events exist OR sunset detected; orchestrator's cadenceEngine.runIfDue('wake', ...) invokes the work. Tail-sync polling runs at orchestrator's poll cadence (3s default).

Sunset wake scope (operator-challenged in-scope): include sunset detection + resumeHarness recovery dispatch in this fold. Important for nightshift mode (operator-offline scenario where stale agent harnesses need automatic kill+restart).

Open questions for pickup /ticket-intake:

  1. Does the wake-coalescing window play well with orchestrator's 3s poll cadence?
  2. Subprocess-to-direct-import migration (#10795) — does this ticket include or sibling-defer?
  3. PID-lock substrate (bridge-daemon.pid) retires; orchestrator's PID-file substrate absorbs single-instance enforcement

Acceptance Criteria

  • /ticket-intake validates premise + 3 open questions
  • ai/daemons/services/WakeSubstrateCoordinatorService.mjs per #11062 sibling shape
  • Bridge tail-sync + delivery + sunset detection + recovery dispatch all fold to coordinator-pattern
  • ai/scripts/bridge-daemon.mjs deleted (entry-point obsoleted by fold)
  • If com.neomjs.bridge-daemon.plist.template ever existed, deleted (it doesn't — was never created post-#11066/#11067 closure)
  • learn/agentos/wake-substrate/PersistentProcessManagement.md scope-trimmed or retired
  • Wire-in via cadenceEngine.runIfDue
  • Cross-family review per pull-request §6.1
  • Operator validation: bridge functionality preserved end-to-end (wake delivery + sunset recovery)
  • v13-path.md:94 updated — replace "out of scope: wake-event delivery" with M4-fold reference

Dependencies

  • Hard: Blocked by #11062 + #11065 merge for wire-in pattern
  • Coordination: plist + docs cleanup ACs ride along
  • Sibling: HeartbeatCoordinatorService (M4 fold sibling; both retire learn/agentos/wake-substrate/ substrate together)

Out of Scope

  • Detailed prescription pre-staged here (would go stale per #11062/#11065 lesson)
  • Cross-platform wake delivery beyond current macOS osascript + tmux scope (sibling-fileable when Linux/Windows operators arrive)
  • Subprocess elimination of remaining wake-substrate scripts beyond what's needed for the fold (ride-along OR sibling-defer per pickup-time judgment)

Related

  • Parent landscape: #11022 → M4
  • Siblings: #11062, #11065, HeartbeatCoord (filed in same batch), DreamCoord (filed in same batch), GoldenPathCoord (filed in same batch), GraphMaintenanceCoord (filed in same batch)
  • Architectural conflict to resolve: learn/agentos/v13-path.md:94 (says bridge stays separate; this ticket reverses that direction per operator clarification 2026-05-10)
  • Source: ai/scripts/bridge-daemon.mjs, ai/scripts/bridge-daemon-queries.mjs
  • Subprocess-companion work: #10795 (CLI-shape scripts → dual-mode imports)
  • Closed-as-anti-pattern: #11066/#11067 (per-daemon plist packaging)
  • Operator correction trail: PR #11067 closure comment + 2026-05-10 swarm broadcast

Self-Identification: @neo-opus-4-7 (Claude Opus 4.7, Claude Code) — landscape-visibility filing 2026-05-10 per operator directive. Includes operator-challenged sunset-wake scope (originally framed out-of-scope; in-scope per nightshift-mode importance).

Origin Session ID: c2912891-b459-4a03-b2af-154d5e264df1