Fix summarizer hot path: capture on SessionEnd, drain in background#8
Open
jamby77 wants to merge 10 commits into
Open
Fix summarizer hot path: capture on SessionEnd, drain in background#8jamby77 wants to merge 10 commits into
jamby77 wants to merge 10 commits into
Conversation
Every SessionSummarySchema field has a default, so {} parses into a
valid-looking husk. Drop those instead of storing them.
The hook duplicated AgingPipeline.processIngestQueue with worse error handling. It now only queues the transcript.
The capture hook now returns immediately and a background drain does the summarization, so no LLM work runs inside a Claude Code hook.
Stop fires each time Claude finishes responding, so the plugin summarized the whole session on every turn. Also removes the stale Stop registration from existing installs.
The hook registration was renamed to SessionEnd but the install summary still printed Stop.
storeMemory embeds buildEmbedText (the full summary); the recall helper re-embedded only oneLineSummary, so with the deterministic fake embed the stored and query vectors diverged past the 0.25 distance threshold and KNN returned nothing. Re-embed the same text so the round-trip is faithful.
jamby77
marked this pull request as ready for review
July 17, 2026 08:42
Install and config already fall back to USERPROFILE; the drain spawn did not, so on Windows the path never resolved and the queue silently never drained.
register-hooks.ts registers hooks as `bun run <src>` and compiles no binaries, so ~/.betterdb/bin/drain does not exist on that path. The exists() guard then skipped the spawn silently and nothing ever drained the queue. Resolve the compiled binary first, the sibling source second, and report to stderr when neither is found.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2e3e752. Configure here.
| // Stop registration must be stripped explicitly or it survives upgrades. | ||
| const existingHooks = stripLegacyBetterdbHooks( | ||
| (settings["hooks"] ?? {}) as Record<string, unknown[]>, | ||
| ); |
There was a problem hiding this comment.
Install omits dev hook markers
Medium Severity
betterdb-memory install calls stripLegacyBetterdbHooks with only the default betterdb marker, while register-hooks.ts also passes the plugin src/hooks path. A leftover Stop registration whose command path does not contain betterdb can survive install and keep firing the old per-turn hook alongside SessionEnd.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 2e3e752. Configure here.
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.


Problem
The
Stophook fires on every turn, so the plugin re-summarized the whole session on each response — burning minutes of local LLM time on a hook, blocking the turn, and discarding the work when the Ollama client timed out. The success path stored empty husks (SessionSummarySchema.parse({})passes and yields "Session recorded — summary unavailable"). Net result over 8 days: one memory, and it was empty; after a GPU fix, near-duplicate memories appeared one-per-turn.Change
SessionEnd(fires once), notStop(every turn) — with a migration that strips the staleStopregistration from existing installs.isEmptySummarypredicate); husks are dropped, not re-queued.Stoplabel in the install summary, fix an integration test that recalled by the wrong embed text, and gitignore.idea/.Verification
bun run typecheckclean ·bun test tests/unitgreen ·bun test tests/integrationgreen (against Valkey on 6390).Stack
Bottom of a 2-PR stack. The follow-on #9 (checkpoint capture) builds directly on this branch — merge this one first.
Note
Medium Risk
Changes when and how session memories are captured (hook lifecycle + async drain); misconfiguration could leave transcripts queued until drain runs, but hooks no longer block on LLM calls.
Overview
Moves session memory capture off the per-turn
Stophook toSessionEnd, so summarization no longer runs on every assistant response or blocks the hook path.The
session-endhook now only parses the transcript, pushes to the Valkey ingest queue, and spawns a detacheddrainprocess (compiled binary orbun runsource).AgingPipeline.processIngestQueueperforms LLM summarization and storage. Install andregister-hooksregisterSessionEndinstead ofStop, andstripLegacyBetterdbHooksremoves staleStopentries on upgrade without touching third-party hooks.Adds
isEmptySummaryso default-schema “husks” are dropped from the ingest queue (not stored or re-queued). Newbetterdb-memory draincommand anddrainbinary in the install set. Hook payload schema switches fromStopPayloadtoSessionEndPayload.Reviewed by Cursor Bugbot for commit 2e3e752. Bugbot is set up for automated code reviews on this repo. Configure here.