Skip to content

Fix stale dialog chunks, fast-mode pricing in Projects, the offline tab icon, the phone topbar and two re-sign-in prompt cases - #1929

Merged
BarganConstantin merged 7 commits into
developmentfrom
fix/web-misc
Oct 4, 2026
Merged

BarganConstantin merged 7 commits into
developmentfrom
fix/web-misc

Conversation

@BarganConstantin

Copy link
Copy Markdown
Owner

What changes

  • Usage history and Browser Watch after an upgrade. A tab older than the build on disk asks for a chunk name that no longer exists. The server now answers a missing file under assets/ with 404 instead of index.html. Each of the two dialogs opens as a short note with Reload and Close, and the deck no longer goes to the crash pane or files a crash report.
  • Projects report and fast mode. The Projects tally now keeps each speed's share of a model's tokens. The tally is rebuilt once from the transcripts (state version 4). Each share is priced at its own speed's rate, as the board prices it, and a speed with no rate is counted as unpriced. On a day ccusage calibrates, the drift is first taken back to the standard basis by that day's own speed mix. The day still totals ccusage's figure, and each project now carries its own premium.
  • The tab's offline icon. Every state's icon file is fetched once while the deck answers and kept in the page as a data: URL. The tab's writer (showTabIcon, which the crash screen also uses) hands those to the links. The offline mark therefore needs no request to a deck that has gone away.
  • "Login expired" popover focus. AnchoredPopover takes a focusRef, and the issue popover now opens on Done. Report this stays one Shift+Tab away.
  • Topbar at phone widths. Under 480px, History, Browser watch and Feedback fold into one ⋯ menu button, which also carries Browser watch's unread badge. The selected-agent ribbon also leaves the bar at that width. The waiting pill stays whole and no control goes off either edge, down to 320px.
  • Re-sign-in prompt after a successful re-sign-in. The verdict cache is now stamped with the time it was asked for. When a collector has stopped, the account counts as a dead login only if the verdict was asked after the deck's last sign-in. The first collection after a re-sign-in no longer opens a new incident.
  • "Deck signed this in" mark when the last account is removed. When sequence.json holds an empty accounts map, the roster read now forgets the marks of accounts that are gone. A file that cannot be read still forgets nothing.

Verification

  • npm run typecheck: clean.
  • Full suite before the rebase (--maxWorkers=3 --minWorkers=1): 846 files, 11383 tests passed, exit 0. After the rebase onto development, the touched and neighbouring tests were run again: 161 files, 2671 tests passed.
  • New regression tests. Each failed on the code before its fix:
    • stale-dialog-chunk.test.ts: the 404 for a missing asset, and each lazy dialog settling on its note. Before the fix this rethrew "Failed to fetch dynamically imported module".
    • projects-report-fast-mode.test.ts: before the fix, a fast Opus 5.5 turn cost $0.744 against the board's $1.488, and the calibrated split was 1:1 instead of the board's ratio.
    • offline-tab-icon.test.ts: before the fix, the offline href was still /state/favicon-error.svg.
    • issue-popover-focus.test.ts: before the fix, the first stop was "Report this".
    • topbar-phone-width.test.ts: cascade arithmetic. Before the fix, the controls left no room for the pill at 320–412px, and the ribbon was not hidden on a phone.
    • reauth-after-resignin.test.ts: the real roster read, against a sandboxed store and faked processes. Before the fix it opened a new incident named by the sign-in.
    • signin-mark-last-account.test.ts: the real roster read, with the real withTidied. Before the fix the mark survived, and a pasted share of the same address came back with origin: ccdeck_signin and an incident.
  • Repointed text pins: the lazy-import spelling (serve-lighter-883), the modal inventories (22 → 23), the tab writer's spelling (ambient-signal), the folded buttons' class (topbar-words-836, visible-feedback-1853), the ribbon rule (detail-sheet-narrow-1790), the stopped-path verdict (reauth-prompt-1893) and the emptied-store expectation (reauth-origins-flow-1893). No guard was removed.
  • Browser, on an isolated deck with its own HOME and fakes for the accounts routes:
    • The two lazy chunks were rewritten to missing names. Each dialog showed its note with Reload focused, Escape closed it, there was no crash pane, and no report was POSTed.
    • The deck was made unreachable and the stream's error fired. The tab's links became the error SVG and PNG data: URLs, with no icon request after the deck went away.
    • The issue popover opened on Done. Shift+Tab reached Report this, and Done handed focus back to the warning.
    • The topbar was measured at 320, 360, 390, 412 and 480px, plain and with a card selected. The waiting pill sat at x ≥ 13, nothing was off either edge, and the page did not scroll. Before the fix the pill was at x = −15 to −29. The ⋯ menu was driven by keyboard (Enter, arrows, Enter opens the dialog, Escape returns to ⋯) and by pointer. At 1440px the three buttons are back and the ⋯ is hidden.

…rade

A tab older than an upgrade asks for the old chunk name. The server now answers a missing file under assets/ with 404 instead of index.html, and Usage history and Browser Watch open as a short note with Reload instead of taking the whole deck to the crash pane.
The Projects tally kept its counters by model alone, so a fast turn was priced at the standard rate: half the board's figure where ccusage did not calibrate the day, and a premium spread over every project where it did. The tally now keeps each speed's share (rebuilt once from the transcripts), each share is priced at its own rate, and a calibrated day's drift is taken back to the standard basis by the day's own speed mix.
…he deck

The offline mark was a path on the deck, first requested when the event stream had already failed, so it could not load and the tab kept its previous mark. Every state's file is now fetched once while the deck answers and handed to the tab's links as a data: URL.
Report this is first in the popover's DOM, so the dismiss hook focused it and a keyboard Enter after opening the popover filed a report. AnchoredPopover now takes a focusRef for its first stop, and the issue popover names Done.
With Feedback on the bar the controls came to 314px, so at 360px the waiting pill was cut off the left edge and at 320px a control went off the right one; a selected agent's ribbon drew its state over the Session list button. Under 480px History, Browser watch and Feedback now open from one menu button, and the ribbon leaves the bar.
…ust worked

After a re-sign-in of an account that had collected nothing for half a day, the first collection stamps its attempt before it records anything, and a roster read in between paired that attempt with the verdict cached before the sign-in: a new incident, and the prompt asked again. A stopped collector now counts as a dead login only on a verdict asked after the last sign-in.
Removing the store's last account leaves sequence.json with an empty accounts map, and the roster read kept every mark over it. The same address pasted from a share later inherited the mark, and a refusal of that shared login opened a re-sign-in prompt. An emptied store now forgets the marks it no longer holds; an unreadable one still forgets nothing.
@BarganConstantin
BarganConstantin merged commit 3a2df4e into development Oct 4, 2026
10 checks passed
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.

1 participant