Repository navigation
fix(kanban): decompose asks each child for its own repo, refuses unanchored worktree children - #103714
Open
lucascmg-vx wants to merge 1 commit into
Open
fix(kanban): decompose asks each child for its own repo, refuses unanchored worktree children#103714lucascmg-vx wants to merge 1 commit into
lucascmg-vx wants to merge 1 commit into
Conversation
…chored worktree children _insert_decomposed_child silently wrote worktree children with no workspace_path and no project_id whenever a decomposed task named no repo and the board had no default_workdir configured. The child could never be dispatched: it failed at spawn, burned its retries, and parked as blocked behind a message that reads like an infrastructure fault rather than a decompose-time mistake. Inheriting the root task's repo is not a safe fallback: measured against every task that hit this failure, the root's repo was the wrong checkout for 3 of 17 (18%) decomposed children with a known outcome -- decomposition routinely fans a single card out across repositories. So the decomposer's LLM contract now asks for a per-child "repo" (from the live registered-project list, injected into the prompt). _clean_children resolves a named repo into workspace_kind / workspace_path / project_id; an unknown name is dropped with a log rather than fuzzy-matched. _insert_decomposed_child now writes project_id (previously omitted unconditionally) and raises ValueError -- inside the same transaction decompose_triage_task already uses -- when a worktree child named no repo and the board has no default_workdir, instead of writing a half-anchored row. Single-repo boards with default_workdir configured are unaffected: an unanchored child still resolves to workspace_path=None and dispatch materializes <repo>/.worktrees/<child-id> from the board anchor exactly as before. test_kanban_worktree_isolation.py is updated to configure one, since it now exercises that anchored path explicitly rather than relying on an unanchored worktree child being silently accepted. Adds test_kanban_decompose_child_repo.py (14 cases): explicit per-child repo, siblings on different repos, no inheritance from the root's repo, loud atomic refusal of an unanchored worktree child, and the board default_workdir anchor still working.
Related / competing: #101629 fixes the same unanchored-decomposed-child failure by inheriting the root's repo anchor (the approach this PR argues against); #92519 rejects unanchored worktree tasks at create time and #103325 covers scratch children. Flagging the cluster so a maintainer can pick one mechanism. |
12 of 13 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
_insert_decomposed_childsilently wroteworkspace_kind=worktreechildrenwith no
workspace_pathand noproject_idwhenever a decomposed tasknamed no repo and the board had no
default_workdirconfigured. The childcould never be dispatched: it failed at spawn, burned its retries, and parked
as
blockedbehind a "missing workdir" message that reads like aninfrastructure fault rather than a decompose-time mistake.
project_idwas also never written at all by_insert_decomposed_child,independent of the anchoring bug above.
Why not just inherit the root's repo?
That was the first fix considered. Measured against every task that hit this
failure, the root's repo would have been the wrong checkout for 3 of 17
(18%) decomposed children with a known outcome — decomposition routinely fans
a single card out across repositories (e.g. a UI child and an API child
belonging to different checkouts). A silent checkout into the wrong repo is
worse than a loud stall at decompose time.
Fix
"repo"(from thelive registered-project list, injected into the prompt as
{repos})._clean_childrenresolves a named repo intoworkspace_kind/workspace_path/project_idvia a new_resolve_repo_choice. An unknownrepo name is dropped with a log rather than fuzzy-matched (a fuzzy match on
a name like
"website"could silently resolve to the wrong of severalsimilarly-named repos).
_insert_decomposed_childnow writesproject_id, and raisesValueError— inside the same transaction
decompose_triage_taskalready uses — when aworktree child named no repo and the board has no
default_workdir, insteadof writing a half-anchored row that can never be dispatched.
default_workdirconfigured are unaffected: anunanchored child still resolves to
workspace_path=Noneand dispatchmaterializes
<repo>/.worktrees/<child-id>from the board anchor, exactlyas before.
test_kanban_worktree_isolation.py'stest_decompose_worktree_children_get_own_workspacenow configures a boarddefault_workdir, since it exercises that anchored path explicitly ratherthan relying on an unanchored worktree child being silently accepted.
Tests
New
test_kanban_decompose_child_repo.py(14 cases): explicit per-child repo,siblings on different repos, no inheritance from the root's repo, unknown repo
name dropped (not fuzzy-matched), loud atomic refusal of an unanchored
worktree child, and the board
default_workdiranchor still working for achild that names no repo.
This is a companion to #103120 (
worktree_without_checkout_rootdiagnostic):that PR surfaces the mis-anchored task while it is still queued; this one
stops it from being created mis-anchored in the first place.