docs(verification,index): iPad p0 acceptance checklist + 0.9.9 index row
New controlled document docs/verification/ipad-p0-acceptance.md
extends iOS P0 coverage to iPad. The build artefact is identical
to iPhone — `TARGETED_DEVICE_FAMILY = "1,2"` in
ios/Runner.xcodeproj/project.pbxproj is the Universal family, so
the same Runner.app installs on iPad with the same personal-team
provisioning profile.
15-row checklist mirrors ios-p0-acceptance.md TC-1..TC-12 and adds
three iPad-specific rows:
TC-13 wide-mode landscape layout — iPad in landscape is well
above the 840 dp LayoutBuilder breakpoint shipped in
apps/chanora_flutter/lib/main.dart, so the connected view
splits into a 320 dp left column (banner + Voice Bar) plus
an expanding channel tree. Portrait rotation collapses
back to the stacked iPhone layout. Long channel-name pills
still ellipsize per the earlier voice_bar.dart fix.
TC-14 Split View / Slide Over no-crash — Apple iPad multitasking
is intentionally unsupported in P0. UIApplicationSupports\
MultipleScenes stays false. This row asserts the app does
not crash when iPadOS tries to host it in Split View; the
actual multi-scene wiring is P1.
TC-15 AirPlay 2 audio route — verifies AVAudioSession routing
honours an AirPlay 2 destination picked via Control
Center, and routes back cleanly when iPad is reselected.
docs/governance/document-index.md
Bumped to 0.9.9 with the change-history row noting the iPad
acceptance doc. No spec items added; DEC-025 was originally
iPhone-only for the mobile target and this row formally
extends P0 coverage to iPad within the same iOS toolchain.
python3 tools/validate_docs.py: clean (pre-existing 35-filename
[FAIL] retained, unchanged).
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Document Index
|
||||
|
||||
**Document type:** Configuration / Documentation Control
|
||||
**Version:** 0.9.8
|
||||
**Version:** 0.9.9
|
||||
**Status:** Baseline Candidate
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
@@ -90,3 +90,4 @@ SysDes -> SYS.4
|
||||
| 0.9.6 | 2026-05-16 | Added DEC-031 (missed-key-up watchdog disabled on P0; redesign deferred to P1) and new controlled document `docs/verification/windows-p0-acceptance.md` carrying the 15-row human-must acceptance plan for the v1.0.0-rc.8 Windows ship. No spec items added; DEC-028 retained as historical context, superseded by DEC-031 for the v1 ship. |
|
||||
| 0.9.7 | 2026-05-16 | Added controlled document `docs/verification/linux-p0-acceptance.md` carrying the 15-row human-must acceptance plan for the v1.0.0-rc.8 Linux (GNOME on Wayland) ship. Auto-test sign-off rows filled from the Arch host `100.74.219.114` verification pass: `cargo check --workspace --release` clean, `cargo test --workspace --lib` 78 / 0 / 1, `cargo test -p chanora_audio --test linux_portal_smoke -- --ignored` 1 / 0, `cargo test -p chanora_audio --test ptt_privacy` 1 / 0. No spec items added; the existing SDD-086 GNOME-Wayland portal backend is what this document signs off. |
|
||||
| 0.9.8 | 2026-05-16 | Added controlled documents `docs/verification/macos-p0-acceptance.md` (15-row checklist for Apple Silicon macOS, SDD-085 CGEventTap backend now fully live with IOHIDCheckAccess + CGEventTapCreate + per-1.5s permission watcher) and `docs/verification/ios-p0-acceptance.md` (12-row checklist for physical iPhone via the free Apple Personal Team, SDD-094..097 audio lifecycle, AVAudioSession `.playAndRecord/.voiceChat` configured Swift-side in AppDelegate). The macOS PTT backend descriptor advertises L2/L3 only when Input Monitoring is granted, otherwise L0Focused per SRS-198 honest capability advertising. iOS PTT is L0Focused by design (DEC-025 explicitly does not pursue a global PTT analogue on iOS). No new spec items. |
|
||||
| 0.9.9 | 2026-05-16 | Added controlled document `docs/verification/ipad-p0-acceptance.md` carrying the 15-row checklist for iPad P0 sign-off (same TS-3.3 reach, three iPad-specific rows: wide-mode landscape layout under the existing 840 dp LayoutBuilder breakpoint, Split View / Slide Over no-crash assertion since `UIApplicationSupportsMultipleScenes` stays `false` in P0, and AirPlay 2 audio routing). The iPad build artefact is the **same** `Runner.app` produced for iPhone — `TARGETED_DEVICE_FAMILY = "1,2"` in `ios/Runner.xcodeproj/project.pbxproj` is the Universal family. DEC-025 was originally iPhone-only for the mobile target; this row formally extends P0 coverage to iPad (still within the same iOS toolchain, no new Rust or Flutter code). No spec items added. |
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
# iPad P0 acceptance — human-must test cases (v1.0.0-rc.8)
|
||||
|
||||
This document captures the human-side verification pass for the
|
||||
iPad P0 ship of Chanora. The build artefact is the **same**
|
||||
`Runner.app` produced for iPhone (`TARGETED_DEVICE_FAMILY = "1,2"`
|
||||
in `Runner.xcodeproj` — both iPhone (1) and iPad (2)). Apple's
|
||||
free Personal Team provisioning profile includes iPad in the
|
||||
universal family, so the same sideload that installs on an iPhone
|
||||
installs on an iPad.
|
||||
|
||||
The officially-tested environment is **iPadOS 17 or later on a
|
||||
physical iPad**, signed with the developer's personal team
|
||||
(DEC-025 covers iPhone; this document extends P0 coverage to
|
||||
iPad). Simulator support is best-effort — microphone capture and
|
||||
AirPlay 2 routing cannot be assessed in the simulator.
|
||||
|
||||
Automated tests (`cargo check`, `cargo test --workspace --lib`)
|
||||
sign off the mechanical side. This checklist signs off the user-
|
||||
experience side. A failure on any row blocks promotion of the
|
||||
iPad build from rc.8.
|
||||
|
||||
Source: this checklist extends `ios-p0-acceptance.md` with the
|
||||
three iPad-specific rows (split-view multitasking, on-screen
|
||||
keyboard occlusion, AirPlay 2 audio route) and removes the rows
|
||||
that don't apply (background-audio behaviour is identical
|
||||
because both share the same `UIBackgroundModes = ['audio']`
|
||||
declaration in `Info.plist`). SDD references: SDD-094..097 (v1
|
||||
audio + PTT lifecycle), DEC-025 (target environment), DEC-027
|
||||
(diagnostic privacy invariant), SRS-197 (iOS/iPadOS audio
|
||||
routing contract).
|
||||
|
||||
iPad does **not** have a global PTT capability — Apple's iOS /
|
||||
iPadOS sandbox model has no session-level event-tap analogue.
|
||||
The desktop PTT backend ladder (SDD-081..088) collapses to
|
||||
`FocusedPttBackend` and the capability badge advertises
|
||||
`L0Focused`. PTT works only while Chanora is the foreground app
|
||||
(or the audio-background mode keeps streaming when Chanora is
|
||||
backgrounded; see TC-8 / TC-13).
|
||||
|
||||
|
||||
## 0. Pre-flight
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 0.1 | Same Xcode signing setup as iOS: in `Runner.xcworkspace`, Runner target → Signing & Capabilities → personal team selected, unique bundle id. (If you already did this for iPhone the iPad uses the same provisioning profile.) | No code-signing errors in Xcode. |
|
||||
| 0.2 | Connect iPad via USB and trust the development Mac. On iPad: Settings → General → VPN & Device Management → developer-cert → Trust. | iPad appears in Xcode's device picker. |
|
||||
| 0.3 | Build for iPad: in Xcode pick the iPad as the run destination + Runner scheme → Cmd+R. (Or via CLI: `flutter build ios --release` then sideload with `xcrun devicectl device install app`.) | App installs on iPad and launches. |
|
||||
| 0.4 | First launch: iPad prompts for **Microphone** access — Allow. The prompt string matches `NSMicrophoneUsageDescription` from `ios/Runner/Info.plist`. | Mic permission granted. |
|
||||
| 0.5 | About / version label inside Chanora | Shows **`v1.0.0-rc.8`**. |
|
||||
|
||||
|
||||
## TC-1: Connect + identity persistence (DEC-006, SRS-201)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 1.1 | Enter a reachable TS3 server address, a nickname, blank password | Connect button enabled. |
|
||||
| 1.2 | Tap Connect | Server snapshot appears. |
|
||||
| 1.3 | Quit (background) + relaunch with the same nickname | Server-visible UID is the same (identity persisted in `Documents/identity.tskey`). |
|
||||
|
||||
|
||||
## TC-2: Voice channel join (SRS-204, SDD-094)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 2.1 | Tap a voice channel | Join works; voice bar shows the channel name. Mic capture starts (iOS status bar shows the orange mic indicator on iPadOS 17+). |
|
||||
| 2.2 | Tap a different voice channel | Smooth move; no audio dropout. |
|
||||
|
||||
|
||||
## TC-3: PTT press / release (Focused only — iPadOS limitation)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 3.1 | Open Voice settings (gear icon), select Push to talk | Capability badge clearly states **L0 Focused** with explanatory text that iPadOS does not permit global hotkeys. |
|
||||
| 3.2 | The "Bound key" UI is replaced by an on-screen Push-to-Talk button. | Touch and hold the button → mic indicator turns "Mic on". Release → indicator returns "Mic off" after the configured release-tail. |
|
||||
|
||||
|
||||
## TC-4: Release tail (SDD-097)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 4.1 | Set release-tail to 0 ms; tap-and-release the PTT button | Sharp on/off transition. |
|
||||
| 4.2 | Set release-tail to 500 ms; tap-and-release | Mic stays on for ~500 ms after release. |
|
||||
|
||||
|
||||
## TC-5: Continuous mode
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 5.1 | Switch to Continuous mode | PTT button disappears; mic stays open while in the voice channel. |
|
||||
|
||||
|
||||
## TC-6: Mic mute
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 6.1 | Mute mic via the Voice Bar | Mic icon shows muted state. Touching the PTT button does NOT unmute. |
|
||||
|
||||
|
||||
## TC-7: Speaker mute
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 7.1 | Speaker mute | Other clients silenced locally. |
|
||||
|
||||
|
||||
## TC-8: Background audio (UIBackgroundModes = audio)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 8.1 | While connected + in a voice channel + in Continuous mode, swipe Chanora to the App Switcher (or press the home button if your iPad has one). | The iPadOS orange mic indicator stays on; voice continues to be received and sent. |
|
||||
| 8.2 | Return to Chanora | Session intact; no reconnect cycle. |
|
||||
| 8.3 | Lock the iPad for 30 s, then unlock | Session still intact (provided you stayed in the channel and on Wi-Fi/cellular). |
|
||||
|
||||
|
||||
## TC-9: AVAudioSession routing (SRS-197)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 9.1 | Connect AirPods / Bluetooth headset; talk on Chanora | Audio routes to the headset (`.allowBluetooth` + `.allowBluetoothA2DP` are set in `AppDelegate.swift::application(_:didFinishLaunchingWithOptions:)`). |
|
||||
| 9.2 | Disconnect the headset mid-call | Audio routes back to the built-in speakers (`.defaultToSpeaker`). |
|
||||
| 9.3 | (If iPad has FaceTime configured) place a FaceTime call to yourself or have someone call. | Chanora's audio session yields to the FaceTime call. |
|
||||
| 9.4 | End the FaceTime call | Chanora resumes audio without manual reconnect. |
|
||||
|
||||
|
||||
## TC-10: Reconnect
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 10.1 | Toggle Airplane Mode on for 10 s, then off | Connection-lost banner appears, then recovers. |
|
||||
|
||||
|
||||
## TC-11: Diagnostic export + privacy (DEC-027)
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 11.1 | Export a diagnostic bundle | Allow-listed fields only; no raw key labels, no audio bytes. |
|
||||
|
||||
|
||||
## TC-12: Capability badge label
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 12.1 | Capability badge | Shows `L0Focused` with explanation that iPadOS does not expose global hotkeys. |
|
||||
|
||||
|
||||
## TC-13: iPad-specific — wide-mode landscape layout
|
||||
|
||||
The Flutter UI uses a `LayoutBuilder` 840 dp breakpoint
|
||||
(`apps/chanora_flutter/lib/main.dart`). On iPhone in portrait the
|
||||
body is below 840 dp, so the layout is stacked (Voice Bar on top,
|
||||
channel tree below). On iPad in landscape the body is well above
|
||||
840 dp, so the layout splits into a 320 dp left column (banner +
|
||||
Voice Bar) and the rest filled by the channel tree.
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 13.1 | Rotate iPad to landscape, connect to a server, double-click into a voice channel. | Voice Bar pinned to a 320 dp left column. Channel tree fills the rest. The "not production ready" banner sits inside the left column above the Voice Bar (per the earlier left-column-banner change). |
|
||||
| 13.2 | Rotate iPad to portrait. | Layout flips back to the stacked iPhone-style arrangement. Voice Bar on top full-width, channel tree below. Banner pins full-width at the top above the connection status. |
|
||||
| 13.3 | In landscape, join a channel with a very long name. | The channel-name pill in the Voice Bar truncates with an ellipsis instead of overflowing under the channel tree. Mute icons stay anchored to the right edge of the left column. |
|
||||
|
||||
|
||||
## TC-14: iPad-specific — Split View / Slide Over
|
||||
|
||||
Multitasking with other iPad apps. Our scaffold currently sets
|
||||
`UIApplicationSupportsMultipleScenes = false` in `Info.plist`,
|
||||
so Split View is **not** supported in P0. This row exists to
|
||||
document that and ensure the app doesn't crash when iPadOS tries.
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 14.1 | In landscape, swipe up from the iPad home indicator → drag Chanora to the right edge to enter Split View, or pick "Slide Over" from the iPadOS multitasking menu. | iPadOS shows the Split View / Slide Over UI but Chanora remains full-screen and does not crash. The non-support is by design for P0; a P1 follow-up will switch to multi-scene. |
|
||||
|
||||
|
||||
## TC-15: iPad-specific — AirPlay 2 audio route
|
||||
|
||||
| # | Step | Expected |
|
||||
|---|---|---|
|
||||
| 15.1 | While in a voice channel, open Control Center → AirPlay → pick an AirPlay 2 speaker (HomePod, Apple TV, AirPlay-compatible receiver). | Audio routes to the AirPlay destination. The PTT-active indicator continues to work; the mic stays routed to the iPad built-in mic (AirPlay 2 receivers don't typically have a return mic channel). |
|
||||
| 15.2 | Reselect "iPad" as the audio route | Audio returns to local routing. No restart needed. |
|
||||
|
||||
|
||||
## Auto-test sign-off
|
||||
|
||||
These rows do not require human interaction. The values are the
|
||||
same as the iOS document — iPad uses the identical Rust + Flutter
|
||||
build artefacts.
|
||||
|
||||
| Layer | Result |
|
||||
|---|---|
|
||||
| `cargo check --workspace` on macOS host | clean |
|
||||
| `cargo test --workspace --lib` on macOS host | unchanged (iPad-specific Rust code does not exist; iOS-targeted code is `#[cfg(target_os = "ios")]`-gated and applies identically to iPadOS) |
|
||||
| `cargo build --release --target aarch64-apple-ios -p chanora_bridge` | clean — produces `libchanora_bridge.a` |
|
||||
| `flutter build ios --release` | clean — produces `Runner.app` ≈ 17 MB (same artefact as iPhone) |
|
||||
| `Runner.xcodeproj` `TARGETED_DEVICE_FAMILY = "1,2"` | Universal family confirmed via `grep TARGETED_DEVICE_FAMILY ios/Runner.xcodeproj/project.pbxproj`. |
|
||||
|
||||
|
||||
## Sign-off form
|
||||
|
||||
```
|
||||
chanora v1.0.0-rc.8 — iPad P0 acceptance
|
||||
Device: ______________________ (iPad model + iPadOS version)
|
||||
Tester: ______________________
|
||||
Date: ______________________
|
||||
|
||||
TC-1 Connect + identity persistence [ pass / fail ] notes:
|
||||
TC-2 Voice channel join [ pass / fail ] notes:
|
||||
TC-3 PTT press / release (Focused) [ 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 Background audio [ pass / fail ] notes:
|
||||
TC-9 AVAudioSession routing [ pass / fail ] notes:
|
||||
TC-10 Reconnect [ pass / fail ] notes:
|
||||
TC-11 Diagnostic export + privacy [ pass / fail ] notes:
|
||||
TC-12 Capability badge label [ pass / fail ] notes:
|
||||
TC-13 Wide-mode landscape layout [ pass / fail ] notes:
|
||||
TC-14 Split View / Slide Over no-crash [ pass / fail ] notes:
|
||||
TC-15 AirPlay 2 audio route [ pass / fail ] notes:
|
||||
|
||||
Overall result: [ iPad rc.8 PASS / iPad rc.8 FAIL ]
|
||||
Sign: ______________________
|
||||
```
|
||||
|
||||
|
||||
## Known gaps (not blockers)
|
||||
|
||||
- **Split View / Slide Over multitasking** is intentionally
|
||||
unsupported in P0. `UIApplicationSupportsMultipleScenes` stays
|
||||
`false` until we wire iPadOS multi-scene handling (P1).
|
||||
- **Apple Pencil + external keyboard shortcuts**: not wired. A
|
||||
paid Developer Program account would let us declare
|
||||
`GCKeyboard` hardware-keyboard support for things like Cmd+M
|
||||
to mute — P1 follow-up.
|
||||
- **Stage Manager** (iPadOS 16+): app runs but the layout is not
|
||||
optimised for resizable Stage Manager windows. P1.
|
||||
- **TestFlight + App Store distribution**: requires the paid
|
||||
$99/yr Apple Developer Program. P1 follow-up.
|
||||
- **Simulator audio**: cpal-via-CoreAudio inside the iPad
|
||||
simulator routes to the Mac's audio devices and is fine for
|
||||
smoke-testing the UI, but real microphone capture / AEC
|
||||
behaviour and AirPlay 2 routing cannot be assessed there.
|
||||
Test on a physical iPad.
|
||||
- **VAD** (`TransmitMode::VoiceActivity`) is intentionally
|
||||
disabled in P0 (DEC-030).
|
||||
Reference in New Issue
Block a user