emrg: fix 7 GUI bugs — upgrade restart loop, false stream timeout, session meta, history loading, slash commands, composer draft, link navigation - #1097
Conversation
…ssion meta, history loading, slash commands, composer draft
…owser (rant 2026-09-01T20:33:44)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260901-205427
Reviewed all 7 fixes on head 722d347 (2 commits, +521/-71, 17 files) vs master a30ba4b:
- Upgrade restart loop —
handleUpgradeRestartnow callsrestartDaemon(full stop chain + GUI relaunch); main.js comment honestly documents the superseded 2026-08-27 decision. Correct root-cause fix (daemon in-memory_run_versionnever updated → heartbeat kept reporting version mismatch). - G94 false timeout —
STREAM_END_TIMEOUT_MS+_resetStreamTimerremoved everywhere (const, 2 call sites, dead method,data.timeoutbranch in transcript.ts,chat.timeoutWarni18n keys zh+en). Grep-clean, no orphans. - Session meta — header shows
title (sid) · project · N msgs+ busy elapsed timer, aligned with TUI status bar;app.msgCountkey added (zh/en parity). - History loading —
listHistorywired through WorkspaceBridge;loadHistory/loadOlderHistoryuse thehistory.tspage state machine (historyLoaded set prevents duplicate append), scroll-to-top trigger in TranscriptView with 150ms debounce. Ordering in prepend path correctly reversed to keep time order. - Slash commands — /model (arg →
setModel, no arg → settings), /rant (@project prefix), /trigger (arg →triggerTask+ task reload).app.modelSwitchedkey added. - Composer draft — per-sid
draftfield in transcript store +getComposerDraft/setComposerDraft; refs bridge the one-time useEditor closure; sid-switch effect saves old + loads new. Sound design. - Link navigation — new pure
nav-policy.js(externalNavPolicy: file:// allow, else open-external) wired into main windowwill-navigate+setWindowOpenHandler(both →shell.openExternal, errors caught); build-config whitelist updated.
Verification (all green):
- CI: test PASS (1m53s) + test-windows PASS (2m53s) — run 33509445498
- Renderer vitest: 487 passed (45 files)
- GUI node: 90 pass / 8 skip (94 total, +4 nav-policy tests)
- typecheck clean, vite build OK
- pytest collect 1213 = Agent.md (1213); import + CLI green
- i18n parity 393 keys zh/en enforced by tests
MERGEABLE/CLEAN, no ❌. LGTM 1/3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM 2/3 — cycle cyc20260901-210210
Re-verified head 722d347 (unchanged since LGTM 1/3 from cyc20260901-205427, same 2 commits aa88267 + 722d347, +521/-71, 17 files) vs master a30ba4b:
- CI still green: test PASS (1m53s) + test-windows PASS (2m53s), run 33509445498
- MERGEABLE / CLEAN, no ❌ in review history
- git hash identity guarantees content identical to the 1/3 review — all 7 fixes re-confirmed:
- upgrade banner restart → restartDaemon full chain (was relaunchGui-only loop)
- G94 false 30s stream timeout removed end-to-end (const, timers, transcript branch, i18n keys)
- session meta header (title (sid) · project · N msgs) + busy timer
- history loading wired (listHistory → history.ts paging → prepend + scroll-top load older)
- slash commands /model /rant /trigger wired (setModel, @project prefix, triggerTask)
- composer draft per-sid persistence (store field + refs bridging one-time useEditor closure)
- main-window navigation interception (nav-policy.js pure fn → will-navigate/setWindowOpenHandler → shell.openExternal)
Local verification this cycle: fetch confirmed branch identity; prior cycle full suite (renderer 487, node 90/8, typecheck, pytest 1213) stands for identical content. Ready for 3rd LGTM from a distinct cycle.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM 3/3 — cycle cyc20260901-210605
Third consecutive LGTM from a distinct cycle (205427 → 210210 → 210605), no ❌ in between.
- head 722d347 unchanged (git identity verified this cycle: 2 commits aa88267 + 722d347, 17 files, +521/-71)
- CI green: test PASS (1m53s) + test-windows PASS (2m53s), run 33509445498
- MERGEABLE / CLEAN, 0 review comments, 0 issue comments
All 7 GUI bug fixes reviewed across three independent cycles: upgrade restart loop, G94 false stream timeout, session metadata, history loading, slash commands, composer draft persistence, main-window link navigation. Ready to merge.
Technical review notes (tested/verified, not a gatekeeping review)I read the full diff and cross-checked the three integration-sensitive claims against the daemon implementation:
Two suggestions (non-blocking)
CI: test + test-windows both pass (33509445498). Draft-per-sid, session-switch save/restore, and the four new Composer tests look correct. |
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Summary
Fixes 7 GUI bugs reported by the host on 2026-09-01 (rants in
~/.emrg/rants.jsonl, timestamps 20:09–20:33). All fixes live in the React renderer,main.js, ordaemon_client.js.Fix 1 — Upgrade banner restart loop (rant
2026-09-01T20:09:41)The banner's "restart to apply" button only restarted the GUI shell (
relaunchGui) while the daemon kept running old code — after restart the version still showed the old one and the banner reappeared forever.Shell.tsx handleUpgradeRestartnow callsb.restartDaemon()(full daemon stop chain + GUI relaunch). TherelaunchGuicomment inmain.jswas updated to reflect the superseding rationale.Fix 2 — False "response timed out" messages (rant
2026-09-01T20:13:36, G94)Removed the 30s
STREAM_END_TIMEOUT_MSfallback indaemon_client.js(2 timer call sites +_resetStreamTimerdead code), thedata.timeoutbranch intranscript.ts, and thechat.timeoutWarni18n keys (zh + en). The daemon streams heartbeat/status so a silent 30s gap is not a real timeout — the fake warning forced users to re-send while the daemon was still generating.Fix 3 — Missing session metadata display (rant
2026-09-01T20:16:55)The GUI header showed no session info. Added
app.msgCounti18n key and a.react-shell-sessionspan inShell.tsxdisplayingtitle (sid) · project · N msgs(aligning with the TUI status bar).Fix 4 — History not loaded when opening a session (rant
2026-09-01T20:19:40)The history-loading chain was never wired in the React GUI. Added
listHistoryto theWorkspaceBridgeinterface;Shell.tsx loadHistoryusesshouldLoadOlder/applyHistoryPagefromhistory.ts, prepends viatranscript.prependHistoryMessage+setLoadBar, and is wired into the auto-select effect,selectProjectSession, andopenTaskSession.TranscriptViewgainedcanLoadOlder/onLoadOlderscroll-to-top trigger (capture-phase scroll listener, 40px threshold).Fix 5 — Slash commands not wired (rant
2026-09-01T20:22:00)/model,/rant,/triggershowed "unknown command" in the GUI. AddedsetModeltoWorkspaceBridge;Shell.tsx handleModelCommand(/model with arg →setModeldirect; no arg → open settings panel),handleTriggerCommand(/trigger →triggerTask+ reload tasks), addedapp.modelSwitchedi18n key.Fix 6 — Composer draft lost on view switch (rant
2026-09-01T20:28:31)Switching to settings/tasks/rants unmounted the Composer and the draft vanished.
SessionTranscriptgained adraftfield +getDraft/setDraftin the transcript store;Composer.tsxbridges the one-timeuseEditorclosure via refs — restores draft inonCreate, saves inonUpdate, clears on send, switches on sid change.Fix 7 — Chat link click navigates the main window to the webpage (rant
2026-09-01T20:33:44)Clicking an http(s) link in a chat message navigated the whole app window to that page (all GUI functions gone until restart). Added a pure
nav-policy.jsmodule (externalNavPolicy: file:// → allow, everything else → open in system browser) and wired it intomain.js:will-navigatehandler (preventDefault +shell.openExternal) andsetWindowOpenHandler(deny +openExternal) on the main window — the same protection the HTML preview view already had.nav-policy.jswas added to the electron-builder files whitelist inpackage.json.Verification
npm run typecheck(renderer): cleanFiles changed (15)
Agent.md,emrg/gui/daemon_client.js,emrg/gui/main.js,emrg/gui/nav-policy.js(new),emrg/gui/package.json,emrg/gui/renderer/src/components/Composer.test.tsx,Composer.tsx,Shell.test.tsx,Shell.tsx,TranscriptView.tsx,emrg/gui/renderer/src/lib/i18n-dicts.ts,i18n.test.ts,transcript.test.ts,transcript.ts,emrg/gui/renderer/src/shell.css,emrg/gui/test/daemon_client.test.js,emrg/gui/test/nav-policy.test.js(new)