Repository navigation
fix(*): make the machine form's connect cancellable and bounded, and reword 'No link' - #1043
Conversation
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: the five-minute ceiling can still hang while sending the cancellation request.
I found one blocking issue, marked inline. I covered the repository rules and CONTEXT vocabulary, the complete diff, the runtime and web callers (including the gateway/transport), relevant history, compatibility of the existing RPC shape, whether tests were weakened, and the source/store architecture boundary.
Verification: PYTHONUTF8=1 uv run --frozen --python 3.12 pytest tests/test_rpc_subagents.py -x passed (168 tests); the three affected web test files passed (209 tests); web type-check, lint, and RPC generation checks passed (lint reported four pre-existing warnings in untouched files); source-language and large-file gates passed; git diff --check passed.
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
The new commit fixes the previously reported boundedness defect: the grace timer is armed before the stop RPC is sent, and the regression test proves both the ceiling and manual-cancel paths return even when both calls remain unresolved. I rechecked the full resulting diff and the new delta against AGENTS.md and CONTEXT vocabulary, callers and transport behavior, relevant history, backward compatibility, test integrity, and the documented source/store architecture; I found no new issue worth raising.
Verification: the three affected web test files passed (210 tests); web type-check, lint, and generated-contract checks passed. Lint reported only four pre-existing warnings in untouched files, and git diff --check passed.
|
No blockers in the reviewed scope. Scope: I reviewed only the This is the PR's second head. The blocking finding on the previous head was gloryfromca's: Confirmed findings:
Verification:
Checked and deliberately not reported: the wider reading of |
|
Windows compatibility review (head Scope: Inspected all 16 changed files ( Findings
Verification and limitations
Exact verification commands# suite: 27 passed, 0 failed, 0 errors, 0 skipped; exit 0
# Working directory: C:\Users\livxu\AppData\Local\Temp\raven-windows-review\045a318bc8c44406a153d58b0fe1b6be\pr1043\source\head
uv run pytest tests/test_rpc_subagents.py -k 'cancel or proving or proves or test_running or machine' -n 0 -x --tb=short --basetemp 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\045a318bc8c44406a153d58b0fe1b6be\checks\1043-suite\pytest' --junitxml 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\045a318bc8c44406a153d58b0fe1b6be\checks\1043-suite\junit.xml' |
|
Not a blocker (review of Severity of this one finding, not a verdict on the pull request. Any blocking findings from this pass are review threads on the changed files; GitHub renders those collapsed, as a file name with no text.
|
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: resolve the open post-ping cancellation race before this merges.
The newly opened review thread changes my standing stance from clean to blocker. It reports a measured path where _RUNNING is cleared after the proof ping, capability recording continues outside the cancellable run, subagents.test_cancel returns false, and the UI nevertheless announces that nothing was written before the add lands. I am not re-grading another reviewer's blocker; while that thread remains unresolved, my earlier clean verdict no longer reflects the whole record.
Verification on the unchanged head: tests/test_rpc_subagents.py passed (168 tests), and the three affected web test files passed (210 tests). Those green suites do not exercise the newly reported post-ping capability-record window.
f14d0f3 to
cb1be2c
Compare
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: the two open post-ping cancellation threads still need their authors or a maintainer to settle them on this head.
The code on cb1be2c8be38 addresses the reported path: capability recording now remains inside _RUNNING, so cancellation reaches the entire pre-write run, and the web form reads cancelled: false, keeps waiting, and guards late corrections by form press. I found no additional defect in this revision. I cannot downgrade or resolve blockers opened by other reviewers, and both threads remain open, so the whole record is still blocking until their owners or a maintainer clear them.
I reviewed the full main-to-head diff and the five new fix/test/docs commits against AGENTS.md and the Runtime/Web CONTEXT vocabulary, callers and transport behavior, relevant history, backward compatibility, test integrity, and the source/store architecture. Verification passed: tests/test_rpc_subagents.py (171 tests), the three affected web test files (217 tests), web type-check, lint, generated-contract check, source-language gate, large-file gate, and git diff --check. Lint reported only four pre-existing warnings in untouched files.
cb1be2c to
4dab418
Compare
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: the two existing post-ping cancellation threads still need their authors or a maintainer to settle them on this head.
I reviewed the new 4dab41806aea revision against github/main, including the project rules and domain context, the full diff, the delta from the previously reviewed implementation, affected callers, history, backward compatibility, and whether tests were weakened. I found no new code defect: capability recording remains inside the cancellable server run; a false stop answer keeps waiting; a missing or failed stop answer now reports an unconfirmed cancel rather than claiming nothing was written; and a later true stop answer or the connect's own cancelled refusal corrects that note.
The two existing blocker threads from @0xKT and @LivXue remain open. Their original concrete failure appears addressed by this revision, but those findings are theirs to close or downgrade, so the whole-record stance remains blocking until they or a maintainer settle them.
Verification on this exact head: uv run --frozen --python 3.12 pytest tests/test_rpc_subagents.py -x (171 passed); the three affected web test files (220 passed); type-check; generated-contract check; source-language check; large-file check; and git diff --check all passed. Lint completed with zero errors and four pre-existing warnings in untouched files.
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: the two existing post-ping cancellation threads still need their authors or a maintainer to settle them on this head.
I reviewed 2d8d7c81f278, including the project rules and domain context, the full PR diff, the two-commit delta from the prior reviewed head, affected callers and timing bounds, history, backward compatibility, and whether tests were weakened. I found no new defect. The ten-minute ceiling exceeds the explicit 420-second proof-plus-capability request budget, and the server now accurately distinguishes cancellation during capability recording from cancellation before the proof answer.
The existing blocker threads from @0xKT and @LivXue remain open without a reply or settlement. This revision still appears to address their reported failure, but those findings belong to their authors or a maintainer to close or downgrade.
Verification on this exact head: the RPC suite passed 171 tests and the three affected web files passed 220 tests. Type-check, generated-contract, source-language, large-file, and diff checks passed. Lint completed with zero errors and the same four warnings in untouched files.
|
Windows compatibility re-review at head Inspected the complete 16-file PR diff and the revision changes during this run: RPC add/toggle/update and cancellation callers, probe/ACP/CLI cleanup paths, machine form state/source/components, contracts, translations, docs, tests, and discussions. No newly introduced Windows compatibility defect was found in this scope. Native Windows verification (Python 3.13.12, Node 25.9.0):
These results add Windows evidence to the existing post-ping cancellation discussion. They are a scoped compatibility report, not a general merge verdict. Limits: UTF-8 mode was enabled. The full RPC suite was not completed: earlier broad runs at the superseded head hit two Unix-oriented fixture assumptions (an extensionless shell shim and Exact verification commands and resultsEach Python invocation used an isolated uv environment and temporary profile/Raven/OAuth/temp directories. UTF-8 mode was enabled and imports were asserted to belong to the selected checkout. $run = 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4'
$env:UV_PROJECT_ENVIRONMENT = Join-Path $run 'python-env'
$env:UV_PYTHON = '3.13'
$env:PYTHONUTF8 = '1'
# 1043-current-changed: 8 passed, 0 failed, 0 skipped; exit 0
Set-Location -LiteralPath 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current'
$env:PYTHONPATH = 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current' + ';' + (Join-Path $run 'probes')
uv 'run' '--frozen' '--no-sync' 'pytest' 'tests/test_rpc_subagents.py::test_cancel_stops_the_run_that_proves_an_add_and_the_add_writes_nothing' 'tests/test_rpc_subagents.py::test_cancel_reaches_the_capability_record_after_the_answer_and_the_add_writes_nothing' 'tests/test_rpc_subagents.py::test_a_test_is_refused_while_a_connect_records_the_capabilities_of_the_same_name' 'tests/test_rpc_subagents.py::test_cancel_stops_the_run_that_proves_a_switch_on_and_the_roster_says_it_is_running' 'tests/test_rpc_subagents.py::test_a_test_is_refused_while_a_connect_proves_the_same_name_and_the_connect_lands' 'tests/test_rpc_subagents.py::test_a_connect_is_refused_while_a_test_of_the_same_name_runs_and_asks_the_agent_nothing' 'tests/test_rpc_subagents.py::test_a_connect_whose_own_call_is_cancelled_ends_its_run_and_writes_nothing' 'tests/test_rpc_subagents.py::test_a_cancelled_connect_refuses_on_the_wire_with_cancelled_in_its_data' '-p' 'no:randomly' '-n' '0' '-x' '--tb=short' '--basetemp' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\checks\1043-current-changed\pytest' '--junitxml' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\checks\1043-current-changed\junit.xml'
# 1043-current-windows: 1 passed, 0 failed, 0 skipped; exit 0
Set-Location -LiteralPath 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current'
$env:PYTHONPATH = 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current' + ';' + (Join-Path $run 'probes')
uv 'run' '--frozen' '--no-sync' 'pytest' 'tests/integration/test_subagent_connect_windows_real_process.py' '-m' 'integration' '-p' 'no:randomly' '-n' '0' '-x' '--tb=short' '--basetemp' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\checks\1043-current-windows\pytest' '--junitxml' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\checks\1043-current-windows\junit.xml'
$bare = Join-Path $run 'objects.git'
git --git-dir=$bare diff --check 8a7ea1ccf6da6114b5f8670e18228e9f3a23e940..a773b5a124652b53d99d085d35a82a4ecef3e5f8 # exit 0Web verification commands# 1043-web-tests: exit 0
Set-Location -LiteralPath 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current/ui-web'
npm.cmd 'test' '--' 'src/features/extAgents/AgentsBody.test.tsx' 'src/features/extAgents/ExtAgentsPage.test.tsx' 'src/features/extAgents/store.test.ts' '--no-file-parallelism'
# 1043-web-types: exit 0
Set-Location -LiteralPath 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current/ui-web'
npm.cmd 'run' 'type-check'
# 1043-web-generated: exit 0
Set-Location -LiteralPath 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\e1c5fcc69a324287bf90beac9314f3a4\pr1043\head-current/ui-web'
npm.cmd 'run' 'gen:check'Dependencies reused this trigger's isolated installation after byte-identical package.json/package-lock.json checks; source imports and commands used the current checkout. |
…reword 'No link' The machine form's connect showed one static line and one disabled button for as long as the server took -- legitimately the node launch plus a 120 s start window plus 60 s for the answer -- and for ever when the socket went quiet without a close event (seen once on 2026-10-20). And every card said "No link" when the tab opened, which read as a fault on healthy machines. Server: the proof prompt a subagents.add, subagents.toggle or subagents.update sends is held in _RUNNING under the entry's name, the map a test's run is held in (_run_once), so subagents.test_cancel reaches it; the connect then refuses with cancelled: true in its error data and writes nothing. One run per name at a time: a Test during a connect's proof is refused as a second test is, a connect during a Test is refused before anything is spent, and the row reports test_running meanwhile. A cancel of the call itself keeps unwinding as cancelled. Page: the form's line counts the seconds, the hint says what the wait is for and its limit, Cancel stops the run server-side, a cancelled run is said as a cancel rather than as the agent failing and is not kept on the row, and after five minutes with no answer the form stops the run itself and names the Agents page; a landing that still arrives is toasted. The resting state reads "Not connected; the link opens when work is sent". Contract summaries of the four subagents.* methods updated (no shape change); i18n keys added; docs en/zh, CHANGELOG and CONTEXT updated.
…wait The wait on a connect's write ends on Cancel or at the ceiling, and then stops the run server-side. That stop request was awaited before the grace timer was even created, and the transport gives a call no timeout of its own -- so on the socket that went silent without closing, the case the ceiling exists for, the wait hung on the stop request exactly as it had hung on the connect, and the form stayed busy for ever a second time. The stop is sent, not awaited; the grace runs from that moment, whatever becomes of the call. A case holds a connect and a stop that never answer, on the ceiling's path and on the Cancel press alike.
An acp row that answered the gate's prompt is measured before the add, switch or update writes, and that record is a second launch and handshake of up to the preset's start window. It ran after _run_once's finally had taken the name out of _RUNNING, so a subagents.test_cancel pressed then answered cancelled: false and the caller went on to write the entry the form had just said was not written. The record now runs inside the same held task as the prompt: a cancel during it ends the handshake and the gate refuses with cancelled: true, and a Test pressed meanwhile is refused as during the prompt. A record that fails is still logged and the connect still stands on the ping.
…lled The machine form's wait sent its stop request and dropped the answer, so a Cancel that found nothing running still ended, after the grace, in "Cancelled; nothing was written" with Connect enabled, while the connect went on to write the entry. The stop is still sent without being awaited, and its answer is now raced against the grace. When it says nothing was running, the connect is past the point where it can be cancelled: the form says it is too late to cancel, drops the Cancel it cannot honour, and keeps waiting for the connect's own answer up to the ceiling (one more grace when the ceiling sent the stop). Unanswered by then, the wait ends as "Not stopped", which says the entry may have been written. A false answer that arrives after the grace turns a cancel or timeout note into that one, and a connect that lands after the wait ended takes the note down besides the toast. New i18n keys in en and zh; the TUI catalogue is regenerated.
…lable The changelog entry, the machines page in en and zh, and the CONTEXT entry now say that a connect's capability record runs inside the run a Cancel reaches, and that a Cancel which finds nothing left to stop is said as too late to cancel while the form waits for the connect to finish.
A stop's answer can arrive after its wait has ended. Two cases pin what it may still change: an earlier press's late answer leaves a later press's note alone while that press's own answer still corrects it, and a false answer that arrives after the connect landed does not put the too-late note back.
…e guard subagents.test_cancel's docstring now names the capability record as part of the run it reaches, as its contract summary does, and the page's cancelRun says what false leaves the connect in. cancelConnect no longer checks the too-late state: the form draws no Cancel then, so nothing calls it.
… the run The machine form's wait read the stop's answer for a false, but a Cancel whose grace ended with the stop still unanswered, or with the call failing, was still said as "Cancelled; nothing was written". Only a stop that answered it stopped the run knows that, so such a Cancel now ends as "Cancel not confirmed", which says the entry may still be written and where to look. A stop that answers after the grace corrects the note: true turns it into the cancel, false into the too-late note as before. The timeout note no longer says the run was stopped, only that the form asked it to stop. New i18n keys in en and zh; the TUI catalogue is regenerated.
…itten The changelog entry and the machines page in en and zh now say that a Cancel whose stop gives no answer is said as not confirmed, and that the five-minute ceiling asks the run to stop rather than saying it stopped it.
A Cancel whose stop failed ended as "Cancel not confirmed", and a refusal from the connect itself that said it was cancelled, arriving after the grace, left that note standing although it is the server saying nothing was written. It now turns the note into the cancel, as a late true answer from the stop does. The hint shown while the connect runs no longer promises that Cancel writes nothing: it says Cancel asks the run to stop and the form says whether anything was written. The TUI catalogue is regenerated.
The machine form stopped a connect after five minutes and said that was the server's own worst case, but the capability record an acp preset is measured with after it answers adds two requests of up to its start window each: 120s + 60s for the ping and 240s for the record is 420s for the slowest preset, before the link's own calls. A connect that was merely slow could be stopped by the form itself. The ceiling is now ten minutes. The hint, the timeout note, the changelog, the machines page in en and zh, and the add, update and toggle contract summaries and docstrings now count the record's time. The TUI catalogue is regenerated.
…swer A cancel that reached a connect while its capabilities were being recorded refused with "was cancelled before it answered", although the agent had already answered. The run now notes when the answer came, and the refusal says "after it answered, while its capabilities were being recorded" then. The case that pins the record's cancel now checks the whole sentence.
2d8d7c8 to
54bbdf9
Compare
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: the two existing post-ping cancellation threads still need their authors or a maintainer to settle them on this rebased head.
I reviewed 54bbdf916cf2 against the freshly fetched github/main. Range-diff shows all 12 PR commits are patch-identical to the previously reviewed revision; the only revision change is rebasing onto the newer target. I also rechecked the project rules and domain context, full PR diff, callers, history, backward compatibility, and test changes. No new defect or integration regression was found.
The existing blocker threads from @0xKT and @LivXue remain open without a reply or settlement. The code still appears to address their reported failure, but those findings belong to their authors or a maintainer to close or downgrade.
Verification on this exact head: the RPC suite passed 171 tests and the three affected web files passed 220 tests. Type-check, generated-contract, source-language, large-file, and diff checks passed. Lint completed with zero errors and the same four warnings in untouched files.
|
Windows compatibility re-review at head No new Windows compatibility issue was found in the inspected scope. Covered the complete 16-file PR diff, RPC add/update/toggle and cancellation callers, probe/ACP process cleanup, machine-form store/source/components, tests, contracts, translations, and docs. The complete diff is byte-identical to the previously inspected revision; I checked the intervening base changes and reran verification at this exact head. The post-ping cancellation discussion is resolved; the capability record remains inside the cancellable run, and the UI distinguishes false or missing stop replies. Native Windows results (Python 3.13.12 with UTF-8 enabled; Node 25.9.0): 8 RPC regression cases, 1 real-process ACP cleanup case, and 220 Web cases passed. TypeScript and generated-contract checks passed. All 4,664 checkout files matched the head tree; all 16 changed files were reverified and Limits: focused RPC cases only; the existing integration case exercises successful local Exact verification commands (all exit 0)The commands below ran in an isolated exact-head checkout, with temporary profile/Raven/OAuth/temp directories and imports checked against that checkout. $run = 'C:/Users/livxu/AppData/Local/Temp/raven-windows-review/927b085ec728402f877567018999273f'
Set-Location -LiteralPath (Join-Path $run 'pr1043/head-tree')
# 8 passed
uv 'run' '--frozen' '--no-sync' 'pytest' 'tests/test_rpc_subagents.py::test_cancel_stops_the_run_that_proves_an_add_and_the_add_writes_nothing' 'tests/test_rpc_subagents.py::test_cancel_reaches_the_capability_record_after_the_answer_and_the_add_writes_nothing' 'tests/test_rpc_subagents.py::test_a_test_is_refused_while_a_connect_records_the_capabilities_of_the_same_name' 'tests/test_rpc_subagents.py::test_cancel_stops_the_run_that_proves_a_switch_on_and_the_roster_says_it_is_running' 'tests/test_rpc_subagents.py::test_a_test_is_refused_while_a_connect_proves_the_same_name_and_the_connect_lands' 'tests/test_rpc_subagents.py::test_a_connect_is_refused_while_a_test_of_the_same_name_runs_and_asks_the_agent_nothing' 'tests/test_rpc_subagents.py::test_a_connect_whose_own_call_is_cancelled_ends_its_run_and_writes_nothing' 'tests/test_rpc_subagents.py::test_a_cancelled_connect_refuses_on_the_wire_with_cancelled_in_its_data' '-p' 'no:randomly' '-n' '0' '-x' '--tb=short' '--basetemp' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\927b085ec728402f877567018999273f\checks\1043-changed\pytest' '--junitxml' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\927b085ec728402f877567018999273f\checks\1043-changed\junit.xml'
# 1 passed
uv 'run' '--frozen' '--no-sync' 'pytest' 'tests/integration/test_subagent_connect_windows_real_process.py' '-m' 'integration' '-p' 'no:randomly' '-n' '0' '-x' '--tb=short' '--basetemp' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\927b085ec728402f877567018999273f\checks\1043-windows\pytest' '--junitxml' 'C:\Users\livxu\AppData\Local\Temp\raven-windows-review\927b085ec728402f877567018999273f\checks\1043-windows\junit.xml'
Set-Location -LiteralPath (Join-Path $run 'pr1043/head-tree/ui-web')
npm.cmd 'test' '--' 'src/features/extAgents/AgentsBody.test.tsx' 'src/features/extAgents/ExtAgentsPage.test.tsx' 'src/features/extAgents/store.test.ts' '--no-file-parallelism'
npm.cmd 'run' 'type-check'
npm.cmd 'run' 'gen:check'
$bare = Join-Path $run 'objects.git'
git --git-dir=$bare diff --check a7e43a07729395311fcfc16dfae2e2bc467d8ada 38c083b7f655985e5eac4b8f71abefe945e94e9e |
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
The whole-record blocker is settled. @LivXue verified the current head against the original post-ping cancellation scenario, documented that both the server run coverage and the client's stop-answer handling now hold, and resolved both outstanding threads on the maintainer's word. My own earlier cancellation-RPC thread is also resolved, so no open objection remains from my side.
Fresh verification on the unchanged 54bbdf916cf2 head: tests/test_rpc_subagents.py passed 171 tests, and the three affected extAgents web files passed 220 tests.
|
Not a blocker -- notes from round 2 on 54bbdf9 (merged onto main 2cbacba; the round-1 thread is closed as fixed). Severity of this one finding, not a verdict on the pull request. Any blocking findings from this pass are review threads on the changed files; GitHub renders those collapsed, as a file name with no text.
Smaller: the ten-minute ceiling and the seconds counter have no test that fails if they change; how the source reads the server's two cancel answers is untested (two mutants survive every ui-web test); docs and CHANGELOG say only the stop's answer can confirm a cancel, though since c6bcf41 the connect's own Checked and fine: the server's worst case for an add-able machine preset is 420 s (ready 120 + answer 60 + 2 x 120 for the record), under the page's 600 s; |
Summary
Two of the three high-severity findings from the 2026-10-20 user-perspective walk of the Machines tab (the third, the narrow-viewport fold, is a separate PR):
subagents.add,subagents.toggleorsubagents.updateruns before it writes is one task held in_RUNNINGunder the entry's name, the map a test's run is held in (_run_once), sosubagents.test_cancelreaches it. That task covers the login-shell capture, the one real prompt, and, for an acp row that answered and whose record wants it, the capability record (_record_after_the_answer), which is a second launch and handshake of up to two start windows. A cancel anywhere in that stretch makes the connect refuse withcancelled: truein its error data and write nothing; the refusal says whether the cancel came before the agent answered or while its capabilities were being recorded. One run per name at a time: a Test during a connect's proof or record is refused as a second test is, and a connect during a Test is refused before anything is spent. The row reportstest_runningmeanwhile. A cancel of the call itself (its connection went) keeps unwinding as cancelled instead of composing a refusal for a socket that is gone.Contract summaries of
subagents.add,subagents.update,subagents.toggleandsubagents.test_cancelupdated (no shape change; both generated clients unchanged); i18n keys added in en and zh; docs (en/zh), CHANGELOG and CONTEXT updated.Type
Verification
New cases: 8 in
tests/test_rpc_subagents.py(among them a cancel during the capability record that answerscancelled: trueand writes nothing, and a Test refused while a connect records the same name) and 14 inui-web/src/features/extAgents/ExtAgentsPage.test.tsx(counting, Cancel, the ceiling, a stop that never answers on both paths, too late to cancel on Connect and Reconnect, not stopped, cancel not confirmed and its later corrections, and which press a late answer may correct). The two capability-record cases fail against the server code from before the record was moved into the run (assert 'OpenCode' in {}).Run on the PR head:
uv run --frozen --python 3.12 --all-extras pytest -q tests/test_rpc_subagents.py: 171 passed.npx vitest run src/features/extAgents/ExtAgentsPage.test.tsx src/features/extAgents/AgentsBody.test.tsx src/features/extAgents/store.test.ts(ui-web): 3 files, 220 passed.npx tsc --noEmit -p tsconfig.json(ui-web): clean.npx eslint src/features/extAgents(ui-web): clean.npm run lint:i18nandnpm run lint:rpc(ui-tui): both in sync.scripts/check_source_language.pyandscripts/check_large_files.pyon the PR's merge-base range, andgit diff --check: all exit 0.Real machine, on the first revision (isolated gateway, the branch's node installed on a second machine in its own directory, real Codex and Claude Code adapters): the tab opens with the new resting-state line on both machines; a Codex connect cancelled at 0.7 s refused with
cancelled: true, the form said cancelled and offered Connect again, nothing was written; a second Codex connect left alone still answered the normal refusal at 2.8 s; Reconnect of a switched-off Claude Code entry cancelled at 1 s ended the agent process on the machine (rc -9, nothing left running) and left the entry off.The docs box is left open: the machines page (en/zh) and CHANGELOG give the ten-minute ceiling, but the connect entry in
CONTEXT.mdstill says the form stops the run after five minutes.Risk
Low. No new method, parameter or input;
subagents.test_cancelalready existed and only reaches more of the same run. The proof path behaves as before when nothing cancels it; the one new refusal (a connect while a Test of the same name runs, or the reverse) replaces a second real prompt that would have raced the first in_RUNNING. Holding the capability record inside the run means a Test pressed during a connect's record is refused until the record ends, where it used to start a second launch. The page's ceiling only fires after the server's own longest wait. The Englishstate_offwording changed; nothing matches on it. No wire shape changed, so reverting the squash commit rolls it all back.Related Issues
Follow-up to #1007 and #1019 (machine-side connect form). Findings 1 and 2 of the 2026-10-20 Machines tab walk; finding 3 (narrow viewport) is the next PR.