#!/usr/bin/env node
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// src/server/recall/git.ts
function gitEnv(gitDir, workTree) {
  const env = { ...process.env, GIT_DIR: gitDir };
  if (workTree) env.GIT_WORK_TREE = workTree;
  return env;
}
function runGitSync(args, opts) {
  const result = (0, import_node_child_process.spawnSync)("git", args, {
    env: opts.env,
    cwd: opts.cwd,
    encoding: "utf8"
  });
  return {
    status: result.status ?? 1,
    stdout: result.stdout ?? "",
    stderr: result.stderr ?? ""
  };
}
function runGit(args, opts) {
  return new Promise((resolve3) => {
    const proc = (0, import_node_child_process.spawn)("git", args, {
      env: opts.env,
      cwd: opts.cwd,
      stdio: opts.stdio ?? "inherit"
    });
    proc.on("exit", (code) => resolve3(code ?? 1));
    proc.on("error", () => resolve3(1));
  });
}
var import_node_child_process;
var init_git = __esm({
  "src/server/recall/git.ts"() {
    "use strict";
    import_node_child_process = require("node:child_process");
  }
});

// src/server/recall/paths.ts
function resolveRecallPaths(cwd = process.cwd()) {
  const workTree = path.resolve(cwd);
  const recallDir = path.join(workTree, RECALL_DIR_NAME);
  const gitDir = path.join(recallDir, RECALL_REPO_DIRNAME);
  return { workTree, recallDir, gitDir };
}
var path, RECALL_DIR_NAME, RECALL_REPO_DIRNAME;
var init_paths = __esm({
  "src/server/recall/paths.ts"() {
    "use strict";
    path = __toESM(require("node:path"));
    RECALL_DIR_NAME = ".recall";
    RECALL_REPO_DIRNAME = "repo.git";
  }
});

// src/server/recall/config.ts
function isPlainObject(v) {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}
function mergeConfig(raw) {
  if (!isPlainObject(raw)) return { ...DEFAULT_CONFIG };
  const out = {
    debounce: DEFAULT_CONFIG.debounce,
    ignore: [...DEFAULT_CONFIG.ignore],
    retention: { ...DEFAULT_CONFIG.retention }
  };
  if (typeof raw.debounce === "number" && raw.debounce > 0) {
    out.debounce = raw.debounce;
  }
  if (Array.isArray(raw.ignore) && raw.ignore.every((x) => typeof x === "string")) {
    out.ignore = raw.ignore;
  }
  if (isPlainObject(raw.retention)) {
    const r = raw.retention;
    if (r.keepLast === null) {
      out.retention.keepLast = null;
    } else if (typeof r.keepLast === "number" && r.keepLast >= 0) {
      out.retention.keepLast = r.keepLast;
    }
    if (r.maxAgeDays === null) {
      out.retention.maxAgeDays = null;
    } else if (typeof r.maxAgeDays === "number" && r.maxAgeDays >= 0) {
      out.retention.maxAgeDays = r.maxAgeDays;
    }
  }
  return out;
}
function loadConfig(workTree) {
  const configPath = path2.join(workTree, CONFIG_FILENAME);
  if (!fs.existsSync(configPath)) {
    return { config: { ...DEFAULT_CONFIG }, source: "defaults", path: configPath };
  }
  try {
    const text2 = fs.readFileSync(configPath, "utf8");
    const raw = JSON.parse(text2);
    return { config: mergeConfig(raw), source: "file", path: configPath };
  } catch (err) {
    process.stderr.write(
      `[launch-recall] warning: failed to parse ${CONFIG_FILENAME} (${err instanceof Error ? err.message : String(err)}) \u2014 using defaults
`
    );
    return { config: { ...DEFAULT_CONFIG }, source: "defaults", path: configPath };
  }
}
function writeDefaultConfig(workTree) {
  const configPath = path2.join(workTree, CONFIG_FILENAME);
  if (fs.existsSync(configPath)) return "present";
  fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
  return "created";
}
function escapeRegex(s) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function buildIgnoreRegex(ignore) {
  if (ignore.length === 0) return /^\b$/;
  const alt = ignore.map(escapeRegex).join("|");
  return new RegExp(`(^|/)(${alt})(/|$)`);
}
function buildPathspecExcludes(ignore) {
  return ignore.map((name) => `:!${name}`);
}
var fs, path2, CONFIG_FILENAME, DEFAULT_CONFIG;
var init_config = __esm({
  "src/server/recall/config.ts"() {
    "use strict";
    fs = __toESM(require("node:fs"));
    path2 = __toESM(require("node:path"));
    CONFIG_FILENAME = ".launch-recall.json";
    DEFAULT_CONFIG = {
      debounce: 3e3,
      ignore: [
        "node_modules",
        ".next",
        "dist",
        "build",
        ".turbo",
        ".git",
        ".recall",
        "coverage",
        ".pnpm-store",
        ".launchsecure/graphs",
        ".claude/settings.local.json"
      ],
      retention: {
        keepLast: 5e3,
        maxAgeDays: 30
      }
    };
  }
});

// src/server/recall/init.ts
var init_exports = {};
__export(init_exports, {
  runInit: () => runInit
});
function ensureGitignoreEntry(workTree) {
  const gitignorePath = path3.join(workTree, ".gitignore");
  if (!fs2.existsSync(gitignorePath)) return "no-gitignore";
  const contents = fs2.readFileSync(gitignorePath, "utf8");
  const lines = contents.split(/\r?\n/);
  const already = lines.some((l) => {
    const t = l.trim();
    return t === GITIGNORE_LINE || t === `${RECALL_DIR_NAME}/` || t === RECALL_DIR_NAME || t === `/${RECALL_DIR_NAME}` || t === `${RECALL_DIR_NAME}/**`;
  });
  if (already) return "present";
  const needsLeadingNewline = contents.length > 0 && !contents.endsWith("\n");
  fs2.appendFileSync(
    gitignorePath,
    `${needsLeadingNewline ? "\n" : ""}${GITIGNORE_LINE}
`
  );
  return "added";
}
async function runInit(_args) {
  const { workTree, recallDir, gitDir } = resolveRecallPaths();
  if (fs2.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] already initialised at ${gitDir}
`);
  } else {
    fs2.mkdirSync(recallDir, { recursive: true });
    const init = runGitSync(["init", "--bare", gitDir], { env: process.env });
    if (init.status !== 0) {
      process.stderr.write(`[launch-recall] git init --bare failed:
${init.stderr}`);
      process.exit(1);
    }
    runGitSync(["config", "gc.auto", "256"], { env: gitEnv(gitDir) });
    runGitSync(["config", "core.logAllRefUpdates", "true"], { env: gitEnv(gitDir) });
    process.stderr.write(`[launch-recall] created shadow repo at ${gitDir}
`);
  }
  const gitignoreResult = ensureGitignoreEntry(workTree);
  switch (gitignoreResult) {
    case "added":
      process.stderr.write(`[launch-recall] added ${GITIGNORE_LINE} to .gitignore
`);
      break;
    case "present":
      process.stderr.write(`[launch-recall] .gitignore already excludes ${RECALL_DIR_NAME}
`);
      break;
    case "no-gitignore":
      process.stderr.write(
        `[launch-recall] no .gitignore in ${workTree} \u2014 create one and add "${GITIGNORE_LINE}"
`
      );
      break;
  }
  const configResult = writeDefaultConfig(workTree);
  if (configResult === "created") {
    process.stderr.write(`[launch-recall] wrote default ${CONFIG_FILENAME}
`);
  } else {
    process.stderr.write(`[launch-recall] ${CONFIG_FILENAME} already present
`);
  }
  process.stderr.write(`[launch-recall] ready. start the watcher with: launch-recall watch
`);
}
var fs2, path3, GITIGNORE_LINE;
var init_init = __esm({
  "src/server/recall/init.ts"() {
    "use strict";
    fs2 = __toESM(require("node:fs"));
    path3 = __toESM(require("node:path"));
    init_git();
    init_paths();
    init_config();
    GITIGNORE_LINE = `/${RECALL_DIR_NAME}/`;
  }
});

// src/server/recall-mcp.ts
var recall_mcp_exports = {};
__export(recall_mcp_exports, {
  startRecallMcpServer: () => startRecallMcpServer
});
function isPidAlive(pid) {
  try {
    process.kill(pid, 0);
    return true;
  } catch (err) {
    const code = err.code;
    if (code === "ESRCH") return false;
    if (code === "EPERM") return true;
    return false;
  }
}
function pidFilePath(recallDir) {
  return `${recallDir}/watch.pid`;
}
function existingWatcherPid() {
  const { recallDir } = resolveRecallPaths();
  const pf = pidFilePath(recallDir);
  if (!(0, import_node_fs.existsSync)(pf)) return null;
  const pid = Number((0, import_node_fs.readFileSync)(pf, "utf-8").trim());
  if (!Number.isFinite(pid) || pid <= 0) return null;
  return isPidAlive(pid) ? pid : null;
}
function ensureWatcher() {
  const { gitDir, workTree } = resolveRecallPaths();
  if (!(0, import_node_fs.existsSync)(gitDir)) {
    process.stderr.write(
      `[launch-recall mcp] shadow repo missing at ${gitDir} \u2014 run \`launch-recall init\` first. MCP tools will still serve read-only queries, but nothing will be captured.
`
    );
    return;
  }
  const existing = existingWatcherPid();
  if (existing !== null) {
    process.stderr.write(
      `[launch-recall mcp] external watcher detected (pid ${existing}) \u2014 serving tools only, not spawning a sibling
`
    );
    return;
  }
  const entry = process.argv[1];
  if (!entry) {
    process.stderr.write(`[launch-recall mcp] cannot resolve entry path from argv \u2014 watcher not spawned
`);
    return;
  }
  childWatcher = (0, import_node_child_process2.spawn)(process.execPath, [entry, "watch"], {
    cwd: workTree,
    stdio: ["ignore", "ignore", "inherit"],
    detached: false
  });
  process.stderr.write(`[launch-recall mcp] spawned watcher (pid ${childWatcher.pid}) in ${workTree}
`);
  childWatcher.on("exit", (code, sig) => {
    process.stderr.write(`[launch-recall mcp] child watcher exited (code=${code} sig=${sig})
`);
    childWatcher = null;
  });
}
function killChildWatcher() {
  if (childWatcher && !childWatcher.killed) {
    try {
      childWatcher.kill("SIGTERM");
    } catch {
    }
  }
}
function text(payload) {
  const t = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
  return { content: [{ type: "text", text: t }] };
}
async function handleTool(name, args) {
  switch (name) {
    case "recall.doctor":
      return text(doctorTool());
    case "recall.report":
      return text(reportTool());
    case "recall.status":
      return text(statusTool());
    case "recall.history": {
      const path7 = String(args.path ?? "");
      if (!path7) return text({ error: "path is required" });
      const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : 50;
      return text(historyTool(path7, limit));
    }
    default:
      return text({ error: `unknown tool: ${name}` });
  }
}
function doctorTool() {
  const { gitDir, recallDir } = resolveRecallPaths();
  const checks = [];
  const shadowOk = (0, import_node_fs.existsSync)(gitDir);
  checks.push({
    name: "shadow_repo",
    ok: shadowOk,
    detail: shadowOk ? gitDir : `missing \u2014 run \`launch-recall init\``
  });
  const pid = existingWatcherPid();
  checks.push({
    name: "watcher_alive",
    ok: pid !== null,
    detail: pid !== null ? `pid ${pid}` : `no live pid in ${pidFilePath(recallDir)}`
  });
  let recentOk = false;
  let recentDetail = "no snapshots yet";
  if (shadowOk) {
    try {
      const out = (0, import_node_child_process2.execFileSync)("git", [`--git-dir=${gitDir}`, "log", "-1", "--format=%aI"], {
        encoding: "utf-8",
        stdio: ["ignore", "pipe", "pipe"]
      }).trim();
      if (out) {
        const ageHours = (Date.now() - new Date(out).getTime()) / 36e5;
        recentOk = ageHours < 24;
        recentDetail = `${out} (${ageHours.toFixed(1)}h ago)`;
      }
    } catch {
    }
  }
  checks.push({ name: "recent_snapshot", ok: recentOk, detail: recentDetail });
  return { ok: checks.every((c) => c.ok), checks };
}
function reportTool() {
  const { gitDir, recallDir, workTree } = resolveRecallPaths();
  if (!(0, import_node_fs.existsSync)(gitDir)) return { error: "shadow repo not initialised" };
  let totalSnapshots = 0;
  try {
    const out = (0, import_node_child_process2.execFileSync)("git", [`--git-dir=${gitDir}`, "rev-list", "--count", "HEAD"], {
      encoding: "utf-8",
      stdio: ["ignore", "pipe", "pipe"]
    }).trim();
    totalSnapshots = Number(out) || 0;
  } catch {
  }
  let shadowSizeBytes = 0;
  try {
    const out = (0, import_node_child_process2.execFileSync)("du", ["-sk", recallDir], { encoding: "utf-8" }).trim();
    const kb = Number(out.split(/\s+/)[0]);
    if (Number.isFinite(kb)) shadowSizeBytes = kb * 1024;
  } catch {
  }
  const recentSnapshots = [];
  let lastSnapshot = null;
  try {
    const out = (0, import_node_child_process2.execFileSync)(
      "git",
      [`--git-dir=${gitDir}`, "log", "-10", "--format=%H|%aI|%s"],
      { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
    );
    for (const line of out.split("\n").filter(Boolean)) {
      const [sha, ts, ...rest] = line.split("|");
      recentSnapshots.push({ sha, ts, message: rest.join("|") });
    }
    if (recentSnapshots.length > 0) lastSnapshot = recentSnapshots[0].ts;
  } catch {
  }
  let config = null;
  const cfgPath = `${workTree}/.launch-recall.json`;
  if ((0, import_node_fs.existsSync)(cfgPath)) {
    try {
      config = JSON.parse((0, import_node_fs.readFileSync)(cfgPath, "utf-8"));
    } catch {
    }
  }
  return { totalSnapshots, shadowSizeBytes, lastSnapshot, recentSnapshots, config, workTree };
}
function historyTool(path7, limit) {
  const { gitDir, workTree } = resolveRecallPaths();
  if (!(0, import_node_fs.existsSync)(gitDir)) return { error: "shadow repo not initialised", path: path7, snapshots: [] };
  const rel = path7.startsWith("/") ? path7.replace(`${workTree}/`, "").replace(/^\/+/, "") : path7;
  const snapshots = [];
  try {
    const out = (0, import_node_child_process2.execFileSync)(
      "git",
      [`--git-dir=${gitDir}`, `--work-tree=${workTree}`, "log", `-${limit}`, "--format=%H|%aI|%s", "--", rel],
      { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
    );
    for (const line of out.split("\n").filter(Boolean)) {
      const [sha, ts, ...rest] = line.split("|");
      snapshots.push({ sha, ts, message: rest.join("|") });
    }
  } catch {
  }
  return { path: rel, snapshots };
}
function statusTool() {
  const { gitDir, workTree } = resolveRecallPaths();
  const pid = existingWatcherPid();
  let lastSnapshotAt = null;
  if ((0, import_node_fs.existsSync)(gitDir)) {
    try {
      lastSnapshotAt = (0, import_node_child_process2.execFileSync)("git", [`--git-dir=${gitDir}`, "log", "-1", "--format=%aI"], {
        encoding: "utf-8",
        stdio: ["ignore", "pipe", "pipe"]
      }).trim() || null;
    } catch {
    }
  }
  return {
    running: pid !== null,
    pid,
    lastSnapshotAt,
    watchTree: workTree,
    shadowRepo: gitDir
  };
}
function send(msg) {
  process.stdout.write(JSON.stringify(msg) + "\n");
}
function sendResponse(id, result) {
  send({ jsonrpc: "2.0", id, result });
}
function sendError(id, code, message) {
  send({ jsonrpc: "2.0", id, error: { code, message } });
}
async function handleMessage(parsed) {
  const id = parsed.id;
  const method = parsed.method;
  const params = parsed.params ?? {};
  switch (method) {
    case "initialize":
      sendResponse(id ?? null, {
        protocolVersion: "2024-11-05",
        capabilities: { tools: {} },
        serverInfo: SERVER_INFO
      });
      break;
    case "notifications/initialized":
      break;
    case "tools/list":
      sendResponse(id ?? null, { tools: TOOLS });
      break;
    case "tools/call": {
      const toolName = params.name;
      const toolArgs = params.arguments ?? {};
      try {
        const result = await handleTool(toolName, toolArgs);
        sendResponse(id ?? null, result);
      } catch (err) {
        sendError(id ?? null, -32603, `Tool error: ${err.message}`);
      }
      break;
    }
    case "ping":
      sendResponse(id ?? null, {});
      break;
    default:
      if (id !== void 0) sendError(id ?? null, -32601, `Method not found: ${method}`);
  }
}
function startRecallMcpServer() {
  process.stderr.write("[launch-recall mcp] starting on stdio\n");
  ensureWatcher();
  const teardown = () => {
    killChildWatcher();
    process.exit(0);
  };
  process.on("SIGTERM", teardown);
  process.on("SIGINT", teardown);
  process.on("exit", killChildWatcher);
  process.stdin.setEncoding("utf-8");
  let buffer = "";
  process.stdin.on("data", (chunk) => {
    buffer += chunk;
    const lines = buffer.split("\n");
    buffer = lines.pop() || "";
    for (const line of lines) {
      const trimmed = line.trim();
      if (!trimmed) continue;
      try {
        handleMessage(JSON.parse(trimmed)).catch((err) => {
          process.stderr.write(`[launch-recall mcp] message error: ${err}
`);
        });
      } catch (err) {
        process.stderr.write(`[launch-recall mcp] parse error: ${err}
`);
      }
    }
  });
  process.stdin.on("end", () => {
    process.stderr.write("[launch-recall mcp] stdin closed, exiting\n");
    teardown();
  });
  void import_node_fs.statSync;
}
var import_node_child_process2, import_node_fs, SERVER_INFO, TOOLS, childWatcher;
var init_recall_mcp = __esm({
  "src/server/recall-mcp.ts"() {
    "use strict";
    import_node_child_process2 = require("node:child_process");
    import_node_fs = require("node:fs");
    init_paths();
    SERVER_INFO = { name: "launch-recall", version: "0.0.1" };
    TOOLS = [
      {
        name: "recall.doctor",
        description: "Health check on the launch-recall watcher and its shadow repo.\n\nReturns: { ok, checks: [{ name, ok, detail }] }. Names: shadow_repo (exists + valid), watcher_alive (pid file points at live pid), recent_snapshot (any snapshot within 24h).",
        inputSchema: { type: "object", properties: {} }
      },
      {
        name: "recall.report",
        description: "Project-wide details on what recall has captured.\n\nReturns: { totalSnapshots, shadowSizeBytes, lastSnapshot, recentSnapshots: [{ sha, ts, message }], config: { debounce, ignore, retention } }. recentSnapshots is the last 10.",
        inputSchema: { type: "object", properties: {} }
      },
      {
        name: "recall.history",
        description: "Snapshot history for a specific file or directory. Path is relative to the project root (or an absolute path under it).\n\nReturns: { path, snapshots: [{ sha, ts, message }] }. Empty array if the path was never captured (e.g. ignored, or simply has no churn).",
        inputSchema: {
          type: "object",
          properties: {
            path: { type: "string", description: "File or directory to query." },
            limit: { type: "number", description: "Max snapshots to return (default 50)." }
          },
          required: ["path"]
        }
      },
      {
        name: "recall.status",
        description: "Quick liveness + last-snapshot info. Cheaper than recall.doctor \u2014 no historical inspection.\n\nReturns: { running, pid, lastSnapshotAt, watchTree }.",
        inputSchema: { type: "object", properties: {} }
      }
    ];
    childWatcher = null;
  }
});

// src/server/recall/stop.ts
var stop_exports = {};
__export(stop_exports, {
  pidFilePath: () => pidFilePath2,
  runStop: () => runStop,
  stopWatcher: () => stopWatcher
});
function pidFilePath2(recallDir) {
  return path4.join(recallDir, "watch.pid");
}
function isAlive(pid) {
  try {
    process.kill(pid, 0);
    return true;
  } catch (err) {
    const code = err.code;
    if (code === "ESRCH") return false;
    if (code === "EPERM") return true;
    return false;
  }
}
function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}
async function stopWatcher(quiet = false) {
  const { recallDir } = resolveRecallPaths();
  const pf = pidFilePath2(recallDir);
  if (!fs3.existsSync(pf)) {
    if (!quiet) process.stderr.write(`[launch-recall] no PID file at ${pf}
`);
    return { state: "no-pid-file" };
  }
  const raw = fs3.readFileSync(pf, "utf8").trim();
  const pid = Number(raw);
  if (!Number.isFinite(pid) || pid <= 0) {
    if (!quiet) process.stderr.write(`[launch-recall] invalid PID file content: ${raw}
`);
    fs3.unlinkSync(pf);
    return { state: "kill-failed" };
  }
  if (!isAlive(pid)) {
    if (!quiet) process.stderr.write(`[launch-recall] process ${pid} not running (stale PID file)
`);
    fs3.unlinkSync(pf);
    return { state: "already-dead", pid };
  }
  try {
    process.kill(pid, "SIGTERM");
    if (!quiet) process.stderr.write(`[launch-recall] sent SIGTERM to ${pid}
`);
  } catch (err) {
    if (!quiet)
      process.stderr.write(
        `[launch-recall] SIGTERM failed: ${err instanceof Error ? err.message : String(err)}
`
      );
    return { state: "kill-failed", pid };
  }
  for (let i = 0; i < 8; i++) {
    await sleep(250);
    if (!isAlive(pid)) {
      if (fs3.existsSync(pf)) fs3.unlinkSync(pf);
      if (!quiet) process.stderr.write(`[launch-recall] watcher ${pid} stopped
`);
      return { state: "stopped", pid };
    }
  }
  try {
    process.kill(pid, "SIGKILL");
    if (!quiet) process.stderr.write(`[launch-recall] sent SIGKILL to ${pid}
`);
  } catch {
  }
  if (fs3.existsSync(pf)) fs3.unlinkSync(pf);
  return { state: "stopped", pid };
}
async function runStop(_args) {
  await stopWatcher(false);
}
var fs3, path4;
var init_stop = __esm({
  "src/server/recall/stop.ts"() {
    "use strict";
    fs3 = __toESM(require("node:fs"));
    path4 = __toESM(require("node:path"));
    init_paths();
  }
});

// src/server/recall/watch.ts
var watch_exports = {};
__export(watch_exports, {
  runWatch: () => runWatch
});
function isPidAlive2(pid) {
  try {
    process.kill(pid, 0);
    return true;
  } catch (err) {
    const code = err.code;
    if (code === "ESRCH") return false;
    return code === "EPERM";
  }
}
function parseDebounceOverride(args) {
  const idx = args.indexOf("--debounce");
  if (idx === -1) return null;
  const raw = args[idx + 1];
  const n = Number(raw);
  if (!Number.isFinite(n) || n <= 0) {
    process.stderr.write(`[launch-recall] invalid --debounce value: ${raw}
`);
    process.exit(2);
  }
  return n;
}
function log(msg) {
  process.stderr.write(`[launch-recall] ${msg}
`);
}
async function runWatch(args) {
  const { workTree, gitDir, recallDir } = resolveRecallPaths();
  if (!fs4.existsSync(gitDir)) {
    log(`not initialised \u2014 run: launch-recall init`);
    process.exit(1);
  }
  const pf = pidFilePath2(recallDir);
  if (fs4.existsSync(pf)) {
    const existing = Number(fs4.readFileSync(pf, "utf8").trim());
    if (Number.isFinite(existing) && isPidAlive2(existing)) {
      log(`watcher already running (pid ${existing}) \u2014 run \`launch-recall stop\` first`);
      process.exit(1);
    }
    try {
      fs4.unlinkSync(pf);
    } catch {
    }
  }
  fs4.writeFileSync(pf, String(process.pid));
  const cleanupPidFile = () => {
    try {
      fs4.unlinkSync(pf);
    } catch {
    }
  };
  const { config, source } = loadConfig(workTree);
  const debounceOverride = parseDebounceOverride(args);
  const debounceMs = debounceOverride ?? config.debounce;
  const ignoreRegex = buildIgnoreRegex(config.ignore);
  const pathspecExcludes = buildPathspecExcludes(config.ignore);
  log(`watching ${workTree}`);
  log(`shadow repo ${gitDir}`);
  log(`config ${source === "file" ? "from .launch-recall.json" : "defaults"}`);
  log(`debounce ${debounceMs}ms`);
  log(`ignoring [${config.ignore.join(", ")}]`);
  let busy = false;
  let queued = false;
  let timer = null;
  const env = gitEnv(gitDir, workTree);
  const addArgs = ["add", "-f", "--", ".", ...pathspecExcludes];
  const stamp = () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
  const snap = () => {
    if (busy) {
      queued = true;
      return;
    }
    busy = true;
    const add = (0, import_node_child_process3.spawn)("git", addArgs, { env, stdio: "ignore" });
    add.on("exit", (addCode) => {
      if (addCode !== 0) {
        busy = false;
        if (queued) {
          queued = false;
          snap();
        }
        return;
      }
      const check = (0, import_node_child_process3.spawn)("git", ["diff", "--cached", "--quiet"], { env, stdio: "ignore" });
      check.on("exit", (checkCode) => {
        if (checkCode === 0) {
          busy = false;
          if (queued) {
            queued = false;
            snap();
          }
          return;
        }
        const commit = (0, import_node_child_process3.spawn)(
          "git",
          ["commit", "-q", "-m", `snap ${stamp()}`],
          { env, stdio: "ignore" }
        );
        commit.on("exit", () => {
          busy = false;
          if (queued) {
            queued = false;
            snap();
          }
        });
      });
    });
  };
  const scheduleSnap = () => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(snap, debounceMs);
  };
  const abort = new AbortController();
  const shutdown = (sig, code) => {
    if (sig === "SIGINT") log("stopping");
    abort.abort();
    if (timer) clearTimeout(timer);
    cleanupPidFile();
    process.exit(code);
  };
  process.on("SIGINT", () => shutdown("SIGINT", 0));
  process.on("SIGTERM", () => shutdown("SIGTERM", 0));
  process.on("exit", cleanupPidFile);
  try {
    const watcher = fsp.watch(workTree, { recursive: true, signal: abort.signal });
    for await (const ev of watcher) {
      if (ev.filename && ignoreRegex.test(ev.filename)) continue;
      scheduleSnap();
    }
  } catch (err) {
    if (err.name === "AbortError") {
      cleanupPidFile();
      return;
    }
    log(`watcher error: ${err instanceof Error ? err.message : String(err)}`);
    cleanupPidFile();
    process.exit(1);
  }
}
var fs4, fsp, import_node_child_process3;
var init_watch = __esm({
  "src/server/recall/watch.ts"() {
    "use strict";
    fs4 = __toESM(require("node:fs"));
    fsp = __toESM(require("node:fs/promises"));
    import_node_child_process3 = require("node:child_process");
    init_git();
    init_paths();
    init_config();
    init_stop();
  }
});

