* fix(mcp): restore live add-branch worktrees * fix(mcp): reject deferred live branch additions * docs(mcp): clarify live branch response contract
4.9 KiB
ADR-2026-07-22-runtime-mutable-task-workspace-sources: Runtime-Mutable Task Workspace Sources
Status: accepted (amended by ADR-2026-07-27-legacy-add-branch-live-rescan) Date: 2026-07-22 Area: backend, frontend, protocol
Context
Task creation can select multiple repositories, but the UI restricts that layout to the worktree
executor. After launch, only the task-mode add_branch_to_task_kandev MCP path can append a source,
and it is both Git-only and worktree-only. Repository-less tasks may start in one arbitrary host
folder, but that single workspace_path is not a durable mixed-source model. Exposing the existing
MCP call in the Files panel would therefore report success only for a subset of tasks and could not
represent arbitrary folders.
Decision
Task workspace sources are durable task-scoped attachments, while executor filesystems remain materialized views of those attachments.
Existing repository identity and Git behavior stay in task_repositories. Arbitrary folders use a
separate task_workspace_folders relation rather than migrating every repository consumer to a new
polymorphic table. Services expose a combined source projection when callers need the complete
workspace.
A batch AttachWorkspaceSources service becomes the mutation boundary for HTTP, UI, and the
add_workspace_sources_kandev MCP tool. It validates the entire batch, persists attachments
transactionally, materializes them through an executor-capability interface, asks agentctl to adopt
and rescan the effective workspace root, and publishes events only after success. Failure rolls
back newly created durable records and owned filesystem entries without touching pre-existing
sources.
The legacy add_branch_to_task_kandev tool retains its worktree-only live-rescan behavior. It may
reuse transactional persistence helpers, but it does not use runtime workspace adoption or its
idle/restart policy. See
ADR-2026-07-27-legacy-add-branch-live-rescan.
Executor adapters own placement and transport:
- local and worktree environments use live references to explicitly trusted host folders and may re-root an idle execution into a Kandev-owned task root;
- Docker, SSH, Sprites, and future remote runtimes materialize repositories in their own workspace but do not accept arbitrary host-folder attachments;
- agentctl owns workspace-root adoption, repository tracker reconciliation, and the file-tree refresh boundary common to every runtime.
Batch workspace-source attachment is rejected while a turn or tool call is active. An idle
environment may be restarted when its process working directory cannot be changed safely in place.
The legacy worktree-only add_branch_to_task_kandev compatibility lane may run during its invoking
turn and updates tracker scope without changing the agent process working directory. Provider
credentials stay behind the existing backend/executor clone boundary and never enter persisted
URLs or agent-visible source metadata.
Consequences
- The Files panel,
add_workspace_sources_kandev, and future batch automation use one source-attachment contract. The legacy add-branch tool remains an explicit worktree-only compatibility exception. - Existing repository, diff, PR, and branch consumers keep their current relational model.
- Arbitrary folders can coexist with Git sources without pretending to be repositories.
- Runtime backends must implement explicit source materialization and rollback capabilities; previously implicit single-repository assumptions become testable interfaces.
- Folder attachment remains a host-executor capability. Remote/container callers receive an explicit unsupported-source error instead of a partial copy with different persistence semantics.
- Idle-only mutation avoids changing a process working directory during an active command, at the cost of making the UI wait for the current turn to finish.
Alternatives Considered
- Expose
add_branch_to_task_kandevdirectly in the Files panel. Rejected because it is worktree-only, Git-only, single-item, and cannot support the requested executor or folder scope. - Replace
task_repositorieswith one polymorphic source table. Rejected because it forces a high-risk migration across mature Git, PR, diff, and session-worktree code for no user-visible benefit. - Treat arbitrary folders as repositories. Rejected because non-Git folders have no branch, diff, PR, or repository identity and would leak invalid assumptions into existing consumers.
- Copy host folders into remote runtimes as snapshots. Rejected because a detached copy is not equivalent to adding the selected live folder and introduces size, retention, and stale-data expectations.
- Continuously synchronize host folders with remote runtimes. Rejected because conflict resolution, deletion propagation, watching, and credential boundaries form a separate product and reliability problem.