Skip to content

Release v0.51.333 — Release KW (collapse old interim progress notes, #3574)#3848

Merged
nesquena-hermes merged 3 commits into
masterfrom
stage-3574
Jun 8, 2026
Merged

Release v0.51.333 — Release KW (collapse old interim progress notes, #3574)#3848
nesquena-hermes merged 3 commits into
masterfrom
stage-3574

Conversation

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Release v0.51.333 — Release KW (collapse old interim progress notes)

Absorbs #3574 (@rodboev) — deep-reviewed, rebased, fixed, and shipped.

What ships

During a long live streaming turn the agent emits many interim progress notes that pushed the latest one out of view. Once more than 3 accumulate, the older ones now collapse behind a "Show N earlier updates" toggle (CSS .interim-collapsed { display:none }) so the most recent notes stay visible. Expanding is sticky — new interim events won't re-hide what the user manually opened.

Deep review (Opus + Codex + live browser drive vs master)

  • Live-verified the collapse + manual-expand guard on a real DOM drive: 5 interims → 2 hidden / 3 visible; user-expand → 0 hidden; new interim while expanded → stays expanded (guard works).
  • Codex caught a real regression the green suite + Opus missed: the toggle's click listener was attached per-element at creation, but snapshotLiveTurnHtmlForSession / restoreLiveTurnHtmlForSession rebuild the live turn via innerHTML on session switch — stripping the listener and leaving collapsed notes permanently unreachable for the rest of the turn.
  • Fix (maintainer, this PR): replaced the per-element listener with a stateless document-level delegated handler (_interimCollapseDelegatedClick) that resolves the toggle via closest(), reads state from the DOM (.interim-collapsed + data-threshold), and survives the innerHTML restore. Live-verified on the exact restore scenario (markup re-parsed via innerHTML → click still toggles). + 4 regression tests pinning the delegated-handler contract.

Greptile flags (all adjudicated)

  • "user expansion undone every event" → REJECT (live-disproven; the data-expanded guard works)
  • "THRESHOLD const re-declared per event" → REJECT (greptile admits harmless)
  • "data-interim lost on flush" → REJECT (_flushPendingSegmentRender writes assistantBody.innerHTML only, not the row attribute)
  • "toggle never repositioned" → FOLD-cosmetic (stays anchored at first-hidden block)
  • i18n: the "Show N" toggle text is English, consistent with the sibling count-toggles in sessions.js ("Show N archived", "Show N from other profiles") which the codebase intentionally leaves un-i18n'd — not a gap.

Gate

  • Full suite 8303 passed, 9 skipped, 3 xpassed (4:27) — includes 4 new restore-path regression tests
  • node -c ✓ · ESLint runtime CLEAN · scope-undef CLEAN · ruff forward CLEAN
  • Opus: SHIP-safe · Codex: SAFE TO SHIP (after the delegated-handler fix to its found regression)

Co-authored-by: rodboev rodboev@users.noreply.github.com

rodboev and others added 3 commits June 8, 2026 22:13
…s live-turn restore

The interim-collapse toggle attached its click listener via per-element
addEventListener at creation time. snapshotLiveTurnHtmlForSession /
restoreLiveTurnHtmlForSession rebuild the live turn via outerHTML/innerHTML
on session switch, which strips JS listeners — so a restored toggle was
visible but inert and the collapsed interim notes became permanently
unreachable for the rest of the turn.

Replace with a stateless document-level delegated click handler
(_interimCollapseDelegatedClick) that resolves the toggle via closest(),
reads state from the DOM (.interim-collapsed) + data-threshold, and works
on both freshly-created and innerHTML-restored toggles. Add 4 regression
tests pinning the delegated-handler contract.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
…3574)

Collapse old interim progress notes after 3 visible during a live turn
(#3574, @rodboev). Maintainer fix during re-gate: replaced the per-element
toggle listener with a stateless document-level delegated handler so the
toggle survives the live-turn DOM restore (Codex caught: innerHTML rebuild
dropped the listener → collapsed notes unreachable). Full suite 8303,
ESLint/scope-undef CLEAN, Opus SHIP-safe, Codex SAFE-TO-SHIP after fix,
collapse + manual-expand-guard + restore-path delegated handler all live-verified.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
@nesquena-hermes nesquena-hermes merged commit 52993af into master Jun 8, 2026
11 checks passed
@nesquena-hermes nesquena-hermes deleted the stage-3574 branch June 8, 2026 22:36
@greptile-apps

greptile-apps Bot commented Jun 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR ships the interim-progress-note collapse feature (#3574): once more than 3 interim notes accumulate during a live streaming turn, older ones are hidden behind a "Show N earlier updates" toggle, with a sticky expand guard so manual opens aren't undone by new events. A key fix over the original implementation replaces per-element click listeners with a document-level delegated handler (_interimCollapseDelegatedClick) that survives the innerHTML rebuild performed by snapshotLiveTurnHtmlForSession/restoreLiveTurnHtmlForSession on session switch.

  • static/messages.js: Adds _interimCollapseDelegatedClick at module level; in the interim_assistant SSE handler, stamps data-interim="1" on each new row, runs collapse logic after flush, creates/updates the toggle span with data-threshold for stateless handler use, and respects data-expanded to skip re-collapse after a manual expand.
  • static/style.css: Adds .interim-collapsed { display:none } and .interim-collapse-toggle styles.
  • tests/test_issue2403_interim_collapse.py: 13 new static-analysis tests covering threshold constant, CSS rules, attribute ordering, and the delegated-handler contract.

Confidence Score: 4/5

The feature works correctly for the primary path and session-switch restore; one gap exists in the reconnect-replay branch where interim rows can be created without the data attribute the collapse query depends on.

The delegated-handler approach and expand guard are sound and live-verified. The alreadyStreamed reconnect branch flushes a row without stamping data-interim="1", so after a mid-turn reconnect the collapse count can diverge and that row is never hidden. This is a narrow but real defect on the changed code path, not a theoretical one.

static/messages.js — specifically the alreadyStreamed branch of the interim_assistant handler (lines 2447–2453).

Important Files Changed

Filename Overview
static/messages.js Adds delegated collapse handler and collapse logic in the interim_assistant SSE handler; the alreadyStreamed reconnect branch does not stamp data-interim="1" on the row it flushes, causing the collapse query to miss it.
static/style.css Adds .interim-collapsed { display:none } and .interim-collapse-toggle styling; straightforward and correct.
tests/test_issue2403_interim_collapse.py Adds 13 static-analysis tests pinning delegated-handler contract, CSS rules, and ordering invariants; well-structured but the alreadyStreamed path is not covered.
CHANGELOG.md Standard release entry for v0.51.333; accurate and complete.

Comments Outside Diff (1)

  1. static/messages.js, line 2447-2453 (link)

    P1 alreadyStreamed branch omits data-interim="1" on the flushed row

    When the SSE connection drops mid-event and reconnects, _freshSegment is true (set by the previous _resetAssistantSegment call), so ensureAssistantRow(true) creates a brand-new DOM row here — but assistantRow.setAttribute('data-interim','1') is never called on that row. The sealed element ends up in blocks without the attribute, so querySelectorAll('[data-interim="1"]') in the collapse logic misses it. The result is that the toggle's count is off and that row is never collapsed, even if it should be hidden. The non-alreadyStreamed path sets the attribute immediately after ensureAssistantRow; the same line is needed here before the flush.

Reviews (1): Last reviewed commit: "Release v0.51.333 — Release KW (collapse..." | Re-trigger Greptile

Comment thread static/messages.js
Comment on lines +2479 to +2481
if(!toggle){
toggle=document.createElement('span');
toggle.className='interim-collapse-toggle';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Toggle <span> is not keyboard-accessible

The collapse toggle is a plain <span> with only a delegated click handler. Keyboard-only users cannot Tab to it (no tabindex="0") and cannot activate it with Enter/Space (no keydown handler or role="button"). Any user navigating without a mouse cannot expand collapsed interim notes at all. Adding role="button" and tabindex="0" to the created element, and extending _interimCollapseDelegatedClick to also listen for keydown with key === 'Enter' || key === ' ', would fix this without touching the delegation pattern.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

2 participants