// src/server/recall/log.ts
var log_exports = {};
__export(log_exports, {
  runLog: () => runLog
});
async function runLog(args) {
  const { workTree, gitDir } = resolveRecallPaths();
  if (!fs5.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] not initialised \u2014 run: launch-recall init
`);
    process.exit(1);
  }
  const env = gitEnv(gitDir, workTree);
  const gitArgs = ["log", "--oneline", "--decorate"];
  if (args.length > 0) {
    gitArgs.push("--", ...args);
  }
  const code = await runGit(gitArgs, { env });
  process.exit(code);
}
var fs5;
var init_log = __esm({
  "src/server/recall/log.ts"() {
    "use strict";
    fs5 = __toESM(require("node:fs"));
    init_git();
    init_paths();
  }
});

// src/server/recall/restore.ts
var restore_exports = {};
__export(restore_exports, {
  runRestore: () => runRestore
});
function parseArgs(args) {
  let target = null;
  let at = "HEAD";
  let outPath = null;
  for (let i = 0; i < args.length; i++) {
    const a = args[i];
    if (a === "--at") {
      at = args[++i] ?? "HEAD";
    } else if (a === "--out" || a === "-o") {
      outPath = args[++i] ?? null;
    } else if (!target) {
      target = a;
    }
  }
  return { target, at, outPath };
}
async function runRestore(args) {
  const { target, at, outPath } = parseArgs(args);
  if (!target) {
    process.stderr.write(
      "Usage: launch-recall restore <path> [--at <ref>] [--out <path>]\n"
    );
    process.exit(2);
  }
  const { workTree, gitDir } = resolveRecallPaths();
  if (!fs6.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] not initialised \u2014 run: launch-recall init
`);
    process.exit(1);
  }
  const env = gitEnv(gitDir, workTree);
  const spec = `${at}:${target}`;
  const result = runGitSync(["show", spec], { env });
  if (result.status !== 0) {
    process.stderr.write(
      `[launch-recall] could not read ${spec} from shadow:
${result.stderr}`
    );
    process.exit(result.status);
  }
  const destination = outPath ?? path5.resolve(workTree, target);
  if (outPath) {
    fs6.mkdirSync(path5.dirname(path5.resolve(destination)), { recursive: true });
  }
  if (fs6.existsSync(destination)) {
    process.stderr.write(
      `[launch-recall] refusing to overwrite existing file: ${destination}
  use --out to write to a different location
`
    );
    process.exit(1);
  }
  fs6.writeFileSync(destination, result.stdout);
  process.stderr.write(`[launch-recall] restored ${spec} \u2192 ${destination}
`);
}
var fs6, path5;
var init_restore = __esm({
  "src/server/recall/restore.ts"() {
    "use strict";
    fs6 = __toESM(require("node:fs"));
    path5 = __toESM(require("node:path"));
    init_git();
    init_paths();
  }
});

