Replace the boolean isGitRepository() check with a tri-state Git detection so environmental git failures (dubious ownership, missing git binary, timeouts) are no longer misreported as "not a Git repository", which previously blocked all task execution in valid repos and survived engine restarts. - Add detectGitRepository() in worktree-pool.ts returning repo / not-repo / error (with reason: dubious-ownership, git-missing, timeout, unknown), classified from git's stderr; bound the git rev-parse call with a 10s timeout and maxBuffer; keep isGitRepository() as a backward-compatible wrapper - Route the executor dispatch preflight guard through detectGitRepository(): only emit the original "not a Git repository / run git init" fatal on a positive not-repo verdict; on error, throw a distinct accurate error naming the real git failure, including the safe.directory remedy for dubious ownership - Route the in-process runtime startup warning through the same tri-state detection so it only warns "not a Git repository" on a positive not-repo verdict - Add a regression test locking extractWorktreeConflictInfo() to NOT misclassify a dubious-ownership git worktree add failure as not-git-repo - Add targeted tests across worktree-pool, executor-worktree, and in-process-runtime test suites covering repo/not-repo/dubious-ownership/git-missing/timeout classifications on Windows OneDrive-style and POSIX paths - Add changeset and a docs/solutions/logic-errors write-up of the false-negative root cause and fix Files changed: .changeset/fn-7799-git-detection-false-negative.md | 7 +++ .../logic-errors/git-detection-false-not-repo.md | 54 ++++++++++++++++ .../engine/src/__tests__/executor-worktree.test.ts | 61 +++++++++++++++++++ .../engine/src/__tests__/worktree-pool.test.ts | 71 +++++++++++++++++++--- packages/engine/src/executor.ts | 38 +++++++++--- .../runtimes/__tests__/in-process-runtime.test.ts | 53 ++++++++++++++-- packages/engine/src/runtimes/in-process-runtime.ts | 16 ++++- packages/engine/src/worktree-pool.ts | 66 ++++++++++++++++++-- 8 files changed, 334 insertions(+), 32 deletions(-) Fusion-Task-Id: FN-7799 Fusion-Task-Lineage: 25a84283-bf47-472b-8a98-a10bf7e494de Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2.9 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 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Git probe failures falsely reported as not a repository | 2026-07-10 | docs/solutions/logic-errors | engine Git detection + task executor preflight | logic_error | engine |
|
error_classification_collapse | code_fix | high |
|
|
Git probe failures falsely reported as not a repository
Problem
A boolean Git repository probe collapses every git rev-parse --git-dir failure into false. That makes a positive non-repo response indistinguishable from environmental failures such as fatal: detected dubious ownership, spawn ENOENT, or a hung Git command. The executor then tells operators to run git init even when the checkout is already a valid repository, blocking all task execution until the underlying Git environment is fixed.
Solution
Use tri-state Git detection: repo, not-repo, or error. Only the not-repo state may produce the existing "Project directory is not a Git repository" / git init guidance. Environmental failures surface the original Git error instead; dubious ownership also includes the explicit safe-directory command:
git config --global --add safe.directory "<project-root>"
The probe remains async and bounded with a timeout, so a hung Git process cannot silently become a false non-repo verdict.
Verification
Cover the invariant at every consumer of repository detection:
- Detection helper: genuine repo →
repo; genuinefatal: not a git repository→not-repo; dubious ownership, missing Git, and timeout →error. - Executor guard:
not-repopreserves the legacy log/error strings;errorlogs and throws a distinct message withoutgit initguidance and does not attemptgit worktree add. - Runtime startup:
not-repopreserves the startup warning;errorwarns with the real Git failure and any safe-directory remedy. - Worktree-add conflict parsing:
detected dubious ownershipstaysunknown, notnot-git-repo, so it does not become a non-retryablegit initerror.
Prevention
Do not use boolean wrappers at guardrails that need operator-facing diagnosis. Keep positive semantic states separate from probe failures, preserve stderr in the result, and add tests for both a POSIX path and a Windows path with spaces passed through cwd rather than interpolated into the shell command.