Skip to content

feat(gateway): wire-first /compress feedback — real measured tokens lead - #176

Merged
Kyzcreig merged 1 commit into
mainfrom
fix/compress-wire-first-feedback
Jul 2, 2026
Merged

Kyzcreig merged 1 commit into
mainfrom
fix/compress-wire-first-feedback

Conversation

@Kyzcreig

@Kyzcreig Kyzcreig commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What

Wire-first /compress feedback: the granular block now leads with the real provider-measured token count, not the chars÷4 archive estimate. One number story — the footer figure and the /compress figure can no longer disagree.

Why

The manual /compress granular block led with Stored transcript: ~328K → ~43K (chars÷4 over the stored archive) while the footer showed the REAL wire count (e.g. 236K). Under LCM the archive holds bulk that was compacted off the wire many turns ago, so the two numbers describe different populations measured with different tokenizers — they disagreed by 100K+ every time and confused the operator.

The real provider-measured before-count already exists at /compress time (session_entry.last_prompt_tokens). This surfaces it as the prominent line.

Change (stored basis only, when a real measured count is available)

  • Context line = the WIRE story: measured before (exact, no ~) → next-request estimate (~); freed/pct computed on wire numbers; tagged before measured, after next-request estimate.
  • Archive totals demoted into the Removed from stored transcript header as an explicit token-est reclaimed from archive parenthetical — can't be misread as request-size savings.
  • Duplicate Full request size: line skipped when the block already carried the wire story.

