Skip to content

feat: attention-first memory injection redesign#77

Merged
emp3thy merged 19 commits into
mainfrom
feat/attention-first-injection
Jul 11, 2026
Merged

feat: attention-first memory injection redesign#77
emp3thy merged 19 commits into
mainfrom
feat/attention-first-injection

Conversation

@emp3thy

@emp3thy emp3thy commented Jul 11, 2026

Copy link
Copy Markdown
Owner

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)

  • Top-N memories (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 stamps
  • Everything else becomes a one-line index + "call memory_retrieve" affordance — nothing invisible, nothing eating attention
  • General-scope semantic memories (behavioural rules) always render in full

Contextual injection (UserPromptSubmit / PreToolUse)

  • Hits-x-activation scoring (title hits weighted, useful_count/confidence boost, misled penalty) with a relevance floor (BETTER_MEMORY_CONTEXT_MIN_HITS, default 2) — below floor, inject nothing
  • Per-session seen-file dedup (state/context_seen_<session>.json) — a memory injects once per session (BETTER_MEMORY_CONTEXT_REINJECT_TURNS to loosen)
  • <project-memory> XML block: factual framing, full ids, ages, dont-items flipped to corrective phrasing, inline memory_credit affordance
  • Exposure rows written with source='contextual' via new record_exposures protocol 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 left
  • 5 diagnostics counters (fired/injected/suppressed) observable on /diagnostics

Rating loop

  • Stop-hook RATE_MEMORIES directive now shows per-source labels ([bootstrap|retrieve|contextual]) and per-source counts
  • E2E integration test covers inject -> exposure -> directive -> rate -> ranking bump

Drive-by fix

  • UI tests leaked a live watchdog thread that 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). All create_app() test call sites now pass start_watchdog=False.

Testing

  • 1240 tests, 0 failures, 0 errors (junit-verified); new unit coverage for scoring/floor/dedup/renderer/exposures/migration round-trip + e2e rating loop
  • Every task passed a two-stage subagent review (spec + quality); final whole-branch review verdict: ready to merge

docs unaffected areas: observation-lifecycle.md, index.md, agentcore-setup.md (verified no drift)

🤖 Generated with Claude Code

emp3thy and others added 18 commits July 11, 2026 11:32
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…confidence-scored)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…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>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…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.

@github-actions github-actions 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.

🟢 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>

@github-actions github-actions 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.

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

@emp3thy
emp3thy merged commit ba2c824 into main Jul 11, 2026
3 checks passed
@emp3thy
emp3thy deleted the feat/attention-first-injection branch July 11, 2026 18:31
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