Skip to content

Fix summarizer hot path: capture on SessionEnd, drain in background#8

Open
jamby77 wants to merge 10 commits into
masterfrom
fix/summarizer-hot-path
Open

Fix summarizer hot path: capture on SessionEnd, drain in background#8
jamby77 wants to merge 10 commits into
masterfrom
fix/summarizer-hot-path

Conversation

@jamby77

@jamby77 jamby77 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Problem

The Stop hook 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

  • Capture on SessionEnd (fires once), not Stop (every turn) — with a migration that strips the stale Stop registration from existing installs.
  • Queue-only capture hook — the hook parses the transcript, pushes to the existing ingest queue, spawns a detached drainer, and exits in milliseconds. No LLM ever runs on a hook.
  • Reject empty summaries before they reach the store (isEmptySummary predicate); husks are dropped, not re-queued.
  • Plus small fixes made while verifying: correct the stale Stop label in the install summary, fix an integration test that recalled by the wrong embed text, and gitignore .idea/.

Verification

bun run typecheck clean · bun test tests/unit green · bun test tests/integration green (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 Stop hook to SessionEnd, so summarization no longer runs on every assistant response or blocks the hook path.

The session-end hook now only parses the transcript, pushes to the Valkey ingest queue, and spawns a detached drain process (compiled binary or bun run source). AgingPipeline.processIngestQueue performs LLM summarization and storage. Install and register-hooks register SessionEnd instead of Stop, and stripLegacyBetterdbHooks removes stale Stop entries on upgrade without touching third-party hooks.

Adds isEmptySummary so default-schema “husks” are dropped from the ingest queue (not stored or re-queued). New betterdb-memory drain command and drain binary in the install set. Hook payload schema switches from StopPayload to SessionEndPayload.

Reviewed by Cursor Bugbot for commit 2e3e752. Bugbot is set up for automated code reviews on this repo. Configure here.

jamby77 added 8 commits July 16, 2026 18:54
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 jamby77 changed the title fix/summarizer hot path Fix summarizer hot path: capture on SessionEnd, drain in background Jul 17, 2026
Comment thread src/hooks/session-end.ts
@jamby77
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.
Comment thread src/hooks/session-end.ts
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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread src/index.ts
// Stop registration must be stripped explicitly or it survives upgrades.
const existingHooks = stripLegacyBetterdbHooks(
(settings["hooks"] ?? {}) as Record<string, unknown[]>,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2e3e752. Configure here.

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