Repository navigation
Hermes Android v3.2.4
Stable release covering everything since 3.2.3. Base build 3032; ABI splits 30321 / 30322 / 30323, each above the highest previously distributed split (3.2.4-rc.2's 30313), so this installs in place over 3.2.3 or either 3.2.4 candidate. Package and signing certificate are unchanged — install over the existing app; do not uninstall or clear app data.
Application code is byte-identical to the tested v3.2.4-rc.2; only release identity and notes differ.
Scheduled jobs are visible before they run (#259)
Crons previously listed cron run conversations, so a job scheduled for next week showed nothing until after its first run. Crons now opens on Upcoming, listing scheduled job definitions with enabled/disabled state, schedule, next run and target conversation where the payload supplies one. History keeps the previous run browser, and the full cron manager still owns every schedule mutation — creating or deleting a job there re-reads Upcoming on return.
Next-run times always state their zone. The schedule payload carries numeric UTC offsets rather than named IANA zones, so a next run renders like Next: 2026-11-09 09:00 (UTC+11:00); where no zone information exists the app says so rather than assuming the phone's zone. A connection with no Dashboard route is told scheduled jobs need one, kept distinct from an empty list.
Configurable server-side Projects root (#232)
Projects created by the app landed under the server's conventional <home>/Projects, while TUI-created projects often live elsewhere, so neither side saw the other's folders.
More → Projects folder on the server now sets the Projects root per saved connection. The default is unchanged, so existing setups behave exactly as before until you use it; a dashboard locked_root still outranks the local choice and shows read-only. Projects → Add an existing folder enumerates server folders, filters out paths already claimed by a registered Project, and adopts your choice through the existing project-creation contract. Where a host doesn't expose that listing route, the app says so and offers manual path entry rather than pretending to have scanned.
Limits: changing the root does not move existing Projects; enumeration covers direct non-hidden children rather than recursing; manual paths get syntactic validation only; server-side symlinks are not resolved.
Ukrainian and in-app language selection (#255)
Ukrainian joins the shipped locales, with a persistent in-app language selector — pick any generated locale or follow the system default, and the choice survives restarts and configuration backup restoration.
Correction: this merged after the v3.2.3 tag, so despite appearing in the 3.2.3 changelog it is absent from that release's APKs. 3.2.4 is the first stable release that actually contains it. Contributed by @simplaerai-sv, original commits preserved.
Clearer API-only send refusals (#253)
On a connection holding only an API-server key, sending into a Dashboard-owned chat is refused by the gateway with an in-band permission_denied; the app previously showed only the bare refusal. The terminal notice now appends what to check while preserving the server's wording verbatim, phrased conditionally — adding Dashboard credentials may allow the send, and the server may equally be refusing deliberately. Send routing, the principal used, the attach gate and retry behaviour are all unchanged, and no prompt is resent.
Lighter background refresh on the chat list (#149)
The visible-pane refresh ran a full aggregate read every ten seconds, including the dashboard's archived=only paging, even on filters that render no archived rows. The passive refresh is now scoped to the authority the selected surface displays. Over three ticks in fixtures, archive requests fall 8 → 2 on Chats and 10 → 4 on Crons, leaving only the initial scan. Archived keeps its full-scope refresh and fetches immediately when selected; previously loaded archived rows, device-local pins and Quick Chat records survive scoped ticks; explicit refreshes keep their scope.
Also included
- Widget coverage pinning API-server versus Dashboard principal routing on the send path (#254). Test-only.
- A Buy Me a Coffee link at the top of the README (#263) — optional, gates nothing.
Verification
flutter analyze --fatal-infosclean; 5,548 tests passed, zero failures, zero skipped, every started test finished.- Published APKs downloaded and re-verified: package
com.hermesagent.hermes_android,versionName 3.2.4, codes30321/30322/30323, matching ABIs, production signer475baf43…f592fb, hashes matchingSHA256SUMSand every GitHub asset digest and size. scripts/verify_release_apks.pyfrom a checkout at the publication commit: exit 0, 22 packaged-blob checks per APK.- Source bundle manifest names commit
001994d6and all three published APK hashes; inner archive digest matches.
Not verified
No on-device or emulator acceptance. No live multi-timezone server, no multi-root server, and no real gateway authorisation reproduction. The gates above are source and artefact checks, not field testing — please report anything that misbehaves on real hardware.
Full notes: docs/releases/3.2.4.md · CHANGELOG