Skip to content

Stop the dream cycle aborting when memory consolidation returns early - #495

Merged
rockfordlhotka merged 2 commits into
mainfrom
fix/dream-cycle-consolidation-abort
Aug 6, 2026
Merged

Stop the dream cycle aborting when memory consolidation returns early#495
rockfordlhotka merged 2 commits into
mainfrom
fix/dream-cycle-consolidation-abort

Conversation

@rockfordlhotka

Copy link
Copy Markdown
Member

Summary

The memory consolidation pass ran inline at the top of DreamAsync, and its two early exits — fewer than two stored entries, or a null result from the LLM — used a bare return. That returned from the whole dream cycle, not just the pass, so every pass behind it was silently skipped.

The worst case is a freshly provisioned agent. With an empty memory store, consolidation hits the all.Count < 2 guard on every cycle, so memory mining never runs and the store can never reach two entries. It is a deadlock: the agent cannot mine its first memory, and nothing in the logs says why — the cycle logs as started but never logs as complete.

// before — inside DreamAsync, so this returns from the cycle
var all = await _memory.SearchAsync(new MemorySearchCriteria(MaxResults: 1000));
if (all.Count < 2) { ...; return; }   // <- skips episode, entity, mining, everything

Extracted into RunMemoryConsolidationPassAsync, returning its deleted/saved counts, so the early exits return from the pass and the cycle continues.

Most of the diff is re-indentation from that extraction; reviewing with ?w=1 shows the real change is ~100 lines.

Also in this change

Two dream-subsystem fixes found while scoping the above. Calling them out rather than burying them:

  • Dream:MemoryConsolidationEnabled (default true, so existing deployments are unaffected). Consolidation is the only pass that rewrites stored entries rather than only adding or deleting them, which makes it the only place a dream model can introduce detail that no source entry contained — and since it reads the memory store as its own input, anything it invents is re-ingested as fact next cycle. Mining, episode and entity extraction all derive from the conversation log and can be checked against it. Turning it off costs duplicate merging, importance re-scoring and decay, all of which live inside the pass.

  • Dream:ModelTier (default Balanced, matching previous behaviour). One pass was hardcoded to ModelTier.Balanced while the rest of the cycle honoured the configured tier. Dream passes are structured extraction — read a transcript, return JSON — so pointing them at a different tier from the conversational one is useful independently of the bug.

Testing

  • New DreamMemoryConsolidationToggleTests: default-enabled, environment-style binding (Dream__MemoryConsolidationEnabled), and independence from Dream:MemoryMiningEnabled.
  • Full RockBot.Host.Tests suite passes (1080), verified with only this change applied and rebased onto current main.

Note on the first commit

This branch also carries a one-line .gitignore fix. deploy/docker-compose/agent-data/ is the bind-mounted runtime directory for the compose agent — profile markdown, long-term memory store, knowledge graph, conversation transcripts. It was untracked but not ignored, so git add -A would stage the entire local agent state. It has never been committed; this only prevents it. agent.extra.env is ignored alongside it for the same reason as the existing .env entry: it can carry provider credentials.

Happy to split that into its own PR if preferred — it is unrelated to the dream fix, but it seemed worth landing promptly.

🤖 Generated with Claude Code

rockfordlhotka and others added 2 commits August 6, 2026 00:00
deploy/docker-compose/agent-data/ is the bind-mounted runtime directory for the
compose agent — it holds the agent profile markdown, the long-term memory store,
the knowledge graph, and full conversation transcripts. It was untracked but not
ignored, so `git add -A` would stage the entire local agent state (517 files in a
working setup) into the repository.

Also ignores agent.extra.env, the optional env_file escape hatch for raw .NET
config keys, which sits next to the already-ignored .env and can likewise contain
provider credentials.

Neither belongs in source control: both are per-operator local state.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The memory consolidation pass ran inline at the top of DreamAsync, and its two
early exits — fewer than two stored entries, or a null result from the LLM — used
a bare `return`. That returned from the whole dream cycle, not just the pass, so
every later pass was silently skipped.

The worst case is a freshly provisioned agent. With an empty memory store,
consolidation hits the `all.Count < 2` guard on every cycle, so memory mining
never runs and the store can never reach two entries. It is a deadlock: the agent
cannot mine its first memory, and nothing in the logs says why, because the cycle
reports as started but never reports as complete.

Extracted the pass into RunMemoryConsolidationPassAsync, returning its deleted and
saved counts, so its early exits return from the pass and the cycle continues.

Also in this change, both dream-subsystem fixes found alongside it:

- Dream:MemoryConsolidationEnabled (default true, so existing deployments are
  unaffected). Consolidation is the only pass that rewrites stored entries rather
  than only adding or deleting them, which makes it the only place a dream model
  can introduce detail no source entry contained. Turning it off costs duplicate
  merging, importance re-scoring and decay, all of which live inside the pass.

- Dream:ModelTier (default Balanced, matching the previous behaviour). One pass
  was hardcoded to ModelTier.Balanced while the rest of the cycle honoured the
  configured tier. Dream passes are structured extraction, so being able to point
  them at a different tier from the conversational one is useful in its own right.

Tests cover the toggle default, environment-style binding, and independence from
Dream:MemoryMiningEnabled. Full RockBot.Host.Tests suite passes (1080).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rockfordlhotka
rockfordlhotka merged commit 984e856 into main Aug 6, 2026
2 checks passed
@rockfordlhotka
rockfordlhotka deleted the fix/dream-cycle-consolidation-abort branch August 6, 2026 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant