Repository navigation
Conversation
Sensitive change review
This PR comes from a fork, so per |
UX Review (Opus 5.5, fork) — ✅ PASS (a BLOCK with no Trigger and no Outcome does not block)UX-level review of UX-Verdict: PASS cannot evaluate: missing the clipboard-failure note and its "Try again" button, plus the picker's loading, load-error, detached-HEAD and truncated-list states. None of the 12 committed screenshots shows any of them. Evidence gaps
Notes
[UX-REVIEWED] 181cb74 Description read[DESCRIPTION-READ] d60c4066a5a766aa9472b64ec5739e359b8279814f426cf3dd9693bd989114d2 That sha256 names everything this verdict read: the PR description, plus the 15 evidence file(s) the workflow collected from it and handed this review. It covers that evidence because the media strip replaces every attachment URL with the same placeholder, so an edit swapping one attachment for another would leave the description's captured text identical while what this review judged changed. Recompute it with |
First Principles Review (Opus 5.5, fork) — ✅ PASSPremise-level review of First-Principles-Verdict: PASS Nothing blocks. The switcher answers a linked user report (#22670), and the busy guard exists because git would otherwise rewrite files under a running turn. What this change shipsInventory (10 items) — 10 justifiedIntent: let a user switch, track or create a git branch from the dashboard instead of going to a terminal — ADDITION.
[FIRST-PRINCIPLES-REVIEWED] 181cb74 Description read[DESCRIPTION-READ] 561fc70f458e32557231fb66ccfa07de34a214af06bc99056175eef0e46e5162 That sha256 names the PR description this verdict read. Recompute it with |
Opus 5.5 Review (fork) — ✅ no blocking findingsReviewed |
GPT 6.1 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
d39aa94 to
1f78cbe
Compare
|
Both GPT 6.1 blocking findings are fixed in 1f78cbe (squashed into the feature commit to stay within the two-commit limit, and rebased onto current main). F1 (cancelled unwritten prompts left the repo busy) - fixed. The runtime and client request writers now call F2 (Windows root death released prompts while descendants ran) - fixed. The teardown probe now consults The rebase also moved the new |
Design Review (Opus 5.5, fork) — ✅ PASSDesign-level review of Design-Verdict: PASS Nothing blocks: if any of the new busy bookkeeping goes wrong, the only effect is that a branch switch is refused, and chat turns, sub-agents and spawning keep working. Notes
[DESIGN-REVIEWED] 181cb74 Description read[DESCRIPTION-READ] 5c85731f819e6de244e12b9415818a462be810f1c7d5ce2b7790dfaf5915a697 That sha256 names everything this verdict read: the PR description, plus the 1 evidence file(s) the workflow collected from it and handed this review. It covers that evidence because the media strip replaces every attachment URL with the same placeholder, so an edit swapping one attachment for another would leave the description's captured text identical while what this review judged changed. Recompute it with |
1f78cbe to
e65b52e
Compare
|
Updated to e65b52e (still two commits):
GPT 6.1 Review on the previous head ended without a verdict (Bedrock 429 on both passes, run 39863015457), so the earlier blocking comment still shows d39aa94. A maintainer re-run on this head would be appreciated. |
e65b52e to
181cb74
Compare
|
Updated to 181cb74 (still two commits, same base as e65b52e). On e65b52e the GPT 6.1 Review produced a blocking verdict but could not post it, and the Opus 5.5 Review stopped in validation; both lanes hit the GitHub API rate limit. I read both reports from the run logs and fixed what they found:
Each fix has a regression test that fails without it. Unrelated Windows failures on e65b52e: A maintainer approval of the fork runs on this head, and a re-run of GPT 6.1 / Opus 5.5 if they hit the rate limit again, would be appreciated. Thanks! |
181cb74 to
893b4dc
Compare
|
Rebased onto main 1241954 (head 893b4dc, still two commits) to clear the merge conflict. The only conflict was Local checks on the rebased head: flake8, isort, black gate, |
Record the design kirodotdev#23102 implements so it can be agreed before any code lands: a branch picker in the Git panel header and the composer chip, an owner-only switch on the worktree route's project boundary, and a busy rule that refuses a switch while any chat turn, linked-channel turn, sub-agent, workflow step or ACP prompt in flight works in the repository, ending no session. Splits the implementation into four phases and lists the open questions for the maintainers. Part of kirodotdev#22670
|
Moved to draft while the design goes through an RFC: #23725. Once it is accepted this pull request will be split along the RFC's four phases. |
Record the design kirodotdev#23102 implements so it can be agreed before any code lands: a branch picker in the Git panel header and the composer chip, an owner-only switch on the worktree route's project boundary, and a busy rule that refuses a switch while any chat turn, linked-channel turn, sub-agent, workflow step or ACP prompt in flight works in the repository, ending no session. Splits the implementation into four phases and lists the open questions for the maintainers. Part of kirodotdev#22670
893b4dc to
84f59d9
Compare
|
Fixed the credit to match CONTRIBUTING.md: both commits now carry One gap I could not close here: CONTRIBUTING asks to keep the superseded author's commits as-is, but #17628's two commits plus this work would exceed the two-commit limit. When the RFC (#23725) is accepted and this is split into its phases, each phase PR will carry the same trailer. |
Record the design kirodotdev#23102 implements so it can be agreed before any code lands: a branch picker in the Git panel header and the composer chip, an owner-only switch on the worktree route's project boundary, and a busy rule that refuses a switch while any chat turn, linked-channel turn, sub-agent, workflow step or ACP prompt in flight works in the repository, ending no session. Splits the implementation into four phases and lists the open questions for the maintainers. Part of kirodotdev#22670
Record the design kirodotdev#23102 implements so it can be agreed before any code lands: a branch picker in the Git panel header and the composer chip, an owner-only switch on the worktree route's project boundary, and a busy rule that refuses a switch while any chat turn, linked-channel turn, sub-agent, workflow step or ACP prompt in flight works in the repository, ending no session. Splits the implementation into four phases and lists the open questions for the maintainers. Part of kirodotdev#22670
Record the design kirodotdev#23102 implements so it can be agreed before any code lands: a branch picker in the Git panel header and the composer chip, an owner-only switch on the worktree route's project boundary, and a busy rule that refuses a switch while any chat turn, linked-channel turn, sub-agent, workflow step or ACP prompt in flight works in the repository, ending no session. Splits the implementation into four phases and lists the open questions for the maintainers. Part of kirodotdev#22670
Clicking the branch name in the Git panel header, or the branch segment of the project chip under the chat box, opens a searchable picker that switches local branches, checks out a remote-only branch as a tracking branch, or creates a branch from the current commit. GET /api/project/git/branches lists branches; POST /api/project/git/switch is owner-gated and audited, runs git sandboxed with hooks off, never overwrites uncommitted or ignored local files, and refuses for subfolder projects and repositories declaring a checkout filter. A switch whose request is cancelled mid-checkout still writes its outcome to the SEL from the worker's own completion. A switch is refused while work runs in the repository: a chat turn, a turn a linked channel runs on a chat's session, pending sub-agents, a workflow step, or any prompt in flight at the ACP transport until the backend answers it. The switch reserves the repository before that check, and turns, sub-agents, workflow steps and prompts wait out a checkout in flight. Workflow steps keep their session whatever the step's outcome; an unanswered prompt is what keeps the repository busy. The refusal names the running chat or workflow. Supersedes kirodotdev#17628. Co-authored-by: kyleseaman <2904635+kyleseaman@users.noreply.github.com>
Fork PRs cannot attach media, so the review lanes read these from the branch. Co-authored-by: kyleseaman <2904635+kyleseaman@users.noreply.github.com>
84f59d9 to
db42efd
Compare
Problem / Motivation
Goal: Switch, check out and create git branches from the dashboard's Git panel and from the project chip under the chat box, the way VS Code and Zed do from their status bar.
Today the Git panel header and the composer's project chip only show the current branch with a click-to-copy button. Changing branch means leaving the dashboard for a terminal, then coming back and waiting for the panel to notice. Users report this as the thing that stops them using the dashboard as their main surface (#22670).
This takes over #17628 by @kyleseaman, rebased onto current
main, with its red CI fixed and its review findings addressed. Kyle is credited as co-author.Why it matters
Moving between local branches is the most common git action while reviewing an agent's work in a session's project folder. Without a switcher the dashboard shows the branch but cannot act on it, so every switch costs a context change to a terminal, and the file tree and Changes list lag until they repoll.
Not a goal
main.What changed (motivation → approach → change)
One searchable picker, reused in the Git panel header and on the composer chip, backed by two narrow endpoints. A switch is refused while any agent work runs in the repository, so git never rewrites files under a live turn.
dashboard/handlers/git_branches.pyGET /api/project/git/branchesand owner-gated, SEL-auditedPOST /api/project/git/switch: sandboxed git with hooks off andLC_ALL=C,--no-overwrite-ignore,--no-recurse-submodules, everything redacted; refused for subfolder projects and checkout filters. A cancelled switch still audits its outcome (_audit_abandoned_switch). A busy refusal names the running chat or workflow (busy).kiro_crew/repo_checkout_guard.py,dashboard/repo_checkout_guard.pyacp/(client_transport.py,client_lifecycle.py,runtime_wire.py,runtime_reader_loop.py,runtime_tree_kill.py,runtime_class.py)dashboard/chat_turn/,dashboard/state_parts/,subagent_manager/run_lifecycle.py,subagent_parts/manager.py,workflows/agent_exec.py,workflows/agent_pool.pypre_run_gate) and workflow steps (tracked_work) wait out a checkout before they touch files. Workflow steps keep their session whatever the step's outcome.website/src/components/BranchSwitcher.tsx,LazyBranchSwitcher.tsx,GitPanel.tsx,ChatInput.tsx,website/src/api/client/files.ts,website/src/pages/chat/ActivityViewer.tsxwebsite/src/i18n/en-XAregenerated, plural keys, translator context.security_posture.py, docslearn-cron-dashboard.mdandacp-client.mdspec text.Changed from #17628, each a review finding:
main's_session_cwdsreplaces the duplicate_session_foldersbehind theAttributeErrorreds.CCWorkeris not counted: it runs in the gateway's own cwd and could mark every repository under it busy until restart (Opus).Backwards compatibility
Compatible: two new routes and a new optional
c_localeflag on_run_git; existing git endpoints and their responses are unchanged. Workflow steps behave as onmain.Changes one click target, removes no capability: when idle, clicking the branch name on the composer chip or Git panel header opens the picker instead of copying (copy is in the picker footer); while a response runs, the same click still copies, as before.
Removes nothing: no route, key, field or record is removed or tightened; the busy registry is new state.
Tests
test/test_project_git_branches.pyandtest/test_project_git_branches_coverage.py: listing, switching, creating, tracking, every refusal and parse path; new: a cancelled switch audits its outcome even through a second cancel, each worker outcome maps to the right SEL verdict, a linked channel's lease on an idle slot is running work (held, unplaced, unreadable), the 409 carries the running chat's name.test/test_repo_checkout_guard.py: the reservation registry and both admission orderings; new: a failed or cancelled workflow step keeps its named session, an unanswered prompt keeps the repository busy after its step ends, the refusal names the tracked workflow.test/test_prompt_checkout_seam.py: prompts counted at both ACP transports from before their write until their exact answer; new: the knowledge pool's worker never marks a repository busy, a teardown survivor keeps the prompt counted across a respawn until it exits, a Windows drain that raises keeps it until its root is gone, an inconclusive probe stays busy, and a steer-started turn ends only on a finished later turn on the same session (not on another session, an error answer, or an earlier turn). Absence assertions wait on a positive signal (the prompt parked on the reservation, or the reader past a trailing frame), not a fixed number of loop yields.-n0, 10 times at-n 4beside their neighbours, and once in reversed order, all green.test/test_workflows_agent_pool*.py,test_workflow_agent_spawn_governance.py,test_workflow_memory_backend_reset.py: back to theirmainexpectations, which now pass unchanged.BranchSwitcher.test.tsx(new: the named busy refusal, the switch affordance on the highlighted row only),GitPanel,GitReposPanel,ChatInput.projectBranch,LazyBranchSwitcher.Local, on this head: black, isort, flake8,
mypy --platform linux, docs lint, tsc, eslint,i18n:check; 1,351 backend tests across the guard, transports, bindings and workflows; 1,195 frontend tests;scripts/local-gate.pyrelated sets: about 130,000 backend tests and 14,961 frontend tests, where every red (48 backend, all in environment-bound tests such astest_dashboard_gallery_*,test_pi_gate_extension_mcp.py,test_local_gate.py) reproduces on a cleanorigin/mainworktree on this host. Full CI is the authority.Manual verification
Driven in the production build with mocked git responses (
website/scripts/capture-branch-switcher.mjs, not a live gateway): open, filter, switch, dirty-tree refusal, named busy refusal, filter-blocked state, composer chip opening upward, copy while a response runs, dark and light themes.Screenshots / video
Picker open, with the one-line hint and the highlighted row's switch affordance:
The busy refusal names the chat that is still running:
While a response runs, the chip copies and says where the stop control is:
More states
Related Issues
Closes #22670. Supersedes #17628.
Checklist
Contribution License Agreement
Contributions are accepted under the project's Apache-2.0 license.