Files
hermes-webui/tests/test_compaction_card_display.py
T
Anthony Ruiz 8fe3325e12 fix(ui): keep current summary visible next to stale compaction markers
The settled current-summary card was only created when no compaction
marker was loaded at all. A transcript with older (stale) markers plus a
newer `compression_anchor_summary` that no loaded marker references
therefore lost the current summary, which master still rendered.

Decide the fallback from `_latestCompressionReferenceMessage()`
(`referenceMessageRawIdx < 0`) instead of marker presence, and feed that
decision into `_selectCompactionCardPlacements()` before any card node is
built so the fallback is the single preserved-task owner and marker cards
never attach the task list a second time.

Add a render-level regression that executes the real `renderMessages()`
over 220 messages, three stale markers, one preserved task-list message
and a newer summary: the current summary is visible and exactly one task
owner is rendered, in full, virtualized and server-truncated windows.
2026-09-20 03:48:19 +00:00

174 lines
5.6 KiB
Python

"""Regression tests for visible ultra-compact compaction cards."""
from __future__ import annotations
import json
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
UI_JS = ROOT / "static" / "ui.js"
def _extract_function(source: str, name: str) -> str:
marker = f"function {name}("
start = source.find(marker)
if start < 0:
raise AssertionError(f"function {name} not found")
brace = source.find("{", start)
depth = 1
pos = brace + 1
while depth and pos < len(source):
if source[pos] == "{":
depth += 1
elif source[pos] == "}":
depth -= 1
pos += 1
return source[start:pos]
def _run_node(script: str) -> None:
completed = subprocess.run(
["node", "-e", script],
cwd=ROOT,
text=True,
capture_output=True,
timeout=30,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
def test_compaction_digest_and_preview_drop_instruction_envelope() -> None:
source = UI_JS.read_text(encoding="utf-8")
functions = "\n".join(
_extract_function(source, name)
for name in ("_compactionDigestText", "_compactionCardPreview")
)
envelope = (
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
"into the summary below. This is a handoff from a previous context window."
)
digest = (
'## Historical Task Snapshot\nUser asked: "fix the planning bug"\n'
"## Goal\nFix the planning defect.\n"
"## Active State\n- worktree ready\n"
"## Détail complet\nRésumé intégral : lire la note "
"docs/compaction-test.md"
)
marker = envelope + "\n" + digest + "\n--- END OF CONTEXT SUMMARY ---"
script = f"""
const assert = require('assert');
{functions}
const marker = {json.dumps(marker)};
const digest = _compactionDigestText(marker);
assert.ok(digest.startsWith('## Historical Task Snapshot'));
assert.ok(!digest.includes('REFERENCE ONLY'));
assert.ok(digest.includes('compaction-test.md'));
const preview = _compactionCardPreview(marker);
assert.ok(preview.includes('fix the planning bug'));
assert.ok(!/REFERENCE ONLY|compacted into the summary/i.test(preview));
assert.ok(preview.length <= 220);
"""
_run_node(script)
def test_loaded_compaction_marker_scan_finds_every_non_tool_marker() -> None:
source = UI_JS.read_text(encoding="utf-8")
functions = "\n".join(
_extract_function(source, name)
for name in (
"_compactionSummarySegment",
"_isContextCompactionText",
"_isContextCompactionMessage",
"_loadedCompactionMarkerRawIdxs",
)
)
marker = "[CONTEXT COMPACTION — REFERENCE ONLY]\n## Goal\nKeep the digest visible."
messages = [
{"role": "user", "content": "first request"},
{"role": "assistant", "content": marker},
{"role": "tool", "content": marker},
{"role": "assistant", "content": "normal answer"},
{"role": "assistant", "content": marker},
]
script = f"""
const assert = require('assert');
const msgContent = (message) => message && typeof message.content === 'string' ? message.content : '';
{functions}
assert.deepStrictEqual(_loadedCompactionMarkerRawIdxs({json.dumps(messages)}), [1, 4]);
"""
_run_node(script)
def test_compaction_placement_selection_covers_window_boundaries() -> None:
source = UI_JS.read_text(encoding="utf-8")
helper = _extract_function(source, "_selectCompactionCardPlacements")
script = f"""
const assert = require('assert');
{helper}
assert.deepStrictEqual(
_selectCompactionCardPlacements([3, 11, 49, 50, 88], 50),
{{
preWindowMarkers: [3, 11, 49],
inlineMarkers: [50, 88],
taskOwner: {{kind: 'inline', rawIdx: 88}},
}},
);
assert.deepStrictEqual(
_selectCompactionCardPlacements([3, 11, 49], 50),
{{
preWindowMarkers: [3, 11, 49],
inlineMarkers: [],
taskOwner: {{kind: 'pre-window', rawIdx: 49}},
}},
);
assert.deepStrictEqual(
_selectCompactionCardPlacements([50, 88], 50),
{{
preWindowMarkers: [],
inlineMarkers: [50, 88],
taskOwner: {{kind: 'inline', rawIdx: 88}},
}},
);
assert.deepStrictEqual(
_selectCompactionCardPlacements([], 50),
{{preWindowMarkers: [], inlineMarkers: [], taskOwner: null}},
);
// A current-summary fallback (no loaded marker matches the session summary)
// owns the preserved tasks even when stale markers are still loaded.
assert.deepStrictEqual(
_selectCompactionCardPlacements([3, 11, 49, 88], 50, true),
{{
preWindowMarkers: [3, 11, 49],
inlineMarkers: [88],
taskOwner: {{kind: 'current-summary', rawIdx: -1}},
}},
);
assert.deepStrictEqual(
_selectCompactionCardPlacements([], 50, true),
{{preWindowMarkers: [], inlineMarkers: [], taskOwner: {{kind: 'current-summary', rawIdx: -1}}}},
);
"""
_run_node(script)
def test_settled_reference_is_pinned_at_top_when_marker_is_outside_tail() -> None:
source = UI_JS.read_text(encoding="utf-8")
pin_helper = _extract_function(source, "_pinCompactionCardAtTop")
helper = _extract_function(source, "_pinSettledCompressionReferenceAtTop")
script = f"""
const assert = require('assert');
{pin_helper}
{helper}
const children = [];
const inner = {{ appendChild(node) {{ children.push(node); return node; }} }};
const card = {{ id: 'compaction-card' }};
assert.strictEqual(_pinSettledCompressionReferenceAtTop(inner, card, -1), true);
assert.deepStrictEqual(children, [card]);
assert.strictEqual(_pinSettledCompressionReferenceAtTop(inner, {{id:'inline'}}, 12), false);
assert.deepStrictEqual(children, [card]);
"""
_run_node(script)