Repository navigation
🤖 fix: a failed branch list says so in the creation view, and Run /init waits for it - #6417
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 80359eb29b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…it waits for it A creation view whose listBranches rejected marked the branches loaded with none, so the git project looked like a non-git one: the runtime silently switched to Local and Send created a Local workspace (#6055). A list that never settled kept Send off with no explanation. The view now tracks the branch list as loading, loaded or failed. A reject, or no answer within 15 s, shows "Could not load branches" in place of the picker and keeps Send off for every runtime except Local; a list that answers late still loads. The dead git-init reloadBranches callback, which had no mounted guard, is removed. The "Run /init" banner sends through the creation composer once, so it is now off while that composer cannot send, instead of leaving /init unsent (#6038). Fixes #6055 Fixes #6038 --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
ProjectPage is reused across projects and drafts while its composer remounts per scope, so the first render of a new scope still showed the previous scope's "can send" and Run /init was enabled until the new composer reported. The flag is now scoped to the composer key and reset during render when the key changes. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
80359eb to
1e1199c
Compare
|
Perf clearance (perf owner): cleared at
Non-blocking note: A new head needs a new clearance. Generated with |
…oder#6458) ## Summary The creation view's "Run /init" button is now off whenever the creation composer cannot send, not only while the branch list loads. While Coder presets load, a send is in flight, attachments are processing or the composer is disabled, a click used to be refused by the composer and left `/init` unsent. Fixes coder#6423 ## Background "Run /init" restores `/init` in the creation composer and calls its `send()` once. coder#6417 (fix for coder#6038) turned the button off while the branch list loads or has failed, but `canSend` has more blockers. The final check of coder#6417 found the gap and coder#6423 tracked it. ## Implementation `useReportCreationSendBlocked` now takes the same blockers that `canSend` checks: `disabled`, a send in flight, processing attachments, Coder presets loading, and the branch list. It leaves out an empty draft, because the banner brings its own text. The page side (`useCreationSendBlocked` in ProjectPage, scoped per composer) is unchanged. The blockers are combined inside the hook, so `ChatInputInner` gains no complexity (CRAP gate). ## Validation Two new tests in `tests/ui/agents/creationWaitsForBranches.test.ts` (real backend) failed on main with `Expected: true, Received: false` (the button was enabled) and pass now: - "Run /init is off while the Coder presets load": `CoderService` reports an available CLI and one template, and `listPresets` is held. After the user picks the Coder runtime, the button turns off, and it turns on again when the presets load. - "Run /init is off while a send is in flight": `WorkspaceService.create` is held after a Send click. The button stays off while the send is in flight. The file passes 9 of 9 (the coder#6033, coder#6055 and coder#6038 tests still pass). The ChatInput and ProjectPage unit tests give 186 pass, 0 fail. Dogfood (production build, mock AI, `git worktree` held so the creation send stays in flight). Run /init during the send: main **enabled**, this PR disabled (1280 and 390 px). Before, send in flight (main, 1280 px):  After, send in flight (1280 px):  After, send in flight (390 px):  First-load JS (`make first-load-js`, base 9aec386 vs this head): total raw 2,266.8 KiB on both, brotli 455.3 KiB to 455.5 KiB, gzip 558.2 KiB to 558.3 KiB. ## Risks Low. Only the creation page banner reads the report. A workspace composer reports nothing. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high` • Cost: `$324.26`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high costs=324.26 -->
Summary
The creation view now tells a failed branch list apart from an empty one. A rejected
listBranches, or one with no answer within 15 s, shows "Could not load branches" where the branch picker was, and Send stays off for every runtime except Local. The "Run /init" banner is now off while the creation composer cannot send, so a click is never left unsent.Fixes #6055
Fixes #6038
Background
Silent switch to Local (the main defect in #6055). When
listBranchesrejected,useCreationWorkspacestill marked the branches loaded, with none.CreationControlsreads "loaded, no branches" as a non-git repo, so its runtime effect switched the selection to Local without telling the user, and Send then created a Local (project-directory) workspace instead of a worktree. The issue text expected the old "Trunk branch is required" toast. In fact no toast appeared, and the workspace was created on the wrong runtime. AlistBranchesthat never settled kept Send off with only the picker skeleton, forever.#6038. "Run /init" sends through the creation composer once. Since #6035 that send is refused while the branch list loads, so the click left
/initin the composer unsent.Implementation
branchListLoad.ts(new):startBranchListLoadruns one load and reportsloadedorfailed. It reportsfailedon a reject or afterBRANCH_LIST_TIMEOUT_MS(15 s). A list that answers after the deadline still reportsloaded, so a slow list recovers. It returns a cancel function, so a remount reports nothing stale.useCreationWorkspace:branchesLoaded: booleanbecomesbranchLoad: "loading" | "loaded" | "failed", loaded throughstartBranchListLoadand cancelled in the effect cleanup. The unusedreloadBranchescallback (no callers, and no mounted guard: 🤖 fix: creation view Send has no feedback when the branch list hangs or fails #6055 item 3) is removed.CreationControls: only a loaded empty list means non-git, so a failed list never switches the runtime. A smallSourceBranchPickershows the skeleton, the select, or the failure text.ChatInput: the Send gate is open only whenbranchLoad === "loaded"(or the runtime is Local), and the composer reports that gate to the page (useReportCreationSendBlocked).ProjectPageandAgentsInitBanner: "Run /init" is disabled until the composer reports it can send. It starts disabled.Decisions (from the issue coordinator): fail closed, with no Retry button, because reopening the project retries (the view remounts per project). The failure state adds no new operation, so it needs no shortcut. The only new copy is "Could not load branches".
Validation
Tests failed on main for the stated reason and pass after the fix (
tests/ui/agents/creationWaitsForBranches.test.ts, 7 of 7):Expected: true, Received: false(the button was enabled).branchListLoad.test.ts(new, fake timers) covers in time, reject, the deadline then a late answer, and cancel. The ChatInput unit tests give 171 pass, 0 fail.Dogfood (production build, mock AI, a
gitwrapper that fails or hangs onfor-each-ref):Before, failed list (main, 1280 px):

After, failed list (1280 px):

After, failed list (390 px):

Before, list loading (main, Run /init enabled):

After, list loading (Run /init disabled):

After, list loaded:

Risks
Low. Only the creation view changes. A list that answers within 15 s behaves as before. The Local runtime is never gated. Projects that really are non-git still switch to Local, because a loaded empty list keeps that meaning.
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$305.66