// src/server/recall/forget.ts
var forget_exports = {};
__export(forget_exports, {
  runForget: () => runForget
});
function parseArgs2(args) {
  const out = {
    keepLast: void 0,
    maxAgeDays: void 0,
    dryRun: false
  };
  for (let i = 0; i < args.length; i++) {
    const a = args[i];
    if (a === "--dry-run" || a === "-n") {
      out.dryRun = true;
    } else if (a === "--keep-last") {
      const raw = args[++i];
      if (raw === "off") {
        out.keepLast = null;
      } else {
        const n = Number(raw);
        if (!Number.isFinite(n) || n < 0) {
          process.stderr.write(`[launch-recall] invalid --keep-last: ${raw}
`);
          process.exit(2);
        }
        out.keepLast = n;
      }
    } else if (a === "--max-age") {
      const raw = args[++i] ?? "";
      if (raw === "off") {
        out.maxAgeDays = null;
      } else {
        const m = /^(\d+)\s*(d|days?)?$/i.exec(raw);
        if (!m) {
          process.stderr.write(`[launch-recall] invalid --max-age: ${raw} (expected e.g. 30 or 30d)
`);
          process.exit(2);
        }
        out.maxAgeDays = Number(m[1]);
      }
    } else {
      process.stderr.write(`[launch-recall] unknown forget arg: ${a}
`);
      process.exit(2);
    }
  }
  return out;
}
function resolveRetention(args, configRetention) {
  return {
    keepLast: args.keepLast === void 0 ? configRetention.keepLast : args.keepLast,
    maxAgeDays: args.maxAgeDays === void 0 ? configRetention.maxAgeDays : args.maxAgeDays
  };
}
function listCommitsOldestFirst(env) {
  const result = runGitSync(
    ["log", "--reverse", "--format=%H %ct", "main"],
    { env }
  );
  if (result.status !== 0) {
    return [];
  }
  return result.stdout.split("\n").filter(Boolean).map((line) => {
    const [sha, ct] = line.split(" ");
    return { sha, committerEpoch: Number(ct) };
  });
}
function pickCutoff(commits, retention) {
  if (commits.length === 0) return { dropCount: 0, firstKeptIndex: 0 };
  let firstKept = 0;
  if (typeof retention.keepLast === "number" && commits.length > retention.keepLast) {
    firstKept = Math.max(firstKept, commits.length - retention.keepLast);
  }
  if (typeof retention.maxAgeDays === "number") {
    const cutoffEpoch = Math.floor(Date.now() / 1e3) - retention.maxAgeDays * 86400;
    let idx = commits.findIndex((c) => c.committerEpoch >= cutoffEpoch);
    if (idx === -1) idx = commits.length;
    firstKept = Math.max(firstKept, idx);
  }
  if (firstKept >= commits.length) {
    firstKept = commits.length - 1;
  }
  return { dropCount: firstKept, firstKeptIndex: firstKept };
}
function rewriteHistory(env, kept) {
  if (kept.length === 0) return { error: "no commits to keep" };
  const first = kept[0];
  const treeResult = runGitSync(["rev-parse", `${first.sha}^{tree}`], { env });
  if (treeResult.status !== 0) return { error: `rev-parse tree failed: ${treeResult.stderr}` };
  const firstTree = treeResult.stdout.trim();
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
  const newRoot = runGitSync(
    ["commit-tree", firstTree, "-m", `snap (truncated ${stamp})`],
    { env }
  );
  if (newRoot.status !== 0) return { error: `commit-tree (root) failed: ${newRoot.stderr}` };
  let parent = newRoot.stdout.trim();
  for (let i = 1; i < kept.length; i++) {
    const c = kept[i];
    const t = runGitSync(["rev-parse", `${c.sha}^{tree}`], { env });
    if (t.status !== 0) return { error: `rev-parse tree ${c.sha} failed: ${t.stderr}` };
    const msg = runGitSync(["log", "-1", "--format=%B", c.sha], { env });
    if (msg.status !== 0) return { error: `log -1 ${c.sha} failed: ${msg.stderr}` };
    const next = runGitSync(
      ["commit-tree", t.stdout.trim(), "-p", parent, "-m", msg.stdout.trim() || "snap"],
      { env }
    );
    if (next.status !== 0) return { error: `commit-tree ${c.sha} failed: ${next.stderr}` };
    parent = next.stdout.trim();
  }
  const update = runGitSync(
    ["update-ref", "refs/heads/main", parent],
    { env }
  );
  if (update.status !== 0) return { error: `update-ref failed: ${update.stderr}` };
  return { newTipSha: parent };
}
async function runForget(args) {
  const parsed = parseArgs2(args);
  const { workTree, gitDir } = resolveRecallPaths();
  if (!fs7.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] not initialised \u2014 run: launch-recall init
`);
    process.exit(1);
  }
  const { config } = loadConfig(workTree);
  const retention = resolveRetention(parsed, config.retention);
  if (retention.keepLast === null && retention.maxAgeDays === null) {
    process.stderr.write(`[launch-recall] no retention rules set \u2014 nothing to do
`);
    return;
  }
  const env = gitEnv(gitDir, workTree);
  const commits = listCommitsOldestFirst(env);
  if (commits.length === 0) {
    process.stderr.write(`[launch-recall] no commits in shadow repo
`);
    return;
  }
  const { dropCount } = pickCutoff(commits, retention);
  const kept = commits.slice(dropCount);
  process.stderr.write(
    `[launch-recall] retention: keepLast=${retention.keepLast ?? "off"} maxAgeDays=${retention.maxAgeDays ?? "off"}
`
  );
  process.stderr.write(
    `[launch-recall] ${commits.length} snapshots total, ${dropCount} to drop, ${kept.length} to keep
`
  );
  if (dropCount === 0) {
    process.stderr.write(`[launch-recall] nothing to drop
`);
    return;
  }
  if (parsed.dryRun) {
    process.stderr.write(`[launch-recall] --dry-run \u2014 no changes written
`);
    return;
  }
  process.stderr.write(`[launch-recall] rewriting history\u2026
`);
  const result = rewriteHistory(env, kept);
  if ("error" in result) {
    process.stderr.write(`[launch-recall] rewrite failed: ${result.error}
`);
    process.exit(1);
  }
  process.stderr.write(`[launch-recall] new main tip: ${result.newTipSha.slice(0, 7)}
`);
  process.stderr.write(`[launch-recall] expiring reflog\u2026
`);
  runGitSync(["reflog", "expire", "--expire=now", "--all"], { env });
  process.stderr.write(`[launch-recall] running gc --prune=now\u2026
`);
  const gc = runGitSync(["gc", "--prune=now", "--quiet"], { env });
  if (gc.status !== 0) {
    process.stderr.write(`[launch-recall] gc warning:
${gc.stderr}`);
  }
  process.stderr.write(`[launch-recall] done
`);
}
var fs7;
var init_forget = __esm({
  "src/server/recall/forget.ts"() {
    "use strict";
    fs7 = __toESM(require("node:fs"));
    init_git();
    init_config();
    init_paths();
  }
});

// src/server/recall/push.ts
var push_exports = {};
__export(push_exports, {
  runPush: () => runPush
});
async function runPush(args) {
  const remote = args[0];
  if (!remote) {
    process.stderr.write("Usage: launch-recall push <remote-url-or-path>\n");
    process.exit(2);
  }
  const { workTree, gitDir } = resolveRecallPaths();
  if (!fs8.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] not initialised \u2014 run: launch-recall init
`);
    process.exit(1);
  }
  const env = gitEnv(gitDir, workTree);
  const code = await runGit(["push", "--mirror", remote], { env });
  process.exit(code);
}
var fs8;
var init_push = __esm({
  "src/server/recall/push.ts"() {
    "use strict";
    fs8 = __toESM(require("node:fs"));
    init_git();
    init_paths();
  }
});

