Add QR pairing (terminal QR, in-app scanner, iris://pair deep link)
CI / Kotlin tests (android host + desktop) (push) Successful in 8m5s
CI / Gateway plugin tests (push) Successful in 9m47s

This commit is contained in:
ARIA committed 2026-08-22 22:43:13 +02:00
1 parent 27dc7917f2
commit 7a6d922d12
63 files changed
+2073 -630

No files matched your search

+10 -8
View File
@@ -3,24 +3,24 @@
## Locked decisions (from planning, 2026-08-19)
| # | Decision | Choice | Rationale |
|---|---|---|---|
| --- | --- | --- | --- |
| 1 | Desktop app tech | **Compose Multiplatform** | Desktop = "the Android app, tweaked"; share protocol/state/UI. |
| 2 | Push backend | **Both — FCM primary, ntfy fallback** | FCM is standard/reliable; ntfy for self-hosters with no Firebase. `ANDROID_PUSH_BACKEND`. |
| 2 | Push backend | **Both — FCM primary, ntfy fallback** | FCM is standard/reliable; ntfy for self-hosters with no Firebase. `IRIS_PUSH_BACKEND`. |
| 3 | Media transport | **Over the WebSocket** | One transport, zero new Python deps; chunked binary frames. |
| 4 | Phone default layout | **User-toggleable, single-pane default** | App-like on phones; auto two-pane on large screens; desktop defaults two-pane. |
## Additional decisions made during planning
| Decision | Choice | Note |
|---|---|---|
| Connection point | **Messaging gateway** (platform plugin `android`), not `tui_gateway` | Makes cron/`send_message`/slash/coexistence native. |
| --- | --- | --- |
| Connection point | **Messaging gateway** (platform plugin `iris`), not `tui_gateway` | Makes cron/`send_message`/slash/coexistence native. |
| Plugin style | **Community plugin** (`register(ctx)`) | Zero hermes-core changes. |
| Python deps | **None new** (`websockets` + `httpx` are core) | Respects hermes pinning policy. |
| Tool events | **Structured frames; app controls verbosity** | Gateway sends full data; app = everything/truncated/nothing. |
| Reasoning | **Adapter splits the `show_reasoning` prefix** | Clean `reasoning` field → collapsible block above message. |
| Channels/threads | **Map onto `chat_id`/`thread_id`** | Existing gateway primitives; cron targets them. |
| Offline | **SQLite outbox + sync cursor** | Catch-up on reconnect; push on disconnect. |
| Default chat id | `android:default` | Home channel + cron default. |
| Default chat id | `default` | Home channel + cron default. |
| WS port | `8790` (default) | Configurable. |
| minSdk | 26 (test device API 29) | Broad coverage. |
| Frame routing | **Broadcast to all connected devices** (no per-chat subscribe) | Single-user model; simpler. |
@@ -29,6 +29,8 @@
| Agent lifecycle | **`agent.busy`/`agent.idle`** events + **`agent.stop`/`agent.steer`** requests | App shows thinking indicator; user can abort or steer mid-turn. |
| Local DB (KMP) | **SQLDelight** (not Room) | Room is Android-only; SQLDelight works in commonMain for both platforms. |
| Voice input | **Record → upload as audio media** (no client-side STT) | Agent's STT (if configured) handles transcription. |
| QR encoder | **Pure-stdlib** (`gateway-plugin/qr.py`) | No `qrcode`/`segno`/Pillow; byte mode, EC M→L, v1–10, ISO penalty masking. Keeps the plugin's zero-new-dep rule. |
| QR scanner | **ML Kit barcode** (not zxing-android-embedded) | On-device, no Google Play services; better accuracy/latency, Google-maintained. Android-only (desktop has no camera). |
## Open questions (resolve during implementation)
@@ -45,7 +47,7 @@ will proceed with unless you say otherwise.
`reasoning_style: code` for android and split on that; fallback = no
reasoning field (full text) if the prefix isn't found. Verify in M2.
3. **Per-device tokens vs shared token (M1/M5).** *Default (v1):* shared
`ANDROID_TOKEN` + optional `ANDROID_ALLOWED_USERS` device allowlist.
`IRIS_TOKEN` + optional `IRIS_ALLOWED_USERS` device allowlist.
Per-device revocable tokens are a stretch.
4. **Desktop video backend (M6).** *Default:* `libmpv`/`mpv`-backed Compose
surface, WebView fallback. Confirm `mpv` availability on target OSes during
@@ -54,7 +56,7 @@ will proceed with unless you say otherwise.
recommended remote path; WSS + reverse proxy as alternatives. No public bind
by default.
6. **Streaming cadence (M2).** If live updates look chunky, tune
`display.platforms.android.streaming` / consumer edit interval. *Default:*
`display.platforms.iris.streaming` / consumer edit interval. *Default:*
follow global streaming config.
7. **App package name / branding.** *Default:* applicationId `dev.iris.app`,
app name "Iris". Confirm final product name + package + icon.
@@ -72,4 +74,4 @@ will proceed with unless you say otherwise.
- End-to-end encryption (transport WSS only).
- Standalone-cron delivery while the gateway process is fully down (best-effort
push only).
- iOS.
- iOS.