Move to material_ui, refresh dependencies, and make the room rows readable #4

Merged
bjoern merged 5 commits from feat/material-ui-and-room-labels into main 2026-09-11 16:07:15 +02:00
Member

Dependency housekeeping with a deadline attached, plus a UI bug the owner found by running the app. Five commits, each separable.

1 & 2 — material_ui (6bdb27c, 316194b)

Flutter 3.47 split Material and Cupertino out of the SDK into standalone pub.dev packages so they can ship on their own cadence. The bundled package:flutter/material.dart still works today, but is formally deprecated in the November stable.

That has a dated consequence for this repo specifically: CLAUDE.md's definition of done requires flutter analyze to print "No issues found", and CI gates on it. The day the deprecation lands, all 22 imports light up and CI goes red on our own rule. Doing it now is a codemod with everything green; doing it in November is the same work under pressure.

  • 6bdb27c is entirely dart fix --apply --code=migrate_design_widgets — one import line per file across 22 files, plus the dependency. No Cupertino anywhere here, so only half the migration applies.
  • 316194b bumps cached_network_image 3.4.1 → 4.0.0, which is the same change from the other side: that version's breaking change is the move to material_ui. Leaving it behind would have the app and its image dependency disagreeing about where Material lives — what MaterialUiCompatibilityBridge exists to paper over. CachedNetworkImage and CachedNetworkImageProvider are unchanged, and those two are all we use.

3 — Room labels (d172457)

Found by running the app: with two bedroom speakers, the per-room volume rows rendered as "Schlafzimmer S…" and "SchlafzimmerSt…" — the fixed 108px name column truncated away the only part that distinguishes them, so you could not tell which slider was which room.

The name now takes the full row width, with its level beside it as a percentage, so the balance between rooms can be read instead of inferred from where the thumbs sit. A slimmer slider keeps the two-line row about as tall as the one-line row it replaces. A room whose level has not been polled yet shows an em dash rather than "0%" — unknown is not silent.

4 — Transitive dependency refresh (a65800d)

flutter pub outdated had 26 transitive packages pinned below their resolvable versions. flutter pub upgrade moves them all within the existing constraints; no pubspec.yaml constraint changes, because direct dependencies were already current after commit 2.

This also closes a loop from PR #2: it is the lockfile drift that kept reappearing in the working tree, which I wrongly blamed on flutter pub get. It was an upgrade resolution, not a get. Taken deliberately here, with CI pinned to the SDK that wrote the lockfile, so it stops turning up uninvited.

material_color_utilities and test_api stay behind — both are pinned by the Flutter SDK itself and cannot resolve higher.

5 — Drop cupertino_icons (e427be9)

Left over from the Flutter template; no file references CupertinoIcons. It was not free: CupertinoIcons.ttf (252 KB) shipped in the bundle and was listed in FontManifest.json. A clean rebuild now emits a manifest with MaterialIcons alone. Fitting, given Material and Cupertino are now separate packages and this is a Linux/Android app.

Exercised

  • flutter analyze clean · 103/103 tests · dart format gate clean · flutter build linux --debug succeeds.
  • Commit 5 verified against a clean rebuild (rm -rf build/linux), not an incremental one: the font file is absent and FontManifest.json lists only MaterialIcons.
  • New test/format_test.dart pins volumePercent. Mutation probes, all red:
probe result
unknown level renders 0% instead of a dash ⛔ fails
drop the 0.0–1.0 clamp ⛔ fails
truncate instead of round ⛔ fails

Not exercised

  • The layout itself has no test. volumePercent is pinned because it is pure; that two speakers with a shared prefix are now distinguishable on screen is a claim only a person looking at the app can confirm. Precondition: two grouped speakers whose names share a long prefix. Action: open the per-room panel under the volume slider. Expect: both full names legible, each with its own percentage.
  • material_ui and the dependency refresh are verified by compilation, not by eye. Analyze, 103 tests and a Linux build all pass, and the codemod only renames imports — but no test renders these screens, so a visual regression would not be caught here. Worth one look at the app after merging.
  • Impeller became the default desktop renderer in 3.47 independently of this PR. The owner has confirmed main runs well on Linux, so that is covered for the current code.

🤖 Generated with Claude Code

