"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
            if (async) inner = dispose;
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
    return function (env) {
        function fail(e) {
            env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
            env.hasError = true;
        }
        var r, s = 0;
        function next() {
            while (r = env.stack.pop()) {
                try {
                    if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
                    if (r.dispose) {
                        var result = r.dispose.call(r.value);
                        if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
                    }
                    else s |= 1;
                }
                catch (e) {
                    fail(e);
                }
            }
            if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
            if (env.hasError) throw env.error;
        }
        return next();
    };
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalRuntime = void 0;
const child_process_1 = require("child_process");
const fs = __importStar(require("fs"));
const fsPromises = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const stream_1 = require("stream");
const Runtime_1 = require("./Runtime");
const env_1 = require("../constants/env");
const exitCodes_1 = require("../constants/exitCodes");
const git_1 = require("../git");
const initHook_1 = require("./initHook");
const disposableExec_1 = require("../utils/disposableExec");
const helpers_1 = require("../utils/runtime/helpers");
const errors_1 = require("../utils/errors");
const tildeExpansion_1 = require("./tildeExpansion");
/**
 * Local runtime implementation that executes commands and file operations
 * directly on the host machine using Node.js APIs.
 */
class LocalRuntime {
    srcBaseDir;
    constructor(srcBaseDir) {
        // Expand tilde to actual home directory path for local file system operations
        this.srcBaseDir = (0, tildeExpansion_1.expandTilde)(srcBaseDir);
    }
    async exec(command, options) {
        const startTime = performance.now();
        // Use the specified working directory (must be a specific workspace path)
        const cwd = options.cwd;
        // Check if working directory exists before spawning
        // This prevents confusing ENOENT errors from spawn()
        try {
            await fsPromises.access(cwd);
        }
        catch (err) {
            throw new Runtime_1.RuntimeError(`Working directory does not exist: ${cwd}`, "exec", err instanceof Error ? err : undefined);
        }
        // If niceness is specified, spawn nice directly to avoid escaping issues
        const spawnCommand = options.niceness !== undefined ? "nice" : "bash";
        const bashPath = "bash";
        const spawnArgs = options.niceness !== undefined
            ? ["-n", options.niceness.toString(), bashPath, "-c", command]
            : ["-c", command];
        const childProcess = (0, child_process_1.spawn)(spawnCommand, spawnArgs, {
            cwd,
            env: {
                ...process.env,
                ...(options.env ?? {}),
                ...env_1.NON_INTERACTIVE_ENV_VARS,
            },
            stdio: ["pipe", "pipe", "pipe"],
            // CRITICAL: Spawn as detached process group leader to enable cleanup of background processes.
            // When a bash script spawns background processes (e.g., `sleep 100 &`), we need to kill
            // the entire process group (including all backgrounded children) via process.kill(-pid).
            // NOTE: detached:true does NOT cause bash to wait for background jobs when using 'exit' event
            // instead of 'close' event. The 'exit' event fires when bash exits, ignoring background children.
            detached: true,
        });
        // Convert Node.js streams to Web Streams
        const stdout = stream_1.Readable.toWeb(childProcess.stdout);
        const stderr = stream_1.Readable.toWeb(childProcess.stderr);
        const stdin = stream_1.Writable.toWeb(childProcess.stdin);
        // Track if we killed the process due to timeout
        let timedOut = false;
        // Create promises for exit code and duration
        // Uses special exit codes (EXIT_CODE_ABORTED, EXIT_CODE_TIMEOUT) for expected error conditions
        const exitCode = new Promise((resolve, reject) => {
            // Use 'exit' event instead of 'close' to handle background processes correctly.
            // The 'close' event waits for ALL child processes (including background ones) to exit,
            // which causes hangs when users spawn background processes like servers.
            // The 'exit' event fires when the main bash process exits, which is what we want.
            //
            // However, stdio streams may not be fully flushed when 'exit' fires, so we need to:
            // 1. Track when process exits and when streams close
            // 2. Resolve immediately if streams have closed
            // 3. Wait with a grace period (50ms) for streams to flush if they haven't closed yet
            // 4. Force-close streams after grace period to prevent hangs
            let stdoutClosed = false;
            let stderrClosed = false;
            let processExited = false;
            let exitedCode = null;
            // Track stream closures
            childProcess.stdout?.on("close", () => {
                stdoutClosed = true;
                tryResolve();
            });
            childProcess.stderr?.on("close", () => {
                stderrClosed = true;
                tryResolve();
            });
            const tryResolve = () => {
                // Only resolve if process has exited AND streams are closed
                if (processExited && stdoutClosed && stderrClosed) {
                    finalizeExit();
                }
            };
            const finalizeExit = () => {
                // Check abort first (highest priority)
                if (options.abortSignal?.aborted) {
                    resolve(exitCodes_1.EXIT_CODE_ABORTED);
                    return;
                }
                // Check if we killed the process due to timeout
                if (timedOut) {
                    resolve(exitCodes_1.EXIT_CODE_TIMEOUT);
                    return;
                }
                resolve(exitedCode ?? 0);
            };
            childProcess.on("exit", (code) => {
                processExited = true;
                exitedCode = code;
                // Clean up any background processes (process group cleanup)
                // This prevents zombie processes when scripts spawn background tasks
                if (childProcess.pid !== undefined) {
                    try {
                        // Kill entire process group with SIGKILL - cannot be caught/ignored
                        // Use negative PID to signal the entire process group
                        process.kill(-childProcess.pid, "SIGKILL");
                    }
                    catch {
                        // Process group already dead or doesn't exist - ignore
                    }
                }
                // Try to resolve immediately if streams have already closed
                tryResolve();
                // Set a grace period timer - if streams don't close within 50ms, finalize anyway
                // This handles background processes that keep stdio open
                setTimeout(() => {
                    if (!stdoutClosed || !stderrClosed) {
                        // Mark streams as closed and finalize without destroying them
                        // Destroying converted Web Streams causes errors in the conversion layer
                        stdoutClosed = true;
                        stderrClosed = true;
                        finalizeExit();
                    }
                }, 50);
            });
            childProcess.on("error", (err) => {
                reject(new Runtime_1.RuntimeError(`Failed to execute command: ${err.message}`, "exec", err));
            });
        });
        const duration = exitCode.then(() => performance.now() - startTime);
        // Helper to kill entire process group (including background children)
        const killProcessGroup = () => {
            if (childProcess.pid === undefined)
                return;
            try {
                // Kill entire process group with SIGKILL - cannot be caught/ignored
                process.kill(-childProcess.pid, "SIGKILL");
            }
            catch {
                // Fallback: try killing just the main process
                try {
                    childProcess.kill("SIGKILL");
                }
                catch {
                    // Process already dead - ignore
                }
            }
        };
        // Handle abort signal
        if (options.abortSignal) {
            options.abortSignal.addEventListener("abort", killProcessGroup);
        }
        // Handle timeout
        if (options.timeout !== undefined) {
            setTimeout(() => {
                timedOut = true;
                killProcessGroup();
            }, options.timeout * 1000);
        }
        return { stdout, stderr, stdin, exitCode, duration };
    }
    readFile(filePath, _abortSignal) {
        // Note: _abortSignal ignored for local operations (fast, no need for cancellation)
        const nodeStream = fs.createReadStream(filePath);
        // Handle errors by wrapping in a transform
        const webStream = stream_1.Readable.toWeb(nodeStream);
        return new ReadableStream({
            async start(controller) {
                try {
                    const reader = webStream.getReader();
                    while (true) {
                        const { done, value } = await reader.read();
                        if (done)
                            break;
                        controller.enqueue(value);
                    }
                    controller.close();
                }
                catch (err) {
                    controller.error(new Runtime_1.RuntimeError(`Failed to read file ${filePath}: ${err instanceof Error ? err.message : String(err)}`, "file_io", err instanceof Error ? err : undefined));
                }
            },
        });
    }
    writeFile(filePath, _abortSignal) {
        // Note: _abortSignal ignored for local operations (fast, no need for cancellation)
        let tempPath;
        let writer;
        let resolvedPath;
        let originalMode;
        return new WritableStream({
            async start() {
                // Resolve symlinks to write through them (preserves the symlink)
                try {
                    resolvedPath = await fsPromises.realpath(filePath);
                    // Save original permissions to restore after write
                    const stat = await fsPromises.stat(resolvedPath);
                    originalMode = stat.mode;
                }
                catch {
                    // If file doesn't exist, use the original path and default permissions
                    resolvedPath = filePath;
                    originalMode = undefined;
                }
                // Create parent directories if they don't exist
                const parentDir = path.dirname(resolvedPath);
                await fsPromises.mkdir(parentDir, { recursive: true });
                // Create temp file for atomic write
                tempPath = `${resolvedPath}.tmp.${Date.now()}`;
                const nodeStream = fs.createWriteStream(tempPath);
                const webStream = stream_1.Writable.toWeb(nodeStream);
                writer = webStream.getWriter();
            },
            async write(chunk) {
                await writer.write(chunk);
            },
            async close() {
                // Close the writer and rename to final location
                await writer.close();
                try {
                    // If we have original permissions, apply them to temp file before rename
                    if (originalMode !== undefined) {
                        await fsPromises.chmod(tempPath, originalMode);
                    }
                    await fsPromises.rename(tempPath, resolvedPath);
                }
                catch (err) {
                    throw new Runtime_1.RuntimeError(`Failed to write file ${filePath}: ${err instanceof Error ? err.message : String(err)}`, "file_io", err instanceof Error ? err : undefined);
                }
            },
            async abort(reason) {
                // Clean up temp file on abort
                await writer.abort();
                try {
                    await fsPromises.unlink(tempPath);
                }
                catch {
                    // Ignore errors cleaning up temp file
                }
                throw new Runtime_1.RuntimeError(`Failed to write file ${filePath}: ${String(reason)}`, "file_io");
            },
        });
    }
    async stat(filePath, _abortSignal) {
        // Note: _abortSignal ignored for local operations (fast, no need for cancellation)
        try {
            const stats = await fsPromises.stat(filePath);
            return {
                size: stats.size,
                modifiedTime: stats.mtime,
                isDirectory: stats.isDirectory(),
            };
        }
        catch (err) {
            throw new Runtime_1.RuntimeError(`Failed to stat ${filePath}: ${err instanceof Error ? err.message : String(err)}`, "file_io", err instanceof Error ? err : undefined);
        }
    }
    resolvePath(filePath) {
        // Expand tilde to actual home directory path
        const expanded = (0, tildeExpansion_1.expandTilde)(filePath);
        // Resolve to absolute path (handles relative paths like "./foo")
        return Promise.resolve(path.resolve(expanded));
    }
    normalizePath(targetPath, basePath) {
        // For local runtime, use Node.js path resolution
        // Handle special case: current directory
        const target = targetPath.trim();
        if (target === ".") {
            return path.resolve(basePath);
        }
        return path.resolve(basePath, target);
    }
    getWorkspacePath(projectPath, workspaceName) {
        const projectName = (0, helpers_1.getProjectName)(projectPath);
        return path.join(this.srcBaseDir, projectName, workspaceName);
    }
    async createWorkspace(params) {
        const { projectPath, branchName, trunkBranch, initLogger } = params;
        try {
            // Compute workspace path using the canonical method
            const workspacePath = this.getWorkspacePath(projectPath, branchName);
            initLogger.logStep("Creating git worktree...");
            // Create parent directory if needed
            const parentDir = path.dirname(workspacePath);
            try {
                await fsPromises.access(parentDir);
            }
            catch {
                await fsPromises.mkdir(parentDir, { recursive: true });
            }
            // Check if workspace already exists
            try {
                await fsPromises.access(workspacePath);
                return {
                    success: false,
                    error: `Workspace already exists at ${workspacePath}`,
                };
            }
            catch {
                // Workspace doesn't exist, proceed with creation
            }
            // Check if branch exists locally
            const localBranches = await (0, git_1.listLocalBranches)(projectPath);
            const branchExists = localBranches.includes(branchName);
            // Create worktree (git worktree is typically fast)
            if (branchExists) {
                const env_2 = { stack: [], error: void 0, hasError: false };
                try {
                    // Branch exists, just add worktree pointing to it
                    const proc = __addDisposableResource(env_2, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree add "${workspacePath}" "${branchName}"`), false);
                    await proc.result;
                }
                catch (e_1) {
                    env_2.error = e_1;
                    env_2.hasError = true;
                }
                finally {
                    __disposeResources(env_2);
                }
            }
            else {
                const env_3 = { stack: [], error: void 0, hasError: false };
                try {
                    // Branch doesn't exist, create it from trunk
                    const proc = __addDisposableResource(env_3, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree add -b "${branchName}" "${workspacePath}" "${trunkBranch}"`), false);
                    await proc.result;
                }
                catch (e_2) {
                    env_3.error = e_2;
                    env_3.hasError = true;
                }
                finally {
                    __disposeResources(env_3);
                }
            }
            initLogger.logStep("Worktree created successfully");
            return { success: true, workspacePath };
        }
        catch (error) {
            return {
                success: false,
                error: (0, errors_1.getErrorMessage)(error),
            };
        }
    }
    async initWorkspace(params) {
        const { projectPath, workspacePath, initLogger } = params;
        try {
            // Run .cmux/init hook if it exists
            // Note: runInitHook calls logComplete() internally if hook exists
            const hookExists = await (0, initHook_1.checkInitHookExists)(projectPath);
            if (hookExists) {
                await this.runInitHook(projectPath, workspacePath, initLogger);
            }
            else {
                // No hook - signal completion immediately
                initLogger.logComplete(0);
            }
            return { success: true };
        }
        catch (error) {
            const errorMsg = (0, errors_1.getErrorMessage)(error);
            initLogger.logStderr(`Initialization failed: ${errorMsg}`);
            initLogger.logComplete(-1);
            return {
                success: false,
                error: errorMsg,
            };
        }
    }
    /**
     * Run .cmux/init hook if it exists and is executable
     */
    async runInitHook(projectPath, workspacePath, initLogger) {
        // Check if hook exists and is executable
        const hookExists = await (0, initHook_1.checkInitHookExists)(projectPath);
        if (!hookExists) {
            return;
        }
        const hookPath = (0, initHook_1.getInitHookPath)(projectPath);
        initLogger.logStep(`Running init hook: ${hookPath}`);
        // Create line-buffered loggers
        const loggers = (0, initHook_1.createLineBufferedLoggers)(initLogger);
        return new Promise((resolve) => {
            const proc = (0, child_process_1.spawn)("bash", ["-c", `"${hookPath}"`], {
                cwd: workspacePath,
                stdio: ["ignore", "pipe", "pipe"],
            });
            proc.stdout.on("data", (data) => {
                loggers.stdout.append(data.toString());
            });
            proc.stderr.on("data", (data) => {
                loggers.stderr.append(data.toString());
            });
            proc.on("close", (code) => {
                // Flush any remaining buffered output
                loggers.stdout.flush();
                loggers.stderr.flush();
                initLogger.logComplete(code ?? 0);
                resolve();
            });
            proc.on("error", (err) => {
                initLogger.logStderr(`Error running init hook: ${err.message}`);
                initLogger.logComplete(-1);
                resolve();
            });
        });
    }
    async renameWorkspace(projectPath, oldName, newName, _abortSignal) {
        // Note: _abortSignal ignored for local operations (fast, no need for cancellation)
        // Compute workspace paths using canonical method
        const oldPath = this.getWorkspacePath(projectPath, oldName);
        const newPath = this.getWorkspacePath(projectPath, newName);
        try {
            const env_4 = { stack: [], error: void 0, hasError: false };
            try {
                // Use git worktree move to rename the worktree directory
                // This updates git's internal worktree metadata correctly
                const proc = __addDisposableResource(env_4, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree move "${oldPath}" "${newPath}"`), false);
                await proc.result;
                return { success: true, oldPath, newPath };
            }
            catch (e_3) {
                env_4.error = e_3;
                env_4.hasError = true;
            }
            finally {
                __disposeResources(env_4);
            }
        }
        catch (error) {
            return { success: false, error: `Failed to move worktree: ${(0, errors_1.getErrorMessage)(error)}` };
        }
    }
    async deleteWorkspace(projectPath, workspaceName, force, _abortSignal) {
        // Note: _abortSignal ignored for local operations (fast, no need for cancellation)
        // In-place workspaces are identified by projectPath === workspaceName
        // These are direct workspace directories (e.g., CLI/benchmark sessions), not git worktrees
        const isInPlace = projectPath === workspaceName;
        // Compute workspace path using the canonical method
        const deletedPath = this.getWorkspacePath(projectPath, workspaceName);
        // Check if directory exists - if not, operation is idempotent
        try {
            await fsPromises.access(deletedPath);
        }
        catch {
            // Directory doesn't exist - operation is idempotent
            // For standard worktrees, prune stale git records (best effort)
            if (!isInPlace) {
                try {
                    const env_5 = { stack: [], error: void 0, hasError: false };
                    try {
                        const pruneProc = __addDisposableResource(env_5, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree prune`), false);
                        await pruneProc.result;
                    }
                    catch (e_4) {
                        env_5.error = e_4;
                        env_5.hasError = true;
                    }
                    finally {
                        __disposeResources(env_5);
                    }
                }
                catch {
                    // Ignore prune errors - directory is already deleted, which is the goal
                }
            }
            return { success: true, deletedPath };
        }
        // For in-place workspaces, there's no worktree to remove
        // Just return success - the workspace directory itself should not be deleted
        // as it may contain the user's actual project files
        if (isInPlace) {
            return { success: true, deletedPath };
        }
        try {
            const env_6 = { stack: [], error: void 0, hasError: false };
            try {
                // Use git worktree remove to delete the worktree
                // This updates git's internal worktree metadata correctly
                // Only use --force if explicitly requested by the caller
                const forceFlag = force ? " --force" : "";
                const proc = __addDisposableResource(env_6, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree remove${forceFlag} "${deletedPath}"`), false);
                await proc.result;
                return { success: true, deletedPath };
            }
            catch (e_5) {
                env_6.error = e_5;
                env_6.hasError = true;
            }
            finally {
                __disposeResources(env_6);
            }
        }
        catch (error) {
            const message = (0, errors_1.getErrorMessage)(error);
            // Check if the error is due to missing/stale worktree
            const normalizedError = message.toLowerCase();
            const looksLikeMissingWorktree = normalizedError.includes("not a working tree") ||
                normalizedError.includes("does not exist") ||
                normalizedError.includes("no such file");
            if (looksLikeMissingWorktree) {
                // Worktree records are stale - prune them
                try {
                    const env_7 = { stack: [], error: void 0, hasError: false };
                    try {
                        const pruneProc = __addDisposableResource(env_7, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree prune`), false);
                        await pruneProc.result;
                    }
                    catch (e_6) {
                        env_7.error = e_6;
                        env_7.hasError = true;
                    }
                    finally {
                        __disposeResources(env_7);
                    }
                }
                catch {
                    // Ignore prune errors
                }
                // Treat as success - workspace is gone (idempotent)
                return { success: true, deletedPath };
            }
            // If force is enabled and git worktree remove failed, fall back to rm -rf
            // This handles edge cases like submodules where git refuses to delete
            if (force) {
                try {
                    const env_8 = { stack: [], error: void 0, hasError: false };
                    try {
                        // Prune git's worktree records first (best effort)
                        try {
                            const env_9 = { stack: [], error: void 0, hasError: false };
                            try {
                                const pruneProc = __addDisposableResource(env_9, (0, disposableExec_1.execAsync)(`git -C "${projectPath}" worktree prune`), false);
                                await pruneProc.result;
                            }
                            catch (e_7) {
                                env_9.error = e_7;
                                env_9.hasError = true;
                            }
                            finally {
                                __disposeResources(env_9);
                            }
                        }
                        catch {
                            // Ignore prune errors - we'll still try rm -rf
                        }
                        // Force delete the directory
                        const rmProc = __addDisposableResource(env_8, (0, disposableExec_1.execAsync)(`rm -rf "${deletedPath}"`), false);
                        await rmProc.result;
                        return { success: true, deletedPath };
                    }
                    catch (e_8) {
                        env_8.error = e_8;
                        env_8.hasError = true;
                    }
                    finally {
                        __disposeResources(env_8);
                    }
                }
                catch (rmError) {
                    return {
                        success: false,
                        error: `Failed to remove worktree via git and rm: ${(0, errors_1.getErrorMessage)(rmError)}`,
                    };
                }
            }
            // force=false - return the git error without attempting rm -rf
            return { success: false, error: `Failed to remove worktree: ${message}` };
        }
    }
    async forkWorkspace(params) {
        const { projectPath, sourceWorkspaceName, newWorkspaceName, initLogger } = params;
        // Get source workspace path
        const sourceWorkspacePath = this.getWorkspacePath(projectPath, sourceWorkspaceName);
        // Get current branch from source workspace
        try {
            const env_10 = { stack: [], error: void 0, hasError: false };
            try {
                const proc = __addDisposableResource(env_10, (0, disposableExec_1.execAsync)(`git -C "${sourceWorkspacePath}" branch --show-current`), false);
                const { stdout } = await proc.result;
                const sourceBranch = stdout.trim();
                if (!sourceBranch) {
                    return {
                        success: false,
                        error: "Failed to detect branch in source workspace",
                    };
                }
                // Use createWorkspace with sourceBranch as trunk to fork from source branch
                const createResult = await this.createWorkspace({
                    projectPath,
                    branchName: newWorkspaceName,
                    trunkBranch: sourceBranch, // Fork from source branch instead of main/master
                    directoryName: newWorkspaceName,
                    initLogger,
                });
                if (!createResult.success || !createResult.workspacePath) {
                    return {
                        success: false,
                        error: createResult.error ?? "Failed to create workspace",
                    };
                }
                return {
                    success: true,
                    workspacePath: createResult.workspacePath,
                    sourceBranch,
                };
            }
            catch (e_9) {
                env_10.error = e_9;
                env_10.hasError = true;
            }
            finally {
                __disposeResources(env_10);
            }
        }
        catch (error) {
            return {
                success: false,
                error: (0, errors_1.getErrorMessage)(error),
            };
        }
    }
}
exports.LocalRuntime = LocalRuntime;
//# sourceMappingURL=LocalRuntime.js.map