Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 47 additions & 4 deletions agent/conversation_compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ def _format_granular_announce(
head: str, stats: "Any", model_part: str,
after_fallback: bool, window_from: "int | None", window_to: "int | None",
*, basis: str = "live",
wire_before: "int | None" = None,
wire_after: "int | None" = None,
) -> str:
"""Render the multi-line single-unit (messages) breakdown from a validated
``CompactionStats``. Every line leads with messages; tokens are the
Expand All @@ -437,10 +439,21 @@ def _format_granular_announce(
transcript:`` / ``Removed from stored transcript`` / ``kept in
transcript``. The real wire cut is the caller's separate ``Full request
size:`` line (provider-measured), appended below this block.

``wire_before`` / ``wire_after`` (stored basis only): when the caller has a
REAL provider-measured before-count and a pre-flight next-request estimate,
the prominent token line becomes the WIRE story (``Context:
303,201 → ~80K``) — real numbers first, per Ace's 2026-07-02 decision. The
stored-transcript token totals are then demoted into the ``Removed from
stored transcript`` header as an explicitly-labeled ``token-est``
parenthetical, and the caller should NOT append a duplicate ``Full request
size:`` line. Both must be > 0; otherwise the stored-basis rendering is
unchanged (post-restart sessions have no measured count).
"""
stored = basis == "stored"
ctx_label = "Stored transcript:" if stored else "Context: "
freed_verb = "reclaimed" if stored else "freed"
wire_mode = bool(stored and (wire_before or 0) > 0 and (wire_after or 0) > 0)
ctx_label = "Stored transcript:" if (stored and not wire_mode) else "Context: "
freed_verb = "reclaimed" if (stored and not wire_mode) else "freed"
removed_hdr = "stored transcript" if stored else "live context"
kept_where = "transcript" if stored else "context"
lines: list[str] = []
Expand All @@ -453,8 +466,28 @@ def _format_granular_announce(
lines.append(f"{head}")
lines.append(f" Messages: {stats.pre_messages} → {stats.post_messages} ({' + '.join(kept_bits)})")

# Token line. Wire mode (stored basis + real measured count available):
# the wire story — REAL before (exact, no ~), estimated after (~). The
# freed/pct math runs on the wire numbers so the headline savings are the
# request-size truth, not archive storage.
if wire_mode:
_wb, _wa = int(wire_before or 0), int(wire_after or 0)
_wfreed = _wb - _wa
if _wfreed > 0:
_wpct = round(_wfreed * 100 / _wb) if _wb else 0
lines.append(
f" Context: {_wb:,} → ~{_wa:,} tokens"
f" (freed {_abbrev_tokens(_wfreed)}, {_wpct}% smaller"
f" · before measured, after next-request estimate)"
)
else:
lines.append(
f" Context: {_wb:,} → ~{_wa:,} tokens"
f" (no net reduction expected"
f" · before measured, after next-request estimate)"
)
# Context/Stored line — guard freed<=0 (no net reduction)
if stats.freed_tokens > 0 and stats.freed_pct is not None:
elif stats.freed_tokens > 0 and stats.freed_pct is not None:
lines.append(
f" {ctx_label} {_abbrev_tokens(stats.pre_tokens)} → {_abbrev_tokens(stats.post_tokens)} tokens"
f" ({freed_verb} {_abbrev_tokens(stats.freed_tokens)}, {stats.freed_pct}% smaller)"
Expand All @@ -468,7 +501,17 @@ def _format_granular_announce(
# "Removed from <basis>" block — omit entirely when nothing cleared
removed = stats.cleared_count + stats.folded_count
if removed > 0:
lines.append(f" Removed from {removed_hdr} ({removed} messages):")
if wire_mode:
# Wire mode: the stored-transcript totals live HERE, explicitly
# labeled as archive token-estimates so they can't be read as
# request-size savings.
_arch_freed = max(int(stats.freed_tokens or 0), 0)
lines.append(
f" Removed from {removed_hdr} ({removed} messages,"
f" {_abbrev_tokens(_arch_freed)} token-est reclaimed from archive):"
)
else:
lines.append(f" Removed from {removed_hdr} ({removed} messages):")
# cleared bucket: render the tool/other sub-split when populated, else coarse line
if stats.cleared_count > 0:
if stats.cleared_tool_count is not None:
Expand Down
19 changes: 19 additions & 0 deletions gateway/slash_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3048,6 +3048,7 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
# ANY failure — a reconcile bug must never break /compress or
# ship wrong math (same contract as the hygiene announce).
_granular = None
_granular_has_wire = False
if _rewritten and len(compressed) != len(history):
try:
from agent.compaction_stats import build_hygiene_stats
Expand Down Expand Up @@ -3088,6 +3089,17 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
None,
None,
basis="stored",
# Wire-first (Ace 2026-07-02): when the REAL
# provider-measured before-count exists, the
# block's Context line carries the wire story
# (measured before → next-request estimate)
# and the trailing Full-request line below is
# skipped as a duplicate.
wire_before=real_before_tokens,
wire_after=full_after_tokens,
)
_granular_has_wire = (
real_before_tokens > 0 and full_after_tokens > 0
)
# Honest, store-correct recovery pointer.
if _engine_name == "lcm":
Expand All @@ -3113,6 +3125,7 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
exc_info=True,
)
_granular = None
_granular_has_wire = False
# Detect summary-generation failure so we can surface a
# visible warning to the user even on the manual /compress
# path (otherwise the failure is silently logged).
Expand Down Expand Up @@ -3178,6 +3191,10 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
# estimate — the real post-compression count doesn't exist until
# the next live API call.
#
# Wire-first: when the granular block already rendered the wire
# story on its Context line (measured before → next-request
# estimate), this line would be a duplicate — skip it.
#
# When the stored transcript was NOT rewritten, the next request
# resends the same context — say "unchanged" instead of printing a
# before → after pair whose delta is pure estimator noise (#F2).
Expand All @@ -3190,6 +3207,8 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:
lines.append(
t("gateway.compress.full_request_unchanged", before=_fr_before)
)
elif _granular_has_wire:
pass # wire story already on the granular Context line
elif real_before_tokens > 0:
lines.append(
t(
Expand Down
65 changes: 65 additions & 0 deletions tests/agent/test_compaction_announce.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,71 @@ def test_stored_basis_keeps_full_request_line_separate(self):
assert "Full request size" not in stored # caller appends it, not the renderer


class TestGranularWireFirst:
"""Wire-first /compress feedback (Ace 2026-07-02): when the caller supplies
the REAL provider-measured before-count + a next-request estimate, the
stored-basis block's prominent token line becomes the WIRE story (exact
measured before, ~estimated after), and the archive totals are demoted into
the Removed header as an explicit 'token-est' parenthetical. One number
story — the footer figure and the /compress figure can no longer disagree."""

def test_wire_mode_context_line_uses_measured_numbers(self):
s = _good_stats()
out = _format_granular_announce(
"🗜️ head", s, "m", False, None, None,
basis="stored", wire_before=236_012, wire_after=80_143,
)
# exact measured before (commas, no ~), estimated after (~)
assert "Context: 236,012 → ~80,143 tokens" in out
# freed/pct computed on WIRE numbers: 155,869 → ~155K, 66%
assert "freed ~155K, 66% smaller" in out
assert "before measured, after next-request estimate" in out
# the stored-transcript label must NOT be the prominent line anymore
assert "Stored transcript:" not in out

def test_wire_mode_demotes_archive_totals_into_removed_header(self):
s = _good_stats()
out = _format_granular_announce(
"🗜️ head", s, "m", False, None, None,
basis="stored", wire_before=236_012, wire_after=80_143,
)
# archive story explicitly labeled as token-est, in the Removed header
assert "Removed from stored transcript (716 messages," in out
assert "token-est reclaimed from archive):" in out
# kept-in-transcript replacement-cost wording unchanged
assert "kept in transcript" in out

def test_wire_mode_no_net_reduction_guard(self):
s = _good_stats()
out = _format_granular_announce(
"🗜️ head", s, "m", False, None, None,
basis="stored", wire_before=50_000, wire_after=60_000,
)
assert "no net reduction expected" in out
assert "% smaller" not in out

def test_wire_mode_requires_both_numbers(self):
# Missing/zero wire numbers → unchanged stored-basis rendering
s = _good_stats()
for wb, wa in ((0, 80_143), (236_012, 0), (None, None)):
out = _format_granular_announce(
"🗜️ head", s, "m", False, None, None,
basis="stored", wire_before=wb, wire_after=wa,
)
assert "Stored transcript:" in out
assert "token-est reclaimed from archive" not in out

def test_wire_kwargs_ignored_on_live_basis(self):
# Auto-announce path must stay byte-identical even if kwargs leak in
s = _good_stats()
live_plain = _format_granular_announce("h", s, "m", False, None, None)
live_kw = _format_granular_announce(
"h", s, "m", False, None, None,
wire_before=236_012, wire_after=80_143,
)
assert live_kw == live_plain


class TestProviderModelSplit:
def test_no_triple_prefix(self):
# model carries its own provider prefix AND a provider is passed
Expand Down
54 changes: 33 additions & 21 deletions tests/gateway/test_compress_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,27 +601,32 @@ def _compress(messages, *_args, **_kwargs):
):
result = await runner._handle_compress_command(_make_event())

# Granular block present: Messages/Stored-transcript axis lines + removed buckets.
# Granular block present: Messages axis + wire Context line + removed buckets.
assert "Messages:" in result
# The summary row must be classified as summary, not "kept chat"
# (built-in SUMMARY_PREFIX marker → kept 2 recent chat + 1 summary).
assert "kept 2 recent chat + 1 summary" in result
# Manual /compress measures the STORED transcript, not the live wire — the
# labels must say so (2026-07-02 basis-honesty fix). The live-context
# wording belongs only to the auto-compaction announce.
assert "Stored transcript:" in result
# Wire-first (Ace 2026-07-02): with a REAL provider-measured before-count
# (453,542), the prominent token line is the WIRE story — measured before →
# next-request estimate — NOT the archive estimate.
assert "Context: 453,542 → ~" in result
assert "before measured, after next-request estimate" in result
# The archive totals are demoted into the Removed header, explicitly labeled
# token-est so they can't be read as request-size savings.
assert "Removed from stored transcript" in result
assert "Context:" not in result
assert "token-est reclaimed from archive" in result
# The old stand-alone 'Stored transcript:' prominent line is gone in wire mode.
assert "Stored transcript:" not in result
assert "Removed from live context" not in result
# Tool sub-split names the tool-result rows explicitly.
assert "tool-result message" in result
# Model line carries provider/model.
assert "Model: test-prov/test-model" in result
# Recovery pointer for the rotated (non-LCM) store.
assert "previous transcript preserved: sess-1" in result
# Full-request line (the REAL wire truth) still appended beside the
# storage block — this is the number that reflects request-size.
assert "Full request size: 453,542" in result
# The duplicate Full-request line is SKIPPED — the wire story is already on
# the Context line above (no double-reporting of 453,542).
assert "Full request size: 453,542" not in result
# And it must never claim "No changes".
assert "No changes" not in result

Expand Down Expand Up @@ -672,12 +677,15 @@ def _compress(messages, *_args, **_kwargs):


@pytest.mark.asyncio
async def test_compress_command_lcm_engine_uses_stored_basis_labels():
async def test_compress_command_lcm_engine_wire_first_context_line():
"""Ace's live case (2026-07-02): an LCM session whose /compress granular
block measured the STORED transcript but labeled it 'Context:' / 'Removed
from live context' — overstating wire savings (~689K→~37K, 'freed 651K')
against a real 303K request. The block must now read STORED-transcript
wording, while the separate Full-request line stays the wire truth.
against a real 303K request. The fix: with a REAL provider-measured
before-count, the prominent Context line becomes the WIRE story (measured
303,201 → next-request estimate); the archive totals are demoted into the
Removed header as token-est; and the duplicate Full-request line is skipped.
One number story — footer and /compress can no longer disagree.
"""
history = _make_tool_heavy_history()
chat = _tool_heavy_chat(history)
Expand Down Expand Up @@ -719,20 +727,24 @@ def _compress(messages, *_args, **_kwargs):
# E2E proof — print the full delivered message.
print("\n───── delivered /compress message (LCM) ─────\n" + result + "\n────────────────────────────────────────────")

# Storage-basis labels — the fix.
assert "Stored transcript:" in result
# Wire-first: the prominent token line is the WIRE story with the REAL
# measured before (303,201), not the archive estimate.
assert "Context: 303,201 → ~" in result
assert "before measured, after next-request estimate" in result
# Archive totals demoted into the Removed header, labeled token-est.
assert "Removed from stored transcript" in result
# The replacement-cost line is present in this scenario; when present it must
# carry the stored-basis 'kept in transcript' wording (not 'kept in context').
assert "token-est reclaimed from archive" in result
# The replacement-cost line, when present, carries the stored-basis wording.
if "Replacement cost" in result:
assert "kept in transcript" in result
# The misleading live-wire wording must be gone from the manual path.
assert "Context:" not in result
# The old stand-alone 'Stored transcript:' line and the misleading live-wire
# wording must both be absent from the manual wire-first path.
assert "Stored transcript:" not in result
assert "Removed from live context" not in result
assert "kept in context" not in result
# The wire truth is the separate Full-request line, carrying the REAL
# provider-measured before (303,201) — NOT the storage estimate.
assert "Full request size: 303,201" in result
# The duplicate Full-request line is SKIPPED — the wire truth (303,201) is
# already the Context line above; no double-reporting.
assert "Full request size: 303,201" not in result
# LCM recovery pointer.
assert "lcm.db" in result
assert "No changes" not in result
Loading