Repository navigation
Description
Before submitting
- I searched open and closed issues and did not find a report of this problem.
- I reviewed this report and removed credentials, tokens, private paths, hostnames, and other sensitive data.
Problem
gentle-ai-verify cannot verify work performed in a Git worktree. Its preparation helper scripts/prepare-verifier.mjs rejects any directory that is not an ordinary single-root checkout, so an admitted verifier aborts with exit 1 before running a single probe.
This is deterministic and platform-independent: it is a directory-shape check, not a copy, timeout or artifact problem. It hits the workflow the harness itself prescribes — AGENTS.md requires tracked ODD work to live in <repo-parent>/<repo-name>-worktrees/<worktree-name> — so independent verification is unavailable precisely where ODD work is supposed to happen, and the returned verdict reads like a candidate failure instead of a setup blocker.
Related but distinct: #3009 (isolated preparation reliability: copy, sockets, timeout) and #2986 (Windows whole-worktree copy timeout). Those are about the copy step; this report is about the guard that refuses the source directory before any copy is attempted.
Cause: scripts/prepare-verifier.mjs requires .git to be a real directory and git rev-parse --git-common-dir to resolve to <source>/.git. A linked worktree fails both by construction: .git is a file containing gitdir: …, and --git-common-dir resolves to the main repository's .git, which is the shared object store. The helper is injected for this role only (lib/agents-runner.ts, GENTLE_PI_VERIFIER_PREPARER).
What the guard actually needs is isolation, not checkout shape: not shallow, no objects/info/alternates, no sparse/partial/replace, a stable index, and the worktree contained inside the source. All of those are satisfiable by a linked worktree.
Possible fix:
- Accept either shape:
.gitas a directory, or.gitas a regular file whosegitdir:target resolves under the same common dir (<common>/.git/worktrees/<name>); keep--show-toplevelequal to the source, and keep every existing rejection (shallow, alternates, sparse, partial, replace, index flags) unchanged. - Cover it in
tests/verifier-preparation.test.tswith a realgit worktree addfixture, asserting preparation succeeds and that a shallow or alternates worktree is still refused. - Cheaper alternative if the isolation argument is not accepted: detect a worktree source in the runner and fail the delegation immediately with an actionable message ("verification requires a non-worktree checkout"), instead of letting the subagent spend turns and then emit a FAIL that is indistinguishable from a defect verdict.
- Until then,
docs/delegated-verification.mdshould state that worktrees are unsupported and how to work around it (disposable clone).
Steps to reproduce
- Create a worktree for a repository, exactly as the harness documentation prescribes:
git worktree add ../<repo>-worktrees/feature -b feat/example main - Delegate verification with that worktree as the workspace, e.g.
subagent_runwithagent: "gentle-ai-verify"andworkspace_root: "<path>/<repo>-worktrees/feature". Calling the helper directly shows the same thing:
s=$(mktemp -d) && node "$GENTLE_PI_VERIFIER_PREPARER" "$PWD" "$s" '{"include":[],"checks":["node --test tools/*.test.js"]}'
run from inside the worktree. - Observe exit 1 with
unsupported repository: ordinary single-root Git directory required, and zero probes executed.
Control: the identical candidate in an ordinary clone at the same commit prepares successfully and runs the checks. Observed on Linux with gentle-pi 4.7.0 and Pi 1.5.2, worktree created from Gentleman-Programming/gentle-shell main.
Expected and actual behavior
Expected: the verifier prepares the source it was pointed at (HEAD, index and tracked bytes of a worktree are self-contained), or the runner refuses that delegation up front with an actionable message, before a subagent spends turns on it. A setup failure must be reported as a setup failure, never as a verification verdict.
Actual: preparation exits 1, no check runs, and the only signal is the prose paragraph in the verifier's report; the summary line still reads FAIL. The parent has to infer that the code was never examined.
gentle-pi version
4.7.0
Pi version
1.5.2
Operating system
Linux
Relevant logs or error output (optional)
The delegated verifier ran the documented preparation command and got:
exit 1
unsupported repository: ordinary single-root Git directory required
The guard, from scripts/prepare-verifier.mjs:
if (!lstatSync(join(source, ".git")).isDirectory() || lstatSync(join(source, ".git")).isSymbolicLink() ||
realpathSync(git(source, ["rev-parse", "--show-toplevel"]).trim()) !== source ||
resolve(source, git(source, ["rev-parse", "--git-common-dir"]).trim()) !== join(source, ".git")) fail("unsupported repository: ordinary single-root Git directory required");In a linked worktree, git rev-parse --git-common-dir prints the main repository's .git path, and .git is a file, so this condition always fails.
Injection point, from lib/agents-runner.ts:
if (request.agent.name === "gentle-ai-verify") env.GENTLE_PI_VERIFIER_PREPARER = fileURLToPath(new URL("../scripts/prepare-verifier.mjs", import.meta.url));
Activity
jonasotoaguilar commentedon Nov 14, 2026
Additional reproduction in a separate project: a
gentle-ai-verifydelegation against a linked worktree with uncommitted changes failed during the mandatory Git preparation step withunsupported repository: ordinary single-root Git directory required(exit 1). The verifier reportedprobesRun: 0, so neither the candidate nor baseline checks ran. It could only provide a read-only structural review; the required independent functional verification remained unavailable and blocked delivery. This is the same worktree restriction described above, not evidence of a candidate test failure.