// src/server/recall/gc.ts
var gc_exports = {};
__export(gc_exports, {
  runGc: () => runGc
});
async function runGc(_args) {
  const { workTree, gitDir } = resolveRecallPaths();
  if (!fs9.existsSync(gitDir)) {
    process.stderr.write(`[launch-recall] not initialised \u2014 run: launch-recall init
`);
    process.exit(1);
  }
  const env = gitEnv(gitDir, workTree);
  const code = await runGit(["gc", "--auto"], { env });
  process.exit(code);
}
var fs9;
var init_gc = __esm({
  "src/server/recall/gc.ts"() {
    "use strict";
    fs9 = __toESM(require("node:fs"));
    init_git();
    init_paths();
  }
});

// src/server/recall/uninstall.ts
var uninstall_exports = {};
__export(uninstall_exports, {
  runUninstall: () => runUninstall
});
function parseArgs3(args) {
  const out = { keepHistory: false, keepConfig: false, force: false };
  for (const a of args) {
    if (a === "--keep-history") out.keepHistory = true;
    else if (a === "--keep-config") out.keepConfig = true;
    else if (a === "--force" || a === "-y") out.force = true;
    else {
      process.stderr.write(`[launch-recall] unknown uninstall arg: ${a}
`);
      process.exit(2);
    }
  }
  return out;
}
function formatSize(bytes) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
}
function dirSizeBytes(dir) {
  if (!fs10.existsSync(dir)) return 0;
  let total = 0;
  const stack = [dir];
  while (stack.length > 0) {
    const cur = stack.pop();
    let entries;
    try {
      entries = fs10.readdirSync(cur, { withFileTypes: true });
    } catch {
      continue;
    }
    for (const e of entries) {
      const full = path6.join(cur, e.name);
      try {
        if (e.isDirectory()) {
          stack.push(full);
        } else if (e.isFile()) {
          total += fs10.statSync(full).size;
        }
      } catch {
      }
    }
  }
  return total;
}
function promptYesNo(question) {
  return new Promise((resolve3) => {
    if (!process.stdin.isTTY) {
      process.stderr.write(
        `${question} \u2014 non-interactive shell, refusing without --force
`
      );
      resolve3(false);
      return;
    }
    const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
    rl.question(`${question} (y/N): `, (answer) => {
      rl.close();
      const a = answer.trim().toLowerCase();
      resolve3(a === "y" || a === "yes");
    });
  });
}
function removeGitignoreLine(gitignorePath) {
  if (!fs10.existsSync(gitignorePath)) return "no-file";
  const text2 = fs10.readFileSync(gitignorePath, "utf8");
  const lines = text2.split(/\r?\n/);
  const matches = (l) => {
    const t = l.trim();
    return t === `/${RECALL_DIR_NAME}/` || t === `${RECALL_DIR_NAME}/` || t === RECALL_DIR_NAME || t === `/${RECALL_DIR_NAME}` || t === `${RECALL_DIR_NAME}/**`;
  };
  if (!lines.some(matches)) return "no-line";
  const kept = lines.filter((l) => !matches(l));
  fs10.writeFileSync(gitignorePath, kept.join("\n"));
  return "removed";
}
async function runUninstall(args) {
  const parsed = parseArgs3(args);
  const { workTree, recallDir } = resolveRecallPaths();
  const configPath = path6.join(workTree, CONFIG_FILENAME);
  const gitignorePath = path6.join(workTree, ".gitignore");
  const pf = pidFilePath2(recallDir);
  const watcherRunning = fs10.existsSync(pf);
  const shadowPresent = fs10.existsSync(recallDir);
  const configPresent = fs10.existsSync(configPath);
  const shadowSize = shadowPresent ? dirSizeBytes(recallDir) : 0;
  let gitignoreHasLine = false;
  if (fs10.existsSync(gitignorePath)) {
    const text2 = fs10.readFileSync(gitignorePath, "utf8");
    gitignoreHasLine = text2.split(/\r?\n/).some((l) => {
      const t = l.trim();
      return t === `/${RECALL_DIR_NAME}/` || t === `${RECALL_DIR_NAME}/` || t === RECALL_DIR_NAME || t === `/${RECALL_DIR_NAME}` || t === `${RECALL_DIR_NAME}/**`;
    });
  }
  const willStopWatcher = watcherRunning;
  const willRemoveShadow = !parsed.keepHistory && shadowPresent;
  const willRemoveConfig = !parsed.keepConfig && configPresent;
  const willPatchGitignore = !parsed.keepConfig && gitignoreHasLine;
  const plan = [];
  if (willStopWatcher) plan.push("Stop running watcher");
  if (willRemoveShadow) plan.push(`Delete ${recallDir} (${formatSize(shadowSize)})`);
  if (willRemoveConfig) plan.push(`Delete ${configPath}`);
  if (willPatchGitignore) plan.push(`Remove /${RECALL_DIR_NAME}/ from .gitignore`);
  if (plan.length === 0) {
    process.stderr.write("[launch-recall] nothing to uninstall\n");
    return;
  }
  process.stderr.write("[launch-recall] uninstall plan:\n");
  for (const a of plan) process.stderr.write(`  - ${a}
`);
  if (!parsed.force) {
    const ok = await promptYesNo("Proceed?");
    if (!ok) {
      process.stderr.write("[launch-recall] aborted\n");
      return;
    }
  }
  if (willStopWatcher) {
    await stopWatcher(false);
  }
  if (willRemoveShadow) {
    fs10.rmSync(recallDir, { recursive: true, force: true });
    process.stderr.write(`[launch-recall] removed ${recallDir}
`);
  }
  if (willRemoveConfig) {
    try {
      fs10.unlinkSync(configPath);
      process.stderr.write(`[launch-recall] removed ${configPath}
`);
    } catch {
    }
  }
  if (willPatchGitignore) {
    const res = removeGitignoreLine(gitignorePath);
    if (res === "removed") {
      process.stderr.write(`[launch-recall] removed /${RECALL_DIR_NAME}/ from .gitignore
`);
    }
  }
  process.stderr.write("[launch-recall] uninstall complete\n");
}
var fs10, path6, readline;
var init_uninstall = __esm({
  "src/server/recall/uninstall.ts"() {
    "use strict";
    fs10 = __toESM(require("node:fs"));
    path6 = __toESM(require("node:path"));
    readline = __toESM(require("node:readline"));
    init_config();
    init_paths();
    init_stop();
  }
});

