Release / build-and-push (push) Successful in 3m29s
User report: the Purge Archived dialog ('Permanently delete all
archived items?...') opened, and Cancel did nothing — and Confirm
would have been equally dead, leaving the page stuck behind the
overlay until a reload.
Root cause: confirm.ts wired the modal's buttons ONLY inside the
htmx:confirm interceptor. confirmDialog() — the promise API used by
purgeArchivedItems, remove-account, and other TS call sites — never
wired them. So whenever a page's first confirm interaction came from
the promise path (no hx-confirm element clicked first), both buttons
had no listeners. The 2026-10-30 confirm_probe spec only exercised the
hx-confirm path, which is why it survived.
Fix: wireButtons() now runs at module init (the header renders before
deferred modules) and inside confirmDialog() — both idempotent via the
existing data-wired guard.
Pinned by tests/ui/promise_confirm_probe.spec.ts (no env gating): the
purge POST is route-intercepted, so the probe asserts Cancel closes
the modal and Confirm issues the guarded request without deleting any
dev data. hx-confirm path re-pinned green (confirm_probe with BH_FEED).
Verified manually at 390x844: open -> cancelWired=true -> Cancel
closes -> Confirm fires the intercepted request.
tests/ui — Playwright sweep (plan §7.5)
Real-browser sweep of the SSR/HTMX frontend. Dev server must be up on localhost:8765. Run inside the official image (no host browsers needed):
cd tests/ui
docker run --rm --network host \
-v "$PWD":/work -w /work \
mcr.microsoft.com/playwright:v1.49.0 \
bash -c "npm install --no-audit --no-fund && npx playwright test"
Personas (see rls_sweep.spec.ts): testuser (admin) and rls-phone
(restricted — Audiobooks hidden from them).
Coverage: COVERAGE.md enumerates every swept page/control per the
plan; new pages/controls get a line when added.