Skip to content

Re-inject recalled learnings after /compact#6

Merged
rainxchzed merged 1 commit into
mainfrom
compact-reinjection
May 31, 2026
Merged

Re-inject recalled learnings after /compact#6
rainxchzed merged 1 commit into
mainfrom
compact-reinjection

Conversation

@rainxchzed
Copy link
Copy Markdown
Contributor

Makes recall compaction-aware: after a /compact, the agent can drop the learnings injected at SessionStart, so we re-inject on SessionStart(compact) (JSON additionalContext) AND PostCompact (plain stdout) — registering both because neither is fully reliable alone on current Claude Code (SessionStart-compact output is dropped per #15174; PostCompact injection is under-documented). Recomputes recall fresh at compaction; background maintenance stays session-start-only; degrades to a no-op if neither injects. Tests added; suite 215 passed, 1 skipped. Needs on-device verification.

🤖 Generated with Claude Code

…ecall)

After a /compact (manual or auto), the agent can lose the learnings injected at
SessionStart and stop applying them mid-session. This makes the recall hook
compaction-aware so it re-injects them.

Research finding that shaped the design: no single compaction hook reliably injects
context on current Claude Code — SessionStart(source=compact) fires but its
additionalContext is dropped (issue #15174), and PostCompact's context injection is
under-documented. So we register on BOTH and emit the format each one supports:

- hook_recall.main() now routes by hook_event_name + source:
  * SessionStart (startup/resume/clear): JSON hookSpecificOutput.additionalContext
    (unchanged primary path; frozen-snapshot discipline preserved).
  * SessionStart (compact): same JSON path, with framing telling the model these are
    re-applied after compaction.
  * PostCompact: PLAIN stdout (the documented "stdout is added to context" path for
    PostCompact), framed the same way.
  Recall is recomputed fresh at compaction so it includes anything learned earlier
  this session. Background maintenance (pool sync, curator) runs ONLY on a genuine
  session start, never on a compaction re-inject.
- new hook_compact.py: thin PostCompact entry point delegating to hook_recall.main().
- setup.py + plugin hooks/hooks.json register PostCompact (merge-not-clobber,
  idempotent, absolute interpreter path, removed on uninstall).

Best-effort by design: if a host version injects on neither event, it degrades to a
harmless no-op (learnings stay on disk, reload fully next session). Needs on-device
verification given the upstream hook bugs.

Tests: tests/test_compact_reinjection.py (event routing, framing, plain-vs-JSON,
graceful failure, maintenance-only-on-start, installer registers + idempotent +
uninstall + plugin manifest). Full suite 215 passed, 1 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rainxchzed rainxchzed merged commit f088e43 into main May 31, 2026
5 checks passed
@rainxchzed rainxchzed deleted the compact-reinjection branch May 31, 2026 06:01
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