Fix Transparent Streaming live anchor scene replay - #5257
3 commits merged into
Conversation
|
| Filename | Overview |
|---|---|
| static/ui.js | Adds _renderLiveAnchorActivitySceneTransparent, dispatches from renderLiveAnchorActivityScene, makes data-anchor-settled-scene-row conditional on settled flag, and updates _renderLiveAnchorActivitySceneForStream to override mode for transparent streams. The return-value asymmetry (wrote vs unconditional true) and the conditional _syncTransparentEventControls call remain from the prior review round. |
| tests/test_live_to_final_anchor_visible_order.py | Adds two new tests: a structural assertion test confirming the transparent gate precedes the compact gate, and a DOM-executed Node.js regression covering idempotency, legacy row hiding, settled/live marker isolation, and compact fallback after transparent render. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant SSE as SSE/Reattach
participant rLAAS as renderLiveAnchorActivityScene
participant rTrans as _renderLiveAnchorActivitySceneTransparent
participant rComp as compact path
participant DOM as DOM (liveAssistantTurn / blocks)
SSE->>rLAAS: streamId, scene, opts
rLAAS->>rLAAS: isTransparentStream()?
alt Transparent Stream (NEW path)
rLAAS->>rTrans: streamId, scene, opts
rTrans->>rTrans: guard: session / streamId / rows.length
rTrans->>DOM: remove [data-anchor-scene-row], legacy live rows
rTrans->>DOM: hide [data-live-assistant] segments as anchors
loop for each row in scene
rTrans->>DOM: "_anchorSceneTransparentNodeForRow(row, {live:true})"
DOM-->>rTrans: "node | null"
rTrans->>DOM: insertBefore(liveRunStatus) / appendChild
end
rTrans->>rTrans: if(wrote) _syncTransparentEventControls(turn)
rTrans-->>rLAAS: wrote (bool)
else Compact Worklog path (existing)
rLAAS->>rLAAS: !isCompactWorklogMode? return false
rLAAS->>DOM: _anchorSceneWorklogGroup + _renderAnchorSceneRowsIntoWorklog
rLAAS-->>SSE: true (unconditional)
end
%%{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"}}}%%
sequenceDiagram
participant SSE as SSE/Reattach
participant rLAAS as renderLiveAnchorActivityScene
participant rTrans as _renderLiveAnchorActivitySceneTransparent
participant rComp as compact path
participant DOM as DOM (liveAssistantTurn / blocks)
SSE->>rLAAS: streamId, scene, opts
rLAAS->>rLAAS: isTransparentStream()?
alt Transparent Stream (NEW path)
rLAAS->>rTrans: streamId, scene, opts
rTrans->>rTrans: guard: session / streamId / rows.length
rTrans->>DOM: remove [data-anchor-scene-row], legacy live rows
rTrans->>DOM: hide [data-live-assistant] segments as anchors
loop for each row in scene
rTrans->>DOM: "_anchorSceneTransparentNodeForRow(row, {live:true})"
DOM-->>rTrans: "node | null"
rTrans->>DOM: insertBefore(liveRunStatus) / appendChild
end
rTrans->>rTrans: if(wrote) _syncTransparentEventControls(turn)
rTrans-->>rLAAS: wrote (bool)
else Compact Worklog path (existing)
rLAAS->>rLAAS: !isCompactWorklogMode? return false
rLAAS->>DOM: _anchorSceneWorklogGroup + _renderAnchorSceneRowsIntoWorklog
rLAAS-->>SSE: true (unconditional)
end
Reviews (4): Last reviewed commit: "Merge branch 'master' into franksong2702..." | Re-trigger Greptile
| else blocks.appendChild(node); | ||
| wrote=true; | ||
| } | ||
| if(wrote) _syncTransparentEventControls(turn); |
There was a problem hiding this comment.
_syncTransparentEventControls skipped after DOM clear when no rows are written
_syncTransparentEventControls is guarded by if(wrote), but the DOM-clearing sweeps above (removing [data-anchor-scene-row="1"], legacy live rows, [data-live-stream-owned="1"], etc.) run unconditionally once the rows-length guard is passed. If every row in a non-empty scene produces null from _anchorSceneTransparentNodeForRow — e.g. a scene containing only thinking rows when window._showThinking===false — the function clears all visible live content but leaves the turn's expand/collapse and copy-button controls wired to nodes that no longer exist. The compact path avoids this by not gating its equivalent sync call on whether content was written.
🔬 Gate certification — GREEN ✅Certified head: What I ran (isolated worktree
|
| Gate | Result |
|---|---|
| Codex (reproduce) | SAFE TO SHIP (no findings — ordering/idempotency/stream-ownership/no-jump all correct) |
Full pytest suite (-p no:xdist, rebased) |
11163 passed, 0 failed |
PR's tests (test_live_to_final_anchor_visible_order, +2 new) |
59 passed |
node --check static/ui.js |
OK |
Findings (clean)
- ✅ Correct live→final ordering —
_renderLiveAnchorActivitySceneTransparentrenders the transparent live-activity rows (worklog/tool) into#liveAssistantTurnbefore the compact gate, so they appear in the right order; no out-of-order or duplicate rows (test_..._renders_transparent_rows_before_compact_gate). - ✅ Idempotent — re-render clears prior
[data-anchor-scene-owner]/[data-anchor-scene-row]+ legacy live-activity surfaces (.live-worklogetc) before rebuilding, so no duplication/flicker; legacy rows hidden once (test_..._idempotent_and_hides_legacy_rows). Anchor-scene rows are the single source of truth. - ✅ Stream-id ownership — rows tagged
data-anchor-stream-id+data-live-stream-owned; Codex confirmed the renderer doesn't clobber another stream's live turn (the fix(auth): enforce active-profile session IDs #5198 stream_id-axis concern). - ✅ No scroll jump — uses a scroll-rebuild guard (
_prepareLiveAnchorScrollRebuildGuard), so the rebuild doesn't reintroduce the Source WebUI: hidden-tab return triggers visible 'disappear and reappear' of transcript when bg-review or main turn added messages during hidden window (gap not covered by #5061/#5122) #5177/fix(webui): keep stale transcript mounted while hidden-tab return reloads new messages (#5177) #5189 jump. No settled/final-render or renderMd-anchor-path regression (Codex verified). Rebases cleanly; node-check clean.
Concept: 4/5 — fixes visible live-activity rendering glitches during transparent streaming (anchor-scene replay ordering); existing-flow streaming reliability.
Recommendation to the next agent
Ready to merge — cert fresh for sha:0c5e2f0c7a7d. crit=2 transparent-streaming anchor-scene-replay fix; Codex SAFE, full suite green, 2 new ordering/idempotency tests (59 in file), correct live→final ordering, idempotent legacy-row replacement, stream-id ownership intact, scroll-rebuild guard (no #5177/#5189 jump). Streaming-render surface but logic-verified by the tests + Codex. Rebases cleanly. Concept 4/5. Cert valid only at sha:0c5e2f0c7a7d.
Gate-certifier layer (warm-up → gate → release). I do not merge/tag/deploy/close. Cert valid only at sha:0c5e2f0c7a7d; a new push invalidates it → re-gate.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
0c5e2f0 to
6ac5b9d
Compare
|
↻ Cert re-confirmed at current head |
…o franksong2702/fix-transparent-live-snapshot Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Base refreshed again against current
CI has started for the refreshed head; leaving this in CI/review monitoring. |
Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Base refreshed again against current
CI has started for the refreshed head; leaving this in CI/review monitoring. |
8d5ff4c
|
Shipped in v0.51.765 (Wave 1 batch, via release PR #5277). Thanks @franksong2702! Combined-stage Codex SAFE + full pytest suite green + ESLint/ruff gates clean. 🎉 |
Thinking Path
runtime_journal_snapshot.anchor_activity_sceneduring live reattach/reload.renderLiveAnchorActivityScene()returned before the compact-only gate.Refs #3400.
Refs #2361.
What Changed
activity_scene_v1rows before the compact-only gate.Why It Matters
Transparent Streaming should not show less visible progress than Compact Worklog for the same live turn. When a runtime journal snapshot already contains ordered process prose and tool activity, both display modes should rebuild from that same source of truth instead of falling back to a partial live tail.
Verification
./scripts/test.sh tests/test_live_to_final_anchor_visible_order.py tests/test_issue3820_chat_activity_display_mode.py tests/test_pr1366_finalize_thinking_card_guard.py tests/test_issue3479_ios_stream_scroll_jump.py tests/test_live_anchor_progress_echo.py109 passednode --check static/ui.jsRisks / Follow-ups
Model Used
OpenAI GPT-5 coordinator with a delegated GPT-5.5 implementation worker. Claude Code CLI was used for independent read-only review of the diff.