diff --git a/docs/governance/document-index.md b/docs/governance/document-index.md index d6b31a6..b0fed34 100644 --- a/docs/governance/document-index.md +++ b/docs/governance/document-index.md @@ -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. | diff --git a/docs/verification/ipad-p0-acceptance.md b/docs/verification/ipad-p0-acceptance.md new file mode 100644 index 0000000..ee6ffd1 --- /dev/null +++ b/docs/verification/ipad-p0-acceptance.md @@ -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).