docs(verification): windows-p0-acceptance.md — human-side rc.8 sign-off

Captures the 15 TC rows the lead walks through on the Korean
Win 11 host before tagging v1.0.0-rc.8, plus the auto-test
sign-off matrix (Linux + Windows cargo + flutter analyze +
validator + windows-smoke).

Each TC row maps to a spec requirement (DEC / SRS / SDD) or to a
regression the rc.7 review found. Failures block the tag.

Known gaps recorded at the bottom: macOS / iOS / Android P0 are
separate documents; VAD (DEC-030) and missed-key-up watchdog
redesign (DEC-031) are P1; real RMS level meter is P1.
This commit is contained in:
EdisonJwa
2026-05-16 02:11:21 +08:00
parent 881321595e
commit 0b6ea11077
+246
View File
@@ -0,0 +1,246 @@
# Windows P0 acceptance — human-must test cases (v1.0.0-rc.8)
This document captures the human-side verification pass for the
Windows P0 ship of Chanora. Automated tests (cargo + flutter
analyze + windows-smoke.cmd) sign off the mechanical side; this
checklist signs off the user-experience side. A failure on any
row blocks the rc.8 tag.
Source: this checklist supersedes the inline plan in the
conversation that produced the v1.0.0-rc.8 baseline. The auto-test
sign-off lives in this document's "Auto-test sign-off" section.
## 0. Pre-flight
| # | Step | Expected |
|---|---|---|
| 0.1 | RDP into `100.84.219.45` as `admin` / `jkorisno1` | Desktop visible |
| 0.2 | Wipe stale install: delete `%LOCALAPPDATA%\app.chanora\` and `%APPDATA%\app.chanora\` if they exist | First-launch from clean state |
| 0.3 | Launch `C:\Users\admin\chanora\apps\chanora_flutter\build\windows\x64\runner\Release\chanora_flutter.exe` | Window opens, no crash |
| 0.4 | Open About / version label | Shows **`v1.0.0-rc.8`** (not rc.1) |
| 0.5 | Open `C:\Users\admin\AppData\Local\app.chanora\chanora_flutter\logs\chanora.log` | Contains `bridge initialised`, `log file path …`, `identity store initialised`, `bookmark store initialised`. File size <1 MB. |
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
| # | Step | Expected |
|---|---|---|
| 1.1 | Enter `cn.teamspeak.app` (or your own test server), nickname, blank password | "Connect" button enabled |
| 1.2 | Click Connect | Server snapshot appears: channel tree on left, client list visible |
| 1.3 | Note the connected server name + the channel tree | Tree is sorted (parents above children); no duplicate roots |
| 1.4 | Disconnect, reconnect with the same nickname | Server-visible UID is the same as previous session (identity persisted) |
| 1.5 | Disconnect | Returns to connect form, no error |
## TC-2: Voice channel join (SRS-204, SDD-094)
| # | Step | Expected |
|---|---|---|
| 2.1 | After connecting, observe the UI | **No "Start audio" button anywhere** |
| 2.2 | Click a non-default voice channel in the tree | Voice Bar widget appears at top |
| 2.3 | Voice Bar shows: channel-name pill on left, speaker-mute + mic-mute on right, mode badge ("PTT"), capability badge — expected `L2GlobalHoldToTalk (raw-input)` or `L3GlobalWithMouseButtons (raw-input)` after a successful Raw Input register | All five visible; capability NOT `L0Focused` on this Win 11 host |
| 2.4 | Tap a different voice channel | Voice Bar's channel-name pill updates to the new channel; other clients see us move |
| 2.5 | There is **no** "Leave voice" button | TS3 model: you are always in *some* channel |
## TC-3: PTT mode press / release (SDD-088, SDD-096, SAD-083)
| # | Step | Expected |
|---|---|---|
| 3.1 | In a voice channel, click the gear "Voice settings" | Dialog opens with three mode radio rows (PTT selected, Voice activity disabled "Coming soon"), bind-key button, release-tail slider at 200 ms |
| 3.2 | Click "Bind PTT key", press Space, observe Captured value, click Save | "Captured: **Space**" (not blank); after Save the Voice Bar's PTT line reads **"PTT: Space"** + release tail value |
| 3.3 | Press and hold Space, watch the stats line | Within ~100 ms: **"Mic on"** appears; level meter goes active |
| 3.4 | Release Space | After ~200 ms: **"Mic off"** appears; level meter returns to idle |
| 3.5 | Repeat 3.33.4 ten times rapidly | Each press toggles Mic on/off; no stuck-on state |
| 3.6 | Hold Space for 60 seconds continuously while saying something | **Mic stays on the entire time** (watchdog is disabled per DEC-031; no mid-sentence cut-off) |
| 3.7 | Alt-tab to another application, press Space (no mouse focus on chanora) | Mic on toggles even though chanora is not focused (verifies L2/L3 global path); other clients hear you |
## TC-4: Release tail (SDD-096, SRS-206)
| # | Step | Expected |
|---|---|---|
| 4.1 | Open Voice settings, slide release tail to 0 ms, save | Slider shows "0 ms" |
| 4.2 | Hold Space briefly then release | "Mic off" appears within ~100 ms of release |
| 4.3 | Set release tail to 500 ms, save | Slider shows "500 ms" |
| 4.4 | Hold Space briefly then release | "Mic on" persists for ~500 ms after release, then "Mic off" |
| 4.5 | Set release tail back to 200 ms | Slider shows "200 ms" |
## TC-5: Continuous mode (SAD-083, SRS-205, regression: DEC-031)
| # | Step | Expected |
|---|---|---|
| 5.1 | Open Voice settings → select "Continuous" radio → Save | Mode badge reads "Continuous"; **no "PTT: …" line**; **no release-tail line**; **no capability badge** (all PTT-only surfaces hidden) |
| 5.2 | Observe the stats line | "Mic on" immediately and **stays on** indefinitely |
| 5.3 | Wait 60 seconds continuously | **Mic stays on** the whole time (the old bug — watchdog disabling Continuous after 30 s — must not reproduce) |
| 5.4 | Switch back to PTT mode | Mode badge reads "PTT: Space"; PTT-only lines reappear; Mic off (no key held) |
## TC-6: Mic mute toggle (SRS-207, regression: log spam)
| # | Step | Expected |
|---|---|---|
| 6.1 | In Continuous mode, click the mic-mute icon | Icon toggles to crossed-out; Mic shows off immediately |
| 6.2 | Have a second client check our status | Other client sees a microphone-off icon next to your nickname |
| 6.3 | Wait 30 seconds while muted, then check log file size | `chanora.log` stays <500 KB (no "Sending audio while muted" flood) |
| 6.4 | Click mic-mute again to unmute | Icon clears; Mic returns to on |
| 6.5 | In PTT mode with key held, click mic-mute | Mic immediately goes off mid-press; key release is ignored as long as muted |
| 6.6 | Unmute, key still held | Mic returns to on |
## TC-7: Speaker mute (server-broadcast)
| # | Step | Expected |
|---|---|---|
| 7.1 | Have a second client talk to you | You hear them |
| 7.2 | Click speaker-mute (headset icon) | Icon toggles; their voice is silent |
| 7.3 | Other client checks our status | They see a headset-off icon next to our nickname |
| 7.4 | Click speaker-mute again | Voice returns |
## TC-8: Binding persistence across restart (SDD-095)
| # | Step | Expected |
|---|---|---|
| 8.1 | Bind PTT to F10 → Save | Voice Bar shows "PTT: F10" |
| 8.2 | Close the app entirely | Window dismissed |
| 8.3 | Relaunch | Connect form appears |
| 8.4 | Connect + join a voice channel | Voice Bar shows **"PTT: F10"** (binding survived restart) |
| 8.5 | Press F10 | Mic on |
## TC-9: Binding before voice-join (SDD-094 follow-up)
| # | Step | Expected |
|---|---|---|
| 9.1 | Wipe storage again (steps 0.2) | Clean state |
| 9.2 | Launch, connect, but do not join a voice channel yet | Channel tree visible |
| 9.3 | Open Voice settings, bind a key, Save | No `audio not started` error |
| 9.4 | Join a voice channel | Voice Bar reflects the binding |
## TC-10: No-permission channel rejection (issue 3 from rc.7 review)
| # | Step | Expected |
|---|---|---|
| 10.1 | Identify a channel where your account lacks join permission | Server tree shows it as locked or similar |
| 10.2 | Tap it | After ~1.5 s, **red error banner** appears: "channel move rejected by server (no permission, wrong password, or channel full)" |
| 10.3 | Voice Bar's channel-name pill does **not** update | We did NOT join the channel locally |
| 10.4 | Other clients confirm we are NOT in the requested channel | Server-side reality matches the error banner |
## TC-11: Reconnect (real disconnect, not transient blip)
| # | Step | Expected |
|---|---|---|
| 11.1 | Connect, join a voice channel | Voice Bar visible |
| 11.2 | Force a hard disconnect (server-side kick, firewall block, or `nm-cli con down` on Linux RDP host) | UI shows red "Connection lost" banner with a spinning indicator and reconnect attempt counter |
| 11.3 | Restore network | Reconnect succeeds; voice channel rejoined automatically; banner disappears |
## TC-12: Diagnostic export + privacy (DEC-027)
| # | Step | Expected |
|---|---|---|
| 12.1 | Trigger a settings change (e.g. toggle mode) | Activity in log |
| 12.2 | Trigger the diagnostic export (if a button exists) or copy `%LOCALAPPDATA%\app.chanora\chanora_flutter\logs\chanora.log` | Multi-line text |
| 12.3 | Read it — privacy invariant | Contains `capability_level`, `backend_id`, `bound_input_class` (`keyboard` / `mouse-side-button`); **does NOT** contain any `vk`, `scan_code`, `keysym`, the actual key label, or any timing sequence of presses |
| 12.4 | File size at end of session | <5 MB (rotation: previous session is at `chanora.log.1`; the one before at `chanora.log.2`) |
## TC-13: PTT bind dialog labels (regression)
| # | Step | Expected |
|---|---|---|
| 13.1 | Open binding dialog | Initial state: "Captured: " is blank or shows a placeholder |
| 13.2 | Press Space | "Captured: **Space**" (not blank — the rc.7 regression) |
| 13.3 | Press Enter | "Captured: Enter" |
| 13.4 | Press Tab | "Captured: Tab" |
| 13.5 | Press A | "Captured: A" |
| 13.6 | Press F12 | "Captured: F12" |
| 13.7 | Press Shift alone | Captured field unchanged (modifier-only press ignored) |
| 13.8 | Press a mouse side button (Mouse4 / Back) | "Captured: mouse-side-button:8" |
## TC-14: Capability badge gating
| # | Step | Expected |
|---|---|---|
| 14.1 | In PTT mode | Capability badge visible (`L2GlobalHoldToTalk (raw-input)` or similar) |
| 14.2 | Switch to Continuous mode | **Capability badge disappears** (no info-icon, no level label) |
| 14.3 | Switch to "Voice activity (coming soon)" | Cannot select (disabled); confirms the radio row is non-interactive |
## TC-15: Indicator label (regression)
| # | Step | Expected |
|---|---|---|
| 15.1 | In any mode, look at the stats line | Reads "Mic on" / "Mic off" (mode-neutral); **not** "PTT on" / "PTT off" |
## Auto-test sign-off
These rows do not require human interaction. The values are filled
in from CI / local invocation.
| Layer | Result on Linux | Result on Korean Win 11 |
|---|---|---|
| `cargo check --workspace` | clean | clean |
| `cargo test --workspace --lib` | 80 / 0 / 3 | 124 / 0 / 2 |
| `flutter analyze` | clean (6 pre-existing Radio.groupValue infos) | n/a |
| `python3 tools/validate_docs.py` | strict layered sourcing OK; pre-existing 35-filename warning | n/a |
| `tools/windows-smoke.cmd` | n/a | exit 0 |
The Windows host runs 44 more tests than Linux because of the
`#[cfg(target_os = "windows")]`-gated PTT-backend, dispatcher, and
full-chain tests in `crates/chanora_audio/src/ptt_backends/windows.rs`
and `core/chanora_core/src/ptt.rs::windows_full_chain_tests`.
## Sign-off form
```
chanora v1.0.0-rc.8 — Windows P0 acceptance
Host: Korean Win 11 (HP LAPTOP-37KAQO05, ko-KR locale)
Tester: ______________________
Date: ______________________
Build: chanora_flutter.exe @ ______________________
chanora_bridge.dll @ ______________________
data\app.so @ ______________________
TC-1 Connect + identity persistence [ pass / fail ] notes:
TC-2 Voice channel join [ pass / fail ] notes:
TC-3 PTT press / release [ pass / fail ] notes:
TC-4 Release tail [ pass / fail ] notes:
TC-5 Continuous mode [ pass / fail ] notes:
TC-6 Mic mute [ pass / fail ] notes:
TC-7 Speaker mute [ pass / fail ] notes:
TC-8 Binding persistence across restart [ pass / fail ] notes:
TC-9 Binding before voice-join [ pass / fail ] notes:
TC-10 No-permission channel rejection [ pass / fail ] notes:
TC-11 Reconnect [ pass / fail ] notes:
TC-12 Diagnostic export + privacy [ pass / fail ] notes:
TC-13 PTT bind dialog labels [ pass / fail ] notes:
TC-14 Capability badge gating [ pass / fail ] notes:
TC-15 Indicator label [ pass / fail ] notes:
Overall result: [ rc.8 PASS / rc.8 FAIL ]
Sign: ______________________
```
## Known gaps (not blockers)
- **macOS / iOS / Linux** P0 acceptance is NOT covered here; this
document is Windows-only. Tagging rc.8 ships Linux from a separate
pass and remains Windows-gated for macOS / iOS / Android.
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally disabled
per DEC-030 (deferred to P1). UI shows it as a "Coming soon" radio
row.
- **Missed-key-up watchdog** is disabled on P0 per DEC-031 (long PTT
speech would have been cut off at 30 s). P1 reintroduces a
redesigned variant.
- **Audio level meter** is binary (`pttActive` only). Real RMS meter
is a P1 follow-up.