Skip to content

fix(agent): historicalize persisted compaction handoffs - #42895

Closed
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/historicalize-compaction-handoff
Closed

fix(agent): historicalize persisted compaction handoffs#42895
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/historicalize-compaction-handoff

Conversation

@konsisumer

Copy link
Copy Markdown
Contributor

What does this PR do?

This hardens context-compaction handoffs so resumed or idle-reset conversations do not see live-sounding persisted headings like ## Active Task and continue stale work from an old session. Persisted summaries now use explicitly historical section names in the transcript, while resume-time rehydration converts them back to the canonical internal headings the iterative compressor expects.

Related Issue

Fixes #42812

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • agent/context_compressor.py: rewrite persisted handoff headings from canonical active names to explicit historical names before prefixing the compaction summary, and canonicalize those headings again when a resumed session rehydrates the summary for iterative updates.
  • tests/agent/test_resume_stale_active_task.py: add resume-path regressions proving historicalized handoffs are restored to canonical internal headings while old prefixes still normalize correctly.
  • tests/agent/test_context_compressor_summary_continuity.py: add coverage that the transcript-facing handoff is historicalized without mutating the compressor's internal _previous_summary state.

How to Test

  1. Run pytest tests/agent/test_resume_stale_active_task.py tests/agent/test_context_compressor_summary_continuity.py -q and confirm the new stale-handoff regressions pass.
  2. Create or load a conversation with a compaction handoff, then verify the persisted handoff text now uses ## Historical Task (prior session), ## Previous In-Flight Work, ## Previous Pending User Asks, and ## Previous Work State instead of the live-sounding headings.
  3. Re-run compaction on that resumed transcript and verify iterative summary state still restores to canonical internal headings, so the compressor updates the prior summary instead of treating the historical headings as a brand-new user instruction.
  4. Optionally run the broader compressor-focused subset used here: pytest tests/agent/test_compress_focus.py tests/agent/test_compression_concurrent_fork.py tests/agent/test_compression_logging_session_context.py tests/agent/test_compressor_historical_media.py tests/agent/test_compressor_image_tokens.py tests/agent/test_context_compressor.py tests/agent/test_context_compressor_cross_session_guard.py tests/agent/test_context_compressor_summary_continuity.py tests/agent/test_context_compressor_temporal_anchoring.py tests/agent/test_context_engine.py tests/agent/test_context_engine_host_contract.py tests/agent/test_last_total_tokens.py tests/agent/test_memory_provider.py tests/agent/test_resume_stale_active_task.py tests/agent/test_summary_prefix_semantics.py tests/agent/test_turn_context.py tests/gateway/test_compress_command.py tests/gateway/test_compress_focus.py tests/gateway/test_compress_plugin_engine.py tests/gateway/test_compression_concurrent_sessions.py tests/gateway/test_session_hygiene.py tests/gateway/test_usage_command.py -q.

What platforms tested on

  • macOS 15 / darwin-arm64 (local worktree)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 / darwin-arm64

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

  • Targeted regressions passed: pytest tests/agent/test_resume_stale_active_task.py tests/agent/test_context_compressor_summary_continuity.py -q
  • The required broad local command /opt/homebrew/bin/timeout -k 30 480 sh -c 'pytest tests/ -q -x --timeout=60 "$@"' sh stopped early on an unrelated shared-venv import error: ModuleNotFoundError: No module named 'fastapi' while collecting tests/hermes_cli/test_dashboard_auth_401_reauth.py.
  • The mechanical compressor-covering subset completed and our changed-module tests passed, but several unrelated pre-existing tests failed under the sandbox when they instantiated AIAgent and tried to open /Users/kon5i/.hermes/logs/agent.log (PermissionError: [Errno 1] Operation not permitted).

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Jun 9, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Positive verification: Reviewed the diff — expanding on_session_end() to clear all per-session compressor state (matching on_session_reset()'s surface) is correct defense-in-depth. The original #38788 fix only cleared _previous_summary, but stale _ineffective_compression_count, _summary_failure_cooldown_until, _last_compress_aborted, and _context_probed could all leak across session boundaries on compressor reuse. The test file covers each variable individually. LGTM.

@konsisumer

Copy link
Copy Markdown
Contributor Author

For maintainer context: #42813 (by @JerryLiu369, opened ~3.5h before this PR) is already open on the same issue #42812 and overlaps this change directly — both edit agent/context_compressor.py and tests/agent/test_resume_stale_active_task.py. #42813 is Refs: #42812 (relates), this PR is Fixes #42812. They appear to be competing/overlapping approaches to the same compaction-historicalization fix; flagging so they can be consolidated / one picked rather than landing both.

@konsisumer

Copy link
Copy Markdown
Contributor Author

Closing — #35344 (merged) covers this. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale compaction Active Task hijacks resumed sessions after idle timeout

3 participants