"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../_virtual/_rolldown/runtime.js');
const require_primordials_error = require('../primordials/error.js');
const require_primordials_math = require('../primordials/math.js');
const require_primordials_array = require('../primordials/array.js');
const require_primordials_date = require('../primordials/date.js');
const require_errors_message = require('../errors/message.js');
const require_process_spawn_errors = require('../process/spawn/errors.js');
const require_process_spawn_child = require('../process/spawn/child.js');
const require_primordials_promise = require('../primordials/promise.js');
let node_fs = require("node:fs");
let node_path = require("node:path");
node_path = require_runtime.__toESM(node_path, 1);

//#region src/ai/worktree.mts
/**
* @file Run AI agents in parallel, each in its own git worktree, and merge
*   results back to the base branch. The fleet's CLAUDE.md "Parallel Claude
*   sessions" rule mandates worktree isolation when multiple agents touch the
*   same checkout. This helper enforces that contract: each item gets a fresh
*   worktree branched from the base, the per-item function runs inside it, then
*   the helper either fast-forward-merges the worktree branch back into the
*   base (when changes were committed) or removes the worktree silently (when
*   no changes happened). Concurrency: caller-controlled with a default cap of
*   4. Per the "Programmatic Claude calls" CLAUDE.md rule, very high
*   concurrency saturates the API rate limits; 4 is safe headroom for most
*   accounts. The hard cap of 8 prevents accidental flag-finger disasters.
*   Cleanup policy: see `WorktreeCleanup` in types.mts. Default 'always' —
*   fail-or-pass, the worktree is removed.
*/
const DEFAULT_CONCURRENCY = 4;
const MAX_CONCURRENCY = 8;
function currentBranch(repo) {
	return git(repo, "symbolic-ref", "--short", "HEAD");
}
function git(cwd, ...args) {
	const result = require_process_spawn_child.spawnSync("git", args, {
		cwd,
		stdio: "pipe",
		stdioString: true
	});
	return String(result.stdout ?? "").trim();
}
function hasCommittedChanges(worktree, baseBranch) {
	const log = tryGit(worktree, "log", "--oneline", `${baseBranch}..HEAD`);
	if (!log.ok) return false;
	return log.output.trim().length > 0;
}
function hasStagedOrUnstaged(worktree) {
	const status = tryGit(worktree, "status", "--porcelain");
	return status.ok && status.output.trim().length > 0;
}
async function runOne(item, index, worktreeBranch, worktreePath, baseRepo, branch, cleanup, fn) {
	const add = tryGit(baseRepo, "worktree", "add", "-b", worktreeBranch, worktreePath, branch);
	if (!add.ok) return {
		cleanup: "kept",
		error: new require_primordials_error.ErrorCtor(`git worktree add failed: ${add.output}`),
		merged: false,
		status: "rejected",
		worktreePath
	};
	let value;
	let error;
	try {
		value = await fn(item, {
			branch: worktreeBranch,
			cwd: worktreePath,
			index
		});
	} catch (e) {
		error = e;
	}
	const hasCommitted = hasCommittedChanges(worktreePath, branch);
	const hasUncommitted = hasStagedOrUnstaged(worktreePath);
	let merged = false;
	if (error === void 0 && hasCommitted) {
		const merge = tryGit(baseRepo, "merge", "--ff-only", worktreeBranch);
		if (merge.ok) merged = true;
		else error = new require_primordials_error.ErrorCtor(`git merge --ff-only failed: ${merge.output}`);
	}
	let didCleanup = "kept";
	if (error === void 0 && (cleanup === "always" || cleanup === "on-empty" && !hasCommitted && !hasUncommitted)) {
		if (tryGit(baseRepo, "worktree", "remove", worktreePath).ok) {
			didCleanup = "removed";
			tryGit(baseRepo, "branch", "-D", worktreeBranch);
		}
	}
	if (error !== void 0) return {
		cleanup: didCleanup,
		error,
		merged,
		status: "rejected",
		worktreePath
	};
	return {
		cleanup: didCleanup,
		merged,
		status: "fulfilled",
		value,
		worktreePath
	};
}
/**
* Run `fn` for each item in parallel, each invocation isolated in its own git
* worktree. Results are merged back into the base branch with `git merge
* --ff-only`; non-FF merges are reported as failures and the worktree is
* preserved (regardless of cleanup policy).
*
* @example
*   ;```ts
*   import { spawnAiAgentsInWorktrees } from '@socketsecurity/lib/ai/worktree'
*   import { spawnAiAgent } from '@socketsecurity/lib/ai/spawn'
*   import { AI_PROFILE } from '@socketsecurity/lib/ai/profiles'
*
*   const repos = ['socket-addon', 'socket-btm', 'socket-lib']
*   const settled = await spawnAiAgentsInWorktrees(
*     repos,
*     async ({ cwd }) => {
*       return await spawnAiAgent({
*         ...AI_PROFILE.create,
*         prompt: 'Run the cleanup task',
*         cwd,
*       })
*     },
*     {
*       baseRepo: '/Users/<user>/projects/socket-wheelhouse',
*       concurrency: 3,
*       cleanup: 'on-empty',
*     },
*   )
*   ```
*/
async function spawnAiAgentsInWorktrees(items, fn, options) {
	const cleanup = options.cleanup ?? "always";
	const namePrefix = options.namePrefix ?? "agent-task";
	const concurrency = require_primordials_math.MathMax(1, Math.min(options.concurrency ?? DEFAULT_CONCURRENCY, MAX_CONCURRENCY));
	const baseRepo = options.baseRepo;
	if (!(0, node_fs.existsSync)(node_path.default.join(baseRepo, ".git"))) throw new require_primordials_error.ErrorCtor(`spawnAiAgentsInWorktrees: baseRepo is not a git checkout: ${baseRepo}`);
	const branch = options.branch ?? currentBranch(baseRepo);
	const worktreeRoot = options.worktreeRoot ?? node_path.default.join(process.platform === "win32" ? process.env["TEMP"] ?? "." : "/tmp", `${namePrefix}-${Date.now()}`);
	const settled = [];
	let cursor = 0;
	async function worker() {
		for (;;) {
			const idx = cursor;
			cursor += 1;
			if (idx >= items.length) return;
			const item = items[idx];
			settled[idx] = await runOne(item, idx, `${namePrefix}-${idx}-${require_primordials_date.DateNow()}`, node_path.default.join(worktreeRoot, `${namePrefix}-${idx}`), baseRepo, branch, cleanup, fn);
		}
	}
	await require_primordials_promise.PromiseAll(require_primordials_array.ArrayFrom({ length: concurrency }, () => worker()));
	return settled;
}
function tryGit(cwd, ...args) {
	try {
		return {
			ok: true,
			output: git(cwd, ...args)
		};
	} catch (e) {
		if (/* @__PURE__ */ require_process_spawn_errors.isSpawnError(e)) return {
			ok: false,
			output: String(e.stderr ?? e.stdout ?? "")
		};
		return {
			ok: false,
			output: require_errors_message.errorMessage(e)
		};
	}
}

//#endregion
exports.currentBranch = currentBranch;
exports.git = git;
exports.hasCommittedChanges = hasCommittedChanges;
exports.hasStagedOrUnstaged = hasStagedOrUnstaged;
exports.runOne = runOne;
exports.spawnAiAgentsInWorktrees = spawnAiAgentsInWorktrees;
exports.tryGit = tryGit;