Astradial Phone (iOS) — Flow List & Release Test Plan
Purpose: every build handed to Hari must pass this. No more "fix one thing, ship, find three new things." Claude runs everything in the Can Claude test? column before release; Hari only runs the Device-only rows (push/CallKit/audio can't run on the simulator).
Legend: ✅ pass · ❌ fail · ⏭️ skipped · 🅓 device-only · 🅢 simulator-OK
0. Release gate (run in order, every build)
- Compiles —
xcodebuild … -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build → BUILD SUCCEEDED. (Claude) - Simulator smoke — install on sim, launch, confirm it reaches onboarding/keypad in < 5s (screenshot). (Claude) 🅢
- Device call matrix — sections D–G below on a real device. (Hari) 🅓
- Only after 1–3 are green → "ready to test" / TestFlight.
A. Launch & loading 🅢 (mostly sim-testable)
| # | Flow | Steps | Expected |
| A1 | Fresh install launch | Delete app → install → open | Splash → onboarding/keypad in < 5s. Never > 15s. |
| A2 | Subsequent launch | Kill → reopen | < 3s to last screen |
| A3 | Launch, no SIP line | Skip login | Keypad with "no SIP" chip; no hang |
| A4 | Launch, SIP configured | Has account | Registers within a few s; chip shows user |
| A5 | Launch offline | Airplane mode → open | Reaches UI (does NOT hang on splash); shows offline state |
| A6 | Cold launch never blocks main thread | — | Splash is animated/responsive throughout |
B. Auth & accounts 🅢
| # | Flow | Expected |
| B1 | Firebase sign in | Org JWT; analytics/tickets load |
| B2 | Skip login | Usable dialer, no MD tabs gated content |
| B3 | Log out | SIP line cleared, chip gone, session cleared (no stale org name) |
| B4 | Multi-account switch | Re-signs Firebase, restores that org's SIP line |
| B5 | Wrong password | Clear error, no hang |
C. SIP provisioning 🅢 (registration result 🅓)
| # | Flow | Expected |
| C1 | QR scan (editor) | Account created, registers |
| C2 | Manual entry incl. server/domain | Can set host:port (needed for staging); registers |
| C3 | SIP-user dropdown | Lists only human SIP users (routing_type=sip) |
| C4 | Switch SIP user | Old line cleared, new registers |
D. Outbound calls 🅓
| # | Flow | Expected |
| D1 | First call right after launch | Connects + 2-way audio (THE known hang bug) |
| D2 | Second/subsequent call | Connects + audio |
| D3 | Hang up from app | Both sides end immediately |
| D4 | Far side hangs up | App call ends, returns to keypad |
| D5 | In-call: mute / speaker / keypad DTMF / hold | Each works |
| D6 | Call duration timer | Counts up from 0:01 (not stuck) |
E. Inbound — app FOREGROUND 🅓
| # | Flow | Expected |
| E1 | Call arrives, app open | CallKit rings; answer → audio |
| E2 | Decline | Caller gets busy/declined |
| E3 | Hang up either side | Clean end |
F. Inbound — app BACKGROUNDED (not killed) 🅓
| # | Flow | Expected |
| F1 | Home out, call arrives | CallKit full-screen rings |
| F2 | Answer from lock screen | Audio connects |
G. Inbound — app KILLED (VoIP push wake) 🅓 ← headline feature
| # | Flow | Expected |
| G1 | Swipe-kill app, call arrives | Push wakes app; CallKit rings within ~a few s |
| G2 | Answer (after it rings a moment) | Connects + 2-way audio |
| G3 | Answer immediately (during ring) | Auto-connects when INVITE lands (no dead call) |
| G4 | Don't answer | Rings then ends cleanly (no stuck call screen) |
| G5 | Caller cancels mid-ring | App call screen dismisses |
| G6 | After device reboot + 1 unlock | Rings (iOS rule: needs first unlock) |
| G7 | Battery: app suspended between calls | No persistent CPU/socket |
H. Other surfaces 🅢
Recents list · Contacts (org directory, no device perms) · Analytics tiles · Tickets (badge, status change) · Dark mode · number formatting.
Known-open bugs (must be ✅ before release)
What Claude can / can't test
- Can (sim + build): compile, launch/loading, UI flows, onboarding, navigation, dark mode, view logic. Done before every handoff.
- Can't (device-only): PushKit wake, CallKit UI, real SIP registration over the network, audio, background/killed behaviour. These need Hari + a device — so they're explicitly listed for device testing rather than assumed working.