feat(FN-5329): remove orphan rescue and branch-recovery primitives from eng

Removes the branch-recovery CLI surface, orphan-rescue engine primitives, and their associated tests (over 1,500 lines deleted), while restoring a minimal prune-only orphan branch sweep with proper git audit mutation types. Documentation across `cli-reference.md`, `task-management.md`, and `AGENTS.m

Fusion-Task-Id: FN-5329
This commit is contained in:
Fusion (runfusion.ai)
2026-05-20 16:42:50 -07:00
committed by gsxdsm
parent 0e5cb4d292
commit fd202e9356
33 changed files with 131 additions and 1644 deletions

View File

@@ -830,25 +830,14 @@ export async function reapOrphanWorktrees(
return removed;
}
/** Columns where the merger handles branch cleanup — skip these during orphan scanning. */
/** Columns where merger/finalization owns branch lifecycle. */
const MERGER_MANAGED_COLUMNS: ReadonlySet<Column> = new Set(["in-review", "done"]);
/**
* Scan for orphaned `fusion/*` branches that are not associated with any
* non-archived, non-merger-managed task.
*
* Lists all local branches matching the `fusion/*` pattern, then compares
* against branches stored on tasks (via `task.branch` or derived as
* canonicalFusionBranchName(taskId)). Branches belonging to tasks in the
* `in-review` or `done` columns are excluded because the merger is
* responsible for cleaning those up.
*
* @param rootDir — Project root directory (git working tree)
* @param store — Task store for listing tasks and their branch assignments
* @returns Array of orphaned branch names
* Return local `fusion/*` branches not associated with any active task.
* Branches tied to merger-managed or archived tasks are excluded.
*/
export async function scanOrphanedBranches(rootDir: string, store: TaskStore): Promise<string[]> {
// List all local branches matching fusion/*
let allBranches: string[];
try {
const result = await execAsync("git branch --list 'fusion/*'", {
@@ -868,23 +857,14 @@ export async function scanOrphanedBranches(rootDir: string, store: TaskStore): P
if (allBranches.length === 0) return [];
// Build set of branches associated with active (non-archived, non-merger-managed) tasks
const tasks = await store.listTasks({ slim: true, includeArchived: false });
const activeBranches = new Set<string>();
for (const task of tasks) {
// Skip tasks in columns where the merger handles branch cleanup
if (MERGER_MANAGED_COLUMNS.has(task.column)) continue;
// Also skip archived tasks
if (task.column === "archived") continue;
// Use stored branch name if available, otherwise derive from task ID
if (task.branch) {
activeBranches.add(task.branch);
}
// Always add the derived name too — the task may not have `branch` set yet
if (task.branch) activeBranches.add(task.branch);
activeBranches.add(canonicalFusionBranchName(task.id));
}
// Return branches not associated with any active task
return allBranches.filter((branch) => !activeBranches.has(branch));
}