Skip to content

feat(android): hide thinking control and gate sends for models without reasoning support#101002

Merged
steipete merged 1 commit into
mainfrom
feat/android-thinking-gating-nash
Jul 7, 2026
Merged

feat(android): hide thinking control and gate sends for models without reasoning support#101002
steipete merged 1 commit into
mainfrom
feat/android-thinking-gating-nash

Conversation

@steipete

@steipete steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Related: #100699

What Problem This Solves

Fixes an issue where Android chat users could set a thinking level for models that don't support configurable reasoning — the control silently did nothing, and worse, an explicit non-off level sent to such a model is rejected by the gateway (agent-command.ts throws for explicit unsupported levels), failing the send.

Why This Change Was Made

Completes the reasoning-gating pack item on Android, mirroring the iOS behavior landed in #100875. A pure fail-open helper matches the selected model ref (from the in-chat picker landed in #100798) against the gateway model catalog's supportsReasoning flag: unknown/default selections keep the control (fail open); a matched non-reasoning model hides the thinking control (context meter shows a context-only label, composer dropdown hides the entries). The send boundary applies the same rule: gated sends carry thinking: "off" without mutating the stored level, so switching back to a reasoning-capable model restores the user's preference. Queued outbox sends re-evaluate the gate at flush for the active session only; unknown queued sessions deliberately fail open and keep their enqueue-time level (commented at the site) — identical to the iOS contract.

User Impact

The thinking control on Android now appears only when it does something for the selected model, and sends can no longer fail because a stale thinking level hit a non-reasoning model.

Evidence

  • Focused Gradle suites green (30 tests + 5-test model-flip rerun): helper truth table (null/unknown/supported/unsupported), context-meter label with gating, gated send carries off while the stored level is preserved and restored on selection flip, outbox active-session gating and unknown-session fail-open.
  • corepack pnpm native:i18n:sync run; snapshot consistent at head.
  • ktlint: no findings on changed lines (full-project check red only on pre-existing violations in untouched files).
  • Structured review (codex) — clean at head.

@openclaw-barnacle openclaw-barnacle Bot added app: android App: android size: M maintainer Maintainer-authored PR labels Jul 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dbc0f96e72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

val thinking = normalizeThinking(thinkingLevel)
// agent-command.ts throws for explicit unsupported levels, so hidden controls must send off.
val thinking =
if (thinkingSupportedForSelection(_selectedModelRef.value, modelCatalog())) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate sends using the loaded session model

When Android opens or switches to an already-patched session, beginHistoryLoad resets _selectedModelRef to null and it is never repopulated from chat.history/sessions.list: the gateway emits modelProvider and model on session rows (src/gateway/session-event-payload.ts:66-67), but Android parseSessionEntry ignores those fields (apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt:1914-1949). In that scenario this check fail-opens, so a session whose persisted model is non-reasoning still sends the stored high/medium thinking level and can hit the same gateway rejection until the user re-selects the model in this process.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 10:05 PM ET / 02:05 UTC.

Summary
The PR adds Android reasoning-support gating across the chat composer, context meter, live send path, outbox flush, focused tests, and native i18n anchors.

PR surface: Source +3, Tests +36, Other +198. Total +237 across 12 files.

Reproducibility: yes. source-reproducible. Current main sends stored thinking blindly, and the PR still has source-visible unknown-metadata collapse plus a health/reconnect metadata race; I did not run a live Android device reproduction.

Review metrics: 1 noteworthy metric.

  • Optional protocol capability fields: 1 consumed: reasoning. Android UI and send behavior now depend on an optional gateway model-catalog field, so unknown-state compatibility matters before merge.

Stored data model
Persistent data-model change detected: vector/embedding metadata: apps/android/app/src/test/java/ai/openclaw/app/chat/ChatControllerModelSelectionTest.kt, vector/embedding metadata: apps/android/app/src/test/java/ai/openclaw/app/chat/ChatControllerOutboxTest.kt. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100699
Summary: This PR is the Android implementation candidate for the open mobile chat polish umbrella; the iOS/macOS sibling is already merged and the Android model picker prerequisite is already merged.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Preserve unknown model reasoning metadata instead of collapsing absence to unsupported.
  • Make active-session live sends and outbox flushes wait for retained or reloaded selected-model metadata before applying the gate.
  • [P1] Add redacted Android device/emulator proof or runtime logs showing the hidden control and downgraded send; redact private IPs, tokens, phone numbers, endpoints, and other private details.

