/** * Configuration for WorktreeService */ export interface WorktreeConfig { /** Base directory for worktrees, e.g. '.hula-worktrees' */ basePath: string; /** Repository name, e.g. 'hub-launch' */ repoName: string; /** * Optional repository working directory for the top-level git commands * (`git fetch`, `git worktree add/list/remove`). Used by the multi-repo * `--folder` fan-out so a publish targets the correct member repo. Undefined * runs those commands in the process cwd (historical behavior). Commands that * operate inside the created worktree always use the worktree path itself. */ cwd?: string; } /** * Service for Git worktree operations * Single Responsibility: Temporary worktree management for plan and fix isolation */ export declare class WorktreeService { /** Legacy hardcoded worktree directory for backwards compatibility */ private readonly WORKTREE_DIR; private readonly FIX_WORKTREE_PREFIX; private readonly basePath; private readonly repoName; private readonly cwd?; constructor(config?: WorktreeConfig); /** * Get the worktree directory path for a given type and identifier. * Format: /hula//- */ getWorktreeDir(type: string, identifier: string): string; /** * Validate a path segment to prevent command injection. * Uses a blocklist of known dangerous characters including newlines and null bytes. */ private validatePathSegment; /** * Create a generic worktree at the given path from a specified branch. * @param worktreePath - Absolute path for the new worktree * @param branch - Branch name or ref to check out (e.g. 'origin/main', 'fix/issue-42') * @param detached - If true, creates a detached HEAD worktree * @returns The resolved worktree path */ createWorktreeAt(worktreePath: string, branch: string, detached?: boolean): Promise; /** * Check whether a worktree exists at the given path. */ worktreeExistsAt(worktreePath: string): Promise; /** * Remove the worktree at the given path. */ removeWorktreeAt(worktreePath: string): Promise; /** * Check if there are uncommitted changes in a worktree at the given path. */ hasChangesAt(worktreePath: string): Promise; /** * Stage and commit all changes in the worktree at the given path. */ commitChangesAt(worktreePath: string, message: string): Promise; /** * Push the current branch in the worktree at the given path. */ pushAt(worktreePath: string, branch: string): Promise; /** * Re-sync a detached worktree onto the latest origin/: fetch the * branch and rebase the worktree's commit(s) onto it. Used by the plan-upload * push retry loop to recover from a remote-`main` race before re-pushing. * * On a detached HEAD, `git rebase origin/` replays the commits since * the merge-base onto the new remote tip, leaving HEAD detached at the new * tip — exactly what the subsequent `git push HEAD:` needs. * * @param worktreePath - Absolute path of the detached worktree to re-sync. * @param branch - Target branch name (e.g. 'main'). * @throws A `REBASE_CONFLICT:`-prefixed error if the rebase hits a genuine * content conflict (after aborting it), so the caller can stop * retrying and surface a real-conflict error. Fetch/other failures * propagate verbatim. */ rebaseOntoRemote(worktreePath: string, branch: string): Promise; /** * Get the main (root) worktree. The first entry of * `git worktree list --porcelain` is always the main worktree, so this is * correct even when called from inside a linked worktree (where * `git rev-parse --show-toplevel` would return the linked worktree root). * * @returns { path, branch } where `branch` is the checked-out branch name, * or `null` for a detached HEAD; returns `null` if the worktree * list cannot be read. */ getMainWorktree(): Promise<{ path: string; branch: string | null; } | null>; /** * List all active hula worktrees (paths containing '/hula/'). */ listHulaWorktrees(): Promise; /** * Validate worktree directory name to prevent command injection */ private validateWorktreeDirName; /** * Validate branch name to prevent command injection */ private validateBranchName; /** * Get the repository name from the git root directory */ getRepoName(): Promise; /** * Get the directory path for a fix worktree * Returns: /hula//fix- */ getFixWorktreeDir(issueNumber: number): Promise; /** * Create a fix worktree for the given PR branch and issue number * @param branchName - The PR branch name to check out in the worktree * @param issueNumber - The issue number (used for directory naming) * @returns Absolute path to the created worktree */ createFixWorktree(branchName: string, issueNumber: number): Promise; /** * Find any existing fix worktree by scanning git worktree list. * Matches both new convention (fix-) and legacy convention (-fix-). * @returns Object with path and issueNumber, or null if none found */ getAnyFixWorktree(): Promise<{ path: string; issueNumber: number; } | null>; /** * Check if a fix worktree exists for the given issue number */ fixWorktreeExists(issueNumber: number): Promise; /** * Get the path to a fix worktree for the given issue number * @returns Absolute path to the worktree, or null if not found */ getFixWorktreePath(issueNumber: number): Promise; /** * Remove the fix worktree for the given issue number */ removeFixWorktree(issueNumber: number): Promise; /** * Commit and push changes in the fix worktree */ commitAndPushFixWorktree(issueNumber: number, message: string): Promise; /** * Create a temporary worktree off origin/main * @returns Path to the worktree directory */ createPlanWorktree(): Promise; /** * Check if a plan worktree exists */ worktreeExists(): Promise; /** * Get the path to existing worktree */ getWorktreePath(): Promise; /** * Remove the worktree after upload */ removeWorktree(): Promise; /** * Check if there are uncommitted changes in worktree */ hasWorktreeChanges(): Promise; /** * Commit changes in the worktree */ commitWorktreeChanges(message: string): Promise; /** * Get the HEAD ref (commit SHA) of the worktree * Used when merging worktree changes into main */ getHeadRef(): Promise; } //# sourceMappingURL=WorktreeService.d.ts.map