Real delivered message (LCM E2E, Ace's 303,201 scenario):

🗜️ Compressed: 7 → 3 stored messages
   Messages:  7 → 3   (kept 2 recent chat + 1 summary)
   Context:   303,201 → ~49 tokens   (freed ~303K, 100% smaller · before measured, after next-request estimate)
   Removed from stored transcript (5 messages, ~515 token-est reclaimed from archive):
     • 2 tool-result messages  →  ~502 reclaimed   (raw tool output)
     • 1 other messages  →  ~19 reclaimed   (system + tool-call turns, cleared)
     • 2 folded messages   →  ~22 reclaimed   (older chat condensed into 1 summary)
   Replacement cost: ~28 kept in transcript (summary + anchors)
   Model: test-prov/test-model · engine: lcm
↩ Nothing lost — original messages preserved in lcm.db (recover with lcm_grep / lcm_expand)

Fallbacks (unchanged, covered)

  • No real measured count (post-restart) → prior stored-basis rendering.
  • Auto-compaction announce (basis="live") → byte-identical; wire kwargs ignored on the live basis.
  • No-rewrite / two-line forms → unchanged.

Tests

New renderer kwargs wire_before/wire_after, honored only for basis="stored" with both > 0. 11 new renderer tests + 2 updated gateway E2E (the LCM case reproduces Ace's exact scenario). 217 compaction/compress tests green.

…ead, one number story

The manual /compress granular block led with the stored-transcript estimate
(Stored transcript: ~328K -> ~43K, chars/4 over the archive) while the footer
showed the REAL provider-measured wire count (e.g. 236K). Two numbers, two
populations, two tokenizers -> they disagreed by 100K+ every time and confused
the operator (and the agent explaining it).

The real provider-measured before-count already exists at /compress time
(session_entry.last_prompt_tokens). This makes the granular block lead with it.

Change (stored basis only, when a real measured count is available):
- Context line becomes the WIRE story: measured before (exact, no ~) ->
  next-request estimate (~), freed/pct computed on wire numbers, tagged
  "before measured, after next-request estimate".
- Stored-transcript totals are demoted into the "Removed from stored transcript"
  header as an explicit "token-est reclaimed from archive" parenthetical, so
  they can never be read as request-size savings.
- The trailing "Full request size:" line is skipped when the block already
  carried the wire story (no double-reporting).

Fallbacks unchanged and covered:
- No real measured count (post-restart) -> prior stored-basis rendering.
- Auto-compaction announce (basis="live") -> byte-identical; wire kwargs are
  ignored on the live basis.
- No-rewrite / two-line forms -> unchanged.

New renderer kwargs wire_before/wire_after are honored only for basis="stored"
with both > 0. 11 new renderer tests + 2 updated gateway E2E tests (the LCM
case reproduces Ace's exact 303,201 scenario). 217 compaction/compress tests
green.
@Kyzcreig
Kyzcreig merged commit 3eecff4 into main Jul 2, 2026
35 checks passed
@Kyzcreig
Kyzcreig deleted the fix/compress-wire-first-feedback branch July 2, 2026 18:28
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR surfaces the real provider-measured token count as the leading line in the /compress granular block, replacing the previous chars÷4 archive estimate. When both wire_before and wire_after are available on a stored basis, the renderer's prominent "Context:" line shows the exact measured before-count and an estimated after-count, while archive totals are demoted into the "Removed from stored transcript" header as an explicit token-est parenthetical; the standalone Full request size: line is then skipped to avoid duplicating the same numbers.

  • conversation_compression.py: New wire_before/wire_after kwargs to _format_granular_announce; wire_mode activates only for basis=\"stored\" with both values positive, with correct fallback to stored-basis rendering when either is zero/None.
  • gateway/slash_commands.py: Passes real_before_tokens/full_after_tokens as wire kwargs and tracks _granular_has_wire to conditionally suppress the now-redundant Full request size: line; the exception-handler path correctly resets both _granular and _granular_has_wire together.
  • Tests: 5 new unit tests for _format_granular_announce wire mode (including live-basis isolation and no-net-reduction guard) and two updated E2E tests reproducing the original 303K LCM scenario.

Confidence Score: 4/5

Safe to merge; the change is additive, all fallback paths (post-restart, auto-compaction, no-rewrite, granular failure) are explicitly tested and preserve existing behaviour.

The full_request_no_fixed honesty note can appear visually orphaned in wire mode — its referent (the → ~N tokens estimate) is now inside the granular Context line rather than directly above the note, which may confuse operators when the no-resident-agent path fires. Everything else — flag consistency between caller and renderer, fallback ordering, exception-handler resets — is correct and well-tested.

gateway/slash_commands.py — the full_request_no_fixed note emission at line 3232 may warrant a guard or a note tweak for the wire-mode path.

Important Files Changed

Filename Overview
agent/conversation_compression.py Added wire_before/wire_after kwargs to _format_granular_announce; when both are positive on stored basis, the Context line shows wire-measured tokens instead of archive estimates, and archive totals are demoted to the Removed header. Logic is correct and fallbacks are well-guarded.
gateway/slash_commands.py Adds _granular_has_wire flag and passes real_before_tokens/full_after_tokens as wire kwargs; skips the Full request size: line when the granular block already carries the wire story. One minor concern: the full_request_no_fixed honesty note can appear in wire mode right after the granular block, without the Full request size line it was originally paired with, making it feel slightly orphaned.
tests/agent/test_compaction_announce.py Adds 5 new TestGranularWireFirst tests covering wire mode rendering, fallback to stored-basis when either number is missing/zero, no-net-reduction guard, and live-basis isolation. Tests are thorough and well-constructed.
tests/gateway/test_compress_command.py Updates two existing E2E tests to reflect wire-first rendering: asserts the wire Context line appears, Full request size line is absent, and archive totals are demoted. The LCM test reproduces Ace's exact 303K scenario end-to-end.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["/compress called"] --> B{transcript rewritten\nAND length changed?}
    B -- No --> C[_granular = None\n_granular_has_wire = False]
    B -- Yes --> D[build_hygiene_stats\n+ validate]
    D -- validate fails\nor exception --> C
    D -- ok --> E["_format_granular_announce(\n  basis='stored',\n  wire_before=real_before_tokens,\n  wire_after=full_after_tokens\n)"]
    E --> F{wire_mode?\nboth > 0 & stored}
    F -- Yes --> G["Context line = WIRE story\n(measured before → ~estimated after)\nRemoved header = archive token-est"]
    F -- No --> H["Stored transcript: label\n(archive estimate)"]
    G --> I[_granular_has_wire = True]
    H --> J[_granular_has_wire = False]
    I & J --> K{_rewritten?}
    C --> K
    K -- No --> L["Full request size: … (unchanged)"]
    K -- Yes --> M{_granular_has_wire?}
    M -- Yes --> N[skip Full request size line\nwire story already shown]
    M -- No --> O{real_before_tokens > 0?}
    O -- Yes --> P["Full request size: measured → ~est"]
    O -- No --> Q["Full request size: ~est → ~est"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["/compress called"] --> B{transcript rewritten\nAND length changed?}
    B -- No --> C[_granular = None\n_granular_has_wire = False]
    B -- Yes --> D[build_hygiene_stats\n+ validate]
    D -- validate fails\nor exception --> C
    D -- ok --> E["_format_granular_announce(\n  basis='stored',\n  wire_before=real_before_tokens,\n  wire_after=full_after_tokens\n)"]
    E --> F{wire_mode?\nboth > 0 & stored}
    F -- Yes --> G["Context line = WIRE story\n(measured before → ~estimated after)\nRemoved header = archive token-est"]
    F -- No --> H["Stored transcript: label\n(archive estimate)"]
    G --> I[_granular_has_wire = True]
    H --> J[_granular_has_wire = False]
    I & J --> K{_rewritten?}
    C --> K
    K -- No --> L["Full request size: … (unchanged)"]
    K -- Yes --> M{_granular_has_wire?}
    M -- Yes --> N[skip Full request size line\nwire story already shown]
    M -- No --> O{real_before_tokens > 0?}
    O -- Yes --> P["Full request size: measured → ~est"]
    O -- No --> Q["Full request size: ~est → ~est"]
Loading

Reviews (1): Last reviewed commit: "feat(gateway): wire-first /compress feed..." | Re-trigger Greptile

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