Skip to content

emrg: gui — boot-chain contract guard (init→ensureConnected) preventing v0.2.81-style disconnect regressions - #1037

Merged
argszero merged 3 commits into
argszero:masterfrom
how2how2how2-arch:feature/gui-boot-contract-guard
Aug 27, 2026
Merged

emrg: gui — boot-chain contract guard (init→ensureConnected) preventing v0.2.81-style disconnect regressions#1037
argszero merged 3 commits into
argszero:masterfrom
how2how2how2-arch:feature/gui-boot-contract-guard

Conversation

@how2how2how2-arch

Copy link
Copy Markdown
Contributor

Summary

Adds a boot-chain contract guard for the GUI startup path, targeting the v0.2.81 regression class (rant 2026-08-27T10:53:38): the React migration silently dropped window.emrg.init(), so main.js's ensureConnected() — the only renderer-driven path to the daemon websocket — never ran and the GUI stayed permanently disconnected.

Why a static guard

The regression shipped because no test connected the layers:

  • Renderer tests mock window.emrg entirely (they can't see main.js)
  • integration.test.js drives daemon_client.js directly, bypassing the main.js boot path
  • preload-api.test.js guards API existence (52 invoke methods), but existence ≠ being called

#1036 fixes the renderer side with runtime tests. This PR pins the main.js + preload contract statically — the two layers no runtime test covers — so a future refactor can't silently break the chain again:

renderer mount (covered by #1036 runtime tests)
→ window.emrg.init()
→ preload init → ipcRenderer.invoke("emrg:init") ← guarded here
→ main.js emrg:init handler → ensureConnected() ← guarded here
→ daemon websocket

Guards (static regex, build-config.test.js pattern)

  1. main.js emrg:init handler must call ensureConnected() — the critical link; also asserts the config-exists / key-configured early-return gates (G34/G71/G112 semantics) precede it
  2. preload.js init must map to ipcRenderer.invoke("emrg:init") — channel name pinned
  3. ensureConnected must exist and be delegated to conn-manager — catches a "call preserved, implementation hollowed out" regression

Verification

Complementary to #1036: #1036 restores the renderer call + runtime tests; this guard locks the main/preload contract permanently.

@argszeroargszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM 1/3 — cycle 2026-08-27T11:30:45. Deep review: adds emrg/gui/test/boot-contract.test.js (3 static-regex tests) pinning the renderer→preload→main boot chain to the daemon websocket: (1) emrg:init handler must call ensureConnected() after checking configExists then gating on !keyConfigured, (2) preload maps init() → emrg:init IPC channel, (3) ensureConnected exists in main.js and conn-manager.js. This closes the v0.2.81 regression (rant 2026-08-27T10:53:38) at the static-contract layer — main.js/preload had no runtime coverage (renderer tests mock window.emrg; integration tests bypass main boot). Verified positive state: all regex targets exist in the real files and the 3 tests pass; the Agent.md GUI count is correctly bumped 89→92. CI run 33036600348 green (test + test-windows).

@argszero

Copy link
Copy Markdown
Owner

Maintainer push: resolved the merge conflict after #1035 merged (Agent.md was the only conflict — GUI count 89 to 92 for the 3 new boot-contract tests; renderer stays 442). Merged master into the fork branch and pushed (head f64f816 to 966f077). The actual change is unchanged; only the Agent.md doc-count line was reconciled. CI re-fired via the synchronize event and is green (test + test-windows).

@argszero

Copy link
Copy Markdown
Owner

Maintainer push: re-resolved the Agent.md conflict after #1036 merged. The fork branch was based on master before #1036, so its Agent.md still showed renderer count 442 (would have reverted the #1036 fix's 445). Merged the new master and reconciled — GUI stays 92 (the 3 boot-contract tests from this PR), renderer stays 445 (from the #1036 init-wiring fix). Only Agent.md was reconciltered; the actual boot-contract test is unchanged. Pushed to the fork (head 966f077 to 47af6bc); CI re-fired via the synchronize event.

@argszeroargszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM 2/3 — cycle 2026-08-27T12:05:00. Independent re-verification at current head 47af6bc after re-resolving the Agent.md conflict (renderer count now stays 445 from the #1036 fix; GUI 92 from this PR's 3 boot-contract tests). Head matches CI run 33038026702 (test + test-windows both pass, MERGEABLE/CLEAN). Re-confirmed the static boot contracts against the real files: emrg:init handler (main.js:282) calls ensureConnected() after checking configExists (line 284) and gating on !keyConfigured (line 292) — line 296; preload.js:10 maps init() to ipcRenderer.invoke("emrg:init"); conn-manager.js exposes ensureConnected. The guard pins the renderer-to-preload-to-main-to-daemon boot chain that had zero runtime coverage on the main/preload side, so a future refactor cannot silently drop renderer init and re-introduce the v0.2.81 disconnect. Verified all 3 boot-contract tests pass locally (GUI 92, 84 pass + 8 skip). No new feedback since 1/3 (113045).

@argszeroargszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM 3/3 — cycle 2026-08-27T12:10:59. Independent re-verification at current head 47af6bc: head matches CI run 33038026702 (test + test-windows pass, MERGEABLE/CLEAN). Re-checked the boot-contract test on the fork tree — 3/3 pass. This static guard is the complement to the now-merged #1036 init-wiring fix: it pins the renderer-init-to-preload-to-main-to-daemon boot chain (emrg:init handler calls ensureConnected after configExists then !keyConfigured gate; preload maps init() to ipcRenderer.invoke emrg:init; conn-manager exposes ensureConnected) so a future refactor cannot silently drop renderer init and re-introduce the v0.2.81 disconnect. The main.js/preload layer had zero runtime test coverage, so this closes the gap. No new feedback since 1/3 (113045) and 2/3 (115549).

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

@how2how2how2-arch@argszero