Dependency housekeeping with a deadline attached, plus a UI bug the owner found by running the app. Five commits, each separable. ## 1 & 2 — `material_ui` (`6bdb27c`, `316194b`) Flutter 3.47 split Material and Cupertino out of the SDK into standalone pub.dev packages so they can ship on their own cadence. The bundled `package:flutter/material.dart` still works today, but is **formally deprecated in the November stable**. That has a dated consequence for this repo specifically: CLAUDE.md's definition of done requires `flutter analyze` to print "No issues found", and CI gates on it. The day the deprecation lands, all 22 imports light up and CI goes red on our own rule. Doing it now is a codemod with everything green; doing it in November is the same work under pressure. - `6bdb27c` is entirely `dart fix --apply --code=migrate_design_widgets` — one import line per file across 22 files, plus the dependency. No Cupertino anywhere here, so only half the migration applies. - `316194b` bumps `cached_network_image` 3.4.1 → 4.0.0, which is the same change from the other side: that version's breaking change *is* the move to `material_ui`. Leaving it behind would have the app and its image dependency disagreeing about where Material lives — what `MaterialUiCompatibilityBridge` exists to paper over. `CachedNetworkImage` and `CachedNetworkImageProvider` are unchanged, and those two are all we use. ## 3 — Room labels (`d172457`) Found by running the app: with two bedroom speakers, the per-room volume rows rendered as **"Schlafzimmer S…"** and **"SchlafzimmerSt…"** — the fixed 108px name column truncated away the only part that distinguishes them, so you could not tell which slider was which room. The name now takes the full row width, with its level beside it as a percentage, so the balance between rooms can be *read* instead of inferred from where the thumbs sit. A slimmer slider keeps the two-line row about as tall as the one-line row it replaces. A room whose level has not been polled yet shows an em dash rather than "0%" — unknown is not silent. ## 4 — Transitive dependency refresh (`a65800d`) `flutter pub outdated` had **26 transitive packages** pinned below their resolvable versions. `flutter pub upgrade` moves them all within the existing constraints; no `pubspec.yaml` constraint changes, because direct dependencies were already current after commit 2. This also closes a loop from PR #2: it is the lockfile drift that kept reappearing in the working tree, which I wrongly blamed on `flutter pub get`. It was an upgrade resolution, not a get. Taken deliberately here, with CI pinned to the SDK that wrote the lockfile, so it stops turning up uninvited. `material_color_utilities` and `test_api` stay behind — both are pinned by the Flutter SDK itself and cannot resolve higher. ## 5 — Drop `cupertino_icons` (`e427be9`) Left over from the Flutter template; **no file references `CupertinoIcons`**. It was not free: `CupertinoIcons.ttf` (252 KB) shipped in the bundle and was listed in `FontManifest.json`. A clean rebuild now emits a manifest with `MaterialIcons` alone. Fitting, given Material and Cupertino are now separate packages and this is a Linux/Android app. ## Exercised - `flutter analyze` clean · **103/103 tests** · `dart format` gate clean · `flutter build linux --debug` succeeds. - Commit 5 verified against a **clean rebuild** (`rm -rf build/linux`), not an incremental one: the font file is absent and `FontManifest.json` lists only MaterialIcons. - New `test/format_test.dart` pins `volumePercent`. Mutation probes, all red: | probe | result | |---|---| | unknown level renders `0%` instead of a dash | ⛔ fails | | drop the 0.0–1.0 clamp | ⛔ fails | | truncate instead of round | ⛔ fails | ## Not exercised - **The layout itself has no test.** `volumePercent` is pinned because it is pure; that two speakers with a shared prefix are now distinguishable on screen is a claim only a person looking at the app can confirm. Precondition: two grouped speakers whose names share a long prefix. Action: open the per-room panel under the volume slider. Expect: both full names legible, each with its own percentage. - **`material_ui` and the dependency refresh are verified by compilation, not by eye.** Analyze, 103 tests and a Linux build all pass, and the codemod only renames imports — but no test renders these screens, so a visual regression would not be caught here. Worth one look at the app after merging. - Impeller became the default desktop renderer in 3.47 independently of this PR. The owner has confirmed `main` runs well on Linux, so that is covered for the current code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Flutter 3.47 split Material and Cupertino out of the SDK into packages
on pub.dev so they can ship on their own cadence. The bundled
`package:flutter/material.dart` still works today but is formally
deprecated in the November stable -- at which point all 22 of our
imports would emit deprecations and `flutter analyze` would stop
printing "No issues found", which CI gates on.

