emrg: gui renderer React migration Batch 1 — pure-logic ports (commands/copywriting) + preload API-surface guard - #992
Conversation
…ds/copywriting) + preload API-surface guard Renderer migration Batch 1 (design doc v0.1 §5, rant 2026-08-26T12:16:48, D1-D7 decided). Follows #991 (Batch 0) now merged. - renderer/src/lib/commands.ts: vanilla renderer/js/commands.js ported to TS (pure logic, no DOM/window deps) — COMMANDS registry (16), parseInput three-state, getCompletions prefix filter, hintText with injectable t - renderer/src/lib/copywriting.ts: vanilla renderer/js/copywriting.js ported to TS — toolPhrases/buildCopy/createCopywriting factory (injectable t, refresh() locale-switch rebuild) - renderer/src/lib/commands.test.ts + copywriting.test.ts: vitest tests mirroring the old node:test assertions (design: pure-logic tests migrate to Vitest with identical assertions); old test/commands.test.js stays until Batch 5 switch (D3/D6) - emrg/gui/test/preload-api.test.js: window.emrg API-surface guard — freezes the full 53-member contract (52 invoke + onEvent) with channel/event-name assertions (red line #1; closes gap found in cycle cyc20260826-131007: design doc said 46 methods but preload.js actually exposes 52 + onEvent, only spot checks existed before) - Agent.md: doc-count guard sync — gui 262→265 (+3 preload-api), renderer vitest 19→34 (+11 commands +4 copywriting), API surface 46→52+onEvent Verification: renderer typecheck clean, renderer vitest 34/34, gui npm test 265 (257 pass + 8 integration skipped), pytest 1094 passed/1 skipped, doc-count guard 4/4, import + CLI OK.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260826-133715
Verified this cycle:
- Head b47eb51 unchanged since submission; PR mergeable
- CI green: test + test-windows both pass (run 32934366024)
- Diff review: 6 files / +447 — commands.ts + copywriting.ts pure-logic ports with vitest mirrors (15 tests), preload-api.test.js frozen 52-invoke + onEvent surface guard (closes the design-doc count gap found in cycle 131007), Agent.md count sync (gui 265, renderer 34)
- Spot-checked preload-api.test.js: static parse of preload.js api block vs frozen expected list + channel/event-name drift assertions — sound
Batch 1 ready for merge once 3 consecutive LGTMs accumulate.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260826-134710 (2/3)
Re-verified this cycle:
- Head b47eb51 unchanged since submission; PR MERGEABLE
- CI still green: test + test-windows pass (run 32934366024)
- Diff unchanged (6 files / +447); Batch 1 pure-logic ports + preload API-surface guard remain sound
Consecutive LGTMs so far: cyc20260826-133715 (1/3) → this cycle (2/3).
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260826-135353 (3/3)
Re-verified this cycle:
- Head b47eb51 unchanged; mergeStateStatus CLEAN / MERGEABLE
- CI still green: test + test-windows pass (run 32934366024)
- Diff unchanged (6 files / +447)
3 consecutive LGTMs from different cycles (133715 → 134710 → 135353), no ❌ in between. Merge condition satisfied.
Uh oh!
There was an error while loading. Please reload this page.
how2how2how2-arch
commented
Aug 26, 2026
Independent technical verification (cycle cyc20260826-1353,
No issues found. The guard closes the stale 46-method count gap from cycle cyc20260826-131007 and gives the Batch 2-5 migration a hard contract to preserve. |
GUI renderer React migration — Batch 1 (pure-logic ports + API-surface guard)
Second batch of the host rant 2026-08-26T12:16:48 (GUI renderer full React migration, route A, decisions D1–D7). Follows #991 (Batch 0) which merged as
bfb7bce. Per design doc §5 Batch 1: migrate the pure-logic modules to TS with zero UI risk — vanilla renderer files stay live until the Batch 5 one-shot switch (D3).What's in this PR
1.
renderer/src/lib/commands.ts— vanillarenderer/js/commands.jsported to TypeScript (pure logic, nowindow/DOM dependency):COMMANDSregistry (16 entries),parseInput(message/command/unknown),getCompletions(prefix filter),hintText— withtinjected as a parameter instead of readingwindow.EMRG_I18N2.
renderer/src/lib/copywriting.ts— vanillarenderer/js/copywriting.jsported to TS:toolPhrases,buildCopy, and acreateCopywriting(t)factory exposingCOPY/refresh()/TOOL_FAIL_TEXT— locale-switch rebuild semantics preserved3. Vitest tests —
commands.test.ts(11 tests) +copywriting.test.ts(4 tests) mirroring the old node:test assertions (design: pure-logic tests migrate to Vitest with identical assertions). Oldtest/commands.test.jsis kept until Batch 5 cleanup (D3/D6).4.
emrg/gui/test/preload-api.test.js—window.emrgAPI-surface guard (red line #1):onEventemrg:<name>channel (no channel drift)onEventsubscribes to theemrg:eventbroadcast channelcyc20260826-131007: the design doc claimed 46 methods butpreload.jsactually exposes 52 + onEvent (the design doc's count was stale), and only spot checks (listFiles/readFile) existed before. Any future method removal/rename/new addition now fails CI until the frozen list is deliberately updated.5. Agent.md — doc-count guard sync: GUI 262→265 (+3 preload-api), renderer vitest 19→34 (+11 commands +4 copywriting), API surface 46→52+onEvent.
External contracts preserved
window.emrgbridge: frozen by the new guard test (52 invoke + onEvent)main.js/preload.js: zero diff; vanilla renderer still loads until Batch 5Verification (local)
cd emrg/gui/renderer && npm run typecheck— clean (TS strict)cd emrg/gui/renderer && npm test— 34/34 passcd emrg/gui && EMRG_SKIP_INTEGRATION=1 npm test— 265 tests, 0 failurespytest tests/— 1094 passed, 1 skipped; doc-count guard 4/4python -c "from emrg.client.app import run_client"+python -m emrg --help— OKFollow-ups
Batches 2–5 (chat → sidebar/panels → dialogs → switch & cleanup) land in subsequent evolution cycles; Batch 1 remaining items (i18n full dict, markdown wrapper) continue next.