| **7** | **Authenticated navs** | ❌ **cancelled** — was: `GET /api/v1/settings/nav` behind a session-keyed repository; label/hidden for the four mapped rows (§6.4). See "Phase 7, cancelled" below |
| **8** | **Docs, coverage & cutover** | This doc's "as landed" notes and any amendments the build forces, the `PLAN.md` §9 M12 entry refreshed, Sonar coverage for the new modules, AC-5 on-device walk, then `edge` → `main` |
| **8** ✅ | **Docs, coverage & cutover** | This doc's "as landed" notes and any amendments the build forces, the `PLAN.md` §9 M12 entry refreshed, Sonar coverage for the new modules, AC-5 on-device walk, then `edge` → `main`. **The walk found two theming defects and phase 8 fixed them** — see "Phase 8 as landed" |
Phase 0 is the one with a hard rule attached: **it must change nothing on
screen.** Everything after it is additive on top of a store that is already
@@ -762,7 +762,12 @@ proven not to have moved anything.
### Phase 2 as landed
- **The app is flat, so §5.4 is the milestone's one visible default change.**
- **The app is flat, so §5.4 is a visible default change.** (It was written here
as the milestone's *only* one. Phase 8 found a second — the card *container*
colour — and a third that is not a change at all but a correction to this
record: an instance with a `BRAND_HERO_IMAGE` and no `brand_assets` row now
draws a hero on Home, because `brand.hero` carries the env default. See
"Phase 8 as landed".)
Material3 1.3.0's filled `Card` is `ElevationTokens.Level0` — 0dp, checked in
the artifact's bytecode, not assumed — and `FeatureCard` was a `Box` with a
clip, a gradient and a border, drawing none of the "soft shadow" its own KDoc
@@ -1022,6 +1027,108 @@ Consequences, all of them wanted:
If it is ever picked up, §6.4 is the spec and the merge would reuse phase 5's.
### Phase 8 as landed
Phase 8 was scoped as docs, coverage and the cutover. The AC-5 walk turned it
into a phase with code in it, which is the outcome the walk existed to produce.
**AC-5 confirmed what the JVM could not reach.** Two passes on the AVD against a
local website, the themed one walked at every role rung. Everything phases 1–6
had deferred to it held: the Fantasy palette on screen; radii visibly square
against the untouched build's rounded; **EB Garamond arriving in the *sans* role**,
which is phase 3's preset-bypass finding proved on a device rather than in a test;
the logo replacing the top bar's text with the 6× width cap holding; the hero
centre-cropped into its 180dp band with the top and bottom of a 4:3 image cut;
reorder, relabel and hide; the section header with its indented children; the
added link with a native route carrying **no** badge and the handing-off one
carrying it; and the Custom Tab genuinely opening — confirmed as
`CustomTabActivity` in `dumpsys activity`, not by eye. AC-3's role dimension held
at every rung: an anonymous caller saw the reordered, sectioned public nav with
**no player or staff row leaking**, and the player rung stopped at `My houses`.
AC-4 fell out for free when the second AVD started against an unreachable server:
shipped theme, coded menu, one retry, no error surface.
**A correction the walk forced, with no code behind it.** An untouched instance
**gains a hero on Home**. `brand.hero` carries the `BRAND_HERO_IMAGE` env default
— `/assets/img/runic-emblem.png` on this one — so "admin has set nothing" does not
mean "the slot is empty", and phase 4's `BrandHero` draws it. Nothing is wrong
here: the website's own Home shows the same emblem, and §5.6's rule is that a
blank slot draws nothing, which still holds. What was wrong is the *record* —
phase 2 claimed the card shadow was the milestone's only visible change to an
untouched app, and this was the second before the card container made it three.
Worth stating plainly because a shard operator upgrading the app sees it without
having touched Appearance at all.
**Two defects, one root cause, and it is phase 2's.** Material takes some themed
values as **default arguments** rather than from the theme. Phase 2 found this for
card elevation and answered it by sweeping every `Card(` into `ShardCard(`. Nobody
then asked whether *colour* and *shape* had the same problem. They did:
- **Every `ShardCard` drew in Material's grey, not the shard's panel colour.**
`CardDefaults.cardColors()` takes its container from `surfaceContainerHighest`
— `FilledCardTokens.ContainerColor`, checked in the material3 1.3.0 artifact's
bytecode the same way phases 1 and 2 checked theirs — and `shardColorScheme`
mapped `surfaceContainer`, `…High` and `…Low` but not `…Highest`. All 26 call
sites in 20 files. `FeatureCard` was unaffected because it reads
`LocalShardPalette` directly, which is exactly why Home looked right and every
other screen did not — the single most misleading thing about the bug.
and `surfaceTint` are latent — the app draws no Snackbar, tonal button, elevated
or outlined card. Adding one of those components means checking this list again.
**Coverage: the exclusion list had gone stale under the milestone.**
`sonar.coverage.exclusions` carried a `ui/theme/**` directory glob from the M11
coverage push, when that directory held only constants and composables. M12 put
three pure resolvers in it — `ShardPalette`, `ShardStructure`, `ShardTypeface`,
the reason phases 1–3 could prove their no-op invariants as JVM assertions — and
the glob was dropping all three out of the denominator at 98%, 100% and 100%. It
is now the one file it was really about, `ui/theme/Theme.kt`. This did not rescue
the gate: M12's already-measured code (`data/appearance/` and `ui/navigation/`,
93–100%) clears `new_coverage ≥ 50` on its own. It makes the number honest about
which code the tests hold, so deleting those tests would move it.
**Tests: 477 green** (476 + the card-container assertion), `lintDebug` and
`assembleDebug` clean. The JVM limit from phase 4 is unchanged and is why this
phase needed a device at all: no Robolectric, no `androidTest` source set, so a
composable body cannot run in a unit test. Both defects were invisible to 476
passing tests and obvious within two minutes of looking at a themed screen.
**Rig notes, for the next walk.** The emulator reaches a local website through
`adb reverse tcp:3000 tcp:3000`, which lets the app use `http://127.0.0.1:3000`
and the debug `network_security_config`'s loopback exception **unchanged** — do
not add `10.0.2.2` to it for a test rig. The Custom Tab resolves against the same
base URL, so hand-off links work under the same tunnel.
## 9. Out of scope
- **Light mode / a light preset.** The website cancelled its Parchment phase; the
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.