Consolidate duplicated git helpers into shared git-context - #867
Merged
Conversation
resolveRepoRoot (--show-toplevel flavor), resolveCurrentBranch, and normalizePath each had drifted copies across worktree.ts, github/pr.ts, and git-context.ts. git-context.ts now owns the canonical helpers (resolveCheckoutRoot, resolveCurrentBranch, exported normalizePath); worktree.ts and pr.ts keep thin wrappers that rewrap failures in their own error classes with the exact same messages and status codes. The identical CommandRunner type declared in five files now lives once in shared/lib/run-command.ts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Consolidates three drifted helper duplications in
apps/server/src/shared/(top backlog item from the 2026-07-21 tech-debt audit):resolveRepoRoothad 3 implementations: the robust worktree-aware one ingit-context.ts, plus plain--show-toplevelcopies ingit/worktree.tsandgithub/pr.tsthat differed only in error class (andpr.tsskipped path normalization).git-context.tsnow exports a canonicalresolveCheckoutRoot(--show-toplevelsemantics, injectable command runner, optional timeout);worktree.tsandpr.tskeep 6-line wrappers that rewrap failures inGitWorktreeError/GitHubPrErrorwith the exact same messages and status codes.resolveCurrentBranchwas byte-identical inworktree.tsandpr.ts— now exported once fromgit-context.ts, andprobeGitContextreuses it too.normalizePathexisted ingit-context.ts(with a root-path guard) andworktree.ts(without) — the guarded version is now exported and shared.CommandRunner— the identical injectable-runner type was declared locally in 5 files (worktree.ts,pr.ts,base-ref.ts,agent-diff.ts,diff-stats.ts); it now lives once inshared/lib/run-command.tsnext toRunCommandResult.Net −35 lines. No git command lines, options, error messages, or status codes changed; the only observable delta is that
pr.ts's repo root is now trailing-slash-normalized like every other caller (a no-op for real--show-topleveloutput).Why it's tech debt
Three copies of the same git plumbing had already drifted (different error classes, inconsistent normalization) and sat directly on the worktree-creation path, where the #794 concurrency fix showed how sensitive this code is to subtle divergence.
Validation
pnpm run check✅pnpm run test— 2390 server / 541 web / 60 misc ✅pnpm run test:e2e— 175 passed, 12 skipped ✅Queued next
Top of the tech-debt backlog: deduplicating the ~90-line AgentTypeCombobox/AgentTypeSelect pair in the web app.
🤖 Generated with Claude Code