# NousResearch/hermes-agent · Context compression summary duplication and accuracy bugs

## Open now

- Nothing open on GitHub.

These issues and fixes relate to bugs in context compression where the latest user message gets triplicated and historical tasks are not correctly framed in fallback summaries. Multiple fix attempts target the same core compression summary generation problems.

## TL;DR

- 4 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #49986. Verify it addresses your case.
- **Recommended:** read PR #49986 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.50`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #49307: Context compression causes answer repetition + new instruction loss (Bug B: critical)

## Prior & competing PRs

- **#49986: fix(compression): stop fallback summary triplicating the latest user ask (#49307)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/context_compressor.py`, `tests/agent/test_context_compressor.py`
  - fix hunks:
  - `agent/context_compressor.py`

    ```diff
    @@ -1253,7 +1253,10 @@ def _bullets(items: list[str], limit: int = 8) -> str:
     Unknown from deterministic fallback. Inspect current repository/session state if needed.
     
     {HISTORICAL_IN_PROGRESS_HEADING}
    -{active_task}
    +Unknown from deterministic fallback — the latest user ask is recorded once under
    +"{HISTORICAL_TASK_HEADING}" above as historical context only. Do NOT treat it as an
    +unfulfilled instruction to re-answer; verify current state and continue from the
    +protected recent messages after this summary.
     
     ## Blocked
     {_bullets(blockers, limit=5)}
    ```

    ```diff
    @@ -1265,7 +1268,9 @@ def _bullets(items: list[str], limit: int = 8) -> str:
     None recoverable from deterministic fallback.
     
     {HISTORICAL_PENDING_ASKS_HEADING}
    -{active_task}
    +None recoverable from deterministic fallback. (The latest user ask is preserved once
    +under "{HISTORICAL_TASK_HEADING}" as historical context — it is NOT necessarily
    +outstanding.)
     
     ## Relevant Files
     {_bullets(relevant_files, limit=12)}
    ```
  - `tests/agent/test_context_compressor.py`

    ```diff
    @@ -170,6 +170,40 @@ def test_summary_failure_uses_deterministic_fallback_with_recovered_context(self
             assert c._last_summary_fallback_used is True
             assert c._last_summary_dropped_count == 3
     
    +    def test_fallback_summary_does_not_triplicate_latest_user_ask(self):
    +        """Regression for #49307: the deterministic fallback summary used to
    +        render the latest user ask verbatim under THREE headings (Task
    +        Snapshot, In-Progress, Pending Asks). The model then re-answered it
    +        and buried the genuinely-new post-compaction turn (answer repetition +
    +        new-instruction loss). The latest ask must appear ONCE, as historical
    +        context only — never re-presented as unfulfilled in-progress/pending
    +        work.
    +        """
    +        with patch("agent.context_compressor.get_model_context_length", return_value=100000):
    +            c = ContextCompressor(model="test/model", quiet_mode=True)
    +
    +        unique_ask = "PLEASE_COMPUTE_THE_ARITHMETIC_CHAIN_XYZ"
    +        turns = [
    +            {"role": "user", "content": unique_ask},
    +            {"role": "assistant", "content": "working on it"},
    +        ]
    +        summary = c._build_static_fallback_summary(turns, reason="provider down")
    +
    +        # The triplication bug rendered the SAME ``active_task`` line —
    +        # formatted as ``User asked: '<ask>'`` — verbatim under three
    +        # headings (Task Snapshot, In-Progress, Pending Asks), making the
    +        # model treat an already-handled ask as unresolved work and re-answer
    +        # it. That exact formatted line must now appear at most ONCE (only as
    +        # the historical Task Snapshot record). The raw ask text may still
    +        # appear elsewhere (e.g. the "Last Dropped Turns" verbatim transcript),
    +        # but never re-labeled as in-progress/pending work.
    +        active_task_line = f"User asked: {unique_ask!r}"
    +        count = summary.count(active_task_line)
    +        assert count <= 1, (
    +            f"active_task line should appear at most once (was triplicated in "
    +            f"#49307), found {count}x:\n{summary}"
    +        )
    +
         def test_compression_increments_count(self, compressor):
             msgs = self._make_messages(10)
             # Default config (abort_on_summary_failure=False) — fallback path
    ```
- **#49347: fix(agent): stop deterministic fallback summary from triplicating the latest user ask (#49307)**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#49986`
- **#49381: fix(agent): frame historical tasks as resolved in compression summary (#49307)**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#49986`

## Fix status

- Merged to main in PR #49986 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-21`.
- Subsystem: `agent`
