Karou's pick after U18: "lets do all small/cleanup first, then medium, then larger".
U19 is the medium wave. Kick auditing now records the kicker + kicked terminal whenever
POS unlocks rotate the sid; Starter in-app workspace gets a kick banner so phone-vs-tablet
handoff is legible; Starter listProductsForPos finally aggregates by template
so multi-variant Starter products render as 1 tile + picker; admin override warning surfaces
blast radius when editing a global default extra price.
mintActivePosSessionToken returns MintResult { sid, previousSid } via a tx-wrapped SELECT-then-UPDATE. All 4 POS unlock callsites (PIN unlock + manager override + openStarterShift + ensureStarterCashierCookie) emit a pos.kicked audit row when previousSid is non-null. Metadata captures kickedActor / kickerSession / priorSid / origin. PIN unlock migrated from the legacy mintPinSessionToken to the unified DAO so PIN kicks also get audited.<StarterKickBanner> client component mounted above the workspace on starter-register-page.tsx when peekKickReason() returns non-null. Auto-dismisses after 10s, manually dismissable × button, fires clearStaleActiveCashierCookieAction on mount. testid starter-pos-kick-banner.listProductsForPos template aggregation (U15-B parity) — multi-variant Starter templates now render as 1 tile + variant picker (resolveVariant fires) instead of N separate tiles. variants[] populated via product_tmpl_id correlated SELECT + combo JOIN for labels; sorted by price ascending; representative = cheapest variant. Threaded through StarterRegisterMount.ProductInput, normalizeStarterProducts, and loadStarterOpenPhaseBundle./cafe/settings/attributes Edit dialog. listAttributesForAdmin.values[].overrideCount populated via correlated subquery counting distinct templates with price_extra_usd_override IS NOT NULL. Edit dialog renders amber inline warning when overrideCount > 0: "N product templates override this value's extra price. Editing the global default won't affect those overrides."| ✓ | Pre-flight: lumiere owner has POS PIN; pre-clean state |
| ✓ | Load-bearing: Two-terminal manager unlock → pos.kicked audit row written in cafe.audit_log with kickedActorKind="user" + priorSid populated + resource_id matches the register |
| ✓ | Override-count correlated subquery returns 2 for a value with 2 template overrides (full SQL shape matches the DAO; proves Hyperdrive doesn't poison the count) |
| ✓ | No HTTP 5xx during the flow |
| ✓ | Cleanup: close test sessions + zero owner POS sid + delete seeds |
Gate 1 (9/9) covered the rendering chain end-to-end (DAO → page → dialog source contracts + 3 DAO probes). Gate 2 focused on the load-bearing prod-side assertions: real audit row on a real kick + real subquery count through Hyperdrive.
termAdmin context that never unlocked POS. Then collapsed the UI drive to a SQL probe since Gate 1 already covered the rendering chain end-to-end.feedback_mkdir_before_bash_redirect.export and missed it. Fix: back up to /** start before slicing.| test-phase1-prod.mjs | 11/11 |
| test-phase2-sso-outdoor-prod.mjs | 6/6 |
| test-m1-prod.mjs | 10/10 |
| test-r7-prod.mjs | 14/14 |
| test-r8-prod.mjs | 4/4 |
| test-phase2-cafe-multishop-prod.mjs | 6/6 |
feedback_phase2_cafe_multishop_solo_retry.