Proof guidance:

  • [P1] Needs real behavior proof before merge: Missing: the PR body lists Gradle, i18n, ktlint, and structured-review checks only; add redacted Android device/emulator recording, terminal live output, or logs showing the after-fix behavior, then update the PR body for re-review.

Risk before merge

  • [P1] Optional gateway model rows that omit reasoning are treated as explicit no-reasoning rows, which can hide Android thinking controls and force thinking: off for capable legacy or incomplete catalogs.
  • [P1] A health/reconnect window can flush queued active-session sends before model metadata is loaded, so a stale high/medium thinking value can still reach the gateway and be rejected.
  • [P1] The PR still lacks real Android runtime proof; tests and static checks are useful but do not satisfy the external contributor proof gate.

Maintainer options:

  1. Fix Android gating semantics before merge (recommended)
    Preserve unknown reasoning metadata and make active-session live/outbox sends wait for retained or reloaded model metadata before applying the gate.
  2. Accept stricter metadata semantics explicitly
    Maintainers could intentionally treat missing Android reasoning metadata as unsupported, but that should be documented and covered as a compatibility decision.
  3. Pause for contributor proof
    Hold the PR until the author adds redacted Android after-fix proof showing the hidden control and downgraded send behavior in a real device or emulator setup.

Next step before merge

  • [P1] Manual review remains the right route because the external PR needs contributor real-behavior proof plus compatibility-sensitive source fixes before merge.

Security
Cleared: No concrete security or supply-chain concern found; the effective merge delta is Android Kotlin UI/controller/tests and native i18n metadata, with no dependency, workflow, secret, or package-execution changes.

Review findings

  • [P2] Preserve unknown reasoning metadata — apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatModelPicker.kt:23
  • [P2] Wait for model metadata before gated sends — apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt:1603
Review details

Best possible solution:

Mirror the merged iOS contract on Android: preserve true/false/unknown reasoning metadata, gate only explicit unsupported models, make live/outbox sends metadata-ready, then add redacted Android runtime proof.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible. Current main sends stored thinking blindly, and the PR still has source-visible unknown-metadata collapse plus a health/reconnect metadata race; I did not run a live Android device reproduction.

Is this the best way to solve the issue?

No. The direction matches the merged iOS sibling, but this implementation is not the best fix until Android preserves unknown reasoning metadata and waits for current model metadata before applying live/outbox send gates.

Full review comments:

  • [P2] Preserve unknown reasoning metadata — apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatModelPicker.kt:23
    The gateway schema keeps reasoning optional, but Android parses an omitted field into supportsReasoning=false; this helper then hides thinking and sends off for any matched legacy or incomplete row. Carry a nullable/unknown state and gate only explicit reasoning: false.
    Confidence: 0.94
  • [P2] Wait for model metadata before gated sends — apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt:1603
    markHealthOk() can launch the outbox flush before chat.metadata reloads. For an active session with a known non-reasoning selected model and an empty catalog, this condition fails open and can send the queued high/medium thinking value, so the first flushed turn can still be rejected.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against f3106057e62b.

Label changes

Label justifications:

  • P2: The PR targets a real Android chat UX/send failure with limited platform blast radius, but source-level blockers and missing proof remain.
  • merge-risk: 🚨 compatibility: Merging as-is could make legacy or incomplete Android model catalog rows without reasoning behave as explicit no-reasoning rows.
  • merge-risk: 🚨 message-delivery: Queued or first-after-reconnect sends can still carry unsupported non-off thinking and be rejected by the gateway.
  • merge-risk: 🚨 session-state: The effective sent thinking value can diverge from selected-model metadata and the stored user preference during metadata reload edges.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Missing: the PR body lists Gradle, i18n, ktlint, and structured-review checks only; add redacted Android device/emulator recording, terminal live output, or logs showing the after-fix behavior, then update the PR body for re-review.
Evidence reviewed

PR surface:

Source +3, Tests +36, Other +198. Total +237 across 12 files.

View PR surface stats
Area Files Added Removed Net
Source 1 8 5 +3
Tests 1 37 1 +36
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 10 283 85 +198
Total 12 328 91 +237

What I checked:

