From a61b47a947b8f4a1f0f488d7442d17abbc242496 Mon Sep 17 00:00:00 2001 From: ARIA Date: Mon, 24 Aug 2026 21:44:02 +0200 Subject: [PATCH] docs: replace stale 'android' name mentions with 'iris' The plugin is named 'iris' (IrisAdapter, IRIS_HOME_CHANNEL, label Iris), but several docs still referred to it as the android platform/plugin and to the product as 'the Android app'. Rename name-mentions to iris/IRIS and product-mentions to 'Iris app'; keep legitimate OS references (androidApp, Android SDK, Android 10, androidx, test_android.py, ...). Also includes pi-lens markdown-lint autofixes (table spacing, trailing newlines) in the touched files. --- docs/00-overview.md | 4 ++-- docs/01-architecture.md | 10 +++++----- docs/03-gateway-plugin.md | 8 ++++---- docs/06-channels-cron-search.md | 4 ++-- docs/10-android-app.md | 2 +- docs/11-desktop-app.md | 10 +++++----- docs/12-toolchain.md | 2 +- docs/13-testing.md | 10 +++++++--- docs/14-milestones.md | 6 +++--- docs/16-open-questions.md | 4 ++-- docs/18-code-review.md | 10 +++++----- docs/20-qr-pairing.md | 2 +- docs/README.md | 6 +++--- docs/diagrams/architecture.mmd | 6 +++--- docs/setup.md | 2 +- 15 files changed, 45 insertions(+), 41 deletions(-) diff --git a/docs/00-overview.md b/docs/00-overview.md index c93d248..33b6645 100644 --- a/docs/00-overview.md +++ b/docs/00-overview.md @@ -11,8 +11,8 @@ create. ## Goals -- **Native feel.** Real Android app (Kotlin/Compose), not a WebView. Desktop - app that is the same app, resized for a big screen. +- **Native feel.** Real native app (Iris on Android, Kotlin/Compose), not a + WebView. Desktop app that is the same app, resized for a big screen. - **First-class gateway citizen.** The app is a hermes *messaging platform*, so everything the gateway already does "just works": slash commands, cron delivery, `send_message` routing, coexistence with Telegram/Discord/etc. diff --git a/docs/01-architecture.md b/docs/01-architecture.md index 6750418..cd5c16c 100644 --- a/docs/01-architecture.md +++ b/docs/01-architecture.md @@ -11,7 +11,7 @@ │ │ │ │ │ │ │ ▼ legacy stream callbacks (delta / tool-progress / commentary) │ │ │ │ ┌──────────────────────────────┐ ┌────────────────────────────────┐ │ │ -│ │ │ android PLATFORM PLUGIN │◄───────►│ WebSocket SERVER (websockets) │ │ │ +│ │ │ IRIS PLATFORM PLUGIN │◄───────►│ WebSocket SERVER (websockets) │ │ │ │ │ │ IrisAdapter │ JSON │ ws://host:8790/ws │ │ │ │ │ │ (BasePlatformAdapter) │ frames │ + media + FCM-token + pairing │ │ │ │ │ │ • send / edit / stream │ └───────────────┬────────────────┘ │ │ @@ -26,7 +26,7 @@ │ │ Google FCM cloud │ ▼ │ │ │ ┌────────────────────────┐ │ ▼ │ - │ ANDROID APP │◄──┴── (wake) ┌──────────┐ + │ IRIS APP (ANDROID) │◄──┴── (wake) ┌──────────┐ │ (Kotlin / Compose) │ WSS │ PHONE │ │ • WS client (OkHttp) │◄───────────►│ MIX 2S │ │ • ExoPlayer │ │ (API 29) │ @@ -72,7 +72,7 @@ protocol (`04-wire-protocol.md`) that borrows familiar names (`message.*`, ## Key architectural decisions + rationale | Decision | Rationale | -|---|---| +| --- | --- | | **Community-style platform plugin** (`register(ctx)` → `ctx.register_platform`) | Zero hermes-core changes; survives hermes updates; follows `ADDING_A_PLATFORM.md` "Plugin Path". | | **Single WS transport** for chat, streaming, tools, media, pairing, FCM-token | One connection, one auth, one dependency (`websockets`, already core). Media as chunked binary frames avoids adding an HTTP server. | | **`websockets` + `httpx` only** | Both are hermes *core* deps → the plugin adds **zero** new Python dependencies (respects hermes supply-chain pinning policy). | @@ -80,7 +80,7 @@ protocol (`04-wire-protocol.md`) that borrows familiar names (`message.*`, | **Reasoning split in the adapter** | The gateway prepends reasoning to the final text when `show_reasoning` is on; the adapter splits the stable prefix into a `reasoning` field so the app renders a clean collapsible block. | | **Channels/threads = `chat_id`/`thread_id`** | The gateway's `SessionSource` already models this; cron delivery already targets `platform:chat_id:thread_id`. We map app concepts onto existing primitives. | | **SQLite outbox + sync cursor** | Offline delivery + reconnect catch-up without re-reading full history. | -| **Compose Multiplatform** | Desktop is "the Android app, tweaked" → share protocol/state/UI; only platform services + layout differ. | +| **Compose Multiplatform** | Desktop is "the Iris app, tweaked" → share protocol/state/UI; only platform services + layout differ. | ## Data flow (one turn) @@ -103,4 +103,4 @@ protocol (`04-wire-protocol.md`) that borrows familiar names (`message.*`, > (not the ACP-only event-native `render_message_event` path). We therefore map > the legacy `send`/`edit_message`/progress calls to our frames. The exact > tool-progress vs commentary classification is verified empirically in M2 by -> running the real gateway with a test WS client (see `13-testing.md`). \ No newline at end of file +> running the real gateway with a test WS client (see `13-testing.md`). diff --git a/docs/03-gateway-plugin.md b/docs/03-gateway-plugin.md index c4ec996..3fd0c02 100644 --- a/docs/03-gateway-plugin.md +++ b/docs/03-gateway-plugin.md @@ -12,7 +12,7 @@ and the canonical example `hermes-agent/plugins/platforms/irc/adapter.py`. ```yaml name: iris-platform -label: Android +label: Iris kind: platform version: 0.1.0 description: > @@ -24,7 +24,7 @@ author: requires_env: - name: IRIS_TOKEN description: "Shared pairing token the app presents on connect" - prompt: "Android pairing token" + prompt: "Iris pairing token" password: true optional_env: - name: IRIS_WS_HOST @@ -35,7 +35,7 @@ optional_env: description: "WS port (default 8790)" prompt: "WS port" password: false - - name: ANDROID_HOME_CHANNEL + - name: IRIS_HOME_CHANNEL description: "Default chat id for cron/notification delivery (default default)" prompt: "Home channel" password: false @@ -97,7 +97,7 @@ def register(ctx): install_hint="No extra packages needed (websockets + httpx are core deps)", setup_fn=interactive_setup, # hermes gateway setup flow env_enablement_fn=_env_enablement, # seed extra + home_channel from env - cron_deliver_env_var="ANDROID_HOME_CHANNEL", + cron_deliver_env_var="IRIS_HOME_CHANNEL", standalone_sender_fn=_standalone_send, # best-effort out-of-proc cron (stretch) parse_target_ref_fn=_parse_target_ref, # "iris:[:]" allowed_users_env="IRIS_ALLOWED_USERS", diff --git a/docs/06-channels-cron-search.md b/docs/06-channels-cron-search.md index 6953a2d..04704c6 100644 --- a/docs/06-channels-cron-search.md +++ b/docs/06-channels-cron-search.md @@ -23,10 +23,10 @@ gateway identity concepts**. ## 6.2 Default chat - On first connect, the plugin ensures a **default channel** exists: - `chat_id = ANDROID_HOME_CHANNEL` (default `default`), `kind=default`, + `chat_id = IRIS_HOME_CHANNEL` (default `default`), `kind=default`, `is_default=true`, name "Default". - It is also the **cron home channel** (`cron_deliver_env_var= - ANDROID_HOME_CHANNEL`), so `deliver=android` (bare) routes here. + IRIS_HOME_CHANNEL`), so `deliver=iris` (bare) routes here. - The app opens the default chat on launch. ## 6.3 Threads (toggle for overview) diff --git a/docs/10-android-app.md b/docs/10-android-app.md index 8a2efb0..511645e 100644 --- a/docs/10-android-app.md +++ b/docs/10-android-app.md @@ -1,4 +1,4 @@ -# 10 — Android App (Kotlin + Jetpack Compose) +# 10 — Iris App (Android; Kotlin + Jetpack Compose) Native client. Lives in the Compose Multiplatform project at `app/`; the bulk of the code is in `app/shared` (commonMain) so the Desktop app reuses it. diff --git a/docs/11-desktop-app.md b/docs/11-desktop-app.md index f74a64b..ca6d9d5 100644 --- a/docs/11-desktop-app.md +++ b/docs/11-desktop-app.md @@ -1,13 +1,13 @@ # 11 — Desktop App (Kotlin + Compose Multiplatform) -The desktop app is **the Android app, tweaked for a big screen**. It reuses the +The desktop app is **the Iris app, tweaked for a big screen**. It reuses the entire `app/shared` module (protocol, network, repositories, state, most UI) and only adds desktop platform services + a wider default layout. ## 11.1 What's shared vs desktop-specific | Layer | Shared (commonMain) | Desktop-specific (desktopMain) | -|---|---|---| +| --- | --- | --- | | Protocol / WS client | ✅ | — | | Repositories / state | ✅ | — | | Most Compose UI | ✅ | layout tweaks, keyboard shortcuts | @@ -62,9 +62,9 @@ only adds desktop platform services + a wider default layout. - The desktop app connects to the **same** gateway WS server as the phone (the user's home server / Tailscale). It does **not** spawn its own backend (unlike hermes's existing Electron desktop, which spawns `hermes serve`) — our - desktop is a pure client of the messaging gateway, matching the Android app. + desktop is a pure client of the messaging gateway, matching the Iris app. -## 11.5 Parity checklist (same functionality as Android) +## 11.5 Parity checklist (same functionality as the Iris app) - [ ] Streaming, reasoning block, tool cards (3-level verbosity), commentary. - [ ] Channels + threads + new channel + cron target. @@ -72,4 +72,4 @@ only adds desktop platform services + a wider default layout. - [ ] Media attach + live playback (via desktop player). - [ ] Slash command menu + autocomplete + interactive pickers. - [ ] Push (tray + OS notifications) + outbox/sync. -- [ ] Pairing/Connect screen (URL + token, WSS cert pin). \ No newline at end of file +- [ ] Pairing/Connect screen (URL + token, WSS cert pin). diff --git a/docs/12-toolchain.md b/docs/12-toolchain.md index fc0b432..099bc65 100644 --- a/docs/12-toolchain.md +++ b/docs/12-toolchain.md @@ -132,7 +132,7 @@ display: ```bash # 1. gateway up with plugin -hermes gateway status | grep -i android +hermes gateway status | grep -i iris # 2. a raw WS client can pair + echo python - <<'PY' diff --git a/docs/13-testing.md b/docs/13-testing.md index 832d3c2..4918324 100644 --- a/docs/13-testing.md +++ b/docs/13-testing.md @@ -10,16 +10,18 @@ without the app (critical for verifying frame shapes early). into the hermes `tests/gateway/test_android.py` pattern when running under hermes's suite). - **Run with hermes's hermetic runner** (never bare `pytest`): + ```bash cd hermes-agent scripts/run_tests.sh tests/gateway/test_android.py scripts/run_tests.sh # full suite (CI parity) ``` + - Coverage to write (behavioral, not change-detector — per hermes test policy): - `register(ctx)` produces a valid `PlatformEntry` (name, cron env var, parse_target_ref). - `check_requirements` / `validate_config` / `is_connected` truth table. - - `_parse_target_ref`: `iris:`, `iris::`, non-android + - `_parse_target_ref`: `iris:`, `iris::`, non-iris → None. - **Reasoning split:** given a `show_reasoning`-style final text, `send()` emits `message {reasoning, text}` correctly; no-prefix → no reasoning field. @@ -53,12 +55,13 @@ commentary classification and the reasoning prefix) before/while building the Kotlin client. ```bash -hermes gateway & # with the android plugin +hermes gateway & # with the iris plugin python gateway-plugin/tests/ws_probe.py --token \ --send "list the files and summarize" # prints: hello.ack, typing, message.start, message.update…, tool.start, tool.end, # commentary, message.stop {reasoning,…}, … ``` + Use it to lock `04-wire-protocol.md` against reality and to debug the adapter without waiting for the app. @@ -102,6 +105,7 @@ adb logcat -d > /tmp/logcat.txt ``` **E2E scenarios (script where possible):** + 1. **Pair:** connect screen → enter URL+token → `hello.ack` → main. (Verify auth leg, not just TCP.) 2. **Text round-trip:** send "hello" → streamed reply appears (message.start → @@ -155,4 +159,4 @@ adb logcat -d > /tmp/logcat.txt account can mint a token, and the app's `onNewToken` re-registered after `pm clear`. - **Profile leaks:** if tokens look wrong under multiple profiles, verify the - scope-aware secret read (`_get_scoped_secret`) is used. \ No newline at end of file + scope-aware secret read (`_get_scoped_secret`) is used. diff --git a/docs/14-milestones.md b/docs/14-milestones.md index d2eb1b8..e4ba8d7 100644 --- a/docs/14-milestones.md +++ b/docs/14-milestones.md @@ -161,11 +161,11 @@ has explicit **acceptance criteria**. Work top-to-bottom; don't skip M0/M1. - [x] `desktopMain`: tray + OS notifications; `MediaPlayer` actual (mpv/WebView); `MediaPicker` actual (file dialog); `SecureStore` actual; window mgmt. - [x] Two-pane default layout; keyboard shortcuts; optional inspector pane. -- [ ] Parity pass vs Android feature checklist (`11-desktop-app.md`). +- [ ] Parity pass vs Iris app feature checklist (`11-desktop-app.md`). - [x] jpackage builds (Linux first; macOS/Windows as available). - **Demo:** desktop app pairs to the same gateway; full feature parity; tray notifications; media plays. -- **Accept:** all Android features work on desktop; tray + shortcuts work; +- **Accept:** all Iris app features work on desktop; tray + shortcuts work; native binary launches. - **Status (complete, 2026-08-19):** All `desktopMain` actuals implemented and verified on Linux (X11). `DesktopSecureStore`: non-secrets in @@ -274,7 +274,7 @@ in-app scanner and `iris://pair` deep link (closes gap #12, `docs/20`). build it in M1. - **M3 (cron) and M5 (push) both touch the outbox** — build the outbox in M3, extend for push in M5. -- **M6 (desktop) reuses M1–M5 shared code** — do it after the Android features +- **M6 (desktop) reuses M1–M5 shared code** — do it after the Iris app features are stable so the shared module is settled. - Parallelizable: plugin (Python) and app (Kotlin) can be worked on concurrently once the protocol (`04-wire-protocol.md`) is agreed; the probe diff --git a/docs/16-open-questions.md b/docs/16-open-questions.md index 084fcb3..aba8393 100644 --- a/docs/16-open-questions.md +++ b/docs/16-open-questions.md @@ -4,7 +4,7 @@ | # | Decision | Choice | Rationale | | --- | --- | --- | --- | -| 1 | Desktop app tech | **Compose Multiplatform** | Desktop = "the Android app, tweaked"; share protocol/state/UI. | +| 1 | Desktop app tech | **Compose Multiplatform** | Desktop = "the Iris app, tweaked"; share protocol/state/UI. | | 2 | Push backend | **Both — ntfy default, FCM optional** (issue #10: FCM metadata — title, device token — is routed via Google's servers, contradicting the privacy claim; ntfy keeps it on your own infrastructure) | `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. | @@ -44,7 +44,7 @@ will proceed with unless you say otherwise. live gateway. If a clean metadata marker exists, prefer it. 2. **Reasoning prefix format stability (M2).** We split on the `code`-style `💭 **Reasoning:**\n```\n…\n```\n\n` prefix. *Default:* set - `reasoning_style: code` for android and split on that; fallback = no + `reasoning_style: code` for iris 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 `IRIS_TOKEN` + optional `IRIS_ALLOWED_USERS` device allowlist. diff --git a/docs/18-code-review.md b/docs/18-code-review.md index f1688c7..9fca046 100644 --- a/docs/18-code-review.md +++ b/docs/18-code-review.md @@ -1,7 +1,7 @@ # 18 — Code Review & Lint/LSP Cleanup (alpha → stable) -Comprehensive review of all three components — **gateway plugin**, **Android -app**, and **Desktop app** — performed to take the project from alpha to a +Comprehensive review of all three components — **gateway plugin**, **Iris app +(Android)**, and **Desktop app** — performed to take the project from alpha to a clean, stable baseline. Each section records what was found, what was fixed, how it was verified, and what was deliberately left (with rationale). @@ -50,7 +50,7 @@ findings. Categories: `hermes_cli.config`, but those live in `hermes_cli.cli_output`; it also imported a `print_code` that does not exist in hermes at all. The whole import block raised `ImportError`, which the surrounding `try/except` swallowed, so - `hermes gateway setup` for the android platform **always bailed out early** with + `hermes gateway setup` for the iris platform **always bailed out early** with "setup helpers unavailable" and never generated a token or prompted for host/port. Fixed by importing the print helpers from `hermes_cli.cli_output`, the env helpers from `hermes_cli.config`, and dropping the non-existent @@ -127,9 +127,9 @@ rule set (`E W F I UP B SIM PL RET C4`) and `line-length = 100`. Changes: --- -## 18.2 Android app (`app/androidApp` + `app/shared`) +## 18.2 Iris app — Android (`app/androidApp` + `app/shared`) -The Android and Desktop apps share the `:shared` KMP module (`commonMain` + +The Iris Android and Desktop apps share the `:shared` KMP module (`commonMain` + `jvmMain`), so most Kotlin code is covered here and in 18.3. ### 18.2.1 Findings (before) diff --git a/docs/20-qr-pairing.md b/docs/20-qr-pairing.md index 28d83cb..372000c 100644 --- a/docs/20-qr-pairing.md +++ b/docs/20-qr-pairing.md @@ -315,7 +315,7 @@ interleaved (different languages, no shared surface). - **QR display in the app** (showing a QR for other devices to scan) — single-device pairing today; revisit if multi-device lands. -- **`hermes android pair` stretch CLI** (re-issue token + new QR, +- **`hermes iris pair` stretch CLI** (re-issue token + new QR, `09-pairing-security.md` §9.2 line 48) — separate backlog item. - **WSS cert pinning** (gap #6) — orthogonal; QR carries `secure=1` already, pinning is app-side. diff --git a/docs/README.md b/docs/README.md index 76b61e1..a509a24 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,7 +32,7 @@ top-to-bottom once, then use the numbered docs as a lookup while implementing. | 7 | [`07-media.md`](07-media.md) | Media upload/download + playback. | | 8 | [`08-push.md`](08-push.md) | Push (ntfy default + FCM optional), outbox, sync. | | 9 | [`09-pairing-security.md`](09-pairing-security.md) | Pairing, auth, security model. | -| 10 | [`10-android-app.md`](10-android-app.md) | When building the Android app. | +| 10 | [`10-android-app.md`](10-android-app.md) | When building the Iris app (Android). | | 11 | [`11-desktop-app.md`](11-desktop-app.md) | When building the Desktop app. | | 12 | [`12-toolchain.md`](12-toolchain.md) | First time on a machine (JDK/SDK/uv/Firebase). | | 13 | [`13-testing.md`](13-testing.md) | Writing tests + on-device ADB workflow. | @@ -59,9 +59,9 @@ Machine-readable / diagrams: Python dependencies, zero hermes-core changes.** 2. **`app/androidApp`** — native Kotlin + Jetpack Compose client. 3. **`app/desktopApp`** — Kotlin + Compose Multiplatform client that *shares* - the Android app's code and is "tweaked" for a big screen. + the Iris app's code and is "tweaked" for a big screen. -The Android and Desktop clients live in **one Compose Multiplatform Gradle +The Iris Android and Desktop clients live in **one Compose Multiplatform Gradle project** (`app/`) with a shared KMP module (`app/shared`). --- diff --git a/docs/diagrams/architecture.mmd b/docs/diagrams/architecture.mmd index 1559f2d..be3afc8 100644 --- a/docs/diagrams/architecture.mmd +++ b/docs/diagrams/architecture.mmd @@ -6,8 +6,8 @@ flowchart TB AGENT["Agent core
(run_agent.py)"] SESS["Sessions
(SQLite + FTS5)"] CRON["Cron scheduler"] - subgraph PLUGIN["android PLATFORM PLUGIN"] - ADAPTER["AndroidAdapter
(BasePlatformAdapter)"] + subgraph PLUGIN["IRIS PLATFORM PLUGIN"] + ADAPTER["IrisAdapter
(BasePlatformAdapter)"] OUTBOX["Outbox (SQLite)
+ sync cursor"] PUSH["push.py
FcmBackend / NtfyBackend"] MEDIA["media.py
cache + chunk stream"] @@ -33,7 +33,7 @@ flowchart TB end subgraph DEVICES["Clients"] - PHONE["ANDROID APP
(Kotlin / Compose)
WS client + ExoPlayer + FCM"] + PHONE["IRIS APP (ANDROID)
(Kotlin / Compose)
WS client + ExoPlayer + FCM"] DESKTOP["DESKTOP APP
(Compose Multiplatform)
WS client + tray + desktop player"] end diff --git a/docs/setup.md b/docs/setup.md index b8eb95a..d379f78 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -56,7 +56,7 @@ hermes gateway # or: hermes gateway restart after config changes > the LAN, re-run `hermes gateway setup` (or edit `~/.hermes/.env`) and set > `IRIS_WS_HOST` to the host's LAN IP (e.g. `192.168.1.10`). -## 2. Android app +## 2. Iris app (Android) Build and install (ADB device connected):