Skip to content

The persistent "update available" header chip is never rendered — app.update_available is written and never read #7136

Closed

Description

@ronohara

Before you start

  • I searched existing issues and this is not a duplicate. 我已搜索过现有 issue。

What happened? 发生了什么?

saw no notification

Steps to reproduce 复现步骤

Using codewhale - the update available notification for 0.10.2 was not given

Codewhale version 版本

codewhale 0.10.1

Where did it happen? 在哪里出现?

TUI (terminal interface)

Operating system 操作系统

Linux

How did you get Codewhale? 获取方式

Official script (codewhale.net/install.sh)

Provider and model 提供商和模型

No response

Terminal and shell 终端

No response

codewhale doctor (optional)

Logs, screenshots, anything else (optional)

The persistent "update available" header chip is never rendered — app.update_available is written and never read

Labels: bug

Surface: TUI (terminal interface)

Version: codewhale 0.10.1 (fead51eeea0f)

OS: Linux (Linux Mint 22.2, x86-64)

Confirmed present in: v0.10.1 tag and HEAD (687a38c6e, 2026-10-28) — 281 commits after the tag, still unreproduced.


What happened

A newer release was available and Codewhale never told me — or told me only for twelve seconds, at startup, four days before I noticed.

Running 0.10.1 with 0.10.2 published:

Fact Value
Installed codewhale 0.10.1 (fead51eeea0f), /usr/local/bin/codewhale, 8 Oct
v0.10.2 published 2026-10-24T17:31:14Z
Session started 2026-10-25T04:27:16Z
Update-check cache written 2026-10-25T04:27:11Z — 5 seconds before the session row
Cache contents {"checked_at_unix": 1792902431, "latest_tag": "v0.10.2"}

So the startup check ran, reached GitHub about ten hours after the release, and correctly found v0.10.2. The session that was told is the session I was using — and I saw nothing across four days of continuous use.

Nothing suppressed it: no CODEWHALE_NO_UPDATE_CHECK, no NO_UPDATE_NOTIFIER, no CI variables set, no [update] section in config.toml. The default check interval is one hour, so a fresh launch re-checks.

The defect

app.update_available is assigned when the startup check completes, and nothing in the tree ever reads it. A repo-wide grep returns exactly three hits — the field declaration, its initialisation to None, and the assignment:

crates/tui/src/tui/app.rs:1676:        pub update_available: Option<String>,
crates/tui/src/tui/app/init.rs:850:            update_available: None,
crates/tui/src/tui/ui/event_loop.rs:2247:            app.update_available = Some(notice.chip_label());

There is no render site, no serialisation, no non-Rust consumer. The write is dead.

The field's own doc comment describes the feature that is missing (app.rs:1672–1675):

/// Header chip label (e.g. `↑ v0.9.5`) set once by the fire-and-forget
/// startup version check when a newer stable release exists. Drives the
/// small persistent update chip in the header so the affordance survives
/// the transient toast without nagging (FINISH-0.9.4 #14).
pub update_available: Option<String>,

And the assignment site repeats the claim (event_loop.rs:2240–2242):

// Transient toast for immediate visibility, plus a durable
// in-transcript notice so the prompt survives the toast TTL and
// stays actionable during a busy session (#3961). The persistent
// header chip keeps a quiet affordance after both (#14).

#14 — the persistent chip — was implemented as a field, a label generator and a doc comment, but never wired to the header.

Why the test suite did not catch it

There is a test for the chip, and it passes:

// crates/tui/src/tui/ui/tests.rs:18665-18667
// The persistent header chip is quiet: version only, no action verb —
// the toast and this block carry the instructions (#14).
assert_eq!(notice.chip_label(), "↑ v0.8.47");

It asserts the label generator returns the right string. It never asserts that any render path consumes it — so a fully working chip_label() with no consumer passes cleanly. That is the shape of the defect: the unit under test is correct, and the integration is absent.

What this costs a user

