Files
fusion/docs/solutions/logic-errors/repo-root-task-worktree-requeue-loop.md
gsxdsm 7ee1fec22c FN-6861: reject repo-root task worktrees
Prevent stale task metadata from treating the project repository root as a reusable task worktree.

- Classify root-equal task worktree paths as repo-root before registered-worktree checks.
- Clear stale resumed repo-root assignments so acquisition creates a fresh configured task worktree.
- Add structured executor audit metadata and regression coverage for repo-root liveness collisions.
- Document the repo-root requeue-loop invariant and recovery behavior.

Files changed:
 docs/architecture.md                               |  2 +-
 .../repo-root-task-worktree-requeue-loop.md        | 49 ++++++++++++++++
 .../__tests__/executor-worktree-liveness.test.ts   | 23 +++++++-
 .../src/__tests__/worktree-acquisition.test.ts     | 67 +++++++++++++++++++++-
 .../src/__tests__/worktree-pool-liveness.test.ts   | 25 ++++++++
 packages/engine/src/executor.ts                    | 22 ++++++-
 packages/engine/src/worktree-acquisition.ts        |  4 ++
 packages/engine/src/worktree-pool.ts               | 13 ++++-
 8 files changed, 198 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-6861

Fusion-Task-Lineage: d6a4922e-5a21-4037-b2c2-86ff53d8e9e3
2026-06-21 14:28:58 -07:00

3.0 KiB

title, date, category, module, problem_type, component, symptoms, root_cause, resolution_type, severity, related_components, tags
title date category module problem_type component symptoms root_cause resolution_type severity related_components tags
Repo-root task worktree causes executor requeue loop 2026-06-21 docs/solutions/logic-errors engine worktree acquisition + executor liveness logic_error engine
A resumed task is repeatedly requeued to todo with realpath_matches_repo_root
git worktree list includes the project root, so worktree classification treats the main checkout as usable
Acquisition returns the repo root again after recovery, and the executor gate rejects it again
invariant_gap code_fix high
packages/engine/src/worktree-pool.ts (classifyTaskWorktree)
packages/engine/src/worktree-acquisition.ts (resume fallback)
packages/engine/src/executor.ts (pre-session liveness gate)
worktrees
executor
self-healing
liveness
requeue-loop

Repo-root task worktree causes executor requeue loop

Problem

A recovered task can carry task.worktree that canonicalizes to the project repository root. The root is a valid Git worktree and appears in git worktree list, but it is the main checkout, not an isolated task checkout. Before FN-6861, classifyTaskWorktree(rootDir, rootDir) returned usable, so resume acquisition returned the root unchanged. The executor then rejected the same path via realpath_matches_repo_root and requeued the task, setting up an acquisition → gate → requeue loop.

Solution

Make the invariant explicit at the shared classification boundary: the project root is never a usable task worktree. classifyTaskWorktree now compares canonicalized paths and returns classification: "repo-root" for root-equal paths even when Git reports the path as registered.

Because acquireTaskWorktree already treats non-usable resume classifications as self-healable stale metadata, a root-valued task.worktree is cleared and replaced with a fresh checkout under the configured worktrees directory. The executor liveness gate remains defense-in-depth and emits structured worktree:incomplete-detected evidence if a repo-root path still reaches it.

Verification

Cover the invariant at three seams:

  • Classification: real Git repo root registered in git worktree list must classify as repo-root, including canonical-equal variants such as trailing slashes or symlink-normalized paths.
  • Acquisition: resume with task.worktree === rootDir must return a fresh .worktrees/* (or configured worktrees-dir) checkout and must not return the root.
  • Executor diagnostics: if the root reaches the pre-session liveness gate, the audit payload must identify classification: "repo-root", the observed path, the registered snapshot, and that the expected task-worktree pattern excludes the root.

Prevention

Registered Git worktree membership is necessary but not sufficient for task execution. Any new worktree-liveness or self-healing path should call the shared classifier and preserve the distinction between the main checkout (repo-root) and isolated task checkouts under the configured worktrees directory.