# QA Checklist

Manual pre-release pass across the three shipping surfaces: the web board, the
Mac desktop app, and the Android app. Automated coverage (unit, integration,
e2e, Android JVM) runs in CI; this checklist covers what those cannot — real
rendering, native shells, and cross-surface consistency.

Run the automated gate first: `npm run check` and `npm run android:test`. Only
proceed to manual QA once both pass.

## Web board (`http://127.0.0.1:4217/demo-website`)

Launch: `npm run dev -- --port 4217 --host 127.0.0.1` from the `development`
checkout, then open the URL.

- [ ] Board renders four+ lanes; empty lanes show the "Nothing here yet"
      placeholder, not blank space.
- [ ] Create a task from Backlog; it appears and opens the inline editor.
- [ ] A long card title truncates to one line and reveals in full on hover.
- [ ] The card overflow (⋯) menu lists Archive / Delete / Remove, each with a
      "Moves to the … view" description; each moves the card to the matching
      board-bar view (Archive / Deleted / Removed).
- [ ] Top-bar Sync control shows `N↓ N↑`; opening it lists Fetch / Pull / Push
      with descriptions, and each action runs.
- [ ] Settings dialog opens; the section nav highlights the current section; on
      a narrow window (<768px) a section `<select>` appears.
- [ ] Agent picker announces as a radio group (VoiceOver: "radio button,
      selected") — not a list of plain buttons.
- [ ] Keyboard: Tab reaches interactive controls with a visible focus ring;
      Escape closes dialogs and the inline editor.
- [ ] Disconnect the runtime (stop the server) — the disconnected fallback
      renders and is announced (role="alert").

## Mac desktop app (Electron)

Build + launch: `npm --prefix platforms/desktop run build:ts` then
`node platforms/desktop/scripts/launch-electron.mjs`.

- [ ] Menu bar and window title read "ZoneGaze Matrix" (not "Electron").
- [ ] Launchpad status is coherent: the header status matches the ZoneGaze
      runtime row (no "Running" header while the runtime row says OFFLINE); when
      only unrelated dev ports are live, the copy says so.
- [ ] "Last refreshed" advances on its own within ~10s (auto-refresh) without
      clicking Refresh.
- [ ] Primary action reads "Open ZoneGaze Matrix" and opens the board (starting
      the runtime first if needed).
- [ ] A live local port (e.g. Web Dev 4217) shows LIVE with an Open action.
- [ ] Accent color uses the Signal accent, consistent with the Matrix shell.
- [ ] Disconnected screen offers Restart runtime and the terminal-fallback
      command.

## Android app (emulator)

Setup and screenshots: see `zonegaze/memory/android-matrix-full-parity/00-status.md`. In short:
`ANDROID_SDK_ROOT=~/Android/others/sdk`, boot `ZoneGaze_Matrix_API36` headless on a Matrix-only emulator port,
`adb install -r platforms/android/app/build/outputs/apk/debug/app-debug.apk`,
launch `com.zonegaze.matrix`, screenshot with `adb exec-out screencap -p`.

- [ ] Bottom nav: Dashboard / Plugins / Runtime / Ports; active tab uses the Signal accent.
- [ ] Dashboard shows Matrix activity cards, plugin summaries, and quick actions without treating Dashboard as a plugin.
- [ ] Runtime tab: permissions card, Android runtime overview, and detailed Zone Terminal backend section render as structured checklist rows, not a raw `label: ready` log dump.
- [ ] Runtime copy says ZoneGaze Matrix for the app, while the bundled payload remains accurately labeled as the ZoneGaze Flow runtime.
- [ ] Ports tab: port lists render as ranges (`3484-3489`), show ownership/source/process, and hide external listeners by default.
- [ ] Plugin tab shows Install for absent plugins and Uninstall for installed plugins.

## Cross-surface consistency

- [ ] The Signal accent and dark surface hierarchy are consistent across web, Mac shell, and Android.
- [ ] Branding uses ZoneGaze Matrix for platform shells and plugin-specific names only inside plugin surfaces.
- [ ] Text meets WCAG AA contrast (≥4.5:1) on every theme — spot-check the
      lowest-contrast secondary/tertiary text on the default and one alternate
      theme.