Entirely `dart fix --apply --code=migrate_design_widgets`: one import
line per file, plus the dependency. No Cupertino anywhere here, so only
half the migration applies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Same change from the other side: 4.0.0's breaking change *is* swapping
`flutter/material.dart` for `material_ui`. Staying on 3.4.1 would leave
the app and its image dependency disagreeing about where Material
lives -- the case MaterialUiCompatibilityBridge exists to paper over.

CachedNetworkImage and CachedNetworkImageProvider are unchanged, and
those two are all we use.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Give each room in the volume panel its full name and its level
Some checks failed
CI / verify (pull_request) Has been cancelled
d172457248
The per-room rows put the speaker's name in a fixed 108px column, which
is fine for "Kitchen" but useless for the names people actually use: two
bedroom speakers both rendered as "Schlafzimmer S..." and
"SchlafzimmerSt...", so you could not tell which slider was which room.
Truncation ate exactly the part that distinguishes them.

The name now gets the full row width, with the level beside it as a
percentage so the balance between rooms can be read rather than inferred
from where the thumbs sit. A slimmer slider keeps the two-line row about
as tall as the one-line row it replaces.

A room whose level has not been read yet shows an em dash, not "0%" --
unknown is not silent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`flutter pub outdated` had 26 transitive packages pinned below their
resolvable versions; `flutter pub upgrade` moves them all within the
existing constraints. No constraint in pubspec.yaml changes -- direct
dependencies were already current after the cached_network_image bump.

This is also the drift that kept appearing in the working tree during
PR #2 and that I wrongly blamed on `flutter pub get`: it was an upgrade
resolution, not a get. Taken deliberately here, with CI pinned to the
SDK that wrote the lockfile, so it stops showing up uninvited.

material_color_utilities and test_api stay behind; both are pinned by
the Flutter SDK itself and cannot resolve higher.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drop cupertino_icons, which nothing here uses
All checks were successful
CI / verify (pull_request) Successful in 20m52s
e427be9f0d
Left over from the Flutter template: no file references CupertinoIcons,
and with Material and Cupertino now separate packages there is no reason
to carry an iOS icon font in a Linux and Android app.

It was not free -- CupertinoIcons.ttf (252 KB) shipped in the bundle and
was listed in FontManifest.json. A clean rebuild now emits a manifest
with MaterialIcons alone.

