TUI: persistent top-right update banner (+ --fake-update testing ground) - #317
Merged
Conversation
The startup update modal is skippable, and skipping it left no trace on screen — an operator who pressed n once stayed on the old version with nothing reminding them a newer one exists. The offer now also raises a banner pinned to the right edge of the status bar: 'new version vX.Y.Z available [ Update ]'. It renders inverse-video, so it is the opposite of whatever ground the palette and terminal use — distinguishable by construction, and static, so it never pulls the eye away from the work. Clicking Update runs the same path as the modal's y (including the refusal while a turn is in flight); the modal itself is untouched and remains the keyboard route. The banner survives update_dismissed (the modal is the question, the banner is the memory), yields while an update runs or has finished, and returns on a failed install so there is still a way to retry. On narrow rows it degrades — full sentence, bare version, button alone, nothing — instead of wrapping the one-row bar. Testing ground: 'atomic-agent tui --fake-update 9.9.9' pretends that version is released — the real check and the real installer are both bypassed, so the modal, the banner and its degradations can be eyeballed on a dev build.
Two field reports from the first demo round: The obvious first click a fresh launch invites is the banner's Update button — while the startup offer modal is still on screen. The modal raises the mouse floor to the modal rung, so that click was silently swallowed. The button now registers on the modal rung itself: a click there is exactly the modal's y, so answering the offer from the corner is the same decision, not a bypass. And once an update is accepted, the corner went quiet at the very moment it had something worth saying. The strip now narrates the lifecycle instead of hiding: 'updating to vX — do not close' while the installer runs (degrading to 'updating — do not close', then 'updating…'), 'updated to vX — restart to apply' once it lands, and back to the offer — the retry path — after a failure. --fake-update's accept now walks the same event sequence the real installer emits (update_started, feed lines, update_finished ok) on a watchable timeline instead of a one-line notice, so the whole arc — modal, click-through, do-not-close strip, restart prompt — is on show; the restart re-execs the same dev command, so nothing is ever installed.
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.
What
A persistent update strip in the top-right corner of the status bar, shown whenever a newer release exists, that also narrates the install once accepted:
The existing startup modal (
y = update now · n / Esc = skip) is untouched. What changes is what happens around it: skipping no longer erases all trace of the update, and accepting no longer leaves the corner silent while the installer works.Design
Updateis additionally accent-tinted + bold so the actionable cell reads as the button.Updatejust works — including while the startup modal is still open. The modal raises the mouse floor to the modal rung, so the button registers on that rung too; a click there is exactly the modal'sy(sameonUpdateConfirmed→runUpdate()path, including its refusal while a turn is in flight), so answering the offer from the corner is the same decision, not a bypass.update_available; survivesupdate_dismissed; showsupdating to vX — do not closewhile the installer runs;updated to vX — restart to applyonce it lands; returns to the offer — the retry path — after a failed install.new version v9.9.9 available [Update]→v9.9.9 [Update]→[Update]→ nothing;updating to v9.9.9 — do not close→updating — do not close→updating…. Verified live at 100/70/52/46/42 columns.Testing ground
(from a checkout:
npm run build && node dist/cli/index.js tui --fake-update 9.9.9)The flag pretends that version is on GitHub Releases: the real check is bypassed (a dev build fails
canSelfUpdateanyway), and accepting — via the modal'syor the banner'sUpdate— walks the same event sequence the real installer emits (started → feed lines → finished ok) on a watchable timeline, without ever runninginstall.sh. The whole arc is on show: offer, click-through-the-modal, do-not-close strip, restart prompt; the post-update restart re-execs the same dev command, so nothing on the machine is ever replaced.--fake-update v9.9.9also works; a missing/flag-shaped value is a usage error. Advertised intui --help.Tests
update-banner.test.tsx— offer/running/done phase texts, per-phase degradation ladders, disappearance below the minimum, plan-never-exceeds-budget sweep across all phases.status-bar-update.test.tsx— banner shown on offer, survives modal dismissal, "do not close" while running (button gone), restart hint when done, retry offer after failure, absent with no offer, right-edge pinning, bar stays one row.update_availableraises modal+banner,update_dismissedclears only the modal, repeat offers during a run stay ignored.tui-args:--fake-updateparsing (default null, v-prefix tolerated, missing value refused, in--help).Full
src/tuisuite: 246 files / 2658 tests green (plus this machine's known pre-existingllama-serverspawn-EACCES artifact, unrelated). Also verified in a real PTY: inverse attribute present on the whole strip, SGR mouse click onUpdatefires with the startup modal still on screen, the running and done strips render at the right moments, and the banner survivesn.