A branches/ directory that is not a git worktree is left alone, never acted on as the main checkout (#1654) - #1656
Conversation
… acted on as the main checkout (#1654) A checkout removed by hand, then a failed-start marker written into its path, left a directory under `branches/` that git did not know as a worktree. Git answers inside any directory of a repository, so every command the framework ran there acted on the enclosing repo: the sweep read the run's branch as `main`, tried to commit the user's checkout and push the user's `main` (it failed only because origin was ahead), the rename pass linked `main ->` the directory, and #1653's first cut judged `main` for deletion. The store now asks the one question that tells the two apart — is git's top level this very directory — and every consumer of a `branches/<run>` path goes through it: removal refuses and reports ("not a git worktree; left alone") before any git runs, the rename pass links nothing for it, teardown records no branch from it. And the failed-start marker is no longer written where the checkout is gone, which is how the directory came to exist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 automated
An interrupted edit had already written it once before the second edit added it again. Removing the duplicate in a follow-up commit. |
An interrupted edit had written it before the second edit added it again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 automated Dogfooded on the rig from this branch's build, 2026-08-23 15:53 IDT — no agent needed. The residue from this morning was recreated exactly: Daemon restarted; its startup sweep: After: The dashboard's Remove button runs the same |
🤖 automated
Closes #1654.
The bug, plainly
Git answers inside any directory of a repository. A directory under
.the-framework/branches/that is no longer a worktree — on the rig: a checkout I removed by hand, then a failed-start marker written into the path at shutdown — therefore answers for the enclosing repo, i.e. the user's own checkout. Every consumer took that answer as the run's:main, ran the recoverability rule on the user's checkout (git add -A+ commit — the tree happened to be clean), and tried to push the user'smainto origin; it failed only because origin was ahead, and logged that every pass for 12 hoursbranches/main -> tf-agent-…mainas "holds nothing" and rangit branch -D main, stopped only by the primary checkout having it outWhat changes
One question tells a checkout from residue: is git's top level this very directory (
git rev-parse --show-toplevel, both sides realpath'd).isWorktreeRootin the store, andworktreeBranch= the branch read guarded by it. Applied at every place abranches/<run>path is acted on:removeProjectWorktree(teardown, the sweep, the dashboard's Remove button) refuses before any git runs:session …'s directory is not a git worktree; left alone. The sweep reports it once, like any other kept checkout. Nothing is committed, pushed, linked or deleted through it.main ->linkmainmarkFailedStartno longer writes a marker where the checkout is gone — the daemon's log line is the record instead. That is how the residue directory came to exist (second half of the issue).The directory itself is left where it is: the framework cannot know what a non-worktree directory holds, so it reports rather than deletes. Removal is a human
rm.Verification
pnpm test: 1560 node + 799 dashboard, green.isWorktreeRoottrue for the main checkout and a linked worktree, false for a subdirectory, a residue directory, and a directory outside any repo — and the test states the bug directly: a plaincurrentBranchin the residue answers with the enclosing repo's branch,worktreeBranchanswers nothingmainlink for the residue (without the guard the test shows'main'appearing)No per-file SPEC edits (post-wipe, #1655 regenerates them); one
FEATURES-SPEC.mdline.