// src/server/recall-entry.ts
function logStderr(msg) {
  process.stderr.write(`[launch-recall] ${msg}
`);
}
function printUsage() {
  process.stdout.write(
    [
      "Usage: launch-recall <command> [options]",
      "",
      "Commands:",
      "  init                              create .recall/repo.git + gitignore entry + default config",
      "  watch [--debounce <ms>]           foreground watcher (defaults from .launch-recall.json)",
      "  stop                              terminate the running watcher",
      "  mcp                               stdio MCP server (spawns watcher as child)",
      "  log [path]                        show shadow history (passthrough to git log)",
      "  restore <path> [--at <ref>]       extract a file from a snapshot",
      "  forget [--keep-last N] [--max-age 30d] [--dry-run]",
      "                                    prune history per retention rules",
      "  push <remote>                     mirror shadow to an external bare repo",
      "  gc                                pack and prune the shadow repo",
      "  uninstall [--keep-history] [--keep-config] [--force]",
      "                                    stop watcher + remove shadow + config + gitignore line",
      ""
    ].join("\n")
  );
}
async function main() {
  const argv = process.argv.slice(2);
  const subcommand = argv[0];
  if (!subcommand || subcommand === "--help" || subcommand === "-h") {
    printUsage();
    return;
  }
  switch (subcommand) {
    case "init": {
      const { runInit: runInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
      await runInit2(argv.slice(1));
      return;
    }
    case "mcp": {
      const { startRecallMcpServer: startRecallMcpServer2 } = await Promise.resolve().then(() => (init_recall_mcp(), recall_mcp_exports));
      startRecallMcpServer2();
      return;
    }
    case "watch": {
      const { runWatch: runWatch2 } = await Promise.resolve().then(() => (init_watch(), watch_exports));
      await runWatch2(argv.slice(1));
      return;
    }
    case "stop": {
      const { runStop: runStop2 } = await Promise.resolve().then(() => (init_stop(), stop_exports));
      await runStop2(argv.slice(1));
      return;
    }
    case "log": {
      const { runLog: runLog2 } = await Promise.resolve().then(() => (init_log(), log_exports));
      await runLog2(argv.slice(1));
      return;
    }
    case "restore": {
      const { runRestore: runRestore2 } = await Promise.resolve().then(() => (init_restore(), restore_exports));
      await runRestore2(argv.slice(1));
      return;
    }
    case "forget": {
      const { runForget: runForget2 } = await Promise.resolve().then(() => (init_forget(), forget_exports));
      await runForget2(argv.slice(1));
      return;
    }
    case "push": {
      const { runPush: runPush2 } = await Promise.resolve().then(() => (init_push(), push_exports));
      await runPush2(argv.slice(1));
      return;
    }
    case "gc": {
      const { runGc: runGc2 } = await Promise.resolve().then(() => (init_gc(), gc_exports));
      await runGc2(argv.slice(1));
      return;
    }
    case "uninstall": {
      const { runUninstall: runUninstall2 } = await Promise.resolve().then(() => (init_uninstall(), uninstall_exports));
      await runUninstall2(argv.slice(1));
      return;
    }
    default: {
      logStderr(`unknown command: ${subcommand}`);
      printUsage();
      process.exit(2);
    }
  }
}
main().catch((err) => {
  logStderr(`fatal: ${err instanceof Error ? err.message : String(err)}`);
  process.exit(1);
});