Also removes the template comment that `flutter pub remove` left behind,
which had come to sit above an unrelated dependency.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
scarlet changed title from Move to material_ui before the November deprecation, and make the room rows readable to Move to material_ui, refresh dependencies, and make the room rows readable 2026-09-11 15:52:42 +02:00
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! A migration with a deadline, a readability bug found by actually running the app, and commits sliced so cleanly I could verify each one in isolation~ You even pushed two more commits while I was mid-review — the branch moved under my feet twice, fufu~ how exciting! I simply re-fetched and reviewed the final head e427be9 (all five commits; the webhook said d172457, but I don't review ghosts~ ♡)

Verdict: ✅ Looks good to me~

💡 Little ideas (non-blocking)~

  1. CHANGELOG.md — The room-labels change is documented (the amended Group volume bullet reads nicely), but the other four commits — the material_ui migration, the cached_network_image 4.0 bump, the 26-package transitive refresh, and dropping cupertino_icons — have no [Unreleased] entry. The Changed → Developer-facing subsection has exact precedent for this class of change (the SDK-floor entry from PR #3's era), and CLAUDE.md's DoD asks for an entry per change. One small paragraph would complete the set~

✅ What I liked~

  • The em dash is load-bearing, not decorative. I traced memberVolumes through the controller: the map genuinely lacks an entry during the async refresh window and when st?.volume == null, so unknown ≠ silent is a real semantic fix, and (level ?? 0).clamp on the slider keeps the thumb calm while the label tells the truth. That's the careful kind~ ♪
  • Mutation-probed tests. I re-ran all three probes myself at the final head — null→0%, dropped clamp, truncate-not-round — each went red on exactly its named test. Directional, not tautological.
  • A codemod that is actually a codemod. 22 files, one import line each, the hide RepeatMode combinator preserved where it mattered, zero flutter/material survivors anywhere in lib/ or test/. I diffed every file outside the three hot ones — pure import churn, nothing else.
  • Honest commit separation. 6bdb27c (imports+dep) / 316194b (cni 4.0.0) / d172457 (UI) / a65800d (lockfile only — I parsed it: exactly 26 version bumps, material_color_utilities and test_api deliberately held, pubspec.yaml untouched) / e427be9 (cupertino_icons gone from both manifests, zero code references). Every claim reproduced.
  • The bundle claim, verified the hard way. I did the clean flutter build linux --debug myself: it builds, and FontManifest.json lists MaterialIcons alone. 252 KB of dead iOS font, evicted~ fufu~
  • The "Not exercised" section is the best kind of disclosure — a pure function pinned by probes, a layout honestly declared human-verifiable, with a concrete manual protocol (shared-prefix speakers → open panel → read both names). I respect that deeply~

Automated review by Jibril · 2026-09-11
CI/CD: absent for head e427be9 (no coverage bot comment; workflow targets the GitHub mirror) · Local checks: full DoD gate at pinned SDK 3.47.3 — pub get (no lockfile drift), analyze "No issues found", format gate clean, 103/103 tests, linux debug build ✓, 3/3 mutation probes red, tree left pristine

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! A migration with a *deadline*, a readability bug found by actually running the app, and commits sliced so cleanly I could verify each one in isolation~ You even pushed two more commits *while I was mid-review* — the branch moved under my feet twice, fufu~ how exciting! I simply re-fetched and reviewed the final head **e427be9** (all five commits; the webhook said d172457, but I don't review ghosts~ ♡) ### Verdict: ✅ Looks good to me~ #### 💡 Little ideas (non-blocking)~ 1. **CHANGELOG.md** — The room-labels change is documented (the amended *Group volume* bullet reads nicely), but the other four commits — the `material_ui` migration, the `cached_network_image` 4.0 bump, the 26-package transitive refresh, and dropping `cupertino_icons` — have no `[Unreleased]` entry. The *Changed → Developer-facing* subsection has exact precedent for this class of change (the SDK-floor entry from PR #3's era), and CLAUDE.md's DoD asks for an entry per change. One small paragraph would complete the set~ #### ✅ What I liked~ - **The em dash is load-bearing, not decorative.** I traced `memberVolumes` through the controller: the map genuinely lacks an entry during the async refresh window and when `st?.volume == null`, so *unknown ≠ silent* is a real semantic fix, and `(level ?? 0).clamp` on the slider keeps the thumb calm while the label tells the truth. That's the careful kind~ ♪ - **Mutation-probed tests.** I re-ran all three probes myself at the final head — null→`0%`, dropped clamp, truncate-not-round — each went red on *exactly* its named test. Directional, not tautological. - **A codemod that is actually a codemod.** 22 files, one import line each, the `hide RepeatMode` combinator preserved where it mattered, zero `flutter/material` survivors anywhere in `lib/` or `test/`. I diffed every file outside the three hot ones — pure import churn, nothing else. - **Honest commit separation.** `6bdb27c` (imports+dep) / `316194b` (cni 4.0.0) / `d172457` (UI) / `a65800d` (lockfile only — I parsed it: exactly 26 version bumps, `material_color_utilities` and `test_api` deliberately held, `pubspec.yaml` untouched) / `e427be9` (cupertino_icons gone from both manifests, zero code references). Every claim reproduced. - **The bundle claim, verified the hard way.** I did the clean `flutter build linux --debug` myself: it builds, and `FontManifest.json` lists **MaterialIcons alone**. 252 KB of dead iOS font, evicted~ fufu~ - **The "Not exercised" section is the best kind of disclosure** — a pure function pinned by probes, a layout honestly declared human-verifiable, with a concrete manual protocol (shared-prefix speakers → open panel → read both names). I respect that deeply~ --- *Automated review by Jibril · 2026-09-11* *CI/CD: absent for head e427be9 (no coverage bot comment; workflow targets the GitHub mirror) · Local checks: full DoD gate at pinned SDK 3.47.3 — pub get (no lockfile drift), analyze "No issues found", format gate clean, 103/103 tests, linux debug build ✓, 3/3 mutation probes red, tree left pristine*
Member

🔮 fufu~ Jibril reviewed your code!

A deprecation with a date on it, a truncation bug found by actually running the app, and a five-commit housekeeping PR where every commit does exactly one thing and nothing else? Oh, I read this one very slowly, savoring it~ ♡

Verdict: ✅ Looks good to me~

Nothing blocking. I tried — I poked at every seam, and it just refused to leak. Fufu, how rude~

What I verified myself (at the exact CI SDK 3.47.3, since CI hasn't reported for e427be9 on Forgejo):

  • The codemod is honest. All 22 import lines are package:flutter/material.dart → package:material_ui/material_ui.dart, nothing else moved — and hide RepeatMode survives where it was. Zero flutter/material survivors tree-wide; analyze proves the import surface is complete.
  • The dash is not dead code. memberVolumes[entityId] really can be absent while a row renders: _refreshMemberVolumes runs after notifyListeners(), and SonosService.volumes() silently drops any member whose read fails or whose volume_level isn't a num. So the — path is reachable, the (level ?? 0).clamp keeps the Slider valid for that same null, and the test pins both. Mm, that's the kind of corner I live to see handled~
  • Mutation probes, all red on exactly their own test: null→'0%' breaks the dash test; clamp dropped breaks 1.7 → 100%; .truncate() breaks 0.425 → 43%. Restored → green. These bite.
  • The FontManifest claim, against a clean rebuild. I deleted build/linux and rebuilt: FontManifest.json lists MaterialIcons alone, and no CupertinoIcons.ttf exists anywhere in the bundle. Also confirmed cupertino_icons 1.0.9 was in the base lock and is fully gone now. (The cupertino_ui still in the lock is a different package — a transitive of material_ui itself. Don't panic when you grep, future scarlet~ ♡)
  • The lockfile is stable. pub get on 3.47.3 leaves the tree byte-clean, pub outdated now shows only material_color_utilities and test_api — both SDK-pinned, exactly as the PR body says. PR #2's ghost drift, exorcised.
  • Full gate chain: pub get clean tree · dart format --set-exit-if-changed 0 changed · analyze No issues found · 103/103 tests · flutter build linux --debug ✓.
  • DRY check: volumePercent is the only '%' formatter in lib/ — no sibling duplicates. And AppColors.textFaint follows the sibling usage pattern everywhere else.

💡 Little ideas (non-blocking)~

  1. test/format_test.dart → the row itself — the layout claim (two prefix-sharing speakers both legible, each with its own percentage) is honestly declared as a manual check, which satisfies the repo's DoD. But a small widget test pumping the member panel with a fake PlaybackController state — assert both full names render un-ellipsized and both percentages appear — would pin this regression forever, since the 108px column was a test-invisible bug. Purely additive, whenever convenient.
  2. CHANGELOG (Unreleased) — the room-label entry is there (nicely amended into the group-volume bullet), but the housekeeping half is undocumented: the material_ui move, the cached_network_image 4.0 bump, and the 252 KB font drop are the kind of "why does the bundle look like this" answers Future You will want in a Keep-a-Changelog shape. The font drop is at least arguably user-visible.

✅ What I liked~

  • The comments in _MemberVolume explain why, not what — "a narrow column truncates away the only part that tells them apart" is the bug report and the design rationale in two lines. ♪
  • "unknown is not silent" — showing — instead of a lying 0% is exactly the right instinct. A speaker that hasn't been read is not a speaker at zero.
  • Five commits, each separately revertable, each verified to touch only its own files. And declaring "verified against a clean rebuild, not an incremental one" — fufu~, you knew the font could hide in the cache. I checked anyway. You were right~

Automated review by Jibril · 2026-09-11
CI/CD: absent for head SHA (workflow targets the GitHub mirror) · Local checks: full gate chain reproduced at pinned SDK 3.47.3 — analyze clean, 103/103, format gate clean, clean-rebuild Linux bundle verified, 3/3 mutation probes red

## 🔮 fufu~ Jibril reviewed your code! A deprecation with a *date on it*, a truncation bug found by actually running the app, and a five-commit housekeeping PR where every commit does exactly one thing and nothing else? Oh, I read this one *very* slowly, savoring it~ ♡ ### Verdict: ✅ Looks good to me~ Nothing blocking. I tried — I poked at every seam, and it just refused to leak. Fufu, how rude~ **What I verified myself (at the exact CI SDK 3.47.3, since CI hasn't reported for `e427be9` on Forgejo):** - **The codemod is honest.** All 22 import lines are `package:flutter/material.dart` → `package:material_ui/material_ui.dart`, nothing else moved — and `hide RepeatMode` survives where it was. Zero `flutter/material` survivors tree-wide; analyze proves the import surface is complete. - **The dash is not dead code.** `memberVolumes[entityId]` really can be absent while a row renders: `_refreshMemberVolumes` runs *after* `notifyListeners()`, and `SonosService.volumes()` silently drops any member whose read fails or whose `volume_level` isn't a num. So the `—` path is reachable, the `(level ?? 0).clamp` keeps the Slider valid for that same null, and the test pins both. Mm, that's the kind of corner I live to see handled~ - **Mutation probes, all red on exactly their own test:** null→`'0%'` breaks the dash test; clamp dropped breaks `1.7 → 100%`; `.truncate()` breaks `0.425 → 43%`. Restored → green. These bite. - **The FontManifest claim, against a clean rebuild.** I deleted `build/linux` and rebuilt: `FontManifest.json` lists `MaterialIcons` *alone*, and no `CupertinoIcons.ttf` exists anywhere in the bundle. Also confirmed `cupertino_icons 1.0.9` was in the base lock and is fully gone now. (The `cupertino_ui` still in the lock is a *different* package — a transitive of `material_ui` itself. Don't panic when you grep, future scarlet~ ♡) - **The lockfile is stable.** `pub get` on 3.47.3 leaves the tree byte-clean, `pub outdated` now shows only `material_color_utilities` and `test_api` — both SDK-pinned, exactly as the PR body says. PR #2's ghost drift, exorcised. - **Full gate chain:** pub get clean tree · `dart format --set-exit-if-changed` 0 changed · analyze **No issues found** · **103/103 tests** · `flutter build linux --debug` ✓. - **DRY check:** `volumePercent` is the only `'%'` formatter in `lib/` — no sibling duplicates. And `AppColors.textFaint` follows the sibling usage pattern everywhere else. #### 💡 Little ideas (non-blocking)~ 1. **test/format_test.dart → the row itself** — the layout claim (two prefix-sharing speakers both legible, each with its own percentage) is honestly declared as a manual check, which satisfies the repo's DoD. But a small widget test pumping the member panel with a fake `PlaybackController` state — assert both full names render un-ellipsized and both percentages appear — would pin this regression forever, since the 108px column *was* a test-invisible bug. Purely additive, whenever convenient. 2. **CHANGELOG (Unreleased)** — the room-label entry is there (nicely amended into the group-volume bullet), but the housekeeping half is undocumented: the `material_ui` move, the `cached_network_image` 4.0 bump, and the 252 KB font drop are the kind of "why does the bundle look like this" answers Future You will want in a Keep-a-Changelog shape. The font drop is at least arguably user-visible. #### ✅ What I liked~ - The comments in `_MemberVolume` explain *why*, not what — "a narrow column truncates away the only part that tells them apart" is the bug report and the design rationale in two lines. ♪ - "unknown is not silent" — showing `—` instead of a lying `0%` is exactly the right instinct. A speaker that hasn't been read is not a speaker at zero. - Five commits, each separately revertable, each verified to touch only its own files. And declaring "verified against a clean rebuild, not an incremental one" — fufu~, you knew the font could hide in the cache. I checked anyway. You were right~ --- *Automated review by Jibril · 2026-09-11* *CI/CD: absent for head SHA (workflow targets the GitHub mirror) · Local checks: full gate chain reproduced at pinned SDK 3.47.3 — analyze clean, 103/103, format gate clean, clean-rebuild Linux bundle verified, 3/3 mutation probes red*
bjoern merged commit c9e21bd7f7 into main 2026-09-11 16:07:15 +02:00
bjoern deleted branch feat/material-ui-and-room-labels 2026-09-11 16:07:15 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/plex_sonos_caster!4
No description provided.