LearnNewsExamplesServices
Frontmatter
titlefeat(agentos): extract DreamCoordinatorService — getDueTask only (#11858)
authorneo-opus-ada
stateMerged
createdAtMay 23, 2026, 9:34 PM
updatedAtMay 23, 2026, 10:37 PM
closedAtMay 23, 2026, 10:37 PM
mergedAtMay 23, 2026, 10:37 PM
branchesdevtobiu/11858-dream-coordinator-service
urlhttps://github.com/neomjs/neo/pull/11863
Merged
neo-opus-ada
neo-opus-ada commented on May 23, 2026, 9:34 PM

Authored by Claude Opus 4.7 (Claude Code). Session 5572d9a5-558d-4bea-b416-e31496c289c4.

FAIR-band: in-band [verify @ merge-gate]

Resolves #11858

Summary

Sub 15 of Epic #11831 — first of three coordinator extractions in Discussion #11857 Cycle-3.5 B-prime convergence (GPT [GRADUATION_APPROVED] DC_kwDODSospM4BA-... + operator architectural ratify). Matches D3.1 boundary per learn/agentos/v13-path.md:117: per-task coordinators decide what work is due; orchestrator wires; ProcessSupervisor executes.

Evidence: L1 (8/8 pure-function unit tests pass) → L1 required for pure extraction (no behavioral change at orchestrator surface; new service is not wired in this Sub — Sub 18 #11862 owns the registry integration).

Changes

Creates ai/daemons/orchestrator/services/DreamCoordinatorService.mjs:

  • Pure-function buildDreamTrigger({now, lastRunAt, intervalMs}) returns {taskName, source, reason} or null
  • DreamCoordinatorService.getDueTask({state, now, dreamIntervalMs}) wraps the pure function with state-shape mapping
  • Mirrors SummarizationCoordinatorService.getDueTask({...}) precedent shape

Creates test/playwright/unit/ai/daemons/orchestrator/services/DreamCoordinatorService.spec.mjs (8 pure-function tests).

Strict boundary preserved (per Discussion #11857 Avoided Traps)

  • DreamService retains processUndigestedSessions() and all execution-side methods unchanged
  • Coordinator owns due-trigger selection ONLY (D3.1 boundary)
  • No state writes / no markStarted / markCompleted / recordTaskOutcome calls
  • No reactive-config-aliased wrapper around DreamService (Sub-1 anti-pattern at new layer explicitly avoided)
  • Orchestrator's scheduleDreamCycle() body unchanged in this Sub; Sub 18 #11862 wires the new coordinator into the registry

Test Evidence

npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DreamCoordinatorService.spec.mjs8/8 pass (587ms)

Test coverage:

  • Interval-elapsed boundary: returns trigger when now - lastRunAt >= intervalMs
  • Interval-not-elapsed: returns null
  • Disabled (intervalMs <= 0): returns null for 0 and negative
  • Exactly-equal-to-interval edge: returns trigger (≥ boundary)
  • Reason carries interval verbatim (for telemetry/audit)
  • getDueTask wraps buildDreamTrigger correctly with state mapping
  • getDueTask handles missing state gracefully (lastRunAt defaults to 0)
  • getDueTask returns null when state.lastRunAt is recent

Post-Merge Validation

  • Operator confirms no regression in orchestrator boot or dream-cycle scheduling (new service exists but is not wired yet; should be no observable change)
  • Sub 18 #11862 (registry wire-up) consumes the new coordinator post-merge of Subs 15/16/17/19

Deltas from ticket

None — implementation matches #11858 ACs verbatim.

Depends on

Epic #11831 (parent). Independent of Subs 16/17/19 (parallel-safe extractions).

Unblocks

Sub 18 #11862 (wire-up needs all 3 coordinators registered).

Authority chain

Discussion #11857 Cycle-3.5 GPT [GRADUATION_APPROVED] (DC_kwDODSospM4BA-...) + operator architectural ratify in-session 2026-05-23.

Per @tobiu's "you and me" instruction for Epic #11831 lane: no peer-review broadcast.