* feat(fleet): reapply Compose configuration without a version update
Add a distinct Fleet Reapply configuration path so Compose-managed nodes can recreate Sencho from the current on-disk project when already up to date, without pulling or rewriting the image reference.
* fix(fleet): confirm remote reapply and close concurrent tracker race
Require confirmation for remote compose reapply, and lock dispatch before the remote POST so a second request cannot overwrite a successful in-flight tracker.
* fix(ui): icon-only Reapply control so Up to date badge can breathe
Collapse the Node updates Reapply label into a tooltip so the status pill no longer wraps in the Status column.
* feat(editor): Save & Reapply self-stack via fleet compose reapply (#1726)
* feat(editor): Save & Reapply self-stack via fleet compose reapply
Eligible admins can apply on-disk Compose edits to Sencho's own stack from the editor using the same confirm, dispatch, and reconnect path as Fleet Node Updates.
* fix(editor): gate Save & Reapply label to self-stack only
Ordinary stacks were labeled Save & Reapply whenever the node was
reapply-eligible. Require the selected file to be the self-stack for the
toolbar label and diff confirm CTA.
* fix(ui): move compose diff action label helper out of dialog module
Keep ComposeDiffPreviewDialog component-only so react-refresh Fast Refresh
lint passes after the Save and reapply stacked merge.
* fix(ui): lower-overhead Reduced effects path for constrained GPUs
Disable backdrop-filter glass and solidify chrome fills when data-effects is reduced (Calm default), with Appearance warning and docs for constrained rendering devices. Related to #1614.
* test(ui): harden Reduced effects glass e2e and docs wording
Parse Color Level 4 slash alpha so opacity asserts are not vacuously true, cover dialog/toast/overlay both ways with stable data-sn hooks, and soften troubleshooting copy that overstated the unmeasured diagnosis.
* docs(ui): lead constrained-GPU guidance with Reduced Motion
Rename the troubleshooting section to neutral GPU framing, point Appearance and docs at Reduced Motion first, and show the callout whenever Motion is off so Calm or Reduced effects alone do not hide the validated workaround.
* fix: repin semver compose tags during fleet self-update
Fleet updates failed when docker-compose.yml pinned a semver tag because recreate reused the on-disk pin. Pull the target image first, rewrite semver pins via the update helper, and block digest or unresolved pins with fast 409s.
* fix: update OFFLINE_META shape in capability and node-registry meta tests
* feat(fleet): show stack-label filtering in Fleet View on every tier
Stack labels and their assignments are a Community feature: the per-node
label reads are available to any authenticated user and are already used in
the per-node Stacks view. Fleet View, however, only fetched the fleet-wide
label palette and per-stack chips when the instance was on a paid tier, so a
Community user who had labelled their stacks saw no label dots on node cards
and no Tags filter in the Overview toolbar.
Drop the paid gate on the fleet label fetch so the palette, the per-stack
chips, and the Tags filter render for everyone who has labels. Node-level tag
aggregation (used for topology grouping) stays paid and is unchanged.
* fix(fleet): surface update-status failures and soften the reconnect timeout
Three reliability fixes in the Fleet View update path:
- The fleet update-status poll swallowed fetch errors in an empty catch, so a
failing poll left a silently stale table with no breadcrumb. It now logs the
failure (both thrown errors and non-ok HTTP responses) without toasting on
every tick, and keeps the last-known statuses.
- The local-update reconnecting overlay declared "Update timed out" after five
minutes, which falsely reported failure when a large image pull simply ran
longer than the reconnect window. It now shows a non-failure "Taking longer
than expected" state with a "Reload to check" action, and the timeout is a
named constant that mirrors the backend update timeout.
- The fleet overview fan-out already logged a node that failed to report; the
update-status and update-all fan-outs now log the rejected node and reason
too instead of discarding it.
* test(fleet): backfill Fleet View hook, component, and update-tracker coverage
Adds unit and component coverage for the previously untested Fleet View
surface: all six Overview hooks (overview, update-status, polling cadence,
preferences, fleet labels, node labels), the NodeCard, OverviewTab,
OverviewToolbar, NodeUpdatesSheet, UpdateStatusBadge, and ReconnectingOverlay
components, and the FleetUpdateTrackerService state transitions.
* test(fleet): assert update-status poll preserves last-known statuses on failure
Adds an explicit case that seeds statuses from a successful poll, then fails
the next poll, and verifies the table keeps the seeded statuses (and logs
without toasting) rather than relying on the implementation implicitly.
Move the inline ReconnectingOverlay sub-component out of FleetView.tsx
into its own file under FleetView/. Pure file relocation; logic and
rendered output are unchanged.
FleetView.tsx: 1,630 -> 1,556 LOC. First step in the FleetView
decomposition tracker.