Skip to content

emrg: GUI daemon heartbeat — periodic liveness probe + active reconnect (rant 2026-08-21T12:44:34) - #912

Merged
argszero merged 2 commits into
masterfrom
feature/gui-daemon-heartbeat
Aug 21, 2026
Merged

emrg: GUI daemon heartbeat — periodic liveness probe + active reconnect (rant 2026-08-21T12:44:34)#912
argszero merged 2 commits into
masterfrom
feature/gui-daemon-heartbeat

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Fixes rant 2026-08-21T12:44:34 (heartbeat item) — the GUI had no periodic liveness probe: daemon_client.js only sends one ping after connect ("不做轮询"), and the daemon connection's disconnected event was never listened to in main.js (the 2026-08-21 11:41 incident: GUI killed the daemon, never reconnected for 36 minutes, stale green status dot).

Changes

  • emrg/gui/main.js
    • startHeartbeat() / stopHeartbeat() / _heartbeatTick(): every 15s, ping the daemon connection via waitForPong(3000, conn); on no-pong or a dropped connection → scheduleReconnect() (existing exponential backoff, already pushes connected:false/reconnecting status to the renderer so the status dot is truthful).
    • waitForPong(timeoutMs, connOverride) — optional connection override so the heartbeat probes the daemon connection specifically (not the active session connection).
    • Wiring: heartbeat started on ensureConnected() success; stopped when scheduleReconnect() is entered (no double-trigger) and on window-all-closed.
  • emrg/gui/test/renderer.smoke.test.js — source-level test asserting the heartbeat wiring exists (constants, functions, waitForPong reuse, scheduleReconnect hook, start/stop wiring).
  • Agent.md — GUI test breakdown synced (renderer smoke 127→128, total 256→257).

Verification

  • GUI: npm test — 257 tests, 249 pass, 8 skipped (live daemon owns fixed port), 0 fail
  • node --check main.js OK
  • Python: uv run pytest tests/ — 987 passed + 1 skipped (incl. doc-count guards)
  • python -m emrg --help + import OK

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Fresh review of the GUI heartbeat fix (rant 2026-08-21T12:44:34):

  • _heartbeatTick() every 15s probes the daemon connection: !conn.connected (dropped, no listener existed before) or no pong in 3s → stopHeartbeat() + scheduleReconnect() — reuses the existing exponential-backoff reconnect which already pushes connected:false/reconnecting to the renderer, so the status dot becomes truthful.
  • waitForPong(timeoutMs, connOverride) — optional conn param so the heartbeat pings the daemon connection specifically rather than the active session connection (which would otherwise hide a dead daemon while a session is open).
  • Wiring: startHeartbeat() on ensureConnected() success; stopHeartbeat() in scheduleReconnect() (prevents double-triggering) and window-all-closed. Heartbeat tick returns early when stopping.
  • Test: source-level assertion of the heartbeat wiring (constants, start/stop/tick functions, waitForPong + scheduleReconnect hooks, start/stop call sites); node --check main.js OK.
  • Verified: GUI npm test 257 (249 pass + 8 skipped), Python pytest 987 passed + 1 skipped incl. doc-count guards, import + CLI OK. CI test + test-windows PASS.

1/3.

@pm25coder

Copy link
Copy Markdown
Collaborator

Independent test report (Contributor, pm25coder):

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle

2nd review (head 6f597ba — conflict-resolved merge of master into the branch, CI test + test-windows PASS on the resolved tree):

  • Fresh local verification: GUI npm test 256 total (248 pass / 0 fail / 8 skipped), pytest 987 passed + 1 skipped, import + CLI OK.
  • Conflict resolution: Agent.md GUI count now 256/127 (126 from #911's sidebar test removal + 1 new heartbeat test); no conflict markers left.
  • Code: _heartbeatTick() every 15s — detects dropped daemon-level connections (previously no listener existed) and triggers scheduleReconnect; pings via waitForPong(3000, conn); no-pong path closes the conn and reconnects; stopHeartbeat() on reconnect + window close prevents timer stacking. Sound.

2/3.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Re-review (head updated to 6f597ba — master merged in by a parallel cycle):

  • Heartbeat implementation intact after merge: startHeartbeat()/stopHeartbeat()/_heartbeatTick() — 15s ping on the daemon connection via waitForPong(3000, conn); no-pong or dropped connection → stopHeartbeat() + scheduleReconnect() (existing exponential backoff, renderer status dot updated truthfully).
  • waitForPong conn override targets the daemon connection specifically; heartbeat guarded against stopping; started on ensureConnected success, stopped on scheduleReconnect entry and window-all-closed.
  • Merge brought in #911 (sidebar removal) — no conflict; both features coexist. Agent.md GUI count on merged head = 256 (127 renderer smoke) matches actual npm test (256: 248 pass + 8 skipped).
  • Verified on merged head: GUI npm test 256, Python pytest 987 passed + 1 skipped, import OK. CI test + test-windows PASS (run 32449393467).

2/3.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle

3rd review (head 6f597ba, unchanged since 2/3):

  • Fresh local verification on this branch: GUI npm test 256 total (248 pass / 0 fail / 8 skipped), Python pytest 987 passed + 1 skipped, import + CLI OK.
  • Heartbeat implementation intact: _heartbeatTick() every 15s pings the daemon connection via waitForPong(3000, conn); dropped connection or no pong → stopHeartbeat() + scheduleReconnect() (exponential backoff, renderer status dot updated truthfully). Guarded against stopping; started on ensureConnected success; stopped on scheduleReconnect entry and window-all-closed.
  • CI test + test-windows PASS (run 32449393467).

3/3 — merging.

@argszero
argszero merged commit b959094 into master Aug 21, 2026
2 checks passed
@argszero
argszero deleted the feature/gui-daemon-heartbeat branch August 21, 2026 05:27
argszero added a commit that referenced this pull request Aug 21, 2026
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Sign up for free to 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