These are the manual tests to run before each release. Tick boxes as you go — state is
saved in this browser (localStorage) so a pass can span hours or days. Hit
"Reset all checkboxes" to start the next release pass.
What to run when
Every release: the Smoke Matrix on release artifacts (installed app / TestFlight build, not dev builds), plus the Release Gate.
App changed: the full checklist for each app whose code changed this release.
Backend / shared packages changed: the Cross-Device Scenarios as well — sync regressions only show up between peers.
Hardware / leaf firmware changed: add the ESP32 leaf rows.
Run the robots first
Manual QA assumes the automated suites are already green. Before starting:
listam-mobile: npm run ci (lint, deps, secrets, i18n, security + grocery tests)
listam-desktop: npm run ci
listam-headless: npm run ci (includes the private-testnet matrix)
Cross-device: node tools/cross-device/matrix.mjs and node tools/cross-device/wedge-repro.mjs
Test bed
Role
Notes
Mac (dev machine)
Desktop app, headless instances, harness driver
Personal Listam instance lives here — use scratch storage dirs for headless tests, never pkill broadly.
iPhone + Android phone
Mobile passes (run the mobile checklist once per OS)
npm run ios / npm run android rebuild the Bare backend bundle before installing.
Guest-only for P2P rows — ufw drops inbound holepunch. SSH over Tailscale.
Raspberry Pi
Always-on headless peer, systemd installer target
aarch64; Node 22 under ~/node22.
ESP32-S3 board
Leaf mirror peer
Firmware in hardware/leaf-peer; control key flashed via cfg.toml must match the hub.
Reporting: when a check fails, file it before moving on — note app +
version, the checklist item, and the diagnostics pane / [AUDIT] log output.
A failed smoke item blocks the release; failures in extended sections are judgment calls.
Every release · ~30 minutes · release artifacts only
Smoke Matrix
0 / 0
The minimum cross-platform pass. Tags: M mobile,
D desktop, H headless.
Mobile · iOS & Android · run once per OS
Mobile Checklist
0 / 0
Prep: build with npm run ios / npm run android
(these rebuild the Bare backend bundle first — required whenever backend or RPC code
changed). For first-run items, delete and reinstall the app. Run this checklist on
both platforms; IAP items need a sandbox / test account.
1 · Install & first run
2 · Items — list view
3 · Items — grid view
4 · Categories
5 · Appearance & accessibility
6 · Sharing (host side)
7 · Joining (guest side)
8 · Members & recovery
9 · Owned devices (headless control)
10 · Loyalty cards
11 · Trial & paywall
12 · Language
13 · Overview, lists & new surfaces
14 · Backup, device name & leaf pairing
15 · Lifecycle & sync resilience
Desktop · Pear · macOS
Desktop Checklist
0 / 0
Prep: dev pass with npm run dev in listam-desktop;
the release pass must use the installed /Applications/Listam.app appling.
For UI-only sanity without the Pear runtime, serve the app and open with
?mock=1 (fixtures, no real peers — leaf bridge and owner control show their
"requires Pear" states there).
1 · Launch & shell
2 · Keyboard
3 · Add & edit
4 · Rows, grid & animations
5 · Summary bar & categories
6 · Groups & lists
7 · Overview (Focus & Planner)
8 · Todo & Board surfaces
9 · Move & reorder
10 · Share & join
11 · Peers pane
12 · Leaf bridge
13 · Owner control (headless devices)
14 · Settings
15 · Settings → Backup & data
16 · Settings → Analytics
17 · Servers pane
18 · Voice host
19 · Diagnostics
20 · Dialogs & notices
21 · Persistence & instances
22 · Installer & distribution (release builds)
Headless · Node 22 · Mac / Pi / Geekom VMs
Headless Checklist
0 / 0
Prep: run from listam-headless against a scratch directory
(e.g. /tmp/listam-qa) — never against the personal instance's storage. Ops
are JSON lines on stdin; replies are JSON lines on stdout. Installer items need a Linux
host (Pi or cassandrina-node).
1 · Setup (participant)
2 · Run, status & shutdown
3 · Item ops over stdin
4 · Invite & join
5 · Export & import
6 · Storage lease
7 · Blind storage (C2 boundary)
8 · Owner control
9 · Leaf bridge
10 · BLE leaf provisioning
11 · Voice-enabled run
12 · Peer label (setup --name)
13 · Installer (Linux: Pi / cassandrina-node)
Voice · ESP32 leaf + host (desktop or headless)
Voice Checklist
0 / 0
Prep: the leaf captures mic audio and runs the on-device wake model; the
host does whisper STT + intent parsing and applies the result through normal
backend RPCs. Run this pass against whichever host hosts the pipeline — the desktop Pear
worker or a headless node — with the leaf streaming to the host's audio bridge
(:9994). Use a multilingual GGML model (not medium.en) for
non-English locales.
1 · Wake word
2 · Command paths
3 · Locale & gating
4 · Both host paths
Multi-peer · real devices · mainnet DHT
Cross-Device Scenarios
0 / 0
Pre-pass: run node tools/cross-device/matrix.mjs first
(mainnet by default; add --esp32 when the board is wired) and
node tools/cross-device/wedge-repro.mjs for the unreachable-peer guard.
The manual pass below then focuses on real GUI devices and the flows the harness can't see.
1 · Two-peer pairs
Run for each pairing whose code changed: desktop ↔ mobile, mobile ↔ mobile, desktop ↔ headless, mobile ↔ headless.
2 · Mesh (3+ peers)
3 · Offline & wedge regression
4 · Membership & recovery across devices
5 · ESP32 leaf (when firmware or bridge changed)
Infra gotchas: the Geekom VMs are guest-only for P2P (ufw drops inbound
holepunch) — host from the Mac, phones, or the Pi. Use the mainnet DHT for cross-machine
rows (the LAN testnet bootstrap is broken across machines). After a SIGKILL, wait out the
30 s storage-lease TTL before restarting a node.
Final gate · before tagging / shipping
Release Gate
0 / 0
Known issues — don't re-debug:holepunchto/autobase#374
(silent writer freeze + append busy-loop upstream, filed 2026-06-11 against v7.28.1).
Check the tracker state before chasing any new append hang; the local stale pre-join
"local" block cause was fixed with scoped join writers and is covered by
wedge-repro.mjs.