fix(ui): keep the update verdict beside the stamp it was reached with - #150
Merged
Conversation
Issue #147. The panel restored WHEN coffee-bar last looked and nothing about what it found, so every relaunch printed these two lines together: coffee-bar has not looked for a newer version yet. Last checked: 2026-08-19 12:35. The stamp was persisted and the verdict was not. Read off a maintainer's machine: `defaults read com.coffeebar.app` carried `lastUpdateCheck` and no update-related key beside it. A completed check now writes both, together, and `checkForUpdates` refuses to write one without the other. What goes into `lastUpdateVerdict` is a TAG and, where the case has one, the smallest payload that rebuilds the sentence. Never the sentence. Every line in `UpdateCheck` is prose, prose is rewritten between releases, and a stored one would be replayed by a build that no longer agrees with it: the same defect as this one, a release later. `verdict(of:)` is the single place a stored form becomes words, called by the check that reached it and by the launch that restores it, so a relaunch cannot show a second spelling of the same answer. The tag is decided where the CAUSE is still in hand rather than derived afterwards from the sentence the verdict carries, because deriving it would mean matching prose, which is the thing being kept out of the store. An absent or unreadable verdict restores NOTHING rather than a guess, and `updateStatusLine` gained a third sentence for that state. It does not say "up to date": a missing verdict is silence, and silence read as good news is how a check broken for a year goes unnoticed, which is the argument `neverCheckedLine` already makes. Every install made before this key existed lands there once, and so does a value written by a newer build or left by a key collision. `cannotCompare(unstampedLine)` is deliberately not storable. It is reached before the fetch and records no attempt, so there is no stamp for it to sit beside. GREEN, measured against this tree: swift test rc=0 Test run with 1243 tests in 12 suites passed baseline at b333f41: 1235 tests, so 8 are new Guards mutation-proven. Reverting `updateStatusLine` to its two-state form turns `aRestoredStampWithNoVerdictNeverSaysItHasNotLooked` red on the exact contradiction; dropping the restore or the write turns `aVerdictSurvivesARelaunchBesideItsStamp` red. The never-checked case stays green under all three, so the guard discriminates the pair rather than the sentence. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
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.
Closes #147.
After any relaunch the panel showed both of these, one under the other:
It reported that it had never checked, and then reported when it last checked. Observed on the shipped v0.3.0 build.
Cause
The timestamp was persisted and the verdict was not.
ServingModelwroteSettingsKey.lastUpdateCheckafter each check and restored it at launch, butupdateVerdicthad no such write, so a relaunch held a real stamp beside a nil verdict and renderedneverCheckedLine. Confirmed on the maintainer's Mac:defaults read com.coffeebar.appcarried exactly one update-related key and no verdict.Not an edge case. It was the state of the panel after every launch until the next check fell due, which with a 24-hour interval is most of a day.
Approach
The verdict is persisted as a discriminator plus a minimal payload, and the sentence is rebuilt from current code rather than stored as prose, so an upgrade cannot resurrect wording written by an older build.
The alternative of not persisting
cannotComparewas rejected with reason: the machine in the bug report was in a failed-check state, so restoring no verdict returnsneverCheckedLinebeside a real stamp, which is the reported defect unchanged. It is only safe if the stamp is suppressed too, and the stamp is the sole bound on the app's one outbound request.Every existing install has a stamp and no stored verdict, so a third state was needed regardless. Those users see one honest sentence once, until their next check falls due, rather than a fabricated verdict.
The intent at
UpdateCheck.swiftis preserved: it still reports that nothing has happened rather than assuming "up to date", because silence read as good news is how a check that has been broken for a year goes unnoticed.Testing done
swift testrc=0, 1243 tests in 12 suites pre-rebase, verified independently on a clean scratch path rather than taken from the report.Breaking changes
None. One new settings key, absent-safe.