emrg: upgrade banner — in-memory run version vs live installed_version, dedicated upgrade event (rant 2026-08-21T14:38:27) - #917
Merged
Conversation
…n, dedicated upgrade event (rant 2026-08-21T14:38:27)
argszero
commented
Aug 21, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle
Fresh review of the upgrade-banner judgment refactor (rant 2026-08-21T14:38:27):
- Root causes addressed: (1)
previous-version.txtresidue previously made every launch re-show the banner; (2) livecurrent_versionread hid the "pending restart" state. - daemon:
self._run_versioncaptured once at startup; pong returnscurrent_version(in-memory run) +installed_version(live disk);_previous_installed_version()and pongprevious_versionremoved. - main.js: init baseline unchanged; heartbeat compares
installed_version !== current_version→ dedicatedupgradeevent (nostatusreuse, no handleStatus spam). - app.js:
case "upgrade"→maybeShowUpgradeBanner(installed, run)with from→to text +lastKnownVersiondedup; banner logic removed fromhandleStatus. - Tests cover all three states (show on installed≠run, hide on already-shown, status no longer triggers) + daemon run-vs-installed fixed/live semantics; no previous_version leakage anywhere.
- Verified locally: pytest 994 passed + 1 skipped (995 collected), GUI 257 (249+8), node --check main.js + app.js OK, import + CLI OK.
1/3.
argszero
commented
Aug 21, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle
2nd review (head ca93102, MERGEABLE/CLEAN, CI test + test-windows PASS):
- Fresh local verification on this branch: pytest 994 passed + 1 skipped (995 collected), GUI npm test 257 (249 pass / 0 fail / 8 skipped), import + CLI OK.
- daemon.py: _run_version captured once at startup (fixed for process lifetime); pong now returns current_version = in-memory run version + installed_version = live disk read; previous_version removed from the judgment (previous-version.txt no longer part of the model — addresses the residue flaw).
- main.js: init passes current_version as lastKnownVersion baseline; 15s heartbeat compares installed_version ≠ current_version → dedicated 'upgrade' event (not reusing 'status', avoiding handleStatus side-effect spam).
- renderer: handleEvent case 'upgrade' → maybeShowUpgradeBanner(installed, current) with lastKnownVersion dedup.
- Self-consistency matrix is correct: run==installed → no banner; installed≠run → banner; after restart-to-apply run==installed → gone; dismiss+relaunch without daemon restart → banner again (correct).
2/3.
argszero
commented
Aug 21, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle
3rd review (head ca93102, CI test + test-windows PASS on run 32457292037):
- Fresh local verification: Python pytest 994 passed + 1 skipped (995 collected), GUI npm test 257 (249 pass + 8 skipped),
node --checkmain.js + app.js OK, import OK. - Model verified sound:
self._run_versionfixed at daemon startup; pongcurrent_version= run version,installed_version= live disk; heartbeat emits dedicatedupgradeevent on mismatch; renderercase "upgrade"shows from→to withlastKnownVersiondedup;previous_versionfully removed from judgment path. - New daemon test proves
_run_versionstays fixed while the disk read reflects a later upgrade, and pong carries noprevious_version.
3/3 — merging.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrade banner — in-memory run version vs live installed_version + dedicated
upgradeeventRant 2026-08-21T14:38:27: the banner judgment model had two logic flaws:
previous-version.txtresidue — the daemon's pongcurrent_versionread
version.txtlive andprevious_versionreadprevious-version.txt.The file stays at the pre-upgrade version forever (e.g. 0.2.61), so every
launch judged "version changed" and re-showed the banner even with no new
release.
current_versionreading the filein real time meant that after a daemon restart the GUI saw the new version
and could not distinguish "already applied" from "needs restart".
New model
self._run_version(the code version this daemon process actually runs, fixed for its
lifetime). Pong now returns:
current_version= in-memory_run_version(actually running)installed_version= live disk read (upgrade agent may have updated it)previous_versionremoved —previous-version.txtis no longer part ofthe judgment (the file may still be written by the upgrade agent).
current_versionto the renderer as thelastKnownVersionbaseline; the 15s heartbeat (from emrg: GUI daemon heartbeat — periodic liveness probe + active reconnect (rant 2026-08-21T12:44:34) #912) comparespong.installed_version !== pong.current_version(and installed non-empty)and emits a dedicated
upgradeevent (not reusingstatus, avoidinghandleStatusside-effect spam) with{current_version, installed_version}.handleEventgainscase "upgrade"→maybeShowUpgradeBanner(installed_version, current_version)— text"upgraded from {current} to {installed} — restart to apply" with the
existing
lastKnownVersiondedup (same installed version shown once).Self-consistency: no upgrade (run==installed) → no banner; upgrade installed
but not restarted (run 0.2.61 vs disk 0.2.62) → banner; after restart-to-apply
(new daemon, run==installed) → no banner; dismiss + relaunch GUI without
restarting the daemon → banner again (correct: not yet applied); further
upgrade 0.2.63 → banner again. No cross-session persistence needed.
Tests / verification
tests/test_daemon.py:test_pong_includes_current_versionasserts bothcurrent_versionandinstalled_version; newtest_pong_run_vs_installed_versionverifies_run_versionis fixed atstartup while
_current_installed_version()reflects a later disk write,and that pong no longer carries
previous_version.renderer.smoke.test.js: banner test rewritten for theupgradeevent —positive (installed≠run → from→to shown), negative (already shown version →
hidden), and a new negative asserting
statusno longer triggers thebanner; source-level asserts
case "upgrade"and the heartbeat'ssendToRenderer("upgrade")/pong.installed_version.257 (249 pass + 8 skipped),
node --checkmain.js + app.js OK, import +CLI OK. Test counts unchanged (Agent.md stays valid).