feat(FN-4098): document branch conflict recovery feature
Adds documentation for branch conflict recovery (FN-4098), covering the new CLI command, executor branch rename setting, recovery workflow, and delivery artifacts across the CLI reference, settings reference, and task management docs, with a changeset for the `@runfusion/fusion` package. Fusion-Task-Id: FN-4098
This commit is contained in:
5
.changeset/fn-4098-branch-recovery-docs.md
Normal file
5
.changeset/fn-4098-branch-recovery-docs.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Documented the `fn task branch-recovery` CLI flow and the `executorAllowSiblingBranchRename` project setting.
|
||||
@@ -459,20 +459,6 @@ fn task pause FN-001
|
||||
fn task unpause FN-001
|
||||
```
|
||||
|
||||
### Branch recovery
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001
|
||||
fn task branch-recovery FN-001 --reclaim fusion/fn-001
|
||||
fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes
|
||||
```
|
||||
|
||||
Use `fn task branch-recovery` when executor branch allocation fails because the canonical task branch is already checked out elsewhere.
|
||||
|
||||
- No flags: inspect canonical + sibling recovery candidates, including tip SHA, attached worktree path, and stranded commits.
|
||||
- `--reclaim <branch>`: point the task back at an existing canonical/sibling branch so the next executor run resumes from that branch.
|
||||
- `--discard <branch> --yes`: explicitly delete a stranded branch/worktree. `--yes` is required for destructive cleanup.
|
||||
|
||||
### Node routing controls
|
||||
|
||||
```bash
|
||||
@@ -506,6 +492,44 @@ fn task unarchive FN-001
|
||||
fn task delete FN-001 --force
|
||||
```
|
||||
|
||||
### Branch conflict recovery
|
||||
|
||||
Use `fn task branch-recovery` when executor branch allocation fails because the canonical task branch is already checked out elsewhere. By default, the command lists every recovery candidate for the task, including the branch tip SHA, attached worktree path (if any), and stranded commit subjects that are not reachable from the current run start point.
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001
|
||||
fn task branch-recovery FN-001 --reclaim fusion/fn-001-2
|
||||
fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes
|
||||
```
|
||||
|
||||
| Option | Description |
|
||||
|---|---|
|
||||
| `--reclaim <branch>` | Point the task at an existing canonical or sibling branch so the next executor run resumes from that branch without rewriting commits. |
|
||||
| `--discard <branch>` | Delete a stranded sibling branch and its worktree. Fusion refuses to run this destructive action unless `--yes` is also supplied. |
|
||||
| `--yes` | Confirm destructive discard when `--discard` is used. |
|
||||
|
||||
Example inspect output:
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001
|
||||
|
||||
Branch recovery candidates for FN-001
|
||||
Canonical branch: fusion/fn-001
|
||||
Current task branch: fusion/fn-001
|
||||
Current task worktree: /repo/.worktrees/fn-001
|
||||
• fusion/fn-001 (canonical)
|
||||
tip: 0123456789abcdef0123456789abcdef01234567
|
||||
worktree: /repo/.worktrees/fn-001
|
||||
stranded commits:
|
||||
- 0123456789ab fix: preserve stranded commits
|
||||
• fusion/fn-001-2
|
||||
tip: fedcba9876543210fedcba9876543210fedcba98
|
||||
worktree: (not attached to a worktree)
|
||||
stranded commits: none
|
||||
```
|
||||
|
||||
See [Task Management → Branch conflict recovery](./task-management.md#branch-conflict-recovery) for the operator workflow and [Settings Reference → executorAllowSiblingBranchRename](./settings-reference.md#executorallowsiblingbranchrename) for the legacy opt-out setting.
|
||||
|
||||
### GitHub integration
|
||||
|
||||
```bash
|
||||
|
||||
@@ -212,7 +212,7 @@ Override precedence for direct merges is:
|
||||
| `testCommand` | `string` | `undefined` | Merge-time test command (hard gate). When unset, Fusion auto-detects from lockfile. |
|
||||
| `buildCommand` | `string` | `undefined` | Merge-time build command (hard gate). |
|
||||
| `recycleWorktrees` | `boolean` | `false` | Reuse worktrees from a pool for faster startup. |
|
||||
| `executorAllowSiblingBranchRename` | `boolean` | `false` | Escape hatch for legacy branch-collision behavior. When `false` (default), executor branch-name collisions fail loudly, leave the task in `todo` with `status: "failed"`, and surface stranded commits for explicit recovery. When `true`, Fusion restores the old silent sibling-branch rename flow (`fusion/<task-id>-2`, `-3`, …), which is discouraged because it can hide prior work behind suffixed branches. |
|
||||
| `executorAllowSiblingBranchRename` | `boolean` | `false` | Opt back into the legacy executor behavior that silently allocates sibling branches (`fusion/<task-id>-2`, `-2-2`, …) when the canonical task branch is already checked out elsewhere. When disabled (default), branch conflicts fail loudly, leave the task in `todo` with `status: "failed"`, and expose stranded commits for explicit recovery via [`fn task branch-recovery`](./cli-reference.md#fn-task). See [Task Management → Branch conflict recovery](./task-management.md#branch-conflict-recovery). The dashboard Settings modal exposes the same toggle with warning copy because this legacy mode is discouraged. |
|
||||
| `worktreeNaming` | `"random" \| "task-id" \| "task-title"` | `"random"` | Naming mode for new worktree directories. |
|
||||
| `taskPrefix` | `string` | `"FN"` | Prefix used for newly generated task IDs. |
|
||||
| `includeTaskIdInCommit` | `boolean` | `true` | Include task ID as commit scope in generated commits. |
|
||||
|
||||
@@ -143,30 +143,6 @@ Task branch fields are intentionally distinct:
|
||||
|
||||
`PrInfo.baseBranch` is unchanged and continues to represent pull-request target branch metadata.
|
||||
|
||||
### Loud branch-conflict recovery
|
||||
|
||||
When the executor tries to allocate the canonical task branch (`fusion/<task-id>`) and finds that branch already checked out in another live worktree, Fusion now **fails loudly by default** instead of silently forking work onto `fusion/<task-id>-2`, `-3`, and similar siblings.
|
||||
|
||||
Default behavior:
|
||||
- task moves from `in-progress` back to `todo`
|
||||
- task `status` becomes `"failed"`
|
||||
- task keeps recovery context on the canonical branch/worktree metadata
|
||||
- task lifecycle logs and agent logs include the existing tip SHA plus stranded commit subjects
|
||||
|
||||
Recovery is explicit:
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001
|
||||
fn task branch-recovery FN-001 --reclaim fusion/fn-001
|
||||
fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes
|
||||
```
|
||||
|
||||
- **Inspect** lists the canonical branch and any sibling branches with tip SHA, attached worktree path, and stranded commits.
|
||||
- **Reclaim** updates task metadata so the next executor run resumes from the chosen branch/worktree instead of allocating a fresh sibling.
|
||||
- **Discard** removes a selected stranded branch/worktree only when `--yes` is supplied.
|
||||
|
||||
If you must preserve the old silent suffixing flow for a legacy workflow, set project setting `executorAllowSiblingBranchRename=true`. This is discouraged because it can hide earlier commits behind suffixed sibling branches and make recovery less obvious.
|
||||
|
||||
### Dependency reconciliation guidance
|
||||
|
||||
When a task was created to resolve a temporary failure state in another task (for example, a preserved `in-review/failed` merge condition), its dependency contract may become stale after recovery.
|
||||
@@ -193,6 +169,42 @@ Recommended pattern:
|
||||
|
||||
Do **not** patch `.fusion/fusion.db` directly without synchronizing `.fusion/tasks/*/task.json` through a supported store-backed path.
|
||||
|
||||
## Branch conflict recovery
|
||||
|
||||
When the executor tries to allocate the canonical task branch (`fusion/<task-id>`) and finds that branch already checked out in another live worktree, Fusion now fails loudly by default instead of silently renaming the run onto `fusion/<task-id>-2`, `-3`, or similar sibling branches. See [CLI Reference → Branch conflict recovery](./cli-reference.md#branch-conflict-recovery) for the command reference and [Settings Reference → executorAllowSiblingBranchRename](./settings-reference.md#executorallowsiblingbranchrename) for the legacy opt-out setting.
|
||||
|
||||
1. **When this happens**
|
||||
|
||||
The executor refuses the branch allocation, moves the task from `in-progress` back to `todo`, sets `status: "failed"`, preserves the branch/worktree recovery metadata, and records the existing tip SHA plus stranded commit subjects in the task lifecycle log and structured agent log.
|
||||
|
||||
2. **Inspect candidates**
|
||||
|
||||
Run the recovery command with no flags to list every matching canonical or sibling branch. The output includes the tip SHA, any attached worktree path, and the stranded commits that are not reachable from the run's start point.
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001
|
||||
```
|
||||
|
||||
3. **Reclaim**
|
||||
|
||||
Reclaim points the task back at an existing canonical or sibling branch so the next executor run resumes there instead of allocating a new sibling. No commits are rewritten; Fusion only updates the task metadata.
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001 --reclaim fusion/fn-001-2
|
||||
```
|
||||
|
||||
4. **Discard**
|
||||
|
||||
Discard deletes a stranded sibling branch and its worktree when you have confirmed the old work is no longer needed. `--yes` is mandatory because the action is destructive.
|
||||
|
||||
```bash
|
||||
fn task branch-recovery FN-001 --discard fusion/fn-001-2 --yes
|
||||
```
|
||||
|
||||
5. **Opt-out / legacy mode**
|
||||
|
||||
If you must preserve the pre-FN-4068 behavior for a legacy workflow, enable [`executorAllowSiblingBranchRename`](./settings-reference.md#executorallowsiblingbranchrename). That restores silent suffixing onto sibling branches, but it is discouraged because it recreates the same hidden-work / data-loss pattern that motivated loud branch-conflict recovery in the first place.
|
||||
|
||||
## Task Execution Modes
|
||||
|
||||
Each task has an execution mode that controls how the executor agent approaches the task:
|
||||
|
||||
Reference in New Issue
Block a user