diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d3d577..f0770b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du ## Unreleased ### Added +- Added semantic Android beta package metadata coverage and a direct-gateway-only `v0.1.0-beta.1` build, metadata inspection, clean-install, launch, configuration, evidence, and limitations guide. - Added deterministic small-phone, landscape, and tablet layout policy with navigation rail adaptation, tablet two-pane chat, and narrow/large-font control stacking. - Added accessibility semantics for headings, panes, streaming announcements, selected/busy states, and actionable rows, plus 48dp minimum touch targets and bounded large message/code rendering with retained full-copy actions for code and tool output. - Added capability-gated direct gateway tool lifecycle decoding and compact status cards for `tool.started`, `tool.progress`, `tool.completed`, and `tool.failed` SSE events. @@ -32,6 +33,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du - Added `PROJECT_PLAN.md` as the project-controlled milestone plan. ### Changed +- Changed Android `versionName` to `0.1.0-beta.1`, monotonic `versionCode` to `10001`, and the debug APK base name to `hermes-mobile-v0.1.0-beta.1`; the npm Android build command now runs the native Gradle project without Capacitor synchronization. - Removed the Android portrait lock, enabled `adjustResize` IME behavior, and suppressed top-level screen slides when the system animator duration scale is disabled. - Kept direct artifact handoff actions gated off because the advertised gateway contract has no verified artifact URI/download capability; no upstream route or backend behavior was inferred. - Changed direct session streaming to publish reducer updates to the owning durable send coordinator while retaining the original immutable route/session lease for the entire OkHttp call. @@ -58,6 +60,10 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du - Fixed companion/mobile lint issues from missing Node globals and an unused React settings value. ### Verification +- `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` — passed; Android `:app:assembleDebug` BUILD SUCCESSFUL (37 tasks, 14 executed). +- `GRADLE_USER_HOME=/root/hermes-mobile/.gradle-user ./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest :app:assembleDebug` — passed (43 tasks, 5 executed), including `BetaPackageMetadataTest` for application ID `cloud.molberg.hermesmobile`, `versionName` `0.1.0-beta.1`, and `versionCode` `10001`. +- `git diff --check` — passed for R2 source packaging. +- R2 device installation — not run; ADB daemon sockets are sandbox-prohibited and no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. No APK was published or uploaded, and no release criterion is claimed. - R1 source-level verification: the required recovery preflight passed immediately before this run; direct JUnit execution of the cached, source-current Android unit classes passed all 61 tests, including all 4 `AdaptiveQualityTest` cases; and `git diff --check` passed. `GRADLE_USER_HOME=/root/hermes-mobile/.gradle-user ./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:compileDebugKotlin :app:compileDebugUnitTestKotlin :app:assembleDebug` was blocked before project execution by `java.net.SocketException: Operation not permitted`. ADB 37.0.0 is installed at `/opt/android-sdk/platform-tools/adb`, but its daemon cannot create the smart-socket or netlink sockets; no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target exists. No emulator/device matrix evidence exists, so R1 remains incomplete. - Full Android Kotlin/Compose main-source and unit-test compilation through cached Kotlin 2.0.21 plus direct JUnit execution — passed, 57 tests including B5 large-output bounds, advertised tool lifecycle reduction, and rotation/resume expansion restoration. - Recovery preflight for B5 — passed before this run. diff --git a/PROJECT_PLAN.md b/PROJECT_PLAN.md index 4c4dd7e..46fa9c4 100644 --- a/PROJECT_PLAN.md +++ b/PROJECT_PLAN.md @@ -24,27 +24,20 @@ Complete the Android/client contract pivot before implementing backend behavior. The next release path targets a remote upstream Hermes Agent gateway/API server directly; `apps/companion` is legacy compatibility only. -- [ ] **R1 — Execute and document the adaptive/accessibility device matrix** - - Small phone, normal phone, tablet/two-pane behavior; portrait/landscape. - - Font scaling, TalkBack semantics, contrast, touch targets, reduced motion, IME behavior. - - Verification: emulator/device matrix evidence documented in `docs/ROADMAP.md`. - - Source-level progress on 2026-07-24: removed the portrait lock, enabled resize-on-IME, added deterministic phone/landscape/tablet layout policy and tablet two-pane chat, stacked dense controls for narrow/large-font layouts, respected the disabled system animator-duration setting for top-level navigation, added headings/live regions/roles/state descriptions, raised interactive targets to at least 48dp, and bounded very large message/code rendering while retaining full-copy actions for code and tool output. - - Source verification on 2026-07-24: the required recovery preflight passed immediately before this run; direct JUnit execution of the cached, source-current Android unit classes passed all 61 tests, including all 4 `AdaptiveQualityTest` cases; and `git diff --check` passed. A direct writable-cache Gradle retry was blocked before project execution by `java.net.SocketException: Operation not permitted`. ADB is installed, but its daemon sockets are sandbox-prohibited; no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. R1 remains unchecked because no emulator/device matrix evidence exists. +- [ ] **R2 — Verify a clean `v0.1.0-beta.1` install against a direct gateway** + - On one named real device or emulator, build the source-current versioned debug APK, confirm package metadata, uninstall prior app data, install and launch it, configure an upstream Hermes gateway directly, and record the connection result plus APK SHA-256. + - Verification: required preflight and Android checks pass in the install environment; device/install evidence is recorded in `docs/ROADMAP.md`; no release or final beta criterion is claimed from source-only checks. ## Externally blocked +- **R1 — Execute and document the adaptive/accessibility device matrix** + - Source safeguards and 61 cached source-current unit tests were verified on 2026-07-24, but small-phone, normal-phone, tablet, TalkBack, contrast, motion, and IME evidence still requires a permitted real device or emulator. + - Unblock evidence is maintained in `docs/BLOCKERS.md`; do not mark R1 complete from source review alone. - **B3 — Direct gateway session contract and durable chat state** - Foundation verified 2026-07-24: repository search contract and fake implementation, capability-gated session list/create/get/delete mapping, durable selected-session/draft/pending-send storage, and duplicate-send reducer/UI protection. - Not complete: official upstream documentation still provides no session-search HTTP contract, and the configured local API server was not listening for a live compatibility exercise on 2026-07-24. - Unblock evidence is maintained in `docs/BLOCKERS.md`; do not mark B3 complete until documented search and real gateway behavior are verified. -## Later beta work - -- **R2 — Beta packaging and install guide** - - Version `v0.1.0-beta.1`, reproducible debug/beta APK build, install/run guide, known limitations. - - Publish source commit, APK, release notes, and verification result. - - Verification: clean install on a real device or emulator plus full required checks. - ## V2 backlog - Multiple server profiles and fast switching. @@ -60,6 +53,10 @@ Complete the Android/client contract pivot before implementing backend behavior. _Move finished items here with date, commit, and verification. Keep this section factual; do not claim unverified work._ +- [x] **R2a — Establish beta source packaging and install documentation** — 2026-07-24, commit `98b183e` (`build: establish Android beta packaging`). + - Set Android package metadata to semantic `versionName` `0.1.0-beta.1` with monotonic `versionCode` `10001`, enabled generated metadata coverage, and named the debug APK `hermes-mobile-v0.1.0-beta.1-debug.apk`. + - Added a direct-gateway-only build, metadata inspection, clean-install, launch, configuration, evidence, and known-limitations guide; changed the npm Android build command to run the native Gradle project without Capacitor synchronization. + - Source verification on 2026-07-24: required recovery preflight passed; `:app:testDebugUnitTest :app:assembleDebug` passed with the cached offline Gradle setup (43 tasks, 5 executed); and `git diff --check` passed. No APK was published, uploaded, or installed, so the remaining R2 device task and all final release criteria remain unclaimed. - [x] **B5 — Tool, artifact, and output experience** — 2026-07-24, commit `feat: add gated tool output experience`. - Added capability-gated decoding and reduction for the existing `tool.started`, `tool.progress`, `tool.completed`, and `tool.failed` direct gateway SSE events, with compact lifecycle/status cards for referenced and stream-only tools. - Added full-output copy plus deterministic collapsed/expanded display windows capped at 5/80 lines and 24,000 expanded characters, avoiding same-direction nested scrolling while retaining the complete output in state. diff --git a/README.md b/README.md index bdd4968..0632dd9 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ # Hermes Mobile -Android-first mobile control surface and local companion server for [Hermes Agent](https://github.com/NousResearch/hermes-agent). +Android-first native client for a remote [Hermes Agent](https://github.com/NousResearch/hermes-agent) gateway/API server, with a legacy local companion retained for compatibility. -Hermes Mobile is a self-hosted phone UI for running Hermes from Android: chat prompts, browse/edit workspace files, run terminal commands, and check companion/Hermes status over a simple HTTP API. +The current beta path is a Kotlin/Jetpack Compose thin client that connects directly to an upstream Hermes gateway. Hermes remains authoritative for authentication, sessions, streaming, tools, and backend behavior. -## What Works Now +## Current Android Beta -- Vite React mobile app with Chat, Files, Terminal, Status, and Settings screens. -- Capacitor configuration and scripts for generating/building an Android APK. -- Fastify companion server with bearer-token auth and safe workspace-root file/terminal access. -- Local setup command that generates and persists an access key. -- HTTP API communication between the mobile app and companion server. +- Native Kotlin/Compose chat, session, settings, adaptive layout, and accessibility foundations. +- Direct HTTPS gateway configuration with bearer/no-auth support and local-first routing. +- Capability-gated session streaming and tool lifecycle output. +- Semantic Android beta metadata at `v0.1.0-beta.1`. + +Build and clean-install instructions are in [Android Beta Build and Install](docs/ANDROID_BETA_BUILD.md). Device installation and the release criteria remain unverified until recorded on a real device or emulator. ## Monorepo @@ -75,26 +76,13 @@ Tap **Test connection** to validate the server and key. ## Android APK Build -Install Android Studio/SDK/JDK, then generate the native Android project and build a debug APK: +Build the native direct-gateway client without Capacitor synchronization: ```bash -npm run cap:add:android --workspace @hermes-mobile/mobile -npm run android:build:debug --workspace @hermes-mobile/mobile +npm run android:build:debug ``` -APK output: - -```text -apps/mobile/android/app/build/outputs/apk/debug/app-debug.apk -``` - -For later rebuilds after the native project exists: - -```bash -npm run cap:sync --workspace @hermes-mobile/mobile -cd apps/mobile/android -./gradlew assembleDebug -``` +See [Android Beta Build and Install](docs/ANDROID_BETA_BUILD.md) for prerequisites, the versioned APK path, package checks, clean installation, direct-gateway setup, and known limitations. ## Companion API diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index 49c0294..a45c134 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -4,6 +4,9 @@ plugins { id 'org.jetbrains.kotlin.plugin.compose' } +def betaVersionName = '0.1.0-beta.1' +def betaVersionCode = 10001 + android { namespace 'cloud.molberg.hermesmobile' compileSdk 35 @@ -12,8 +15,9 @@ android { applicationId 'cloud.molberg.hermesmobile' minSdk 23 targetSdk 35 - versionCode 2 - versionName '0.2.0-native' + versionCode betaVersionCode + versionName betaVersionName + setProperty('archivesBaseName', "hermes-mobile-v${betaVersionName}") testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } @@ -34,6 +38,7 @@ android { } buildFeatures { + buildConfig true compose true } } diff --git a/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/BetaPackageMetadataTest.kt b/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/BetaPackageMetadataTest.kt new file mode 100644 index 0000000..88391d7 --- /dev/null +++ b/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/BetaPackageMetadataTest.kt @@ -0,0 +1,13 @@ +package cloud.molberg.hermesmobile + +import org.junit.Assert.assertEquals +import org.junit.Test + +class BetaPackageMetadataTest { + @Test + fun generatedMetadataMatchesFirstBetaIdentity() { + assertEquals("cloud.molberg.hermesmobile", BuildConfig.APPLICATION_ID) + assertEquals("0.1.0-beta.1", BuildConfig.VERSION_NAME) + assertEquals(10001, BuildConfig.VERSION_CODE) + } +} diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 2d8c424..c4bc0d3 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -12,7 +12,7 @@ "cap:add:android": "cap add android", "cap:sync": "npm run build && cap sync android", "android:open": "cap open android", - "android:build:debug": "npm run cap:sync && cd android && ./gradlew assembleDebug" + "android:build:debug": "cd android && ./gradlew :app:testDebugUnitTest :app:assembleDebug" }, "dependencies": { "@hermes-mobile/shared": "file:../../packages/shared", diff --git a/docs/ANDROID_BETA_BUILD.md b/docs/ANDROID_BETA_BUILD.md new file mode 100644 index 0000000..0d0546d --- /dev/null +++ b/docs/ANDROID_BETA_BUILD.md @@ -0,0 +1,94 @@ +# Android Beta Build and Install + +This guide covers the native Kotlin/Compose direct-gateway client at version `v0.1.0-beta.1`. It does not build or require `apps/companion`, publish an APK, or complete the beta release criteria by itself. + +## Package identity + +- Application ID: `cloud.molberg.hermesmobile` +- Android `versionName`: `0.1.0-beta.1` +- Android `versionCode`: `10001` +- Debug APK: `apps/mobile/android/app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk` + +`versionName` is the user-visible semantic version. `versionCode` is an internal monotonically increasing Android package revision and must increase for every later installable build. + +## Prerequisites + +- JDK 17 or newer supported by the checked-in Android Gradle Plugin. +- Android SDK platform 35, matching build tools, and platform tools. +- Network access for the first dependency resolution, or a complete compatible Gradle cache. +- For installation, a real Android device with USB debugging enabled or a running emulator visible to `adb`. +- For use, an HTTPS upstream Hermes Agent gateway/API server and its bearer token when authentication is enabled. + +Do not run Capacitor synchronization for this client. The beta application source is the native project under `apps/mobile/android`. + +## Build and test + +From the repository root: + +```bash +cd apps/mobile/android +GRADLE_USER_HOME="$PWD/../../../.gradle-user" ./gradlew \ + :app:testDebugUnitTest \ + :app:assembleDebug +``` + +The expected APK is: + +```text +app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk +``` + +Confirm the package metadata before distributing the file: + +```bash +aapt dump badging app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk \ + | sed -n '1p' +sha256sum app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk +``` + +Expected badging includes package `cloud.molberg.hermesmobile`, `versionCode='10001'`, and `versionName='0.1.0-beta.1'`. + +The debug APK is signed with the local Android debug key. It is suitable for beta verification, not a production signing or store-release workflow. APKs and build output must remain untracked. + +## Clean install and run + +Confirm that exactly one intended target is attached: + +```bash +adb devices -l +``` + +Remove any prior installation, then install the newly built APK. Uninstalling clears existing Hermes Mobile app data and stored gateway credentials. + +```bash +adb uninstall cloud.molberg.hermesmobile || true +adb install app/build/outputs/apk/debug/hermes-mobile-v0.1.0-beta.1-debug.apk +adb shell monkey -p cloud.molberg.hermesmobile -c android.intent.category.LAUNCHER 1 +``` + +In Hermes Mobile Settings, configure the upstream gateway directly: + +1. Enter the required Remote HTTPS gateway base URL and, optionally, a Local HTTPS URL for the same trusted gateway. +2. Select bearer authentication and enter the gateway token when required, or select no authentication only when the gateway is configured that way. +3. Save and test the connection. The client probes `/health`, validates compatibility through the authenticated gateway surface, and displays the active Local or Remote route. +4. Exercise chat/session behavior only where the gateway advertises the required capabilities. + +Do not enter a legacy companion URL or companion access key. The beta path is the direct upstream Hermes gateway architecture described in `docs/DIRECT_GATEWAY_ARCHITECTURE.md`. + +## Required install evidence + +Record all of the following before claiming R2 installation verification or a beta release: + +- The source commit used for the build. +- Passing Android unit tests and APK assembly. +- `aapt` package/version output and the APK SHA-256. +- A successful clean `adb install` on a named real device or emulator. +- App launch plus direct-gateway configuration and connection result. +- Any observed limitations or failures, without treating source-only checks as device evidence. + +## Known limitations + +- R1 adaptive/accessibility verification still requires the documented real-device/emulator matrix. +- B3 remains blocked on an official session-search contract and live upstream gateway compatibility evidence. +- Direct gateway chat, streaming, tools, artifacts, and recovery remain capability-gated; unsupported or unverified routes are not inferred. +- The debug APK is not a published release artifact. No beta release exists until all release criteria in `docs/ROADMAP.md` are genuinely satisfied. diff --git a/docs/BLOCKERS.md b/docs/BLOCKERS.md index ada838a..854760c 100644 --- a/docs/BLOCKERS.md +++ b/docs/BLOCKERS.md @@ -6,6 +6,14 @@ R1 cannot be marked complete from the current sandbox. On 2026-07-24, the requir Required unblock evidence: run the required preflight and focused Android tests in an environment that permits them, then record the small-phone, normal-phone, and tablet checks in `docs/ROADMAP.md` across portrait/landscape, font scaling, TalkBack, light/dark contrast, touch targets, reduced motion, and IME behavior. Source review, `git diff --check`, and direct execution of cached test classes are supporting evidence only and do not complete R1. +## R2 — Clean beta build/install verification + +The `v0.1.0-beta.1` Android package metadata and direct-gateway build/install guide are present in source. On 2026-07-24, the required recovery preflight passed and the source-current offline Gradle `:app:testDebugUnitTest :app:assembleDebug` command passed. Installation verification cannot be completed in the current sandbox. + +ADB is installed, but the R1 evidence above confirms that its daemon sockets are prohibited and that no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. Therefore no source-current beta APK package inspection, clean uninstall/install, launch, or direct-gateway device connection was verified here. No APK was published or uploaded, and no final release criterion is claimed. + +Required unblock evidence: in a permitted environment, run the preflight and Android checks from `docs/ANDROID_BETA_BUILD.md`, record `aapt` package/version output and the APK SHA-256, clean-install on one named real device or emulator, launch the app, configure the upstream Hermes gateway directly, and record the connection result in `docs/ROADMAP.md`. + ## Stable gateway identity binding The documented direct gateway routes currently available to Hermes Mobile (`GET /health` and authenticated `GET /v1/models`) do not expose a verified stable gateway instance identifier. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index f3cc2aa..f47fb7d 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -12,6 +12,7 @@ Done: - Capability-gated session streaming binds each OkHttp call to an immutable route/session lease, parses SSE into authoritative final responses, ignores cross-session events, and reports transport failure only against the failed lease. - Chat UI supports conversation list/thread navigation, native composer, busy state, selectable replies, error bubbles, and new-chat reset. - Direct gateway compatibility contract is documented in `docs/DIRECT_GATEWAY_ARCHITECTURE.md`. +- Android source packaging identifies the first beta as `versionName` `0.1.0-beta.1` / `versionCode` `10001`, produces a versioned debug APK name, and has a direct-gateway build/install guide in `docs/ANDROID_BETA_BUILD.md`. - Legacy companion chat, terminal, and file utilities remain in the repo during migration but are not the target architecture. - Local build artifacts, Android transient build output, `.gradle-user/`, and `.dev/` are ignored. - Companion and workspace TypeScript typecheck, build, and lint pass as of 2026-07-24. @@ -22,9 +23,9 @@ Remaining for beta: - Exercise a real device or emulator against a running upstream Hermes gateway/API server. - Verify direct gateway behavior end to end beyond B2: chat request/response, session continuity expectations, streamed/final output handling, and failure recovery. - Verify or revise provisional session, streaming, tool-event, artifact, and cancellation route assumptions against official upstream docs. -- Add or run focused Android UI validation for chat/settings flows on small and large screens. +- Add or run focused Android UI validation for chat/settings flows on small and large screens in an environment with a permitted emulator or real device. - Confirm adaptive accessibility: font scaling, TalkBack labels, contrast, keyboard/IME behavior, and reduced-motion tolerance. -- Document beta install/run steps after the native build is verified. +- Build the source-current `v0.1.0-beta.1` APK, verify its package metadata, and record a clean install, launch, and direct-gateway connection on a named real device or emulator. ## R1 Adaptive/Accessibility Matrix @@ -42,6 +43,8 @@ Source-level evidence without device verification: orientation is no longer mani ## Beta Release Criteria +No beta release is claimed. Source packaging and documentation are complete, but APK assembly in this sandbox, clean installation, direct-gateway device exercise, R1, and B3 remain unverified or externally blocked. + - Native Kotlin/Compose Android app is the shipped beta client. - No WebView, Capacitor runtime dependency, fake backend, embedded secrets, or new external infrastructure is introduced for beta. - Direct gateway transport and auth are exercised against the upstream Hermes gateway/API server.