feat(hooks): inject reflections via new SessionStart hook#46
Merged
Conversation
Adds an approved design + TDD implementation plan for a new SessionStart hook (better_memory.hooks.session_retrieve) that injects the project's distilled reflections as additionalContext at session start, eliminating the failure mode where Claude proceeds memory-blind on first turn. Spec covers: architecture (sibling hook, never modifies session_start.py), render format (top-10 per bucket, 600-char hint truncation), failure handling (always exit 0, fallback directive on error, hook_errors row, stderr line), out-of-scope deferrals (setup-script auto-install in Track B, semantic memory surfacing in future work). Plan: 8 TDD tasks, all >= 90% confidence, full test + impl code per step. Self-review pass clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Claude BugBot Analysis
No bugs found. The implementation is well-structured with thorough exception handling throughout. The actual test file correctly imports apply_migrations from better_memory.db.schema (the plan document contains an incorrect example import path better_memory.db.migrations, but this is only in the planning markdown, not the shipped code). The stdin drain using _MAX_STDIN_BYTES + 1 intentionally mirrors session_start.py's pattern. Hint truncation math is correct (599 chars + 1 U+2026 character = 600 chars). The retrieve_reflections call signature matches the service definition exactly.
No bugs were detected in this PR.
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.
Summary
better_memory.hooks.session_retrieve— a SessionStart hook that fetches the project's distilled reflections (do/dont/neutral, top 10 per bucket, hints truncated to 600 chars) and injects them into Claude's first turn asadditionalContext. Eliminates the failure mode where Claude skipsmemory_retrieveand proceeds memory-blind.session_start.pyspool-marker hook: on retrieval error, the hook logs a row tohook_errors, writes a stderr line, injects a fallback directive ("better-memory: memory injection failed (...) — call memory_retrieve manually"), and always exits 0. Hook contract verified bytest_returncode_always_zerowalking 3 distinct failure-states.README.mdManual setup section now registers both SessionStart hooks;website/configuration.mdgains a## Hookssection listing all four shipping hooks and their filesystem interactions.How it works
session_retrieve.main()reads stdin defensively (1 MiB cap, mirrorssession_start.py).memory.db, callsReflectionSynthesisService.retrieve_reflections(project=cwd-derived, limit_per_bucket=10).{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": ...}}, prints to stdout."no reflections recorded yet — use memory_observe"message instead of silent skip.hook_errorsrow + stderr line, still exit 0.Spec:
docs/superpowers/specs/2026-05-06-session-memory-injection-hook-design.mdPlan:
docs/superpowers/plans/2026-05-06-session-retrieve-hook.mdTest plan
uv run pytest tests/hooks/test_session_retrieve.py -v— 7 tests pass (happy path, empty DB, missing DB fallback, simulated SQL error fallback, hint truncation at 600 chars, bucket cap at 10, never-exit-nonzero across 3 states)uv run pytest -m "not integration" -q— full suite green: 717 passed, 22 skipped, 11 deselected (vs. 710 baseline = +7 new tests, zero regressions)uv run pyright better_memory/hooks/session_retrieve.py tests/hooks/test_session_retrieve.py— 0 errors, 0 warningsuv run ruff check— cleanuv run mkdocs build --strict—website/configuration.mdchange builds without warningsgit merge-tree origin/main e3d58b6— no conflicts vs current main (post-docs: align website + README with current MCP surface #45 merge)README.mdManual setup, restart Claude Code, open a fresh session in this repo, verify the first turn's system reminder includes the rendered Markdown bucket sections.BETTER_MEMORY_HOMEcontent, verify the hook injects the "no memory yet" message instead of erroring.Out of scope (deferred to follow-up tracks)
scripts/setup.shwill gain idempotent~/.claude/settings.jsonmerging so users no longer paste JSON manually. Tracked separately.Notes for review
🤖 Generated with Claude Code