Repository navigation
Track which worktrees/branches a session is actually working in #804
Description
What
Track which git worktrees (and therefore which branches) a chat session is
actually working in, and surface them — instead of only the single branch of the
session's project directory.
Follow-up to #673 / PR #760, which added <folder> · <branch> to the active
project button. That label is correct for its scope but structurally cannot cover
a multi-worktree session.
Why
A chat slot has exactly one branch-bearing field — self.project: str in
src/kiro_crew/dashboard/state.py. There is no session→worktrees association
anywhere in state: no list of worktrees used, no set of branches touched. So the
chip renders one project directory's HEAD and nothing else.
For KiroCrew's own development workflow that is the common case, not an edge
case. The kirocrew-worktree-dev skill makes one-worktree-per-feature a hard
rule, and this checkout currently has 78 worktrees. A session that starts in the
main clone and then creates ../kirocrew-wt-<feature> to do the actual work
leaves the chip reading main — a branch that is none of the ones being
worked on, displayed with the same authority as a correct one. A session that
touches several worktrees in one sitting shows whichever single directory happens
to be the project dir.
Two adjacent facts make this worse rather than self-correcting:
set_projectcannot fix it from inside the session. It is one of the six
tools behind the strict session-identity gate (_strict_identity_diagnosisin
src/kiro_crew/mcp_core.py), so on a default install where
mcp_gateway.enabledis false it refuses. See Six session-identity tools are dead on a default install (monitor_start, ask_question, suggest_followup, ...) #755. The agent therefore cannot
retarget the slot to the worktree it just created.- Dev Fleet does not answer this question. It enumerates worktrees with their
branches, but scoped toMAIN_REPOviagit worktree list— every worktree of
the repo, not the ones a given session used. It answers "what worktrees exist",
never "what is this session working on".
Possible approaches (not a decision)
- Track the agent's working directory per turn. Most faithful to "what is
this session working on", but needs the runtime to report cwd per turn, which
it does not today. - Record worktrees created during the session. Cheaper and covers the
dominant KiroCrew pattern (git worktree addmid-session), but misses a
session that merelycds into a pre-existing worktree. - Multi-value the project dir. Let a slot carry several project directories
and render N branches. Largest blast radius — the singleprojectfield is
read in many places (file picker, skills resolution,@-mentions, knowledge
scoping), so this is a data-model change, not a label change.
Whatever the mechanism, the UI question is separate: the composer chip has room
for roughly one <folder> · <branch> pair before truncation bites, so N branches
probably belong in the session's side panel or the sidebar row rather than the
chip.
Explicitly out of scope for #760
PR #760 keeps the project-directory scope as its contract, which is what #673
asked for. This issue is the real multi-worktree gap and needs its own design —
new state, not a rendering tweak.
Not verified
Whether the ACP runtime can cheaply expose the agent's cwd per turn (approach 1)
has not been investigated; it is listed as a candidate, not a known-feasible
path.
Activity
NicholasRBowers commentedon Aug 11, 2026
🤖 Kiro Crew Auto-Pipeline [operator: NicholasRBowers]: The grounding here is right: a chat slot has exactly one branch-bearing field and there is no session-to-worktree association anywhere in state, so the displayed branch can be none of the ones actually being worked in.
What is genuinely open is not the cause but the mechanism: how membership gets detected (observed tool calls and their working directories, explicit registration, or a scan of the checkout's worktrees), how stale entries are retired, and how the chip presents a session that spans several worktrees without asserting one of them with false authority. Those are design choices with a persistence cost, so this needs a human decision before implementation rather than an automated fix.
dwu96 commentedon Aug 24, 2026
🤖 Kiro Crew Auto-Pipeline [operator: dwu96#8c08bee0]: Re-triage — moving to
needs-human. The core claim survives: a slot still has exactly one branch-bearing field (self.project: str = \"\"atsrc/kiro_crew/dashboard/state.py:2747), with no session→worktrees association anywhere. One supporting claim does not survive and should be re-checked before anyone acts on the body:_strict_identity_diagnosisno longer exists insrc/kiro_crew/mcp_core.py, so theset_projectgate described here has since moved or been removed. Routing toneeds-humanbecause the ask is a new tracking surface whose approach is explicitly uncommitted in the issue itself (how worktree use is detected, and whether the chip shows a set or a primary) — that is a product/design decision, not analysis debt.pm25coder commentedon Aug 25, 2026
Verified against current main, plus a mechanism proposal that reuses plumbing that already exists.
Premise check (current line numbers).
self.project: str = ""is atsrc/kiro_crew/dashboard/state.py:3139(the :2747 citation is stale), serialized as"project": self.projectin the slot wire format atstate.py:4876. The strict gate moved but survives:_strict_identity_diagnosisis now_resolve_session_key_strict(src/kiro_crew/mcp_core.py:619) with a diagnostic twinstrict_identity_diagnosis(:679), andset_projectstill fail-closes without a strict identity on the MCP path (mcp_core.py:637-638 lists it explicitly). One nuance for the issue body: the dashboard REST writeapi_chat_slot_project(src/kiro_crew/dashboard/chat_handlers.py:4465-4504) is gated only by_deny_cross_app_slot_access(:4472, defined :4562) plusis_sensitive_path(:4487) — dashboard-user requests always pass (:4571-4573). So "the agent cannot retarget the slot" holds for the MCP tool, but there is a second, identity-ungated write path to the sameslot.project; worth confirming the intended boundary.Approach 1 — the "Not verified" item is now answerable: the ACP runtime's cwd is spawn-time only, not per-turn.
providers/acp.py:436-443exposescwdas the underlying client's_work_dir("the real workspace path", fixed at session create/resume —acp.py:631and:832), threaded into the provider context byworkflows/agent_exec.py:54/:83. There is no per-turn cwd report today, so approach 1 is a runtime/agent-side change (the agent's tool layer reporting cwd per call), not dashboard plumbing.Approach 2 already has a precedent in this repo.
src/kiro_crew/git_coord.py:43-45creates a worktree per scheduled task and storesrun.worktree_pathon the Project object;finalizeremoves it (:110-114). A chat slot could carry the same shape: aworktrees: list[str](path + last-seen round), populated when the session's tool path interceptsgit worktree add.Stale-entry retirement is nearly free with approach 2. Membership = observed ∧ still-existing: diff the recorded set against
git worktree list --porcelain, which Dev Fleet already parses (dev_fleet/server.py:1832+), and drop paths that vanished (the task lifecycle removes them viagit_coord.finalize). No TTL heuristic needed — the worktree list is the ground truth. The.git-as-filehandling in_resolve_primary_checkout(server.py:125-128) is exactly the resolution needed to map a recorded path back to a worktree object (primary vs linked).Approach 3's blast radius is smaller than feared if done additively. The wire format already emits a single
"project"(:4876); adding a sibling"worktrees": [...]while the chip keeps readingprojectas the primary is a wire-format addition, not a change to everyprojectconsumer — the file picker / skills resolution /@-mentions keep reading the unchanged primary.Net: the cheapest faithful mechanism is 2 (record created worktrees) + porcelain-diff retirement, reusing Dev Fleet's existing enumeration; 1 needs a runtime change and can be layered on later as a stricter source.
bolichen97 commentedon Sep 25, 2026
Answers to the questions raised in this thread, checked against current main. The design decision itself (how to track several worktrees and where to show them) is not addressed here and stays open.
1.
set_projectis no longer identity-gated. This corrects the body and the latest comment.Since b756211 (#844, one of the two fixes for #755, with afb1c5f / #907 as the second),
set_projecthas been a stateless directive.What this means for this issue:
mcp_gateway.enabled. In a dashboard chat turn that a person started, the agent can point its slot at a worktree it just created. The change takes effect on the next message, which cold-starts in the new directory.set_projectas a strict-identity tool, and both are stale: the_resolve_session_key_strictdocstring (mcp_core.py#L846) and the macOS/Windowskirocrew doctornote (cli_doctor.py#L2169-L2182). The tool does not run the check they describe.set_project: there is no match undersrc/kiro_crew/builtin_skills/.kirocrew-worktree-devrunsgit worktree addand thencd. After that, the slot keeps its original project unless the agent callsset_projectitself.This only helps with a single worktree.
slot.projectis still one string (state.py#L2673), sent to the frontend as a single"project"key (slot_projection.py#L288). A session that spans several worktrees still has no representation.2. Approach 1, the "Not verified" item: the ACP working directory is set once per session, not per turn. The previous comment reached the same conclusion; here are current citations.
cwdis sent only in thesession/newandsession/load/resume requests (client.py#L9914-L9915, client.py#L10117-L10119, _dispatch.py#L84-L107, runtime.py#L6846-L6850).cwdreturns the same value (providers/acp.py#L567-L575).3. The REST write to
slot.projectis the dashboard's own project picker, not an agent path.POST /api/chat/slots/{slot}/project(ChatPage.tsx#L3117-L3126, client.ts#L3983-L3984).slot.project, next to the in-turnset_projectdirective (L10156-L10165). Session identity is not the relevant control on this route, because the caller is the dashboard user rather than an agent turn.Related existing behaviour: the follow-up card's "Start in new worktree" action creates a worktree and opens a new session scoped to it (ChatPage.tsx#L3355-L3385). That gives one session per worktree. It does not track worktrees inside one session.
Still open, for a maintainer to decide:
Related but separate requests: #13488 (move the single project dir automatically), #12432 and #1607 (worktree pickers).
Triage pass against main @ c66f95b.
KiroCrewCaptain commentedon Oct 8, 2026
Thanks for the report. This issue has been triaged by Crew Captain and will be assigned to a maintainer, who will follow up here.
dodgeblaster commentedon Oct 21, 2026
Re-verified against current main (
0b89e0c6f7). The gap is unchanged; posting refreshed citations becausestate.pywas split since the last triage (the earlierstate.py:3139/slot_projection.py:288line numbers are now stale).The cause still holds — a slot has exactly one branch-bearing field, and there is no session→worktree association anywhere in state.
state.pyinto a state part:self.project = ""now lives atsrc/kiro_crew/dashboard/state_parts/slot_session.py:217, still a single string."project": slot.projectatsrc/kiro_crew/dashboard/slot_projection.py:409.worktreeslist, nobranches_touchedset, and no per-turn cwd record exists on the slot or anywhere session-scoped (grep ofstate_parts/forworktree/branchesreturns only unrelated code-comment uses; theworktrees: list[dict]hits inapps/builtins/dev_fleet/fleet_state.py:1129andrepository.py:1654are Dev Fleet's repo-scopedgit worktree listenumeration, not session membership).No open PR addresses this. The branch-related open PRs (e.g. #17628 Git-panel/composer branch switcher, #21995 remote Git panel, #21260 Kiro Cloud session environments) are about switching or viewing a branch, not recording which worktrees a session has worked in.
What remains open is unchanged from @bolichen97's 2026-09-25 triage — a design/product decision, not analysis debt:
cwdis spawn-time only; record worktrees created mid-session via the tool path; or scan the checkout),git worktree listis nearly free, per the earlier comment),<folder> · <branch>pair, so N branches likely belong in the side panel / sidebar row).Leaving open for a maintainer to commit the design. No code change this pass.
Triage refresh against main @ 0b89e0c.