feat: attention-first memory injection redesign#77
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…confidence-scored) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ts/max_items/reinject_turns)
…ounters Widens session_memory_exposure.source CHECK to admit 'contextual' and seeds 5 contextual_* rating_diagnostics counters, via the standard table-recreation pattern (SQLite can't ALTER a CHECK constraint). Numbered 0012 not 0011 (as the SDD task brief specified) because 0011_trigram_fts.sql landed on main first and claimed that version. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hread os._exit(0)-killed the pytest process mid-suite Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oth backends Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-items cap Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t-flip, rating affordance
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…l ids and age stamps
…p slimming Document the four new injection-tuning env vars (BOOTSTRAP_TOP_N, CONTEXT_MIN_HITS, CONTEXT_MAX_ITEMS, CONTEXT_REINJECT_TURNS), the contextual_inject hook (hits-x-activation scoring, seen-file dedup, project-memory block, contextual exposure source), bootstrap top-N slimming, and the per-source rating directive. All facts verified against the code landed in Tasks 1-11. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… state/ layout REINJECT_TURNS docs implied a turn = one prompt-response cycle; a turn is actually one firing of the contextual_inject hook (each user prompt, plus each matched Skill|Task|Write tool call in mode both). Also note the contextual_* rating_diagnostics counters are per-firing not per-item, and add the state/ directory (context_seen_<session_id>.json) to the BETTER_MEMORY_HOME filesystem-layout tree in configuration.md.
…n agentcore - tests/hooks/test_contextual_inject.py: make the bm_home fixture autouse so every test in the module runs against a tmp BETTER_MEMORY_HOME; five tests previously called hook.main() with no home override and wrote to the developer's real memory.db/diagnostics/state files. - better_memory/hooks/contextual_inject.py: only open a sqlite connection when cfg.storage_backend == "sqlite" (nullcontext(None) otherwise, passed as memory_conn=None to build_backend, whose agentcore branch ignores it). Previously the hook unconditionally created memory.db (+WAL) on agentcore-only installs. _bump_diagnostic now also no-ops on a None conn. - Added test_agentcore_mode_does_not_open_sqlite_connection asserting connect() is never called and build_backend receives memory_conn=None when storage_backend=agentcore. - better_memory/services/relevant.py: _age_days now catches (ValueError, TypeError) from datetime.fromisoformat, not just ValueError.
There was a problem hiding this comment.
🟢 Claude BugBot Analysis
Reviewed all production code changes (config, migration 0012, contextual_inject hook, session_close, context_seen, reflection/relevant scoring, session_bootstrap, and the sqlite/agentcore/protocol storage backends). Signatures, new schema columns, and edge-case guards are all consistent, and no reachable logic errors, null-derefs, or resource issues were found in the added/modified lines.
No bugs were detected in this PR.
… rejected dict-unpack helper Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Claude BugBot Analysis
Reviewed the contextual-injection feature (hook, seen-store dedup, relevance scoring, session-bootstrap slimming, exposure-tracking protocol for sqlite/agentcore, migration 0012, and the rating directive). No genuine bugs found — all cross-file contracts (signatures, dataclass fields, SQL columns/CHECK constraints, config plumbing) verified consistent.
No bugs were detected in this PR.
Summary
Redesigns how better-memory injects memories into running Claude Code sessions so the LLM actually attends to them, and closes the rating feedback loop for contextually-injected memories. Implements the approved spec
docs/superpowers/specs/2026-07-11-attention-first-injection-design.md(research-backed: recency-end injection, precision-over-recall floors, index+affordance over dumps, factual XML framing, Stop-hook rating directives).Bootstrap slimming (SessionStart)
BETTER_MEMORY_BOOTSTRAP_TOP_N, default 5;0= legacy full dump) rendered in full with full ids (fixes 8-char truncation bug that made semantic memories unrateable) and age stampsContextual injection (UserPromptSubmit / PreToolUse)
BETTER_MEMORY_CONTEXT_MIN_HITS, default 2) — below floor, inject nothingstate/context_seen_<session>.json) — a memory injects once per session (BETTER_MEMORY_CONTEXT_REINJECT_TURNSto loosen)<project-memory>XML block: factual framing, full ids, ages, dont-items flipped to corrective phrasing, inlinememory_creditaffordancesource='contextual'via newrecord_exposuresprotocol method (migration 0012; agentcore no-op per its no-exposure-log contract) — contextual injections are now rateable, closing the gap PR Contextual memory injection hook (UserPromptSubmit + PreToolUse) #76 leftRating loop
[bootstrap|retrieve|contextual]) and per-source countsDrive-by fix
os._exit(0)-killed the whole pytest run mid-suite with exit code 0 (looked like a phantom hang; explains the repo-root graveyard of truncated test logs). Allcreate_app()test call sites now passstart_watchdog=False.Testing
docs unaffected areas: observation-lifecycle.md, index.md, agentcore-setup.md (verified no drift)
🤖 Generated with Claude Code