fix(ui): keep composer on Send when run-status toast expires (#88033)#91680
fix(ui): keep composer on Send when run-status toast expires (#88033)#91680tiffanychum wants to merge 3 commits into
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Close this PR as superseded: the useful Gateway/UI active-run identity fix is now carried by the clean open replacement at #100527, while this branch still includes unrelated Swift auth, outbound action, and changelog changes that should not land with the composer-state fix. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Canonical path: Use #100527 as the canonical landing path, preserve the contributor credit there, and leave #88033 open until a clean fix merges. So I’m closing this here and keeping the remaining discussion on #100527 and #88033. Review detailsBest possible solution: Use #100527 as the canonical landing path, preserve the contributor credit there, and leave #88033 open until a clean fix merges. Do we have a high-confidence way to reproduce the issue? Yes at source/proof level: current main lacks the toast-expiry identity-bound reconciliation, the linked issue reports the Send-to-Stop relapse after completion, and the PR body plus proof workflow show a red/green browser/Testbox path. I did not rerun live browser proof in this read-only cleanup pass. Is this the best way to solve the issue? No for this branch: the identity-bound Gateway/UI design is the right fix, but this PR is no longer the best landing vehicle because the clean replacement carries the same useful work without unrelated auth, outbound, or changelog changes. Security review: Security review needs attention: The branch includes an unrelated security-sensitive OpenClawKit device-token retry host-trust change, so the current PR should not be used as the landing candidate.
AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against eda9b9fb1858. |
Notes on CI status and real-behavior proof
None of those touch On real-behavior proof: this fixes a non-deterministic timing race — the composer snaps back from Send to Stop when the run-status toast expires while a completed run is still briefly marked "active" due to session-poll lag. The fix re-reconciles the composer from the current session row when the toast clears ( Because the trigger depends on the precise overlap of toast-expiry and poll-lag windows, it does not reproduce deterministically even in the Playwright e2e harness (an e2e attempt passed both with and without the fix, so it was not a valid guard and was dropped). Visual before/after therefore realistically needs a maintainer environment or a |
|
@clawsweeper re-review Requesting a fresh review. CI has since re-run and the prior |
|
🦞🧹 I asked ClawSweeper to review this item again. |
fe243ce to
a637b1c
Compare
|
Land-ready maintainer pass complete on What changed:
Proof:
Known proof gaps: none for the changed Control UI/Gateway path. GitHub CI is still completing; the repository prepare/merge guard remains the final gate. |
Co-authored-by: tiffanychum <[email protected]>
a637b1c to
eda3eb7
Compare
|
Landed the reviewed fix as #100527 in commit I rebuilt the patch on current Thank you @tiffanychum. For future contributions, keeping Allow edits by maintainers enabled gives us the best chance of applying fixups directly, though GitHub's fork update path can still occasionally prevent a clean ancestry-preserving update. |
Fixes #88033
AI-assisted: Yes (Codex)
What Problem This Solves
After a reply visibly completed, delayed session metadata could make the Control UI composer switch from Send back to Stop when the five-second terminal status expired. A later unrelated session update could restore the same stale active row again.
Why This Change Was Made
Gateway session projections now carry the deterministic ids of visible active runs, including direct agent lifecycle start and terminal events. The local-completion guard runs when the terminal status mask expires and whenever either session-state publication path can republish canonical rows, but it suppresses a row only when its sole active run id exactly matches the completed run. The identity is retained across missing/disconnected session results until Gateway publishes terminal state or a different run; no browser/Gateway wall-clock comparison or arbitrary expiry is involved.
This rewrites the original suggestion around one shared invariant, covers both SessionCapability subscription updates and direct
sessions.changedreconciliation, and fails safe when an older Gateway does not provide run identity.User Impact
Once a completed reply returns the composer to Send, stale poll data can no longer make it revert to Stop. Real follow-up runs still show Stop and retain their stream.
Evidence
main, Blacksmith Testboxtbx_01kwt3gy25f6vrxsven71k22mz: the Chromium scenario failed after toast expiry with one unexpected Stop control.ui/src/e2e/chat-run-lifecycle.e2e.test.ts(Chromium, 1/1 pass).corepack pnpm check:changed(pass).git diff --check(pass).