Skip to content

acpmux: a failed turn says auth.signed_out or auth.expired, and health keeps an expired sign-in - #26658

Merged
teamleaderleo merged 10 commits into
feat-cmux-nextfrom
lane/hb-session-auth-turn
Oct 28, 2026
Merged

teamleaderleo merged 10 commits into
feat-cmux-nextfrom
lane/hb-session-auth-turn

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

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 gets auth.expired. The kind is on the request's error data, on the turn_error and turn_result records, and so on lastTurn. recovery says to sign in with the harness's login command. A sign-in failure now wins over agent.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_cause and resume_cause read a sign-in failure as recovery::auth_kind does, and claude_auth::explain leaves such an error as the agent said it (so "HTTP 503: OAuth token has expired" stays a capacity error, and a dead agent's stays agent.exited). A connection or capacity error (turn_errors::says_unreachable: is_capacity_error, an HTTP 502 or 504, or says_connection_dropped) is never an auth kind, whatever it says about a token, so "HTTP 503: authentication_failed" stays a capacity error. The kinds use claude_auth::is_sign_in_failure and a new claude_auth::is_expired_credential.

Harness health (from #26631, which this PR replaces). A failed auth.check whose output says a credential expired now reads auth: "expired". Before, it read signedOut. A failed check whose output says the provider had no capacity or the connection dropped reads unknown, not signedOut. It still reads unknown when there is no evidence, and nothing reads the keychain. The expired matcher is claude_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 in cmux setup's harness report) is fixed here: Expired reads as signed_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 (errorKind null), 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 beats agent.exited): before it doesn't compile (no kind::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 --check and clippy -D warnings on acpmux and cmux-tui are clean. acpmux lib passes 1574, including turn_errors::tests::a_dead_agent_is_continued_unless_it_died_of_a_limit_or_sign_in with its expired and unreachable cases and claude_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 no expect.

Risk: low. A client that doesn't know the two new kinds treats them as plain errors, as recovery.rs documents. harness/health rows may now say auth: "expired". The web settings card and the Swift settings row read auth as 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

teamleaderleo and others added 3 commits October 27, 2026 21:06
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
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 28, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Found 134 test failures on Blacksmith runners:

Failures

Test View Logs
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build/
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build
View Logs
nightly.yml must derive the embedded key and sign every appcast through the helper/
nightly.yml must derive the embedded key and sign every appcast through the helper
View Logs
src/pages/settings/layout.test.ts/layout.test View Logs
src/pages/settings/layout.test.ts/layout.test View Logs
test/agent-pane-attach-huge-files.test.ts/agent-pane-attach-huge-files.test View Logs
test/agent-pane-attach-huge-files.test.ts/agent-pane-attach-huge-files.test View Logs
test/agent-pane-background-tasks.test.ts/agent-pane-background-tasks.test View Logs
test/agent-pane-background-tasks.test.ts/agent-pane-background-tasks.test View Logs
test/agent-pane-chat-unavailable.test.ts/agent-pane-chat-unavailable.test View Logs
test/agent-pane-chat-unavailable.test.ts/agent-pane-chat-unavailable.test View Logs

...and 124 more test failures. View all on Blacksmith: run 40650049161, run 40650049107

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-mwn0o3 created for this PR by the cmux coordinator.

…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
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 6e69f38: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr26658 -f ref=lane/hb-session-auth-turn -f platform=macos -f backend_mode=local

Gallery before/after for 6e69f38: 16 states rendered, 9 images differ, 2111 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 40655660403 -R manaflow-ai/cmux -n gallery-advisory-26658-6e69f38818ab9f33f6ad4f4d4c1921efcd7b8927 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.chat-inspector/subagents-done Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/subagents-done Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/full Apple System Colors Light changed 0.0674% imports types.ts (2 hops)
agent-pane.chat-inspector/full Apple System Colors changed 0.0174% imports types.ts (2 hops)
agent-pane.chat-inspector/workflow-running Apple System Colors Light changed 0.0045% imports types.ts (2 hops)
agent-pane.chat-inspector/workflow-running Apple System Colors changed 0.0042% imports types.ts (2 hops)
agent-pane.chat-inspector/workflow-finished Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/workflow-finished Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-glance Apple System Colors Light changed 0.0716% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-glance Apple System Colors changed 0.0648% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-glance-open Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-glance-open Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-rules Apple System Colors changed 0.0452% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-rules Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-groups Apple System Colors changed 0.0599% imports types.ts (2 hops)
agent-pane.chat-inspector/layout-groups Apple System Colors Light changed 0.0576% imports types.ts (2 hops)
agent-pane.chat-width/standard Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-width/standard Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.chat-width/wide Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-width/wide Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.chat-width/wide-blocks Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.chat-width/wide-blocks Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.composer-floats/scrolled-to-end Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.composer-floats/scrolled-to-end Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.composer-floats/composer-grown Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.composer-floats/composer-grown Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/new-chat Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/new-chat Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/after-turn Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/after-turn Apple System Colors unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/working Apple System Colors Light unchanged 0% imports types.ts (2 hops)
agent-pane.docked-chat/working Apple System Colors unchanged 0% imports types.ts (2 hops)

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

Unclear: web / react-apps-check failed: no known signature; failed step: Check webview test shards.

CI failed on 6e69f38818 (run 40650049161 attempt 1): 3 code, 1 unknown.

Job Verdict Why
web / react-apps-base-check (4) code a web test failed
web / react-apps-base-check (2) code a web test failed
web / react-apps-base-check (1) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs layout.test.ts only page.css imports the page's sheets: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 1 .bin 2 GB drop remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 2 .mp4 500 MB paste remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 2 .mp4 500 MB drop remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 3 .png 200 MP paste remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 3 .png 200 MP drop remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 4 text 100 MB paste remote: failed (job)
  • seen on other PRs agent-pane-attach-huge-files.test.ts 4 text 100 MB drop remote: failed (job)
  • seen on other PRs agent-pane-background-tasks.test.ts the summary card lists the chat's background tasks: running ones first, the finished folded: failed (job)
  • seen on other PRs agent-pane-chat-unavailable.test.ts loading never shows the unavailable text: a slow attach, then a machine still connecting: failed (job)
  • ... 14 more in the job logs
Matched log lines
web / react-apps-base-check (4): (fail) only page.css imports the page's sheets [20.65ms]
web / react-apps-base-check (2): (fail) the summary card lists the chat's background tasks: running ones first, the finished folded [957.54ms]
web / react-apps-base-check (1): (fail) chromium > the gutter beside every part of the stack scrolls the transcript, and the part keeps the pointer [8532.91ms]

Not re-run automatically: web / react-apps-base-check (4), web / react-apps-base-check (2), web / react-apps-base-check (1), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; base red: the same failure on the base 2e52267; does not block
red: web / react-apps-base-check (1); no finished base run on 2e52267 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (2); no finished base run on 2e52267 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (4); no finished base run on 2e52267 to compare; do not merge until green; see lane-rules
red: web / react-apps-check; base red: the same failure on the base 2e52267; does not block

…chable expiry is retried

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 28, 2026 08:16
@teamleaderleo
teamleaderleo merged commit 988565e into feat-cmux-next Oct 28, 2026
164 of 183 checks passed
@teamleaderleo
teamleaderleo deleted the lane/hb-session-auth-turn branch October 28, 2026 08:16
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 30, 2026
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
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
…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>
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
…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>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 6e69f388 Deployed Oct 28, 2026 by teamleaderleo via wait for same-key tree publisher #70463
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant