feat(android): Android skeleton with reproducible Nix/Gradle gate (#170, #171) #290

Closed
nsaspy wants to merge 0 commits from feat/android-app into master
Owner

Consumed issues: #170 (feasibility bakeoff + architecture decision) and #171 (in-repo Android project skeleton), per the #152/#194 Android roadmap. RAGE Auto-RAGE evidence recorded in rage/170-android-bakeoff.org and rage/171-android-skeleton.org; start SHA e5a4f26.

#170 — bakeoff decision (research: Brave + primary sources)

  • Prolog runtime: Trealla Prolog (MIT, C99, official Android support, C API) embedded via NDK with a thin JNI boundary we own. Rejected: SWI-Prolog NDK (no maintained upstream port; fork burden), swipl-wasm/WebView and Tau-Prolog (JS bridge, fragile in a service process), Scryer (no stable C embedding path).
  • Transport: jeromq 0.6.x (pure Java, ZMTP/3.0, CURVE implemented) wire-compatible with the existing pyzmq CURVE/ZAP server (zara/security_transport.py). Rejected: libzmq NDK (ABI matrix + libsodium for no gain). Protocol-fork clause documented.
  • Platform constraints: API 34 microphone FGS requires foregroundServiceType=microphone + FOREGROUND_SERVICE_MICROPHONE + RECORD_AUDIO; background mic-FGS start is prohibited except for the app providing the VoiceInteractionService — assistant-role invocation is the deterministic always-available voice path; no always-on hot-word assumption (#175 will design within these limits).
  • Fallbacks: Trealla fixture failure → server-authoritative semantics with typed degraded/offline local behavior (#176). jeromq CURVE incompatibility → documented architecture conflict before any replacement.

#171 — skeleton (TDD: RED → GREEN)

  • android/ Gradle project (single app module, ai.zara.app): pins AGP 9.2.0 (built-in Kotlin — AGP 9 rejects the separate kotlin-android plugin; recorded as an as-built correction to #170), Gradle 9.5.1, JDK 21, compileSdk 37 / targetSdk 36 / minSdk 29 (RoleManager.ROLE_ASSISTANT floor); Compose BOM 2026.08.00 pinned for #197, not consumed yet.
  • Single typed runtime state + pure reducer (ai.zara.app.runtime: server connection machine + assistant-role tri-state) — the seed that #196/#197 must extend, no parallel state machine.
  • flake.nix: scoped androidPkgs (allowUnfree + android_sdk.accept_license) and devShells.android (JDK 21 + Gradle 9 + SDK). The broken composite androidenv androidsdk attr in the pinned nixpkgs rev is worked around by assembling the SDK root from the healthy per-package derivations + license hash files derived from androidenv's repo.json (documented deviation).
  • scripts/test-android.sh: JVM unit tests + assembleDebug + APK secret-marker inspection. Dedicated android CI job (45 min cap) uploads the debug APK artifact; deliberately not added to the 30-min-capped test job (documented).

Gates (exact candidate b09d9e4, local)

  • Android gate: 10/10 unit tests, debug APK built, secret inspection ok (RED evidence: unresolved RuntimeState before implementation; one test-setup fix, production reducer unchanged).
  • NIX_CONFIG='experimental-features = nix-command flakes' nix develop -c bash scripts/test-all.sh: 10/10 phases.
  • nix flake check: all checks passed (Linux behavior unchanged).

Next queue items after merge: #172/#173/#195 → #196 (assistant role + VoiceInteractionService surface) → #197 (Compose chat shell).

Consumed issues: #170 (feasibility bakeoff + architecture decision) and #171 (in-repo Android project skeleton), per the #152/#194 Android roadmap. RAGE Auto-RAGE evidence recorded in `rage/170-android-bakeoff.org` and `rage/171-android-skeleton.org`; start SHA e5a4f26. ## #170 — bakeoff decision (research: Brave + primary sources) - **Prolog runtime**: Trealla Prolog (MIT, C99, official Android support, C API) embedded via NDK with a thin JNI boundary we own. Rejected: SWI-Prolog NDK (no maintained upstream port; fork burden), swipl-wasm/WebView and Tau-Prolog (JS bridge, fragile in a service process), Scryer (no stable C embedding path). - **Transport**: jeromq 0.6.x (pure Java, ZMTP/3.0, **CURVE** implemented) wire-compatible with the existing pyzmq CURVE/ZAP server (`zara/security_transport.py`). Rejected: libzmq NDK (ABI matrix + libsodium for no gain). Protocol-fork clause documented. - **Platform constraints**: API 34 microphone FGS requires `foregroundServiceType=microphone` + `FOREGROUND_SERVICE_MICROPHONE` + RECORD_AUDIO; background mic-FGS start is prohibited **except for the app providing the VoiceInteractionService** — assistant-role invocation is the deterministic always-available voice path; no always-on hot-word assumption (#175 will design within these limits). - **Fallbacks**: Trealla fixture failure → server-authoritative semantics with typed degraded/offline local behavior (#176). jeromq CURVE incompatibility → documented architecture conflict before any replacement. ## #171 — skeleton (TDD: RED → GREEN) - `android/` Gradle project (single `app` module, `ai.zara.app`): pins AGP 9.2.0 (built-in Kotlin — AGP 9 rejects the separate kotlin-android plugin; recorded as an as-built correction to #170), Gradle 9.5.1, JDK 21, compileSdk 37 / targetSdk 36 / minSdk 29 (RoleManager.ROLE_ASSISTANT floor); Compose BOM 2026.08.00 pinned for #197, not consumed yet. - Single typed runtime state + pure reducer (`ai.zara.app.runtime`: server connection machine + assistant-role tri-state) — the seed that #196/#197 must extend, no parallel state machine. - `flake.nix`: scoped `androidPkgs` (allowUnfree + android_sdk.accept_license) and `devShells.android` (JDK 21 + Gradle 9 + SDK). The broken composite androidenv `androidsdk` attr in the pinned nixpkgs rev is worked around by assembling the SDK root from the healthy per-package derivations + license hash files derived from androidenv's repo.json (documented deviation). - `scripts/test-android.sh`: JVM unit tests + `assembleDebug` + APK secret-marker inspection. Dedicated `android` CI job (45 min cap) uploads the debug APK artifact; deliberately not added to the 30-min-capped `test` job (documented). ## Gates (exact candidate b09d9e4, local) - Android gate: 10/10 unit tests, debug APK built, secret inspection ok (RED evidence: unresolved `RuntimeState` before implementation; one test-setup fix, production reducer unchanged). - `NIX_CONFIG='experimental-features = nix-command flakes' nix develop -c bash scripts/test-all.sh`: 10/10 phases. - `nix flake check`: all checks passed (Linux behavior unchanged). Next queue items after merge: #172/#173/#195 → #196 (assistant role + VoiceInteractionService surface) → #197 (Compose chat shell).
nsaspy closed this pull request 2026-09-04 23:08:48 +00:00
Some checks failed
CI / test (pull_request) Failing after 7s
CI / android skeleton gate (pull_request) Failing after 8s
CI / shared mic / Arch Linux (pull_request) Failing after 11m35s
CI / shared mic / Ubuntu 24.04 (pull_request) Failing after 13m2s

Pull request closed

Sign in to join this conversation.
No description provided.