Skip to content

emrg: gui renderer React migration Batch 1 — pure-logic ports (commands/copywriting) + preload API-surface guard - #992

Merged
argszero merged 1 commit into
masterfrom
feature/gui-react-batch1-pure-logic
Aug 26, 2026
Merged

emrg: gui renderer React migration Batch 1 — pure-logic ports (commands/copywriting) + preload API-surface guard#992
argszero merged 1 commit into
masterfrom
feature/gui-react-batch1-pure-logic

Conversation

@argszero

Copy link
Copy Markdown
Owner

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 — vanilla renderer/js/commands.js ported to TypeScript (pure logic, no window/DOM dependency):

  • COMMANDS registry (16 entries), parseInput (message/command/unknown), getCompletions (prefix filter), hintText — with t injected as a parameter instead of reading window.EMRG_I18N
  • Contract identical to the vanilla implementation (verified by mirrored tests)

2. renderer/src/lib/copywriting.ts — vanilla renderer/js/copywriting.js ported to TS:

  • toolPhrases, buildCopy, and a createCopywriting(t) factory exposing COPY / refresh() / TOOL_FAIL_TEXT — locale-switch rebuild semantics preserved

3. Vitest testscommands.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). Old test/commands.test.js is kept until Batch 5 cleanup (D3/D6).

4. emrg/gui/test/preload-api.test.jswindow.emrg API-surface guard (red line #1):

  • Freezes the full 53-member contract: 52 invoke methods + onEvent
  • Asserts every invoke method maps to its emrg:<name> channel (no channel drift)
  • Asserts onEvent subscribes to the emrg:event broadcast channel
  • Closes a gap found in cycle cyc20260826-131007: the design doc claimed 46 methods but preload.js actually 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.emrg bridge: frozen by the new guard test (52 invoke + onEvent)
  • daemon broadcast event types: untouched
  • main.js / preload.js: zero diff; vanilla renderer still loads until Batch 5

Verification (local)

  • cd emrg/gui/renderer && npm run typecheck — clean (TS strict)
  • cd emrg/gui/renderer && npm test — 34/34 pass
  • cd emrg/gui && EMRG_SKIP_INTEGRATION=1 npm test — 265 tests, 0 failures
  • pytest tests/ — 1094 passed, 1 skipped; doc-count guard 4/4
  • python -c "from emrg.client.app import run_client" + python -m emrg --help — OK

Follow-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.

…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.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ 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.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ 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).

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ 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.

@argszero
argszero merged commit a544aa7 into masterAug 26, 2026
2 checks passed
@how2how2how2-arch

Copy link
Copy Markdown
Contributor

Independent technical verification (cycle cyc20260826-1353, gh pr checkout 992 → head b47eb51):

  • Renderer vitest: 6 files / 34/34 pass (commands.test 11 + copywriting.test 4 + App 2 + ErrorBoundary 3 + others) — matches the PR claim; typecheck (tsc --noEmit) clean.
  • GUI suite: EMRG_SKIP_INTEGRATION=1 npm test265 tests, 257 pass, 0 fail, 8 skipped — matches.
  • Pure-logic parity spot-check: COMMANDS registry identical across vanilla commands.js and commands.ts — all 16 entries (keys, hints, phases) match one-to-one; parseInput 3-state contract (message/command/unknown) and getCompletions prefix filter preserved; t correctly injected as a parameter instead of reading window.EMRG_I18N (the designed decoupling).
  • Preload API-surface guard (red line emrg: improve tool error handling (glob + edit) #1): frozen list = 52 invoke + onEvent; cross-checked against preload.jsconst api = {...} → exactly 53 keys (52 invoke + onEvent), all channels match emrg:<name> naming, onEvent → emrg:event asserted. The negative state is covered by construction (any removal/rename/new addition breaks the strict equality against the frozen list until deliberately updated).
  • CI: test + test-windows both pass (run 32934366024).

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.

Sign up for freeto 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

@argszero@how2how2how2-arch