LearnNewsExamplesServices
Frontmatter
id11070
titleExtract DreamCoordinatorService as M4 per-task coordinator (DreamService cycle scheduling)
stateClosed
labels
enhancementaiarchitecturemodel-experience
assignees[]
createdAtMay 10, 2026, 12:53 AM
updatedAtMay 12, 2026, 4:08 AM
githubUrlhttps://github.com/neomjs/neo/issues/11070
authorneo-opus-4-7
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 10, 2026, 1:53 AM

Extract DreamCoordinatorService as M4 per-task coordinator (DreamService cycle scheduling)

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

Context

M4 per-task coordinator landscape per learn/agentos/v13-path.md:193:

"DreamCoordinatorService / SandmanCoordinatorService / BackupService / GoldenPathCoordinatorService / GraphMaintenanceCoordinatorService — each owning 'what work is due' semantics; supervisor executes; orchestrator wires per D3.1 boundary."

Sibling-precedent shape: #11062 (BackupCoordinatorService) + #11065 (SandmanCoordinatorService). DreamCoord pairs tightly with SandmanCoord — both schedule DreamService.mjs work — but the two have distinct cadence concerns: Sandman triggers full REM pipeline (heavy gemma4 work); Dream cycle work is the per-session graph extraction inside that pipeline.

The Problem

DreamService cycles currently fire via:

  • autoDream: true startup auto-trigger (operator-disabled per safety pause)
  • Manual npm run ai:run-sandman invocation
  • Inside-Sandman per-session loop

Without orchestrator-driven scheduling, the DreamService cycle vs Sandman REM pipeline boundary is implicit + impossible to schedule independently. M4 separation makes per-task fairness explicit.

Architectural Reality

Open question for pickup: is "Dream cycle scheduling" actually a separate concern from "Sandman REM pipeline scheduling," or does SandmanCoordinatorService (#11065) absorb both? Per v13-path.md:193 they're listed as separate coordinators. Pickup-time /ticket-intake should validate this against post-#11062 + post-#11065 reality.

If they collapse into one coordinator, this ticket may resolve via supersession into #11065. If they stay separate, this ticket needs its own getDueTask({...}) semantics distinct from Sandman's full-REM-pipeline trigger.

Acceptance Criteria

  • /ticket-intake validates premise post-#11065 merge — confirm separate coordinator vs. fold-into-Sandman
  • If separate: ai/daemons/services/DreamCoordinatorService.mjs per #11062 sibling shape (class-only file; pure getDueTask)
  • If fold: close as duplicate of #11065 with rationale
  • Wire-in via cadenceEngine.runIfDue per post-Sub-4 pattern
  • Cross-family review per pull-request §6.1

Dependencies

  • Hard: Blocked by #11062 (BackupCoord) + #11065 (SandmanCoord) merge — wire-in shape post-Sub-4 + interaction with Sandman's REM pipeline trigger
  • Pickup-time intake mandate: prescription deferred to avoid stale wire-in assumptions (lesson from #11062/#11065 going stale post-Sub-4)

Out of Scope

  • Detailed prescription pre-staged here — would go stale per the empirical pattern
  • DreamService itself (already exists at ai/daemons/DreamService.mjs; this ticket is about scheduling, not implementation)

Related

  • Parent landscape: #11022 (M3.5 epic, MERGED) → M4 successor work
  • Sibling M4 coordinators: #11062 (BackupCoord), #11065 (SandmanCoord), + 3 more being filed in same batch
  • Architectural anchor: learn/agentos/v13-path.md:193 (M4 per-task coordinator naming)
  • DreamService source: ai/daemons/DreamService.mjs

Self-Identification: @neo-opus-4-7 (Claude Opus 4.7, Claude Code) — landscape-visibility filing per operator directive 2026-05-10. Open lane for self-selection post-#11062/#11065 cascade.

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