Skip to content

feat(menubar): mark badge when a paired device is unreachable in combined scope - #867

Merged
iamtoruk merged 2 commits into
getagentseal:mainfrom
marcreynolds:feat/menubar-degraded-device-indicator
Aug 3, 2026
Merged

feat(menubar): mark badge when a paired device is unreachable in combined scope#867
iamtoruk merged 2 commits into
getagentseal:mainfrom
marcreynolds:feat/menubar-degraded-device-indicator

Conversation

@marcreynolds

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #866. Under Combined scope the menu bar badge falls back to the
local figure whenever a paired device doesn't report (asleep / off the
network) — which reads as a glitch ("it dropped back to local for a second").
This adds a small, dimmed reachable/total marker to the badge, plus a
matching tooltip, so a degraded total is legibly "a peer is unreachable"
rather than a number that mysteriously shrank.

Example badge: 🔥 $95.94 /mo · 1/2 — tooltip: "CodeBurn month · 1 of 2
devices reporting"
. The marker clears the instant every paired device reports
again.

What changed

  • AppStore.menubarBadgeDeviceShortfall(reachable, total) only when
    Combined scope is active and fewer paired devices reported than are
    paired; nil otherwise (all reported, single device, or Local scope).
  • The badge appends the dimmed marker and sets the device-count tooltip when a
    shortfall is present.
  • Tests for the shortfall condition (unreachable peer → marker; all reachable
    / Local scope → no marker).

Stacked on #866

Note

This branch is stacked on top of #866 (the combined-scope fix), since the
indicator depends on the combined badge payload introduced there. Until #866
merges, this PR's diff also includes #866's commit; once #866 lands on
main, the diff reduces to just the indicator commit. Merge #866 first.

Testing

  • swift build clean; new AppStore shortfall tests added (run under the
    Xcode toolchain: swift test).

…ined scope

Under combined scope the badge falls back to the local figure whenever a
paired device doesn't report (asleep / off-network), which read as a glitch.
Append a dimmed "reachable/total" marker (e.g. "$95.94 /mo · 1/2") and a
matching tooltip so the reduced total is legibly "peer unreachable" instead.
The marker clears the instant every paired device reports again.

Adds AppStore.menubarBadgeDeviceShortfall plus tests.
@iamtoruk
iamtoruk marked this pull request as ready for review August 3, 2026 19:35

@iamtoruk iamtoruk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up to #866 (now merged), and the diff reduces cleanly to just the indicator commit. menubarBadgeDeviceShortfall returns (reachable, total) only when combined scope is active and fewer paired devices reported than are paired — it reads menubarBadgeCombined (nil under local scope), so it is correctly silent on local scope and single-device setups, and clears the instant every peer reports again. That turns #866's graceful drop-to-local into a legible reachable/total marker instead of a number that mysteriously shrank.

On the merged tree: swift test 130 tests + all XCTest suites at 0 failures, including the two new shortfall cases (unreachable peer → marker; all reachable → no marker). Small, self-contained, and correct. Good to merge.

@iamtoruk
iamtoruk merged commit dc3ea24 into getagentseal:main Aug 3, 2026
3 checks passed
iamtoruk added a commit that referenced this pull request Aug 3, 2026
…he all-provider view

buildDurablePeriod derived the today slice of the multi-day, all-provider
headline from the unsliced whole-range parse, so a turn spanning local midnight
kept its category and turn count anchored on its yesterday start. The per-call
cost and calls bucketed onto today correctly, but By Activity and the JSON
daily turn count lost the post-midnight half — categories summed to only the
pre-midnight cost while the headline, By Model and By Project were right.

Slice the today parse with filterProjectsByDays first, which re-anchors the
straddling turn to its surviving today calls, so today's category cost lands on
today. Category cost is the sum of the slice's own calls, so day-N + day-N+1
still equals the whole-range total (no over-count); the per-day turn-count
split matches the cache side and the documented per-day semantics.

Adds a regression test in the straddling-turn conservation suite
(mutation-checked: fails on the pre-fix code). Also fills in the CHANGELOG
Unreleased entries for the batch (#853, #856, #872, #846/#859, #866/#867, #833).
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.

2 participants