Workdir module — cache clone, worktree lifecycle, per-agent git identity #3
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As the runAgent code path, I want a
workdir.tsmodule that owns one cache clone per repo, creates and reuses per-(agent, branch) worktrees, and surfaces git identity + auth helpers, so that we stop re-cloning from Forgejo on every dispatch and worktree state survives between turns.Acceptance criteria
Module surface (
src/workdir.ts)cachePath(repo): string— returns~/.cache/claude-hooks/repos/<owner>/<name>worktreePath(agent, repo, branch): string— returns~/.cache/claude-hooks/worktrees/<agent>/<owner>__<name>__<branch>(branch slashes encoded)ensureCacheClone(repo, agent): Promise<void>— clones tocachePath(repo)if missing; idempotent; uses agent's auth via the strategy chosen in the spike issuefetchLatest(repo, agent): Promise<void>— runsgit fetch origininside the cache clone with the agent's authacquireWorktree(repo, agent, branch): Promise<string>— creates worktree if absent, reuses if present (verify branch matches); returns absolute pathreleaseWorktree(repo, agent, branch, opts: { keep?: boolean }): Promise<void>—keep: true(default) is a no-op;keep: falseremoves the worktree and prunesgitIdentityEnv(agent): Record<string, string>— returnsGIT_AUTHOR_*/GIT_COMMITTER_*env varsgitAuthEnv(agent): Record<string, string>— returns env vars implementing the auth strategy from the spike (likelyGIT_ASKPASS+ a per-agent script path)Behaviour
Bun.spawn; non-zero exits surface as thrownErrorwith stderr included--filter=blob:none(or--depth=N) — pick one based on Forgejo support; document the choice(agent, repo)are safe (worker FIFO already serialises but the module should not assume it)git statusfails), the module nukes it and re-clones — log a warningTests (
src/workdir.test.ts)acquireWorktreethenacquireWorktreeagain on the same key → second call returns same path, no errorreleaseWorktree({ keep: false })removes the directory andgit worktree listno longer shows it.git/HEAD) → nextensureCacheCloneheals ittmpdir()and clean up after themselvesOut of scope
runAgent(separate story)References
git worktreedocs: https://git-scm.com/docs/git-worktreeDependencies
main(apply spike decisions; spike branch itself is throwaway)