Likely related people:

  • steipete: Authored and merged the Android model picker prerequisite and iOS/macOS reasoning-gating sibling, and recent history/blame attributes the Android chat metadata/outbox baseline to his mobile chat work. (role: recent area contributor and likely follow-up owner; confidence: high; commits: d375d349c8c7, 538d4eeb77dd, e8b041278150; files: apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt, apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatModelPicker.kt, apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatScreen.kt)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-06T17:12:28.727Z sha dbc0f96 :: needs real behavior proof before merge. :: [P2] Gate sends from the hydrated session model
  • reviewed 2026-07-06T22:17:15.191Z sha d02e5a4 :: needs real behavior proof before merge. :: [P2] Preserve thinking when reasoning metadata is absent
  • reviewed 2026-07-06T23:05:26.642Z sha 0033948 :: needs real behavior proof before merge. :: [P2] Preserve unknown reasoning metadata | [P2] Load metadata before flushing queued sends
  • reviewed 2026-07-06T23:56:17.091Z sha 9b07da0 :: needs real behavior proof before merge. :: [P2] Preserve unknown reasoning metadata | [P2] Wait for reasoning metadata before gated sends
  • reviewed 2026-07-07T00:35:23.044Z sha 41a03be :: needs real behavior proof before merge. :: [P2] Preserve unknown reasoning metadata | [P2] Wait for metadata before gated sends

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 6, 2026
@steipete
steipete force-pushed the feat/android-thinking-gating-nash branch from dbc0f96 to d02e5a4 Compare July 6, 2026 21:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d02e5a4a05

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

