HERMES-GIELIE/tests/test_topbar_lazy_message_count.py

40 lines
2.3 KiB
Python
Raw Permalink Normal View History

Release v0.51.253 — Release HU (stage-r1) (#3591) ## Release v0.51.253 — Release HU (stage-r1) Phase-1 low-risk batch — 7 PRs (no intervention beyond apply + one inline MUST-FIX). ### Fixed | Issue/PR | Author | Fix | |----------|--------|-----| | #3525 | @TomBanksAU | Streaming DOM-replace "follow" window tightened 1200px→120px — a reader who scrolled up mid-stream no longer gets snapped to the bottom on completion. | | #3556 | @ai-ag2026 | Topbar count distinguishes a partially-loaded transcript ("loaded of total" via server `message_count`); fully-loaded keeps the tool-row-filtered count. | | #3502 follow-up | @rodboev | Sidebar messaging source badges (Telegram/Discord/…) render as chips, not just CLI ones. | | — | @Karlineal | `.pre-header+pre` margin override scoped under `.msg-body` (removes a 10px gap above code blocks). | ### Tests - `test_ctl_script.py` kills orphan fake-python trees on Windows; conftest `_discover_python` checks the Windows venv layout (`Scripts/python.exe`). (#3537, #3577, @rodboev) ### Docs - Explicit WebUI–Agent compatibility policy + Docker pinning guidance. (#3232, @franksong2702) ### Dropped from this batch - **#3538** (self-update stash-pop recovery) — the Codex regression gate found a **BRICK-class data-loss**: the recovery path runs `git reset --merge` then `git stash drop`, permanently discarding the user's local modifications while returning `ok:true` + scheduling a restart. Held with `changes-requested` + a repro and the fix (keep the stash, return `ok:false`, no restart). Concept is good; the destructive `stash drop` must go. ### Gate - Full pytest suite: **7575 passed, 0 failed** - ESLint: CLEAN · ruff: CLEAN · browser-smoke: CLEAN - Codex (regression): SHIP-ONLY-WITH-FIXES (BRICK data-loss #3538 + tool-row count regression #3556) → #3538 dropped, #3556 fixed inline → **SAFE TO SHIP** Co-authored-by: TomBanksAU <TomBanksAU@users.noreply.github.com> Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com> Co-authored-by: rodboev <rodboev@users.noreply.github.com> Co-authored-by: Karlineal <Karlineal@users.noreply.github.com> Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-06-04 17:50:34 +00:00
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
UI_JS = (ROOT / "static" / "ui.js").read_text(encoding="utf-8")
Release v0.51.253 — Release HU (stage-r1) (#3591) ## Release v0.51.253 — Release HU (stage-r1) Phase-1 low-risk batch — 7 PRs (no intervention beyond apply + one inline MUST-FIX). ### Fixed | Issue/PR | Author | Fix | |----------|--------|-----| | #3525 | @TomBanksAU | Streaming DOM-replace "follow" window tightened 1200px→120px — a reader who scrolled up mid-stream no longer gets snapped to the bottom on completion. | | #3556 | @ai-ag2026 | Topbar count distinguishes a partially-loaded transcript ("loaded of total" via server `message_count`); fully-loaded keeps the tool-row-filtered count. | | #3502 follow-up | @rodboev | Sidebar messaging source badges (Telegram/Discord/…) render as chips, not just CLI ones. | | — | @Karlineal | `.pre-header+pre` margin override scoped under `.msg-body` (removes a 10px gap above code blocks). | ### Tests - `test_ctl_script.py` kills orphan fake-python trees on Windows; conftest `_discover_python` checks the Windows venv layout (`Scripts/python.exe`). (#3537, #3577, @rodboev) ### Docs - Explicit WebUI–Agent compatibility policy + Docker pinning guidance. (#3232, @franksong2702) ### Dropped from this batch - **#3538** (self-update stash-pop recovery) — the Codex regression gate found a **BRICK-class data-loss**: the recovery path runs `git reset --merge` then `git stash drop`, permanently discarding the user's local modifications while returning `ok:true` + scheduling a restart. Held with `changes-requested` + a repro and the fix (keep the stash, return `ok:false`, no restart). Concept is good; the destructive `stash drop` must go. ### Gate - Full pytest suite: **7575 passed, 0 failed** - ESLint: CLEAN · ruff: CLEAN · browser-smoke: CLEAN - Codex (regression): SHIP-ONLY-WITH-FIXES (BRICK data-loss #3538 + tool-row count regression #3556) → #3538 dropped, #3556 fixed inline → **SAFE TO SHIP** Co-authored-by: TomBanksAU <TomBanksAU@users.noreply.github.com> Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com> Co-authored-by: rodboev <rodboev@users.noreply.github.com> Co-authored-by: Karlineal <Karlineal@users.noreply.github.com> Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-06-04 17:50:34 +00:00
def test_topbar_uses_session_total_for_lazy_loaded_transcripts():
assert "function _topbarMessageMetaText()" in UI_JS
assert "const isTruncated=!!(typeof _messagesTruncated!=='undefined'&&_messagesTruncated);" in UI_JS
# Truncated transcripts surface the server total as "loaded of total".
assert "return `${loadedCount} loaded of ${totalCount} messages`;" in UI_JS
# Fully-loaded transcripts use the tool-row-filtered loadedCount, NOT the
# raw server total (which counts role:\"tool\" rows the topbar excludes).
Release v0.51.253 — Release HU (stage-r1) (#3591) ## Release v0.51.253 — Release HU (stage-r1) Phase-1 low-risk batch — 7 PRs (no intervention beyond apply + one inline MUST-FIX). ### Fixed | Issue/PR | Author | Fix | |----------|--------|-----| | #3525 | @TomBanksAU | Streaming DOM-replace "follow" window tightened 1200px→120px — a reader who scrolled up mid-stream no longer gets snapped to the bottom on completion. | | #3556 | @ai-ag2026 | Topbar count distinguishes a partially-loaded transcript ("loaded of total" via server `message_count`); fully-loaded keeps the tool-row-filtered count. | | #3502 follow-up | @rodboev | Sidebar messaging source badges (Telegram/Discord/…) render as chips, not just CLI ones. | | — | @Karlineal | `.pre-header+pre` margin override scoped under `.msg-body` (removes a 10px gap above code blocks). | ### Tests - `test_ctl_script.py` kills orphan fake-python trees on Windows; conftest `_discover_python` checks the Windows venv layout (`Scripts/python.exe`). (#3537, #3577, @rodboev) ### Docs - Explicit WebUI–Agent compatibility policy + Docker pinning guidance. (#3232, @franksong2702) ### Dropped from this batch - **#3538** (self-update stash-pop recovery) — the Codex regression gate found a **BRICK-class data-loss**: the recovery path runs `git reset --merge` then `git stash drop`, permanently discarding the user's local modifications while returning `ok:true` + scheduling a restart. Held with `changes-requested` + a repro and the fix (keep the stash, return `ok:false`, no restart). Concept is good; the destructive `stash drop` must go. ### Gate - Full pytest suite: **7575 passed, 0 failed** - ESLint: CLEAN · ruff: CLEAN · browser-smoke: CLEAN - Codex (regression): SHIP-ONLY-WITH-FIXES (BRICK data-loss #3538 + tool-row count regression #3556) → #3538 dropped, #3556 fixed inline → **SAFE TO SHIP** Co-authored-by: TomBanksAU <TomBanksAU@users.noreply.github.com> Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com> Co-authored-by: rodboev <rodboev@users.noreply.github.com> Co-authored-by: Karlineal <Karlineal@users.noreply.github.com> Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-06-04 17:50:34 +00:00
assert "return t('n_messages',loadedCount);" in UI_JS
def test_load_earlier_indicator_names_server_side_older_count():
assert "const serverOlderCount=hasServerOlder&&Number.isFinite(Number(_oldestIdx))?Math.max(0,Number(_oldestIdx)):0;" in UI_JS
assert "Load earlier messages (${serverOlderCount} older)" in UI_JS
def test_sync_topbar_does_not_count_only_loaded_tail_messages():
block = UI_JS[UI_JS.index("function syncTopbar(){") : UI_JS.index("function msgContent", UI_JS.index("function syncTopbar(){"))]
assert "const metaText=_topbarMessageMetaText();" in block
assert "t('n_messages',vis.length)" not in block
assert "S.messages.filter(m=>m&&m.role&&m.role!=='tool')" not in block
assert "document.title=sessionTitle+' \\u2014 '+assistantDisplayName();" in block
assert "document.title='● '+document.title;" in block
assert "const pendingPrefix=(typeof activeSessionHasPendingPromptAttention==='function'&&activeSessionHasPendingPromptAttention())?'● ':'';" not in block
sessions_js = (ROOT / "static" / "sessions.js").read_text(encoding="utf-8")
fn = sessions_js[
sessions_js.index("async function _ensureMessagesLoaded") :
sessions_js.index("function _messageComparableText", sessions_js.index("async function _ensureMessagesLoaded"))
]
assert "_messagesTruncated = !!data.session._messages_truncated;" in fn
assert "S.session.message_count=Number(data.session.message_count || msgs.length);" in fn
after_count_update = fn[fn.index("S.session.message_count=Number(data.session.message_count || msgs.length);") :]
assert "syncTopbar();" in after_count_update