feat(compression): flip in_place default to True + guard fix (#38763) [salvage #51959] - #52658
Merged
Conversation
…guard (#50098) Salvage of #50098 by @srojk34, cherry-picked onto current main. The hygiene auto-compress guard and the /compress slash command both read compression_in_place (config flag — is in-place mode enabled?) instead of _last_compaction_in_place (result flag — did in-place compaction actually succeed?). Both agents are built without a session_db, so archive_and_compact always fails silently and _last_compaction_in_place stays False. Reading the config flag makes the guard think in-place succeeded, triggering rewrite_transcript() which replaces the original messages with only the compressed summary — permanent data loss. Co-authored-by: srojk34 <srojk34@users.noreply.github.com>
In-place compaction (single durable session id, non-destructive soft-archive) becomes the default. Rotation is now the opt-out fallback via compression.in_place: false. Prerequisite: #50098 (hygiene guard reads result flag not config flag) merged first — without it, flipping the default causes permanent transcript loss on gateway hygiene-compress and /compress when no session_db is available. Blast radius (empirically measured on current main): 7 rotation-asserting tests broke and are pinned to in_place=False in the companion test commit: - tests/agent/test_compression_concurrent_fork.py (2) - tests/agent/test_compression_logging_session_context.py (1) - tests/agent/test_compression_rotation_state.py (1) - tests/run_agent/test_compression_boundary_hook.py (2 _make_agent helpers) - tests/gateway/test_compression_concurrent_sessions.py (2) Rotation stays as a working fallback and deserves continued coverage. Plan: .hermes/plans/in-place-compaction-38763.md
…d of default flip These 7 test sites assert rotation behavior (fork, child sessions, lock contention, logging session-context follows id rotation, boundary hooks fire on rotation). Pin each builder to in_place=False explicitly so they keep exercising the retained rotation fallback regardless of the global default (flipped to True in #38763). Rotation stays a working opt-out fallback and deserves continued coverage — these are NOT deleted. Pinned sites: - test_compression_concurrent_fork._build_agent_with_db - test_compression_logging_session_context._build_agent_with_db - test_compression_rotation_state._build_agent_with_db - test_compression_boundary_hook._make_agent (2 helpers: CompressionBoundaryHook + SessionCompressEvent) - test_compression_concurrent_sessions._build_agent_with_db
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-attribute |
7 |
First entries
tests/agent/test_compression_concurrent_fork.py:83: [unresolved-attribute] unresolved-attribute: Unresolved attribute `compression_in_place` on type `AIAgent`
tests/agent/test_compression_rotation_state.py:59: [unresolved-attribute] unresolved-attribute: Unresolved attribute `compression_in_place` on type `AIAgent`
tests/gateway/test_compression_concurrent_sessions.py:77: [unresolved-attribute] unresolved-attribute: Unresolved attribute `compression_in_place` on type `AIAgent`
tests/run_agent/test_compression_boundary_hook.py:185: [unresolved-attribute] unresolved-attribute: Unresolved attribute `compression_in_place` on type `AIAgent`
tests/agent/test_compression_logging_session_context.py:56: [unresolved-attribute] unresolved-attribute: Unresolved attribute `compression_in_place` on type `AIAgent`
run_agent.py:2989: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`
✅ Fixed issues (1):
| Rule | Count |
|---|---|
invalid-assignment |
1 |
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`
Unchanged: 5940 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
This was referenced Jun 25, 2026
Closed
Closed
This was referenced Jun 25, 2026
1 task
12 tasks
This was referenced Jul 9, 2026
1 task
This was referenced Jul 29, 2026
This was referenced Aug 9, 2026
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
Flips
compression.in_placedefault False → True so compaction keeps one durable session id instead of rotating — eliminating the session-id rotation that was the root cause of a P1 cluster (#14238 lost pending response, #13840 search black-hole, #36777/#42228 TUI/desktop stale-cwd/sid). Bundles the guard fix that makes the flip safe.Salvage of #51959 — cherry-picked onto current
main, contributor authorship preserved (@srojk34's guard fix + @kshitijk4poor's flip/tests).This is the staged flip after #49739 (in-place soft-archive machinery, [1/2]) merged and soaked. Rotation remains a working opt-out fallback via
compression.in_place: false.Why the guard fix MUST land with the flip
/compressand the gateway hygiene-compress both build a throwawayAIAgentwithout asession_db, soarchive_and_compactcan't run and_last_compaction_in_placestaysFalse. Both guard sites readcompression_in_place(the config flag — "is in-place enabled?") instead of_last_compaction_in_place(the result flag — "did in-place succeed?"). Harmless while the default isFalse; flip the default and every gateway compress passes the guard with no successful compaction →rewrite_transcript()replaces the transcript with summary-only (permanent data loss, the #21301 class). The fix points both guards at the result flag (matching the canonical read already atgateway/run.py).Changes
gateway/run.py,gateway/slash_commands.py: hygiene guard +/compressread_last_compaction_in_place(result flag) notcompression_in_place(config flag).hermes_cli/config.py:compression.in_placedefaultFalse → True.tests/gateway/test_session_hygiene.py: regression test — in-place configured but nosession_dbmust preserve the transcript (fails without the guard fix).in_place=Falseso the rotation fallback keeps coverage;test_in_place_compactiondefault assertion flipped todefaults_on.scripts/release.py: AUTHOR_MAP entry for @srojk34's legacy prefix-less noreply.Validation
session_db, gateway compressrewrite_transcriptcalled with summary-only → data lossmain; diff is the 11 intended files only (134/-9).Closes #51959. Supersedes #50098.
Infographic