Version
2026.4.12 (1c0672b)
Summary
Dreaming cron is gated by agents.defaults.heartbeat.activeHours. If the configured dreaming.frequency falls outside that window (e.g. common case: nightly dreaming at 03:00 while activeHours = 08:30–22:00), every run is skipped with reason=quiet-hours and no dream runs ever complete.
This contradicts the documentation in docs/concepts/dreaming.md, which uses "0 3 * * *" as the default example — implying dreaming is intended to run overnight.
Reproduction
{
"agents": {
"defaults": {
"heartbeat": {
"every": "4h",
"activeHours": { "start": "08:30", "end": "22:00", "timezone": "Europe/Berlin" }
}
}
},
"plugins": {
"entries": {
"memory-core": {
"enabled": true,
"config": {
"dreaming": { "enabled": true, "frequency": "0 3 * * *" }
}
}
}
}
}
Expected
Dreaming cron fires at 03:00 regardless of heartbeat.activeHours, because dreaming is a background maintenance task, not a user-facing heartbeat.
Actual
openclaw cron list --json shows:
name: Memory Dreaming Promotion
schedule.expr: 0 3 * * *
enabled: true
lastRunStatus: skipped
lastError: quiet-hours
consecutiveErrors: 0
- No dream runs ever complete.
Dreaming artifacts: diary absent · 0 corpus files · ingestion state absent for all agents.
- Code path:
dist/heartbeat-runner-*.js:553: reason: \"quiet-hours\" — dreaming cron executions flow through the shared heartbeat-runner which applies the activeHours check unconditionally.
- Secondary bug: on
skipped, state.lastRunAtMs is not updated, so the state appears frozen at the first skipped run forever. Makes it hard to tell from the CLI that the cron is firing at all.
Workaround (applied)
Move dreaming.frequency to a time inside activeHours (e.g. 31 8 * * * — first tick after 08:30). Semantically awkward ("dreaming at breakfast") but works.
Suggested fix
Dreaming cron should bypass heartbeat.activeHours — it's not a user-interaction signal. Either:
- Skip the activeHours check for
systemEvent cron payloads flagged as managed/background.
- Give
memory-core.dreaming its own activeHours / quietHours config (defaulting to 24/7) that is independent of heartbeat.activeHours.
Possibly related
Version
2026.4.12(1c0672b)Summary
Dreaming cron is gated by
agents.defaults.heartbeat.activeHours. If the configureddreaming.frequencyfalls outside that window (e.g. common case: nightly dreaming at03:00whileactiveHours = 08:30–22:00), every run is skipped withreason=quiet-hoursand no dream runs ever complete.This contradicts the documentation in
docs/concepts/dreaming.md, which uses"0 3 * * *"as the default example — implying dreaming is intended to run overnight.Reproduction
{ "agents": { "defaults": { "heartbeat": { "every": "4h", "activeHours": { "start": "08:30", "end": "22:00", "timezone": "Europe/Berlin" } } } }, "plugins": { "entries": { "memory-core": { "enabled": true, "config": { "dreaming": { "enabled": true, "frequency": "0 3 * * *" } } } } } }Expected
Dreaming cron fires at 03:00 regardless of
heartbeat.activeHours, because dreaming is a background maintenance task, not a user-facing heartbeat.Actual
openclaw cron list --jsonshows:Dreaming artifacts: diary absent · 0 corpus files · ingestion state absentfor all agents.dist/heartbeat-runner-*.js:553: reason: \"quiet-hours\"— dreaming cron executions flow through the shared heartbeat-runner which applies the activeHours check unconditionally.skipped,state.lastRunAtMsis not updated, so the state appears frozen at the first skipped run forever. Makes it hard to tell from the CLI that the cron is firing at all.Workaround (applied)
Move
dreaming.frequencyto a time insideactiveHours(e.g.31 8 * * *— first tick after 08:30). Semantically awkward ("dreaming at breakfast") but works.Suggested fix
Dreaming cron should bypass
heartbeat.activeHours— it's not a user-interaction signal. Either:systemEventcron payloads flagged as managed/background.memory-core.dreamingits ownactiveHours/quietHoursconfig (defaulting to 24/7) that is independent ofheartbeat.activeHours.Possibly related