cmux NEXT sidebar: chats whose PR checks fail rank as Red CI in the Priority view

Merged
TE
16d ago
+349-35

The Priority view now ranks a chat whose pull request checks fail in a Red CI tier, after an unseen result and a failed turn and before the working chats. Its row says "CI failing" in the danger color.

What changes

  • AgentPriorityRanking gets a ciFailing state. The tiers are: Needs you, Done unread, Failed or lost turn, Red CI, Working, Idle. state(_:read:failingChecks:) returns the turn's state unless Red CI ranks higher. It does over Working and Idle, but never over Needs you, Done or a failed turn.
  • The Priority view, the sidebar rows' chip (SidebarLaneStatus.chip) and the row actions' AgentPriorityChats (the row menu and the palette) all rank through the same state and tier, with the same failing-checks answer, so they agree.
  • The signal comes from the session tree's pull request reads (SidebarSessionTreeFeed.checksFailing). It reads the answers SidebarPullRequestStore has for the chat's folder branch and the pull requests it opened, in the badge's failing reading.
  • Those reads now run while sidebar.sessionTree or sidebar.priorityView.enabled is on. Before, they ran only with the session tree on, so Red CI would never show by default. They use the person's own gh CLI through SidebarPullRequestStore: at most two calls at a time, a five-minute cache, and its existing recheck for open pull requests. No new poller and no new GitHub call path. The session tree itself (SidebarSessionTree.state) is still written only while sidebar.sessionTree is on, so turning on the Priority view doesn't change the tree UI.
  • A read mark does not hide Red CI, because it stays until the checks pass. Snoozing does hide it. SidebarPriorityEntry.canMarkRead, the rule from #23527 that the hover button, the row menu and the palette share, now leaves out .ciFailing, since marking a Red CI row read would change nothing.
  • A Red CI chat counts toward the bell's attention dot and never ages out as idle.
  • The new string sidebar.priority.state.ciFailing ("CI failing") is in all 21 catalog languages.

Why a failed turn ranks above Red CI

A failed or lost turn means the agent has stopped. Nothing moves until the person acts, and the cause is right there in the chat. Red CI on a pull request might be a flake or a base red, and the agent may already be fixing it, so it ranks one tier lower. It still ranks above Working, as the brief asks. Needs you stays first.

Limits and follow-up

  • Follow-up, not in this PR: the pull request reads cover only lanes open in a local workspace tab (SidebarSessionTreeFeed.pass builds its asks from workspaces' agent chat tabs on this Mac). Chief chats, peer chats and chats with no tab never get Red CI.
  • A draft pull request reads as draft, not failing, the same as the badge.

Changelog

  • Added: The Priority view ranks a chat whose pull request checks fail as "CI failing", after unseen results and failed turns and before working chats.

Tests

New tests, each committed before its fix:

  • AgentPriorityRankingTests.aChatWhosePullRequestChecksFailRanksAsRedCIBeforeWorking checks the tier order, the .ciFailing state, no age-out, and that a question or unseen result outranks red checks.
  • SidebarPriorityRedCITests, a new suite:
    • failingChecksReadWhileThePriorityViewOrTheTreeIsOn: on with only the Priority view, on with only the tree, off with both off; no Red CI for passing checks, a draft, or another folder.
    • theRowChipSaysCIFailing: SidebarLaneStatus.chip says CI failing, and a question still wins.
    • aRedCIRowOffersNoMarkAsRead: the row's Mark as Read button is disabled.
    • theRowMenuLeavesMarkAsReadOutOnRedCI: canMarkRead and AgentPriorityChats.entry leave Mark as Read out on a Red CI chat.

Red, each a test-only commit, all run with cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref <sha> --key <key> --arg=suite --arg=Packages/macOS/CmuxNext --arg=<suites> --env CMUX_CI_XCODE_APP=/Applications/Xcode_26.6.app:

CommitSuiteStepResult
40aa472c9b6eAgentPriorityRankingTests8ea71082cd7e420d860dd4e4exit 1: extra argument 'failingChecks', no .ciFailing
e82c0fa88dffSidebarPriorityRedCITests (first three tests)a0b96178a50bdc852f6d8d5cexit 1: extra argument 'sections', no readsPullRequests
b7d04f25901d (after merging base 1a5b16b9b6fc)SidebarPriorityRedCITests (adds the menu test)53bd9d5790d76fab369696caexit 1: AgentPriorityChats takes no checksFailing

Green on the head:

  • Fleet step 07f36e20fd8a68b41d17ba86 at a900b71c3c28 exited 0:
    • SidebarPriorityRedCITests: 4 passed
    • AgentPriorityRankingTests: 7 passed
    • SidebarRowStatusTests: 6 passed
    • SidebarSessionTreeTests: 8 passed
    • SidebarPriorityRowActionsTests: 5 passed
  • cmux-ci compile-check --ref a900b71c3c28c7f59970da68d330ee545f08b149 --app: job d9fa2b3e9c1e165759c7c4fb passed.
  • Earlier greens: step 839314ff712c8dc488f6a717 at 72f3103a1621 and step 7d96105d69272165afa561c0 at 3cc3eb45303d. Both are superseded by the head run.

Observed / Not run

Observed:

  • The fleet steps and compile checks above.
  • python3 scripts/cmux-next/prepush-gate.py before every push reported no new violations.
  • The localization catalog check showed the same parity-error count as base, with none on the new key. The base merge was a normal merge; its one conflict, in the row view's Mark as Read line, took #23527's canMarkRead.
  • git merge-tree against leo/priority-reorder-motion and leo/sidebar-now-line (#23474) is clean.

Not run:

  • No native capture, because the lane fixture has no pull request answers to show a Red CI row. The media-tour label asks for one.
  • I didn't watch a real chat with a red pull request in a DEV build.

Agent session: cosmic-gray

🤖 Generated with Claude Code