YazSes Mobile — programme overview¶
Status (2026-08-07): design complete, no code yet. Nothing in this directory ships today. The Android app does not exist; these documents are what has to be true before it does, and they are deliberately written before the first line of Kotlin so that the work can be done by many people at once.
Honesty rule. Nothing here may be described in the README, the docs site, the store listings or a release note as "supported" until it is wired, tested and shipped. The project's existing rule — 141 capabilities, 68 wired and 72 honestly marked planned — applies to mobile without exception.
Why¶
YazSes' thesis is dictation that never leaves your device. That thesis is strongest on a phone: the default dictation on Android is a service the user cannot audit, and the confidential conversations YazSes exists to protect — the client call, the patient note, the source interview — happen where the phone is, not where the laptop is. It is also the project's most-requested missing platform.
Why Android first¶
Not preference — platform capability. Android's InputMethodService lets a third-party keyboard hold the microphone and commit text into any app, which reproduces the desktop's hold-to-talk model exactly. iOS forbids microphone access to every app extension, including keyboards, and has since iOS 8, so an iOS app must be a different product shape (app-switch handoff). Doing Android first means the harder, better design is built first and the iOS wave inherits a proven contract. macOS, meanwhile, is already a supported YazSes platform — it belongs to the desktop line, not here. See ADR-MOB-010.
The decisions¶
| ADR | Decision |
|---|---|
| MOB-001 | Mobile is a first-class port; Android wave 1; in this repository under android/ |
| MOB-002 | Native Kotlin + Compose; pure-Kotlin :core:* (keeps the KMP door open); no Python-on-Android, no Flutter |
| MOB-003 | IME first, RecognitionService second, share/clipboard fallback; no AccessibilityService, no typing keyboard |
| MOB-004 | Hold the mic key; hold/toggle switch for accessibility; headset button; no wake word, ever |
| MOB-005 | An engine seam; whisper.cpp default; sherpa-onnx second (VAD, diarization, Parakeet); benchmarks over claims |
| MOB-006 | Models downloaded, SHA-256 verified, user-owned; never bundled; works with network permanently denied |
| MOB-007 | Permission budget, INTERNET in one module only, CI privacy gate, foreground-service rules |
| MOB-008 | One behaviour, many implementations — a contract/ of golden vectors both platforms run |
| MOB-009 | F-Droid-shaped by default; GitHub APK first, F-Droid/Accrescent next, Play later; own tags and keystore |
| MOB-010 | iOS/iPadOS after Android M2, different product shape; Swift-vs-KMP deferred with evidence |
The documents¶
| Document | What it is for |
|---|---|
| architecture.md | module map, pipeline, threading, error behaviour, testing — read this before your first PR |
| contract.md | the golden-vector mechanism that defines "correct" for every implementation |
| portability.md | every desktop capability → port / adapt / later / no, with milestones |
| contributing.md | how the Mobile Working Group works: stewards, claiming, review bar, no-device path |
Milestones¶
Each milestone is a shippable statement, not a date. Dates are not promised: this is a volunteer effort and pretending otherwise sets everyone up to be disappointed.
M0 — Foundations (no app yet; can be done entirely by Python contributors) contract/ exists with vectors for the shared units, generated from the desktop and guarded by a pytest; the Gradle skeleton, module structure and CI (unit tests + the manifest/dependency privacy gates) are in place. Done when: ./gradlew test runs green on an empty core and pytest tests/test_contract_vectors.py guards the desktop.
M1 — "It types what I say" (the first real release) Keyboard with a mic key; capture → VAD → whisper.cpp → cleanText → disfluency → commit; model chooser and verified download; clipboard fallback; onboarding; About. Done when: a signed android-v0.1.0 APK on GitHub Releases dictates reliably into a third-party app on a real phone, with network access revoked.
M2 — "It's actually good" RecognitionService; voice punctuation, continuation spacing, command grammar, personal vocabulary; the settings screen generated from the feature registry; a diagnostics screen; headset-button activation; F-Droid submission and Accrescent. Done when: a user can replace their phone's dictation for a week without reaching for Gboard. The iOS wave may start once M2 ships.
M3 — "Beyond dictation" File/share transcription; the sherpa-onnx flavour with diarization; Meeting Mode with its foreground service; the floating bubble; the public device-performance matrix from :bench.
M4 — Reach Play listing, localisation, and whatever the M1–M3 device reports say is actually broken.
How to help right now¶
The tracking epic, #81, carries the full work breakdown, and every sub-issue says what it needs from you and what "done" means. Three ways in that need no Android device and no Kotlin:
- M0 contract vectors — Python; write the ugly cases for a unit and generate its expectations. #82 builds the mechanism, #83 is a good first issue.
- Device reports — run the benchmark on your phone (once
:benchexists, #92) and file the JSON; the performance matrix is community-built by design. - Review these ADRs — the best time to disagree with an architecture is before it is built. #98 is an open invitation to attack them.
Read contributing.md next.