Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 5f4b7a9e26af0635cfaecfbc55bfe928dd3466d2)
2.8 KiB
2.8 KiB
Empty-repo hardening — implementation plan
Spec: docs/superpowers/specs/2026-07-30-empty-repo-hardening-design.md
Task 1 — GitService: HasHeadCommitAsync + EnsureHeadCommitAsync + friendly unborn error
Files: src/ClaudeDo.Data/Git/GitService.cs,
tests/ClaudeDo.Worker.Tests/Runner/GitServiceBootstrapTests.cs (new)
- Tests first (skip when git unavailable, mirroring
WorktreeManagerTests):- fresh
git initrepo (no commit):HasHeadCommitAsyncfalse; after a commit true. EnsureHeadCommitAsyncon empty repo → true;RevParseHeadAsyncthen succeeds;git ls-tree HEADempty; second call → false.- staged file in empty repo survives bootstrap: still staged, not in the commit.
- corrupt HEAD (write a garbage SHA into
.git/HEADas a detached head):EnsureHeadCommitAsyncthrowsInvalidOperationExceptionmentioning the dir. RevParseHeadAsyncon empty repo: message says "has no commits yet" (no raw "ambiguous argument").
- fresh
- Implement:
HasHeadCommitAsync(rev-parse --verify --quiet HEAD),EnsureHeadCommitAsync(symbolic-ref guard → hash-object/commit-tree/update-ref plumbing behind a staticSemaphoreSlimwith post-acquire re-check), unborn-HEAD message inRevParseHeadAsync. - Build Data + run new tests. Commit
fix(git): bootstrap empty repos with an initial commit.
Task 2 — CommitAsync identity fallback
Files: same two files.
- Test: repo with local
user.name/user.emailset to empty strings →CommitAsyncsucceeds (retry path), commit exists. - Implement: on identity-signature failure, retry once with
-c user.name=ClaudeDo -c user.email=claudedo@local. - Commit
fix(git): fall back to a ClaudeDo identity when git has none.
Task 3 — call sites
Files: src/ClaudeDo.Worker/Runner/WorktreeManager.cs,
src/ClaudeDo.Worker/Planning/PlanningSessionManager.cs,
tests/ClaudeDo.Worker.Tests/Runner/WorktreeManagerTests.cs
- Test:
CreateAsyncon a commit-less repo succeeds; worktree on disk; DB row Active. - Wire
EnsureHeadCommitAsyncintoWorktreeManager.CreateAsync(log info on bootstrap) andPlanningSessionManager.StartAsync. - Full Worker.Tests run. Commit
fix(worktree): auto-bootstrap commit-less repos before creating worktrees.
Task 4 — docs
src/ClaudeDo.Data/CLAUDE.md: GitService bullet gains bootstrap/identity-fallback.docs/open.md: verification item — open a ConPTY session on a freshgit initrepo on a second PC.- Commit
docs: empty-repo hardening notes.
Verification
dotnet test tests/ClaudeDo.Worker.Tests -c Releasegreen.- Manual: task 61609f79… in "Test List" (
C:\Dev\TestRepo, currently commit-less) — opening the ConPTY session must now succeed and leaveC:\Dev\TestRepowith exactly one empty commit by ClaudeDo.