FN-9161: support operator workspace branches
Allow workspace tasks to use one operator-selected branch consistently across every sub-repository while preserving ownership during recovery. - validate and persist operator branch provenance at task creation and update boundaries - reuse custom branches across workspace worktrees, PR flows, cleanup, and self-healing without deleting operator-owned refs - expose branch validation in task forms and document the workspace behavior - add coverage and a release changeset for shared custom branch handling Files changed: .changeset/fn-9161-workspace-custom-branch.md | 7 ++ docs/workspaces.md | 6 ++ packages/cli/src/commands/pr.ts | 10 ++- packages/cli/src/commands/task-lifecycle.ts | 10 +-- packages/cli/src/commands/task.ts | 4 +- packages/cli/src/extension.ts | 2 +- .../core/src/__tests__/branch-assignment.test.ts | 37 ++++++++++ .../task-update-awaiting-approval-reason.test.ts | 8 +++ .../core/src/async-stores/async-mission-store.ts | 1 + packages/core/src/branch/branch-assignment.ts | 64 +++++++++++++++++ packages/core/src/index.gate.ts | 7 ++ packages/core/src/index.ts | 7 ++ packages/core/src/missions/mission-store.ts | 1 + packages/core/src/store.ts | 2 +- packages/core/src/task-store/branch-context.ts | 35 +++++++-- packages/core/src/task-store/merge-queue-ops.ts | 31 ++++---- packages/core/src/task-store/task-creation.ts | 30 ++++++++ packages/core/src/task-store/task-mutation-ops.ts | 18 ++++- packages/core/src/task-store/task-update.ts | 60 ++++++++++++++-- packages/core/src/types.ts | 5 ++ packages/core/src/types/task/task-core.ts | 20 +++++- packages/dashboard/app/components/NewTaskModal.tsx | 25 +++++-- packages/dashboard/app/components/TaskForm.tsx | 18 ++++- .../app/components/__tests__/NewTaskModal.test.tsx | 12 ++++ packages/dashboard/src/pr-conflict-resolver.ts | 14 ++-- packages/dashboard/src/routes/branch-selection.ts | 7 ++ .../dashboard/src/routes/register-git-github.ts | 18 +++-- .../src/routes/register-task-workflow-routes.ts | 17 ++++- .../engine/src/__tests__/worktree-hooks.test.ts | 6 ++ .../engine/src/__tests__/worktree-pool.test.ts | 8 +++ .../src/auto-recovery-handlers/branch-worktree.ts | 20 +++--- .../engine/src/execution/step-session-executor.ts | 6 +- .../src/executor/build-foreach-worktree-deps.ts | 5 +- .../engine/src/executor/create-task-done-tool.ts | 8 +-- packages/engine/src/executor/dep-abort-cleanup.ts | 4 +- packages/engine/src/executor/mark-stuck-aborted.ts | 2 +- .../src/executor/release-pre-execution-worktree.ts | 2 +- packages/engine/src/executor/run-implementation.ts | 14 ++-- .../src/executor/task-done-refusal-handler.ts | 4 +- .../executor/worktree-branch-conflict-handle.ts | 10 +-- .../src/executor/worktree-cleanup-conflicting.ts | 39 +++++----- .../src/executor/worktree-create-conflict.ts | 1 + .../engine/src/executor/worktree-stale-branch.ts | 9 +++ .../src/healing/restart-recovery-coordinator.ts | 2 +- packages/engine/src/merger.ts | 33 +++++---- .../src/recovery/foreign-only-contamination.ts | 8 ++- packages/engine/src/self-healing.ts | 82 +++++++++++++++------- .../engine/src/worktree/worktree-acquisition.ts | 52 ++++++++++---- packages/engine/src/worktree/worktree-backend.ts | 42 ++++++++--- packages/engine/src/worktree/worktree-hooks.ts | 24 +++++-- packages/engine/src/worktree/worktree-names.ts | 13 ++++ packages/engine/src/worktree/worktree-pool.ts | 17 ++++- 52 files changed, 708 insertions(+), 179 deletions(-) Fusion-Task-Id: FN-9161 Fusion-Task-Lineage: 5b0b9ecc-bead-471f-96f7-bec6698b69fc Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -65,6 +65,12 @@ The tool accepts only a configured repository name and returns an isolated, task
|
||||
|
||||
Fusion adds acquired member paths to the task's active-worktree set, so liveness and ownership checks see the root plus every active member worktree. A live remembered worktree is reused across a resumed task or executor restart. If another task is acquiring the same member, the tool returns a temporary busy error asking the agent to retry `fn_acquire_repo_worktree` shortly; acquire a different member or retry rather than editing the original repository checkout.
|
||||
|
||||
### Custom working branches
|
||||
|
||||
In the task form's **Advanced** branch controls, an operator can enter one branch name for a workspace task. Fusion validates the name as a safe Git branch/ref name: it rejects empty or whitespace-padded names, spaces or control characters, `..`, `@{`, a leading `-`, empty path segments, dot-prefixed segments, and trailing `.` or `.lock` segments. Fusion applies the exact valid name in every acquired sub-repository. If the branch already exists in a member repository, Fusion attaches to it without recreating it; it still refuses a branch that is checked out by another live worktree.
|
||||
|
||||
Fusion records whether a branch was written by an operator or by Fusion. An operator-supplied branch is retained after merge, teardown, and recovery, including a name under the `fusion/` namespace, and PR creation uses it as the head branch. Fusion continues to clean up branches it created itself, including canonical `fusion/<task-id>` branches and entry-point-derived branch-group branches. Ownership follows recorded write provenance, not a branch-name prefix: editing a branch-group task transfers the selected branch to the operator; a later Fusion group reassignment takes ownership back. Shared-group members still work on their canonical task branch. Older tasks without a provenance marker retain their existing behavior.
|
||||
|
||||
## Choosing the base branch
|
||||
|
||||
Set a task's `baseBranch` in the New Task form or Task Detail to choose the base for a workspace task. At acquisition, Fusion verifies that ref independently in every sub-repository. Where it resolves, it is that worktree's start point, base-SHA anchor, land target, and revert target. Where it does not resolve, Fusion safely falls back to that repository's own integration branch rather than failing acquisition; the requested and selected refs are recorded in the task log and Task Detail, while run audit stores only the task/repository identifiers and fixed decision outcome.
|
||||
|
||||
Reference in New Issue
Block a user