catalog: List<GatewayModelSummary>,
): Boolean {
val selected = selectedModelRef ?: return true
return catalog.firstOrNull { it.providerQualifiedRef() == selected }?.supportsReasoning != false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve thinking when reasoning metadata is absent

When the selected model's catalog row omits the optional reasoning field, parseGatewayModels currently materializes it as supportsReasoning=false, so this new helper treats unknown metadata as an explicit no-reasoning signal. That makes Android hide the thinking control and send off for any older Gateway or catalog/plugin row that does not yet populate reasoning, even when the model supports reasoning; the gate should distinguish absent/unknown metadata from an explicit reasoning: false.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 6, 2026
@steipete
steipete force-pushed the feat/android-thinking-gating-nash branch from d02e5a4 to 0033948 Compare July 6, 2026 22:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0033948a4b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1493 to +1497
val thinking =
if (
queuedSessionKey == _sessionKey.value &&
!thinkingSupportedForSelection(_selectedModelRef.value, _modelCatalog.value)
) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delay outbox flush until model metadata is loaded

On reconnect after onDisconnected() clears _modelCatalog, markHealthOk() starts flushOutbox() before fetchChatMetadata() repopulates the catalog. For an active session already set to a non-reasoning model, this new gate sees the selected ref but an empty catalog, so thinkingSupportedForSelection fails open and the else path sends the queued high/medium value; the server's explicit thinking override path then produces the unsupported-thinking response instead of the intended turn. The active-session outbox path needs to hydrate/retain the catalog before flushing, or otherwise treat a known selected ref with missing metadata as not ready.

Useful? React with 👍 / 👎.

@blacksmith-sh

This comment has been minimized.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. label Jul 6, 2026
@steipete
steipete force-pushed the feat/android-thinking-gating-nash branch from 0033948 to 9b07da0 Compare July 6, 2026 23:39

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b07da06b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Applied at enqueue time too so durable rows never persist a level the selected model
// rejects; reconnect flushes with a cleared catalog fail open, matching pre-gating behavior.
val thinking =
if (thinkingSupportedForSelection(_selectedModelRef.value, _modelCatalog.value)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delay sends until reasoning metadata is loaded

When a health event or reconnect marks the gateway healthy, _healthOk becomes true before fetchChatMetadata() finishes, and the health-event path launches that metadata fetch asynchronously. If chat.history has already populated a selected non-reasoning model but _modelCatalog is still empty/cleared, this check treats the missing catalog as supported and sends the stored high/medium override, so the first send in that window can still hit the gateway's unsupported-thinking rejection instead of being downgraded to off; the known-selected/metadata-missing state needs to block or wait rather than fail open.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the feat/android-thinking-gating-nash branch from 9b07da0 to 41a03be Compare July 7, 2026 00:26
@steipete
steipete force-pushed the feat/android-thinking-gating-nash branch from 41a03be to b59f82e Compare July 7, 2026 01:45
@steipete
steipete merged commit b2cecd8 into main Jul 7, 2026
96 checks passed
@steipete
steipete deleted the feat/android-thinking-gating-nash branch July 7, 2026 02:23
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
steipete added a commit that referenced this pull request Jul 7, 2026
…plicit intents (#101799)

* fix(android): keep cold-start gateway auto-connect from overriding explicit intents

NodeRuntime's init-time auto-connect now atomically claims the first gateway
lifecycle intent (CAS 0->1) and stands down permanently when any explicit
connect/disconnect/switch intent already exists, so a late discovery emission
can no longer override a user decision. This was also the root cause of the
CI-only flakes in GatewayBootstrapAuthTest (refreshGatewayConnection_* at
:616/:627 and switchToUndiscoveredGateway* on PRs #101002/#101387/#101396).

GatewaySession.Connection.sendRequestFrame now starts its response watcher
with CoroutineStart.ATOMIC: disconnect teardown cancels connectionJob right
after failPending(), and a DEFAULT-start watcher still queued for dispatch was
cancelled without running, silently dropping the terminal UNAVAILABLE onError
owed to fire-and-forget callers (root cause of the flaky
GatewaySessionInvokeTest.disconnectReportsUnknownOutcomeForFireAndForgetRpc).

Tests neutralize runtime background work (cancel+join the runtime scope)
before arming the registry and scripting lifecycle steps, and add regression
coverage for the auto-connect intent claim.

Proof: refresh flake reproduced at iteration 1 under taskset -c 0,1 on a
Blacksmith Linux box; post-fix 3 pinned stress rounds (120/150 looped
iterations) plus full :app:testPlayDebugUnitTest (109 classes, 0 failures)
and :app:ktlintCheck green on the same box.

* chore(i18n): resync native inventory line positions after NodeRuntime edits
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
…plicit intents (openclaw#101799)

* fix(android): keep cold-start gateway auto-connect from overriding explicit intents

NodeRuntime's init-time auto-connect now atomically claims the first gateway
lifecycle intent (CAS 0->1) and stands down permanently when any explicit
connect/disconnect/switch intent already exists, so a late discovery emission
can no longer override a user decision. This was also the root cause of the
CI-only flakes in GatewayBootstrapAuthTest (refreshGatewayConnection_* at
:616/:627 and switchToUndiscoveredGateway* on PRs openclaw#101002/openclaw#101387/openclaw#101396).

GatewaySession.Connection.sendRequestFrame now starts its response watcher
with CoroutineStart.ATOMIC: disconnect teardown cancels connectionJob right
after failPending(), and a DEFAULT-start watcher still queued for dispatch was
cancelled without running, silently dropping the terminal UNAVAILABLE onError
owed to fire-and-forget callers (root cause of the flaky
GatewaySessionInvokeTest.disconnectReportsUnknownOutcomeForFireAndForgetRpc).

Tests neutralize runtime background work (cancel+join the runtime scope)
before arming the registry and scripting lifecycle steps, and add regression
coverage for the auto-connect intent claim.

Proof: refresh flake reproduced at iteration 1 under taskset -c 0,1 on a
Blacksmith Linux box; post-fix 3 pinned stress rounds (120/150 looped
iterations) plus full :app:testPlayDebugUnitTest (109 classes, 0 failures)
and :app:ktlintCheck green on the same box.

* chore(i18n): resync native inventory line positions after NodeRuntime edits
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…plicit intents (openclaw#101799)

* fix(android): keep cold-start gateway auto-connect from overriding explicit intents

NodeRuntime's init-time auto-connect now atomically claims the first gateway
lifecycle intent (CAS 0->1) and stands down permanently when any explicit
connect/disconnect/switch intent already exists, so a late discovery emission
can no longer override a user decision. This was also the root cause of the
CI-only flakes in GatewayBootstrapAuthTest (refreshGatewayConnection_* at
:616/:627 and switchToUndiscoveredGateway* on PRs openclaw#101002/openclaw#101387/openclaw#101396).

GatewaySession.Connection.sendRequestFrame now starts its response watcher
with CoroutineStart.ATOMIC: disconnect teardown cancels connectionJob right
after failPending(), and a DEFAULT-start watcher still queued for dispatch was
cancelled without running, silently dropping the terminal UNAVAILABLE onError
owed to fire-and-forget callers (root cause of the flaky
GatewaySessionInvokeTest.disconnectReportsUnknownOutcomeForFireAndForgetRpc).

Tests neutralize runtime background work (cancel+join the runtime scope)
before arming the registry and scripting lifecycle steps, and add regression
coverage for the auto-connect intent claim.

Proof: refresh flake reproduced at iteration 1 under taskset -c 0,1 on a
Blacksmith Linux box; post-fix 3 pinned stress rounds (120/150 looped
iterations) plus full :app:testPlayDebugUnitTest (109 classes, 0 failures)
and :app:ktlintCheck green on the same box.

* chore(i18n): resync native inventory line positions after NodeRuntime edits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: android App: android maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant