cmux-next: a new chat's slow start keeps the send's gesture for its first prompt (hq#2569 item 5)

Merged
TE
17d ago
+179-32

Summary

Follow-up to #22138 for manaflow-ai/cmuxterm-hq#2569 item 5. A new chat's first prompt waits for its harness to start: a New Tab ask, a harness switch, Enter in a new chat, or Start on an offer. The relay grants that session/prompt only on the person's live gesture, which lasts 30 s (AgentPaneUserGestures.lifetime). A harness that can't reach its backend can take longer than that to answer session/new. The prompt then reached the relay with no gesture left and came back transport.gesture_required ("Not sent").

The relay now treats a local start the way it already treats a start on another machine (cx-k21v). A session/new on this Mac still needs no gesture. If the person's send gesture is live when it passes, or the frame's folder check just used it, the start takes it as a start credit for that connection. The chat's first session/prompt goes with that credit within startCreditLifetime (120 s, the old remote value, renamed). It's one grant per gesture: the start takes the gesture, and the credit ends once any prompt goes out.

If acpmux holds that prompt for the folder trust answer, the pane reserves a session/prompt ticket at the refusal (heldPrompt.ts). That reservation used to take the still-live gesture. The start now has it, so reserveGesture turns an unspent start credit into the ticket instead, and the ticket keeps its 600 s held-prompt lifetime.

Credits are timed on the gestures' clock (system uptime, settable in tests) instead of reading ProcessInfo directly. A local session/new is no longer a "free" frame, so it passes through the main-actor decision.

Behavior to check in review: a click that starts a local chat now spends its gesture on the start. A gated frame without a ticket, sent after that start and before the first prompt, now needs a fresh gesture. Before, it could take the live one, and the prompt was then refused instead. I found no such frame in the pane: start mode rides in session/new, and the switch's mode and config picks carry tickets.

Testing

The failing test came first, in c5b3718 (AgentPaneSlowStartPromptTests). The fix is 09655e1. CI's cmux-next swift test job can't run on this PR right now: it waits on cmux-next web bundles, which is red on the base too (step "Source key covers imports outside webviews/", same failure on the feat-cmux-next push run 39325964081). So the suites ran on the cmux build fleet, at both commits, with the same command:

cmux-ci run --class light --script scripts/ci/run-swift-testing-suites.sh --arg Packages/macOS/CmuxNext --red --ref <sha>

  • On c5b3718 (test only, base code): AgentPaneSlowStartPromptTests fails. aPromptQueuedBehindASlowStartGoesWithTheSendsGesture fails at line 65: (sent → .gestureRequired) == nil. The prompt that went out 45 s after its start was refused, as in the bug. aStartWithoutTheGestureCarriesNothingAndTheCreditEnds passes.
  • On 09655e1 (the fix): all 3 tests in the suite pass, including aPromptHeldForTrustAfterTheStartStillGetsItsTicket, which was added with the fix.

What the tests cover:

  • aPromptQueuedBehindASlowStartGoesWithTheSendsGesture: the gesture is recorded, then session/new, then 45 s pass, then session/prompt. The prompt is sent. A second prompt with no new gesture stays refused.
  • aStartWithoutTheGestureCarriesNothingAndTheCreditEnds: a start with no gesture gives no credit, and a credit older than its lifetime grants nothing.
  • aPromptHeldForTrustAfterTheStartStillGetsItsTicket: the start takes the gesture, the trust hold still gets its ticket, and that ticket is redeemed 300 s later. It passes on the base too, so it guards against a regression rather than reproducing one.

Observed / Not run

  • Observed: both fleet runs above. Each ran the whole CmuxNext package (541 suites). On c5b3718, 534 passed and 7 failed. On 09655e1, 538 passed and 3 failed. The 3 that fail on the head also failed on c5b3718, which has the base's code, and none are in the agent pane: ActionSurfaceParityTests, SidebarSpacePagingTests, VideoWallpaperTests. RapidWorkspaceCreateTests, SwitchToColdTabTypeAheadTests and BranchStateResourcesTests failed only in the c5b3718 run.
  • After merging feat-cmux-next (81b7a64, which picks up the base's GhosttyKit release fix), I ran the same package run without --red. All 3 AgentPaneSlowStartPromptTests tests passed. Of 542 suites, 537 passed and 5 failed: ActionSurfaceParityTests, SidebarSpacePagingTests, VideoWallpaperTests and RapidWorkspaceCreateTests, which also failed on the base-code run, plus DebugPaletteCaptureTests, which came in with the merge. None of them is in the agent pane.
  • Other red PR checks that also fail on the base: cmux-next checks (the l10n hard ceiling, concurrency's HomeHostView.swift:159 finding and others, the same steps as on other open PRs), nightly-guards / release-notary ("NEXT post-publication dependency contract"), and cmux-next web bundles.
  • Not run: a live dogfood with a slow harness, or the app build.

Changelog

Fixed: A new chat's first message no longer fails with "Not sent" when its agent takes more than 30 seconds to start

đŸ¤– Generated with Claude Code


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


Summary by cubic

Fixes hq#2569 item 5: a new chat's first prompt no longer comes back "Not sent" when its harness takes more than 30 seconds to answer session/new. A local start now carries the send's gesture—or the one the folder check used—as a start credit, and the chat's first prompt can spend it within 120 seconds.

Behavior

  • A local session/new is no longer a free frame, so it passes through the main-actor decision; a gated frame sent after the start and before the first prompt needs a fresh gesture.
  • Credits are timed on the gestures' clock (system uptime, settable in tests) instead of reading ProcessInfo directly; the start and remote-trust credits now share AgentPaneGestureCredit, keeping AgentPaneTransport under its size budget with no behavior change.
  • Tests cover slow starts, missing or expired credits, held prompts, and credit-to-ticket conversion.
  • This PR changes no settings.