Repository navigation
acpmux: a failed turn says auth.signed_out or auth.expired, and health keeps an expired sign-in - #26658
Conversation
Agent-Session: aid-cfe9c4465ee07565bad2
… matcher cmux setup's harness report matches the new Auth::Expired (signed_in false, with the login action), and the expired-credential matcher moves to claude_auth::is_expired_credential so a failed turn can use the same one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
A turn whose agent says it is not signed in (claude_auth::is_sign_in_failure) is typed auth.signed_out, one whose credential expired (claude_auth::is_expired_credential, the matcher harness health uses) is auth.expired, on the request error data, the turn_error and turn_result records and lastTurn. A connection or capacity error is never an auth kind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
|
Owned by an agent session · session |
|
Found 134 test failures on Blacksmith runners: Failures
...and 124 more test failures. View all on Blacksmith: run 40650049161, run 40650049107
|
|
Bead |
…it expiry
A capacity or connection error is never auth.*, even when it names a sign-in
("HTTP 503: authentication_failed"), and only a statement that a credential
expired is auth.expired (not "invalid token expiry" or "expires in 30 days").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Gallery before/after for
States
Pick other states with a Unclear: CI failed on
Failures:
Matched log linesNot re-run automatically: Written by red: web / Web status; base red: the same failure on the base 2e52267; does not block |
… unknown Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…chable expiry is retried Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
|
Shipped in:
|
acpmux's harness health reports auth "expired" (#26658); the Harnesses page, the chat's Log In line, the model picker's signed-out list and Settings > Agents only knew "signedOut", so an expired sign-in read as Ready. Each now treats expired as needing a login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840
…dy (#27742) * test(agent-pane): an expired harness sign-in needs Sign In, never Ready Red: since acpmux reports auth "expired" (#26658), the Harnesses page shows Ready, the chat shows no Log In, the model picker does not dim it and Settings > Agents shows no badge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 * fix(agent-pane): an expired harness sign-in offers Sign In, never Ready acpmux's harness health reports auth "expired" (#26658); the Harnesses page, the chat's Log In line, the model picker's signed-out list and Settings > Agents only knew "signedOut", so an expired sign-in read as Ready. Each now treats expired as needing a login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 * fix(gallery): the sign-in-expired Harnesses state names a login, as acpmux does Without one the expired row fell back to Ready (review finding). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ngs Agents) (carry #27742) (#28834) * test(agent-pane): an expired harness sign-in needs Sign In, never Ready Red: since acpmux reports auth "expired" (#26658), the Harnesses page shows Ready, the chat shows no Log In, the model picker does not dim it and Settings > Agents shows no badge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 * fix(agent-pane): an expired harness sign-in offers Sign In, never Ready acpmux's harness health reports auth "expired" (#26658); the Harnesses page, the chat's Log In line, the model picker's signed-out list and Settings > Agents only knew "signedOut", so an expired sign-in read as Ready. Each now treats expired as needing a login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 * fix(gallery): the sign-in-expired Harnesses state names a login, as acpmux does Without one the expired row fell back to Ready (review finding). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c46713109b72034b1840 * gallery(agent-pane): the chat's Log In line for an expired sign-in A `sign-in-expired` state beside `signed-out` in the harness health notice, so the gallery shows the chat line this PR adds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * gallery(settings): Settings > Agents with an expired harness sign-in `agents-harness-sign-in-expired`: Codex's sign-in expired, so Agents gets its badge and the row says Signed out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 * gallery(settings): the expired-sign-in state scrolls to the Codex row Its row was below the fold, and the base build could not mount the state (it waited for the expired marker). It now waits for the row and focuses its Check button, which both sides have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f71664ebfb6cf5206479 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo: “you gotta re-authenticate. You gotta log in again on the modal picker before the user even sends a prompt.”
The composer needs typed sign-in evidence from the daemon, without parsing an agent's error text. This is the first of three PRs for the daemon's
_acpmux/session/auth. It types a sign-in failure where errors already carry a kind, and it keeps an explicit expired-token answer from collapsing into "signed out".Turn evidence. A failed turn whose agent says it is not signed in gets
errorKind: "auth.signed_out". One whose credential expired getsauth.expired. The kind is on the request's errordata, on theturn_errorandturn_resultrecords, and so onlastTurn.recoverysays to sign in with the harness's login command. A sign-in failure now wins overagent.exited, so an agent that died saying "Not logged in" is not shown as a crash. An agent that died saying its credential expired is not auto-resumed, as one that died signed out already was (turn_errors::resume_cause); an error that says the provider was unreachable is still retried, whatever it says of a credential:transient_causeandresume_causeread a sign-in failure asrecovery::auth_kinddoes, andclaude_auth::explainleaves such an error as the agent said it (so "HTTP 503: OAuth token has expired" stays a capacity error, and a dead agent's staysagent.exited). A connection or capacity error (turn_errors::says_unreachable:is_capacity_error, an HTTP 502 or 504, orsays_connection_dropped) is never an auth kind, whatever it says about a token, so "HTTP 503: authentication_failed" stays a capacity error. The kinds useclaude_auth::is_sign_in_failureand a newclaude_auth::is_expired_credential.Harness health (from #26631, which this PR replaces). A failed
auth.checkwhose output says a credential expired now readsauth: "expired". Before, it readsignedOut. A failed check whose output says the provider had no capacity or the connection dropped readsunknown, notsignedOut. It still readsunknownwhen there is no evidence, and nothing reads the keychain. The expired matcher isclaude_auth::is_expired_credential, shared with the turn kinds so the two cannot drift. It needs an explicit token, credential, API key or login that expired: a bare "session expired", "the MCP session expired", "invalid token expiry value" or "expires in 30 days" doesn't count. #26631's clippy red (E0004 incmux setup's harness report) is fixed here:Expiredreads assigned_in: false, with the same login action as signed out.Tests (before: base 18af98c with only the test added; after: this head):
typed_errors::typed_error_a_turn_that_is_not_signed_in_says_so: before FAILED (errorKindnull), after ok.recovery::tests::a_sign_in_failure_is_typed_and_a_transport_error_is_not(a transport error is never an auth kind; a dead agent's sign-in failure beatsagent.exited): before it doesn't compile (nokind::AUTH_*), after ok.harness_health::tests::expired_login_probe_is_not_just_signed_out(expired phrasings, and the near misses above stay signed out): after ok.Checks at this head (cmux-ci run 40648972324):
cargo fmt --checkand clippy-D warningson acpmux and cmux-tui are clean. acpmux lib passes 1574, includingturn_errors::tests::a_dead_agent_is_continued_unless_it_died_of_a_limit_or_sign_inwith its expired and unreachable cases andclaude_auth::tests::an_outage_that_names_a_token_is_not_explained_as_a_sign_in. typed_errors, harness_health, claude_auth_env, hub_integration (511) and the route suites all pass. The crash ratchet (scripts/ci/crash_ratchet_compare.py) is no worse than base, because the expired matcher carries noexpect.Risk: low. A client that doesn't know the two new kinds treats them as plain errors, as
recovery.rsdocuments.harness/healthrows may now sayauth: "expired". The web settings card and the Swift settings row readauthas a string, and neither treats an unknown value as signed in.No capture: the only webview change is a doc comment in the generated protocol types; nothing renders differently.
Next:
_acpmux/session/auth, which reads these kinds (PR 2), then the route probe, the target form and peers (PR 3).Agent session: agent session
🤖 Generated with Claude Code