fix(kanban): give each subtask its own worktree instead of inheriting parent path (#53983) - #54006
Conversation
… parent path When a worker scoped to a worktree task spawns child tasks without an explicit workspace arg, the children inherited the parent's workspace_path (the parent's own .worktrees/<id> directory). All subtasks ended up sharing one directory, causing file conflicts and git errors when concurrent workers tried to operate in the same worktree. Skip path inheritance for worktree workspaces so create_task derives a fresh .worktrees/<child-id> path from the project repo for each subtask. Dir and scratch inheritance remain unchanged.
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Comment — Clean fix
Small, focused fix that prevents kanban subtasks from inheriting the parent's worktree path. Each subtask now gets its own worktree directory to avoid concurrent worker collisions.
Changes:
tools/kanban_tools.py: Adds a guard so worktree workspace types don't inheritworkspace_pathfrom the parent task. The child gets a fresh<repo>/.worktrees/<task-id>path viacreate_task.tests/tools/test_kanban_tools.py: New test verifying that worktree subtasks get their own path, not the parent's.
Assessment:
- Well-scoped: 2 files, 36 additions
- Test coverage for the specific scenario
- Comment explains the rationale clearly
- No security concerns
Reviewed by Hermes Agent
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
Inlines local send attachments as data URIs for Signal RPC calls. When signal-cli runs in a separate container without shared filesystem access, raw file paths are not dereferenceable. The fix converts local file paths to data:mime;base64,... URIs at the RPC boundary, preserving already-inlined, remote, or missing attachments. Clean implementation with good test coverage for conversion, no-op cases, and RPC integration.
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused collision fix. The current-head premise is real: tools/kanban_tools.py:905-913 copies the running worktree task's persisted concrete path, and hermes_cli/kanban_db.py:5709-5711 reuses an existing linked checkout.
Problems
- The proposed guard drops the repository anchor for unlinked worktree tasks. If the parent has no
project_idand the board has nodefault_workdir, the child has no path; dispatch then raises athermes_cli/kanban_db.py:5672-5699. Derive the parent repository root as the child anchor instead of dropping it. - The added test (
tests/tools/test_kanban_tools.py:807-826) uses a fake non-repository path and only checks inequality, so it accepts a null child path without proving a dispatchable distinct worktree.
Suggested changes
- Cover a real temporary git repository through dispatch and assert separate child/parent linked worktree paths and branches under the same repository.
Automated hermes-sweeper review.
| # directory. create_task will derive a fresh | ||
| # <repo>/.worktrees/<task-id> from the project repo. | ||
| if workspace_kind != "worktree": | ||
| workspace_path = _self_task.workspace_path |
There was a problem hiding this comment.
For an unlinked parent worktree, skipping inheritance leaves the child without a repository anchor. create_task can only derive a fresh path from a resolved project or board default; otherwise dispatch fails. Please derive and pass the parent repository root as the child anchor rather than dropping the path.
|
Closing as superseded by #70143 (merged, SHA 781968b). Your PR was the earliest in this cluster to flag the workspace-inheritance bug (June 28) — thank you. The merged change removed the implicit literal-path inheritance in |
What does this PR do?
Fixes concurrent subtask worktree collision in kanban's worktree workspace mode. When a parent task uses
workspace_kind=worktreeand spawns multiple child tasks, all children inherited the parent'sworkspace_path(its own.worktrees/{parent_task_id}directory) instead of getting their own. This caused file conflicts and git errors when concurrent workers operated in the same directory.Related Issue
Fixes #53983
Type of Change
Changes Made
tools/kanban_tools.py: Skipworkspace_pathinheritance whenworkspace_kind == "worktree". Each subtask now gets its own worktree derived from the project repo bycreate_task. Dir and scratch workspace inheritance remain unchanged.tests/tools/test_kanban_tools.py: Addedtest_create_worktree_subtask_gets_own_path— verifies a child task inheriting a worktree workspace gets a different path than the parent.How to Test
python -m pytest tests/tools/test_kanban_tools.py -x -q— all 91 tests should passtest_create_worktree_subtask_gets_own_pathdirectly verifies the fix: a child task inheritingworkspace_kind=worktreefrom its parent must have aworkspace_paththat differs from the parent's.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
The root cause is in
tools/kanban_tools.pylines 820-826 (workspace inheritance). Before this fix, line 826 unconditionally copied the parent'sworkspace_pathto the child. After the fix, worktree workspaces skip path inheritance socreate_taskinkanban_db.pyderives a fresh.worktrees/{child-task-id}path.