emrg: gui renderer Batch 2 remainder — Composer + CommandMenu + history pagination - #996
Conversation
…ry pagination (lib/history.ts + lib/composer.ts + Composer.tsx, +51 vitest)
… vitest (Batch 2 remainder)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-171816
Reviewed resolved head 8844b9f (master merge 67d5508 + Agent.md conflict resolution: python 1099 from master + renderer 129 vitest; doc-count guard arithmetic exact — verified tests/test_doc_counts.py 4/4 locally).
Fresh review of the diff vs master (954 insertions, 8 files):
- lib/history.ts — pagination state machine mirroring vanilla
historyPages(rant 14:15:12): HISTORY_PAGE=50, per-session {offset,hasMore,loading}, empty-page closes hasMore,scrollCompensationpure fn with Math.max clamp,shouldLoadOlder(≤2px + hasMore + !loading). 15 tests cover wrap/accumulate/empty/guard cases. - lib/composer.ts — CommandMenu state machine (
menuForPrefix/immutablemenuNavigatewrap-around) + P2 queue-injection protocol helpers (#655):queueSend/steerCommitted/partitionRequeue/trackAfterResend(wasBusy||i>0 re-tracking, the #695 lesson)/clearQueued — protocol-aligned with task_queued/steer_committed/queued_requeue/queued_cancelled. 22 tests. - components/Composer.tsx — textarea auto-grow ≤150px, cmd-menu ↑↓/Enter/Esc + mousedown preventDefault, send flow: parseInput → onCommand routing / message → pre-generated requestId (G143), busy queue-injection, error restores text + copy.sendFailed (G49).
sendMessageinjectable,busyoptional controlled prop for Batch 5. CSS class names identical to vanilla for Batch 5 reuse. - lib/transcript.ts — +prependHistoryMessage (older-page prepend; loadBar separate field).
Verification: renderer typecheck ✓, vitest 129/129 ✓, build ✓; gui npm test 265 (257+8) ✓; pytest 1095 passed/1 skipped ✓; import + CLI ✓. CI double-green on exact head (run 32952392415: test + test-windows pass); MERGEABLE.
External contracts untouched (window.emrg bridge, daemon protocol, Electron main/preload).
1/3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-172822
Re-verified on unchanged head 8844b9f:
- Diff vs master unchanged since cycle 171816 review (8 files, +954/−1: lib/history.ts, lib/composer.ts, lib/transcript.ts prependHistoryMessage, components/Composer.tsx).
- Agent.md python 1099 + renderer 129 vitest (post-conflict-resolution state); doc-count guard satisfied.
- CI double-green on exact head (run 32952392415: test + test-windows pass); mergeStateStatus CLEAN.
Consecutive with cycle 171816 (1/3), no ❌ between.
2/3.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260826-173600
Third consecutive approval. Re-verified on unchanged head 8844b9f:
- Diff vs master: 8 files +954/-1 (lib/history.ts pagination state machine, lib/composer.ts CommandMenu + P2 queue protocol, transcript.prependHistoryMessage, components/Composer.tsx, +51 tests)
- Renderer suite on PR head: 129/129 vitest pass (13 files), typecheck OK,
npm run buildOK - Doc-count guard 4/4 (Agent.md: python 1099 + renderer 129)
- CI double-green: test + test-windows (run 32952392415)
- Mergeable: CLEAN
Ready to merge.
Uh oh!
There was an error while loading. Please reload this page.
GUI renderer Batch 2 remainder — Composer + CommandMenu + history pagination
Continues the React migration (design
~/.emrg/designs/gui-react-migration-design.md, Batch 2 remainder deferred from #994 until #990/#995 merged — the Agent.md doc-count line contention cleared).Pure logic (new, zero-DOM, fully unit-tested)
src/lib/history.ts— history on-demand pagination state machine (mirrors vanillaapp.jshistoryPages, rant 14:15:12):HISTORY_PAGE=50, per-session{offset, hasMore, loading},applyHistoryPage(empty page closes hasMore),scrollCompensation(visual-position-preserving pure function),shouldLoadOlder(≤2px + hasMore + !loading guard).src/lib/composer.ts— CommandMenu state machine (menuForPrefix/menuNavigatewrap-around) + P2 queue-injection send queue (emrg: queue messages sent while tool loop busy — inject at round boundary (P1, rant 2026-08-10T21:55:37) #655):queueSend/steerCommitted/partitionRequeue/trackAfterResend(wasBusy||i>0 re-tracking, the emrg: TUI queue-injection client support (P3 of #655) #695 lesson) /clearQueued— protocol-aligned withtask_queued/steer_committed/queued_requeue/queued_cancelled.src/lib/transcript.ts— addedprependHistoryMessage(older-page history prepends at top; loadBar stays a separate field above entries).Component
src/components/Composer.tsx— textarea (auto-grow ≤150px) + send button +/command menu with ↑↓/Enter/Esc keyboard nav and mousedown-select (preventDefault keeps focus), matching vanillaapp.jskeydown handler. Send flow:parseInput→ command routing viaonCommandcallback (Batch 5 wires dialogs) / message → pre-generated requestId (G143), busy queue-injection (wasBusy), error restores input text + system message (G49,copy.sendFailed).sendMessageis injectable (defaults towindow.emrg.sendMessage);busyis an optional controlled prop for Batch 5 daemon-broadcast wiring. CSS class names identical to vanilla (cmd-menu/cmd-menu-item/selected/composer-card/send-btn) for Batch 5 reuse.Verification
npm run typecheck✓,npm test129 passed (was 78; +15 history +22 composer +14 Composer),npm run build✓npm test265 (257 pass / 8 skip) ✓pytest1095 passed / 1 skipped ✓ (doc-count guard 4/4 — Agent.md renderer count updated 78→129)External contracts untouched:
window.emrgbridge, daemon protocol, Electron main/preload — zero changes.