Skip to content

fix(android): stop the idle watchdog interrupting healthy turns - #675

Closed
BrokeSkill wants to merge 2 commits into
Codename-11:devfrom
BrokeSkill:fix/android-no-idle-interrupt
Closed

BrokeSkill wants to merge 2 commits into
Codename-11:devfrom
BrokeSkill:fix/android-no-idle-interrupt

Conversation

@BrokeSkill

@BrokeSkill BrokeSkill commented Oct 5, 2026 •

Copy link
Copy Markdown

Summary

The Android client's idle-progress watchdog armed session.interrupt after 180s
of client-visible silence and then failed the turn with "Gateway turn timed
out". Silence should not equal death: a slow provider prefill on a large prompt, a long
tool call, or a quiet background run all look like that while the turn is
healthy. The interrupt carries no reason, so the Gateway logs it as "explicit
stop requested" and the transcript records "Operation interrupted" even though
the user never pressed Stop. Overnight and background runs were my usual
victims in testing, and no agent ever caught it as theres no record.

This removes the client-side kill. The watchdog now only logs the quiet and
keeps waiting; the server owns turn liveness, and the existing
settleFromAuthoritativeSessionState path settles a turn the Gateway reports as
ended. A real Stop still interrupts-

Related: #668 covers the same behavior with a narrower fix (it keeps the local
stream failure and the per-kind leases). This change goes further and drops the
leases that only decided when to kill.

Changes

  • The idle watchdog no longer calls session.interrupt and no longer fails the
    stream. It is a re-arm loop that logs the quiet interval and waits.
  • Removed the per-kind leash table (watchdogTimeoutFor, the ASK_*
    constants, the compacting lease) and the compactingTimeoutMs test seam. With
    no kill, they only moved the deadline.
  • Removed the 30s post-retarget settle and the retargetedThisTurn flag; a
    rejoin after a route change uses the same watchdog as any other rejoin.
  • cancel() is unchanged: a real Stop still interrupts the Gateway turn.
  • Tests flipped from pinning the kill to pinning its absence.

Verification

  • ./gradlew :app:testSideloadDebugUnitTest --tests "com.hermesandroid.relay.network.upstream.GatewayChatClientTest" -Pandroid.aapt2FromMavenOverride=/opt/android-sdk/build-tools/35.0.0/aapt2
    on this branch rebased on origin/dev: the watchdog tests pass. After silence
    they assert no stream error, no session.interrupt, and that a late
    message.complete still lands.
  • The same command also reports one intermittent failure in
    native approval queue keeps each decision and rejects answers after session clear, a native-ask test that shares no code path with this change (the
    watchdog returns early while an ask is pending, so it never launches). It
    reproduces on unmodified dev in one of five consecutive runs and passes in
    isolation, so it is a pre-existing timing flake rather than this change.
  • Not run: lint, the full unit suite, on-device check, the Gateway contract
    lane.

Screenshots

No visual change.

Compatibility / risk

  • Client-only. Uses the existing Gateway session state and events; no relay
    plugin or host contract change.
  • A turn that never ends server-side and never emits events now stays running
    in the app until the Gateway reports it ended or the socket drops, instead of
    dying at 180s. That is the intended trade: the server owns the turn.
  • Rollback is a revert; no migrations or stored state.

Lineage / contributor credit

Checklist

  • Target branch is dev
  • Scope is focused and related issues/PRs are linked
  • Android changes: focused tests ran (see Verification)
  • Translation changes: N/A
  • Server/plugin changes: N/A
  • Desktop changes: N/A
  • Docs/site changes: N/A
  • UI changes: No visual change
  • Commit messages follow Conventional Commits
  • CHANGELOG.md is updated
  • Public writing hygiene checked
  • Salvaged/replacement work: N/A

@BrokeSkill
BrokeSkill marked this pull request as ready for review October 5, 2026 21:14
@hermes-relay-triage hermes-relay-triage Bot added area:android Kotlin app needs-maintainer-review Automated triage exhausted; needs a human labels Oct 5, 2026
@hermes-relay-triage

Copy link
Copy Markdown

🤖 Hermes-Relay automated PR intake

Thanks for contributing the Android watchdog change! The PR targets dev, includes all template sections, links related work in #668, and documents compatibility, rollback, and no visual change. Verification includes an exact focused-test command, reported watchdog passes, and a separately reported intermittent native-ask failure with baseline reproduction details.

The remaining evidence is Android lint (or a rationale for skipping it) and the relevant Gateway fixture/current-upstream conformance checks for the turn-liveness change. Please add exact commands/results when available, or explain why a lane is not applicable. The body already explicitly identifies the checks that were not run; intake has not independently verified the reported results.

A maintainer will review the verification gaps, relationship to #668, and implementation.

@Codename-11

Copy link
Copy Markdown
Owner

Sorry for the interruptions and the slow turnaround, @BrokeSkill. I kept both of your commits intact in #694 and added recovery for missed events. Closing this one in favor of the combined fix. Thanks for digging into this!

sacgsxr pushed a commit to sacgsxr/hermes-relay that referenced this pull request Oct 16, 2026
Extend the preserved PR Codename-11#675 commits with read-only quiet probes, exact unsolicited settlement, passive reconnect and shutdown, native ask replay, and missing-final history reconciliation. Cover owner and observer paths through real Gateway transport and rendered fixture tests. Update current-upstream conformance for extracted helpers and additive requests.

Adapt cancellation-only diagnostics from PR Codename-11#668. Supersede PR Codename-11#662's eventual interrupt lease; quiet tools use server-owned liveness instead.

Co-authored-by: ophirhan <ophirhan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:android Kotlin app needs-maintainer-review Automated triage exhausted; needs a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants