Repository navigation
[compass] Fix: a desktop action cut short by its deadline answers with a bare "A task was canceled." - #32
Merged
Conversation
…A task was canceled."
DesktopLease stops a desktop action a second before its caller gives up.
An action that doesn't size its work by timeoutMs, or one still waiting for
the desktop behind an earlier action, was cancelled, and the pipe handler
turned the exception into "TaskCanceledException: A task was canceled.". The
reply arrived in time but didn't say the request ran out of time, or whether
anything had run.
HandleAsync now answers the deadline's own cancellation with errorCode
timed_out, the time the request had, and started: false ("Nothing was done")
for a request that never got the desktop, or started: true ("Part of it may
have run") for one stopped partway. A stopping seat still cancels as before.
A quick check ("agent deadline replies") covers both cases, the desktop
staying usable afterwards, and the stopping seat.
Reported in ANODE-BUGS.md as B-023.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…log (B-023) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ws from Both of tonight's fixes inserted at the top of Unreleased and would conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unsent requests From the second review of this PR: - A read-only action stopped partway (seat_wait, observe, screenshot) now says nothing changed and it is safe to repeat, from the tools' read-only hints; a cut-short exec.start points at seat_job action=list; only the rest says "Part of it may have run". - A request whose time runs out before it is sent at all (in JsonPipeClient's queue, or the daemon's forwarding with almost no time left), the usual "never ran" case through the daemon, also answers errorCode timed_out with started: false. - The seat host logs each timeout again, through the lease's record line. - The check counts dispatches, so "Nothing was done" is proven, and covers the read-only and exec.start wording and the log lines; the transport checks require the unsent requests' errorCode and started. - PROTOCOL: "once started" for operations that bound their own work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…art; NotSent's doc in its place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Compass review: ready to merge (merged by compass-merge, 2026-10-10)
|
skulitom
added a commit
that referenced
this pull request
Oct 10, 2026
#31 and #32 - scripts/test-chrome-form.ps1: the window's process went into $chrome, which in PowerShell is the same variable as the -Chrome parameter, so the session check always failed and the final report named a process instead of chrome.exe. It is now $chromeProcess. - #31 (B-025) and #32 (B-023) merged before this candidate, so they ship in 0.11.2: the release notes list both, RELEASE-READINESS drops them from "Known and open", and the check count is 99. - The changelog, readiness record and release-notes anchor date 0.11.2 to 10 October, when its contents were fixed again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
skulitom
added a commit
that referenced
this pull request
Oct 10, 2026
…e launch within days (#30) * [compass] Anode 0.11.2 release candidate - Version 0.11.2 in Anode.csproj, server.json, the MCPB manifest and the Claude Code plugin; CHANGELOG's Unreleased section becomes 0.11.2. - .github/RELEASE_NOTES.md: what's new in 0.11.2, known issues, upgrade. - docs/RELEASE-READINESS.md: a 0.11.2 section with what was checked without a seat, the owner's live check as exact commands (about 25 minutes), what stays covered only by stand-ins, and the known open bugs. - scripts/test-chrome-form.ps1: an opt-in live check for #28 and #29 on a local Chrome page (text field set_value read-back, <select> set_value failing instead of reporting success, the open list observed once). Package manifests, INSTALL.md's pinned example and the README's known issues change after the release, so main never points at a release that doesn't exist yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * [compass] 0.11.2 candidate: review fixes - test-chrome-form.ps1: count Find-Control's results through @(...), since Windows PowerShell 5.1 gives a single PSCustomObject no Count; start Chrome inside the try, and clean up every Chrome process it started. - RELEASE_NOTES: link the validation record on main, where the results are added after the release. - RELEASE-READINESS: say which PRs are in scope; stop if no File Explorer window appeared. - README: the 0.11.1 known issues now say 0.11.2 fixes them, which stays true inside the 0.11.2 package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: align pinned installer example with 0.11.2 * [compass] 0.11.2 candidate: fix test-chrome-form's Chrome variable; add #31 and #32 - scripts/test-chrome-form.ps1: the window's process went into $chrome, which in PowerShell is the same variable as the -Chrome parameter, so the session check always failed and the final report named a process instead of chrome.exe. It is now $chromeProcess. - #31 (B-025) and #32 (B-023) merged before this candidate, so they ship in 0.11.2: the release notes list both, RELEASE-READINESS drops them from "Known and open", and the check count is 99. - The changelog, readiness record and release-notes anchor date 0.11.2 to 10 October, when its contents were fixed again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Report
From Compass's ANODE-BUGS.md inbox (not in this repo), entry B-023 (filed 2026-10-07 by compass-anode-fixer, from the second review of #24): a desktop action cut short by its deadline answers with a bare
"TaskCanceledException: A task was canceled.". Since #24 the reply arrives in time, but it says neither that the request ran out of time nor whether anything ran, which an agent needs to know before it repeats an action.Root cause
DesktopLease.HandleAsyncstops a desktop action a second (or an eighth of a shorter time) before its caller gives up (#24). An admitted action that outlasts the time its request has left is cancelled through the deadline token: for example aseat_wait(10 swaitMsby default) that the daemon forwards with less than 10 s left after it waited behind a longseat_displaychange;DesktopWaitrethrows the cancellation when it comes from that token. So is a request still queued in the seat host for the desktop behind an earlier action. Both throwOperationCanceledException, which reachedJsonPipeServer.ServeAsync's catch-all and became"TaskCanceledException: A task was canceled.".Fix
HandleAsynccatches the cancellation when it is the deadline's own (deadlinecancelled, the seat's stop token not) and answerserrorCode: "timed_out", the time the request arrived with, andstarted:{"ok": false, "errorCode": "timed_out", "started": false, "error": "The request ran out of its 800 ms while it waited behind an earlier desktop action, so it never started. Nothing was done."}With
started: truethe text depends on what the action does:seat_wait,seat_observe,seat_screenshot, ...): "It only reads the desktop, so nothing changed, and it is safe to repeat.";exec.start: "The command may have started: look for it with seat_job action=list before starting it again.";A request whose time runs out before it is sent at all (in
JsonPipeClient's queue, or when the daemon would forward it with almost no time left), the usual "never ran" case through the daemon, now answerstimed_outwithstarted: falsetoo, with its old message ("... while it waited; nothing was sent"). A request that was sent and then timed out is unchanged, with nostarted, since it may have run.A stopping seat (
shutdown, Stop) still cancels as before. Once started, actions that bound their own work by the time keep their own failures (typing_stopped,display_restoring). The seat host logs each timeout (the lease's record line), as the catch-all used to.docs/PROTOCOL.md(request deadlines) anddocs/TROUBLESHOOTING.md("A command timed out and the viewer is still connected") describetimed_outandstarted. One CHANGELOG entry. MCP clients get the failure as before:isError: truewith the whole object,errorCodeandstartedincluded, instructuredContent.How it was tested
agent deadline replies(injected dispatch, no seat):timed_out,started: false, "800 ms" and "Nothing was done", and is never dispatched (a counter);started: true, "1.5 s" and "may have run";desktop.waitstopped partway says "nothing changed", not "may have run"; anexec.startpoints atseat_job action=list;pipe queue deadlineandpipe forwarded time leftrequiretimed_outandstarted: falseon unsent requests;pipe late replyrequires nostartedon a request that timed out after it was sent.agent queue and disconnect);TaskCanceledException: A task was canceled.;exec.startworded as input;dotnet build -c Debugandselftest --quick: 98/98 on the final commit.scripts\build.ps1 -QuickTest -OutputDirectory artifacts\pkg-build: 98/98 on429254f, and documentation links, anchors and tool names consistent.anode-controlpipe was not touched.2793ea0: no P1. It raised one P2 (the "may have run" advice was wrong for read-only actions such asseat_wait, and a cut-shortexec.startdidn't point at its job) and four P3s: the doc overstated whenstarted: falseappears, since through the daemon the never-sent case ended in the pipe client; "report their own failure" holds only once started; the seat host no longer logged these; and the check didn't prove the queued request was never dispatched. All fixed in8704adcand429254f.bin/codex-review.sh,sandbox: read-only) on429254f: "No actionable regressions were found in the diff or affected call paths. Deadline handling preserves shutdown cancellation and conservatively distinguishes unsent requests from potentially executed actions."Needs a manual check in a seat
Not needed for review: the lease gate and the pipe client are covered with injected stand-ins. Reaching the seat-host case in a real seat needs a wait that outlasts the time its request has left, as above (a long
seat_typedoes it only when a busy program stretches the typing well past its 45 s plan, since a wait behind typing that keeps to the plan still has about 15 s).Merge note
It merges cleanly with main, with #30 (the 0.11.2 candidate) and with #31. If #30 merges first, git keeps this CHANGELOG entry inside the
0.11.2section, which ships without this fix: move it under a new## Unreleasedheading above## 0.11.2when merging main in.🤖 Generated with Claude Code