The three intended surfaces degrade to two, and the surviving durable one is weak:

Surface State Reality
Toast works 12 seconds (VERSION_HINT_TOAST_TTL_MS = 12_000)
Transcript system message works scrolls away during a working session
Persistent header chip absent written and never read

The failure mode is worst for the exact user the feature exists for: someone in a long session. The check runs once per process at startup; a session lasting days — mine is four days old — sees the toast once, at the moment of launch, when the terminal is still drawing. After that there is no indication at all, and the version drift is silent.

What I expected

A quiet, persistent affordance in the header reading ↑ v0.10.2 for as long as a newer release is known — as the doc comment and the #14 reference both describe. Clicking or a keystroke would show the update command.

Steps to reproduce

  1. Install any release older than the latest, e.g. 0.10.1, with 0.10.2 available.
  2. Ensure no [update] config and no suppression env vars.
  3. Delete ~/.codewhale/update-check.json if present, then start a new session.
  4. A toast appears for 12 seconds and one transcript line is written.
  5. Look at the header. There is no chip. It never appears, in this session or any later one, even though app.update_available is Some("↑ v0.10.2").

Suggested fix

Two lines and a render, in rough order:

  1. Render it. Emit the chip wherever the header's status chips are composed, gated on app.update_available.is_some(). The label is already correct and quiet (version only), so no wording decision is needed.
  2. Add an integration test that fails today. Assert that after the version check resolves with a newer tag, the composed header contains the chip text — not that chip_label() returns a string. A test at the render boundary is what was missing.
  3. Optionally, consider whether the 12-second toast alone is adequate for sessions that outlive the check interval; the chip was the answer to that question, which is why its absence matters.

Notes

  • The install resolved to InstallMethod::Binary (path has no cellar, node_modules or .cargo/bin), so the notice would advertise codewhale update. On this machine the binary is root:root in /usr/local/bin, so a self-update run as a normal user cannot replace it — a separate observation, not part of this defect, but it makes the advertised command fail with a permissions error rather than prompting for elevation.
  • app.update_available is None initialised and never cleared. If a future render is added, check whether it should also be cleared when a check returns "no newer release" after previously finding one — the cache stores the latest tag, so a downgrade in latest_tag is possible in principle.
  • chip_label() already distinguishes a staged release (↑ v{latest} ready) from an unstaged one (↑ v{latest}), which suggests a download-and-stage flow was intended alongside the chip. Worth confirming whether that path exists before wiring the chip.
  • Reported from a read-only inspection of the source at 687a38c6e plus the on-disk state of a 0.10.1 install; no code was modified and no issue was filed.

Investigation claim — 2026-10-28

Coordinator verified on current Engine source that the update label is assigned but no rendering path reads it. Initial read-only scope is the TUI's existing footer and pet presentation (crates/tui/src/tui/phase_strip.rs, crates/tui/src/tui/pet_watch/full.rs) and their existing rendering fixtures. A safe persistent affordance must preserve higher-priority status and remote-control signals and handle narrow/ASCII layouts. Source is frozen for a contributor build; no fix or verification is claimed yet.

Activity

  1. added
    needs-triageNew external report awaiting maintainer triage; repro, logs and version output help
    on Oct 29, 2026
  2. changed the title [-]he persistent "update available" header chip is never rendered — `app.update_available` is written and never read[/-] [+]The persistent "update available" header chip is never rendered — `app.update_available` is written and never read[/+] on Oct 29, 2026
  3. added this to the v0.10.3 milestone on Oct 29, 2026
  4. Hmbown commented on Oct 29, 2026

    @Hmbown
    Collaborator

    Fixed on main in 71bc853 and bd9d442: the update notice now stays in the metrics line and opens the update check when clicked, so it is no longer lost; thank you @ronohara for the report.

  5. moved this from Backlog to Done in CodeWhaleon Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-triageNew external report awaiting maintainer triage; repro, logs and version output help

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions