Conversation
|
Checked for blocking feedback before making any changes:
There is no blocking review, no merge-conflict notice, and no CI_FAILED notice to act on — the required checks simply haven't finished running yet. No code change to make this round. |
|
VERDICT:CHANGES_NEEDED Reviewed against the 6-point rubric (issue #7 "Javaslat"/Expectation: (1) derive the worktree path from the real repo cwd /
Additional blocking gate: CI is not fully green — |
|
VERDICT:CHANGES_NEEDED Second-pass review against the 6-point rubric. Issue #7 Expectation ("Javaslat"): (1) derive the worktree path from the real repo cwd /
Additional blocking gate: CI is not fully green — |
Reproduces the "already exists" failure from #7: when a bootstrap attempt creates a worktree and is never cleaned up, retrying with the same path/branch must reclaim the stale worktree instead of failing.
…mpts Refs #7. `createWorktree` now recovers when the target path/branch was left behind by an earlier attempt that never ran cleanup: it prunes stale git worktree admin state, force-removes a still-registered worktree at the exact target path, or deletes an orphaned directory, then retries the `worktree add` once. `-b` became `-B` so retrying the same branch resets it in place instead of failing with "branch already exists" (git still refuses if the branch is checked out elsewhere, so this can't clobber live work). This is scoped to the single git-driver layer and only ever touches the exact path being created, so it can't disturb unrelated worktrees. Cross-process/cross-host locking (issue point 2) and NFS stale-handle handling on /share (issue point 3) are out of scope for this repo - see PR description. This is partial work on #7, not a full fix, so this message intentionally uses "Refs" rather than a closing keyword.
The manifest-write-failure test relies on chmod 0o400 blocking a write, but root bypasses DAC permission checks, so it fails whenever the suite runs as root (as in this sandbox) independent of any code change. Skip it in that case; it still runs and protects the behavior under a normal non-root CI user.
…le path Reproduces a gap left by the previous reclaim fix (21d2f12): when a prior attempt's path derivation resolves differently than the current one (e.g. a homedir-relative worktreesDir that differs across hosts or restarts), the target branch ends up registered at a different git-worktree path than the one this attempt just computed. Retrying then fails with "already checked out at '<stale path>'" instead of "already exists", which the exact-path-only reclaim doesn't catch.
…rget branch createWorktree's reclaim logic (21d2f12) only checked for a leftover worktree registered at the exact target path. It missed the case where the target *branch* is registered at a different path from an earlier attempt whose path derivation resolved differently (e.g. a homedir-relative worktreesDir differs across hosts, or after that config changes across restarts). `git worktree add -B` then fails with "already checked out at '<other path>'", which the exact-path check doesn't recognize as reclaimable. reclaimConflictingWorktrees now also looks up `git worktree list --porcelain` for an entry matching the target branch ref and reclaims it too, alongside the exact-path case. Still only ever removes entries matching the exact path or the exact target branch, so it can't touch an unrelated worktree, and it only runs after `git worktree add` has already failed, same conservative trigger as before.
8f7f7a4 to
e6acc4d
Compare
|
Addressed the review's points that had concrete code paths: Item 1 (path derivation) + item 4 (blast radius) — new code. The literal ask was to derive Fixed in Cross-process/cross-host locking (issue point 2) and the rpi Item 6 (scope keyword). Valid catch. Rewrote the CI gate. Deferred to whatever the current check-run state is — not something a commit here can force green if it's still running or blocked by the |
Summary
Issue #7 reports that repeated
git worktree addfailures ("already exists") accumulate orphaned worktrees, because a bootstrap attempt that creates a worktree and then fails partway through is never cleaned up — the next retry for the same issue/branch collides with the leftover.This PR fixes that at the git driver layer (
apps/server/src/vcs/GitVcsDriverCore.ts), increateWorktree:git worktree addfailure, it now attempts to reclaim whatever is sitting at the exact target path:git worktree prunefirst, thengit worktree remove --forceif the path is still a registered worktree, or a plain filesystem removal + prune if it's an orphaned directory left behind after the registration was lost. It then retries theaddonce.-bto-Bfor thenewRefNamecase, so retrying with the same branch name resets the branch in place instead of failing with "branch already exists" (git still refuses if that branch is checked out in another live worktree, so this can't clobber active work).This resolves issue point 1 (cleanup not actually happening / orphan accumulation) and part of point 3 (proactive
git worktree prunebefore create) from the issue's root-cause analysis.What's intentionally left out of scope (why this is "Refs", not "Fixes")
withRepoGitLockis in-process only (keyed bygitCommonDirwithin a single server instance). Protecting against two separate server processes (e.g. mac + rpi, or two redispatch runs) racing on the same shared checkout needs a cross-process lock (e.g. an flock-based lockfile, or a lock service), which is a bigger design decision I didn't want to make unilaterally in this PR./share(issue point 3): the issue calls out/shareNFS-specific stale-handle/lock failure modes on the rpi runner. I don't have an NFS-backed reproduction environment here to validate a fix, so I left this for a follow-up with real repro access.The fix in this PR does make the reported symptom (repeated "already exists" failures from an uncleaned prior attempt) self-healing regardless of host, which should eliminate most of the observed failures even without the cross-process lock.
Test plan
Added a test-first commit (
test(server): cover worktree reclaim on retry with stale leftover) reproducing the exact failure: create a worktree, leave it behind (simulating an uncleaned bootstrap), then retry with the same path/branch and assert it succeeds instead of failing with "already exists". It fails against the pre-fix code and passes after the fix (verified separately before combining commits).Also fixed one unrelated pre-existing failure found while running the full suite:
scripts/update-release-package-versions.test.ts's "preserves manifest write context" test relies onchmod 0o400blocking a write, which root bypasses — it fails in any root-run sandbox/CI independent of this change. Skipped it under root (still runs under normal non-root CI).Verification output
apps/server/src/vcs/GitVcsDriverCore.test.ts(targeted):scriptspackage (targeted, after the skip fix):pnpm lint: exit 0, only pre-existing warnings in files this PR doesn't touch (apps/web/src/components/CommandPalette.tsx,ChatMarkdown.tsx,SidebarUpdatePill.tsx,ThreadTerminalDrawer.tsx).Server typecheck (
vp run --filter t3 typecheck): clean, exit 0.Full-repo
pnpm test(vp run -r test), run twice back-to-back:vp run: 0/12 cache hit (0%), 1 failed— the only failure both times was the same test,apps/web/src/components/chat/MessagesTimeline.test.tsx > keeps assistant changed-files headers sticky below the thread header, timing out under full-monorepo parallel load (not a random flake — it reproduces consistently under this specific load pattern in this sandbox).vitest run src/components/chat/MessagesTimeline.test.tsx, 13/13 passed in 5.7s) and passed in a scopedapps/web-only full run (366/366 passed). This PR never touchesapps/web,apps/mobile, orapps/desktop— the failure is a resource-contention timeout specific to running ~160 test files concurrently on this sandbox's hardware, not a correctness issue.Note:
infra/relay'salchemydependency is pinned tohttps://pkg.ing/alchemy/078ff00, which returns HTTP 404 from this environment — this blocks a full-workspacepnpm install(and thereforevp's auto dependency-status check before lint/test) independent of any change in this PR. Verified by reproducing on a cleanmaincheckout before making any changes. Worked around locally by temporarily excludinginfra/relayfrompnpm-workspace.yamlto install and run the checks above, then reverted that workaround — it is not part of this PR's diff. This is an external resource outage outside this repo's control and unrelated to issue #7; flagging it here since it will block CI too untilpkg.ingis fixed or the dependency is repinned.Closes: partially addresses #7 (see scope notes above).