feat(dream): add bd dream subcommand for memory consolidation (#3263)#3264
Open
boaz-hwang wants to merge 1 commit intogastownhall:mainfrom
Open
feat(dream): add bd dream subcommand for memory consolidation (#3263)#3264boaz-hwang wants to merge 1 commit intogastownhall:mainfrom
boaz-hwang wants to merge 1 commit intogastownhall:mainfrom
Conversation
`bd dream` is a periodic LLM-driven pass over the memory store created by
`bd remember` / `bd memories`. It identifies duplicates, stale references,
and low-signal entries and applies merge / forget / update operations.
Inspired by Claude Code's AutoDream, but built into bd so it's not coupled
to any specific editor.
- New package internal/dream with a Consolidator that wraps the existing
anthropic-sdk-go (already used by internal/compact) — same retry / model
resolution / API key resolution patterns. Tool-use is used for structured
output. A safety guard rejects plans that would delete > 50% of memories.
- New cmd/bd/dream.go subcommand with `run`, `status`, and `--check`.
Threshold gate: at least N hours since last run AND M memories of churn,
defaults 24h / 5 (matching AutoDream's "5 sessions over 24 hours" adapted
to bd's stateless model). All state lives in the Dolt config table under
the `dream.*` prefix so it syncs via `bd dolt push`.
- Added `dream.` to the kv reserved-prefix list so users cannot shadow
dream's state through `bd kv set`.
- Unit tests in internal/dream cover the safety guard, empty/malformed
responses, and the eligibility gate via a fake messagesNewer.
- Integration tests in cmd/bd/dream_embedded_test.go exercise status, the
--check exit codes, churn gating, and the missing-API-key path against
embedded Dolt.
- docs/DREAM.md documents the feature, threshold semantics, scheduler
recipes (cron / launchd / editor stop hooks), and configuration keys.
Out of scope (follow-up PRs): provider abstraction beyond Anthropic,
`bd dream config` interactive setup wizard, native scheduler / `bd dream
schedule` helper, and bd-hook-based triggering.
Reuses: `config.GetString("ai.api_key")`, `config.DefaultAIModel()`,
`store.GetAllConfig` / `SetConfig` / `DeleteConfig` / `CommitPending`,
`getActor`, `kvPrefix + memoryPrefix` from cmd/bd/memory.go.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3263.
Summary
Adds
bd dream— a subcommand that consolidates the memory store (bd remember/bd memories) by asking an LLM to identify duplicates, stale references, and low-signal entries, then applies a structuredforget/merge/updateplan via the existing storage layer. See docs/DREAM.md (added in this PR) for the full design.CLI surface:
--jsonis supported on every subcommand.What's included
internal/dream/(consolidator + prompt + safety guard + types) — all unit-tested with amessagesNewerfake (no network in tests).cmd/bd/dream.go(cobra commands + threshold logic + state read/write + apply pipeline) — integration-tested against embedded Dolt.cmd/bd/kv.go— adds\"dream.\"to the reserved-prefix list so users can't shadow dream's state viabd kv set.docs/DREAM.md+CHANGELOG.md(Unreleased entry).Conventions followed
hooksCmd/kvCmdstyle) withGroupID: \"setup\".CheckReadonly(\"dream\")on mutating ops,ensureDirectModeon every DB-touching op.store.GetAllConfigfiltered bykvPrefix + memoryPrefix(inlined as incmd/bd/memory.go:134-141).store.SetConfig/DeleteConfigfollowed by a singleCommitPending(ctx, getActor())per command run.--jsonflag respected in every subcommand (matchesbd memories/bd recall).internal/compact/haiku.goretry / API-key / model resolution pattern reused for the SDK call.//go:build cgoon the embedded-Dolt integration test file.Threshold semantics
dream.min-interval-hours(default 24) — minimum hours between runs.dream.min-churn(default 5) — minimum memory-count delta since last run.--force(nothing to consolidate otherwise).State (
dream.last-run-at,dream.last-run-status,dream.last-run-summary,dream.memory-count-at-last-run,dream.min-interval-hours,dream.min-churn) lives in the Dolt config table and syncs viabd dolt pushlike every other dream / sync-related key.Test plan
go test ./internal/dream/...— 8 unit tests pass (safety guard, malformed responses, eligibility logic).go test ./cmd/bd/ -run TestDream|TestKVReservedDream— 6 integration tests pass against embedded Dolt (status / status JSON /--checkexit codes / churn gate / missing-API-key path / reserved-prefix guard).gofmt -lclean,golangci-lint run --build-tags=gms_pure_go0 issues on changed files.make buildclean.Out of scope
internal/ai.Executor(sdk + claude-cli) so users on a Claude Code subscription can usebd dream(and eventuallybd compact) without a separate API key. Follow-up PR is already prepared on a stacked branch and will be opened once this lands. Keeping it separate per CONTRIBUTING.md's "one issue per PR" rule.bd dream configinteractive wizard.bd dream schedulehelper.bd compactandbd find-duplicates --method aionto the executor abstraction (lands with the executor PR).Local verification recipe
🤖 Generated with Claude Code