codeam-cli 2.61.90 → 2.61.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +804 -98
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -90,11 +90,11 @@ var require_src = __commonJS({
90
90
  });
91
91
 
92
92
  // src/integrations/stdio-proxy.ts
93
- var import_node_child_process31, import_node_readline3, RESTART_CHECK_INTERVAL_MS, SIGKILL_ESCALATION_MS, TOOL_CALL_TIMEOUT_MS, REPLAY_INIT_ID, RestartableStdioProxy;
93
+ var import_node_child_process32, import_node_readline3, RESTART_CHECK_INTERVAL_MS, SIGKILL_ESCALATION_MS, TOOL_CALL_TIMEOUT_MS, REPLAY_INIT_ID, RestartableStdioProxy;
94
94
  var init_stdio_proxy = __esm({
95
95
  "src/integrations/stdio-proxy.ts"() {
96
96
  "use strict";
97
- import_node_child_process31 = require("child_process");
97
+ import_node_child_process32 = require("child_process");
98
98
  import_node_readline3 = __toESM(require("readline"));
99
99
  RESTART_CHECK_INTERVAL_MS = 3e4;
100
100
  SIGKILL_ESCALATION_MS = 2e3;
@@ -271,7 +271,7 @@ var init_stdio_proxy = __esm({
271
271
  }
272
272
  async spawnChild(stdout, preResolved) {
273
273
  const spec = preResolved ?? await this.opts.spawnSpec();
274
- const spawn44 = this.opts.spawnImpl ?? import_node_child_process31.spawn;
274
+ const spawn44 = this.opts.spawnImpl ?? import_node_child_process32.spawn;
275
275
  const child = spawn44(spec.command, spec.args, {
276
276
  env: { ...process.env, ...spec.env },
277
277
  // env only — never argv
@@ -2635,6 +2635,144 @@ function normalizeGuardrailPolicy(raw) {
2635
2635
  return out2;
2636
2636
  }
2637
2637
 
2638
+ // ../../packages/shared/src/packs/roles.ts
2639
+ var SPECIFIER_PROMPT = `# Role: Specifier
2640
+
2641
+ You turn the user's task into a precise, testable specification the rest of the pipeline implements against. You do NOT write implementation code.
2642
+
2643
+ Method:
2644
+ 1. Read the task and explore the relevant parts of the codebase until you understand the real problem, the desired outcome, and the constraints the code imposes.
2645
+ 2. Write the specification to \`SPEC.pack.md\` at the repo root:
2646
+ - **Problem** \u2014 what is wrong or missing, and for whom.
2647
+ - **Outcome** \u2014 what must be true when this is done.
2648
+ - **Acceptance criteria** \u2014 a numbered checklist of observable, testable conditions. Each criterion must be verifiable by a test or a concrete manual check. They must fully cover the outcome.
2649
+ - **Out of scope** \u2014 what this task deliberately does not touch.
2650
+ - **Verification plan** \u2014 for each criterion, the level that proves it (unit / integration / manual) and why.
2651
+ 3. Right-size: if the task is clearly too large for one pipeline run, narrow the criteria to a coherent first slice and record the rest under "Out of scope / next".
2652
+
2653
+ Handoff bar: the spec file is committed; every acceptance criterion is testable as written; a competent implementer could start without asking you anything.`;
2654
+ var CODER_PROMPT = `# Role: Coder
2655
+
2656
+ You implement the task with test-driven discipline. You are the only stage that adds behavior.
2657
+
2658
+ Method:
2659
+ 1. Read the task \u2014 and \`SPEC.pack.md\` if a Specifier stage produced one; its acceptance criteria are your contract. Without a spec, derive the minimal criteria from the task itself before coding.
2660
+ 2. Test-first where it fits: write the test that proves a criterion, watch it fail, implement until it passes. Where strict test-first doesn't fit, still land tests alongside the change.
2661
+ 3. Match the project's existing style, structure, and conventions. Simplest design that fully solves the problem \u2014 no speculative abstractions, no "while I'm here" changes.
2662
+ 4. Run the project's tests / linters / build and make them pass.
2663
+
2664
+ Handoff bar: every acceptance criterion is implemented and covered by a test; the project's checks pass; the work is committed in focused commits.`;
2665
+ var REVIEWER_PROMPT = `# Role: Reviewer
2666
+
2667
+ You are a skeptical senior reviewer with fresh eyes \u2014 you did NOT write this code, and your job is to find what's wrong, not to approve it. You also own architectural cleanliness for this change.
2668
+
2669
+ Method:
2670
+ 1. Read the task, \`SPEC.pack.md\` (when present), and the diff of the pipeline's commits (\`git log\` + \`git diff\` against the state before the pipeline's first commit). Read enough surrounding code to judge in context.
2671
+ 2. Audit, in priority order:
2672
+ - **Correctness** \u2014 logic, edge cases, error paths. For each acceptance criterion: point to the test that proves it, and check the test would FAIL if the behavior broke.
2673
+ - **Scope** \u2014 anything beyond the task is flagged and reverted unless it is load-bearing.
2674
+ - **Design** \u2014 duplication, dead code, needless complexity, dependency direction, encapsulation. Verify every API/library call actually exists in the project's dependencies.
2675
+ - **Conventions & naming** \u2014 matches the surrounding code; names say what things are.
2676
+ - **Safety** \u2014 no secrets, credentials, or debugging remnants in code, tests, or fixtures.
2677
+ 3. Fix what is justified \u2014 smallest change that resolves the finding, keeping behavior. Re-run the checks after material fixes.
2678
+ 4. Record your findings honestly in your closing summary: what you found, what you fixed, what you deliberately left, and what you could not verify.
2679
+
2680
+ Handoff bar: checks pass on YOUR final commit; every fix is committed; your summary lists findings \u2192 resolutions (an empty findings list must say what you checked).`;
2681
+ var QA_PROMPT = `# Role: QA
2682
+
2683
+ You are the final gate. You verify the delivered work against the acceptance criteria as a whole \u2014 end to end, the way a demanding user would \u2014 and produce the run's closing report.
2684
+
2685
+ Method:
2686
+ 1. Read the task and \`SPEC.pack.md\` (when present). Your contract is the acceptance criteria; without a spec, derive them from the task.
2687
+ 2. For EACH criterion, verify it against the real project: run the relevant tests, execute the code paths where feasible, inspect actual behavior/output. Do not take earlier stages' word for anything.
2688
+ 3. Run the project's full checks (tests, lint, types, build) one final time.
2689
+ 4. Write \`QA-REPORT.pack.md\` at the repo root: per-criterion verdict (\u2705 verified / \u26A0\uFE0F partially / \u274C failed \u2014 with evidence for each), the checks' results, anything not verifiable in this environment (stated plainly), and a short "ready to ship?" conclusion.
2690
+ 5. If a criterion FAILS: fix it only when the fix is small and unambiguous; otherwise mark it failed with exact evidence \u2014 the user decides. Never paper over a failure.
2691
+
2692
+ Handoff bar: the report is committed; every verdict carries evidence; the conclusion is honest about anything unverified.`;
2693
+
2694
+ // ../../packages/shared/src/packs/registry.ts
2695
+ var PACK_REGISTRY = {
2696
+ "quick-pack": {
2697
+ id: "quick-pack",
2698
+ name: "Quick Pack",
2699
+ tagline: "Implement, then a fresh-eyes review \u2014 the tight loop.",
2700
+ gate: "free",
2701
+ stages: [
2702
+ {
2703
+ role: "coder",
2704
+ name: "Coder",
2705
+ description: "Implements the task with tests, TDD-first.",
2706
+ skillIds: ["spec-driven-development"],
2707
+ prompt: CODER_PROMPT
2708
+ },
2709
+ {
2710
+ role: "reviewer",
2711
+ name: "Reviewer",
2712
+ description: "Skeptical review in a fresh context \u2014 finds and fixes what the coder missed.",
2713
+ skillIds: ["code-review", "code-naming"],
2714
+ prompt: REVIEWER_PROMPT
2715
+ }
2716
+ ]
2717
+ },
2718
+ "full-pack": {
2719
+ id: "full-pack",
2720
+ name: "Full Pack",
2721
+ tagline: "Spec \u2192 implement \u2192 review \u2192 verify. Every quality gate, one run.",
2722
+ gate: "pro",
2723
+ stages: [
2724
+ {
2725
+ role: "specifier",
2726
+ name: "Specifier",
2727
+ description: "Turns the task into testable acceptance criteria before any code.",
2728
+ skillIds: ["spec-driven-development"],
2729
+ prompt: SPECIFIER_PROMPT
2730
+ },
2731
+ {
2732
+ role: "coder",
2733
+ name: "Coder",
2734
+ description: "Implements the acceptance criteria with tests, TDD-first.",
2735
+ skillIds: [],
2736
+ prompt: CODER_PROMPT
2737
+ },
2738
+ {
2739
+ role: "reviewer",
2740
+ name: "Reviewer",
2741
+ description: "Audits correctness, scope, design, and conventions with fresh eyes.",
2742
+ skillIds: ["code-review", "code-naming"],
2743
+ prompt: REVIEWER_PROMPT
2744
+ },
2745
+ {
2746
+ role: "qa",
2747
+ name: "QA",
2748
+ description: "Verifies every acceptance criterion end to end and writes the final report.",
2749
+ skillIds: [],
2750
+ prompt: QA_PROMPT
2751
+ }
2752
+ ]
2753
+ }
2754
+ };
2755
+ function isPackId(id) {
2756
+ return Object.prototype.hasOwnProperty.call(PACK_REGISTRY, id);
2757
+ }
2758
+ function getPackDefinition(id) {
2759
+ return isPackId(id) ? PACK_REGISTRY[id] : null;
2760
+ }
2761
+
2762
+ // ../../packages/shared/src/packs/workflow-article.ts
2763
+ var PACK_WORKFLOW_ARTICLE = `## Pipeline rules (you are one stage of an assembly line)
2764
+
2765
+ You are ONE specialist role in a multi-role pipeline running on this repository. Other specialist roles ran before you and/or run after you, each in a separate conversation. Follow these rules exactly:
2766
+
2767
+ - **Do only your role's job.** The next stage exists for a reason \u2014 don't do its work, and don't redo a previous stage's work unless your role explicitly calls for correcting it.
2768
+ - **Work from the handoff.** The previous stage's handoff (commit + summary) is your input. Start by reading the current state of the working tree \u2014 it already contains all prior stages' work.
2769
+ - **Commit your work when your stage is complete.** One or more focused commits; the final state of the tree IS your handoff to the next stage. End every commit message with your role byline on its own line: \`By <role>.\`
2770
+ - **Never leave the tree broken.** Run the project's checks before finishing when the project has them; your stage ends with a working tree the next role can build on.
2771
+ - **Do not push, force-push, or touch remotes** \u2014 the pipeline works locally; publishing is the user's call at the end.
2772
+ - **Never read, edit, or commit anything under \`.codeam/\`** \u2014 that is the pipeline's own ledger, not project code.
2773
+ - **Finish decisively.** When your stage's job is done and committed, say so in 2-4 lines (what you did, what you verified, anything the next stage should know) and stop. Don't ask "should I continue?" \u2014 the pipeline advances automatically.
2774
+ - **If you are genuinely blocked** (contradictory requirements, missing access), say exactly what is blocking you and stop \u2014 the user is supervising and will decide.`;
2775
+
2638
2776
  // ../../packages/shared/src/api-url.ts
2639
2777
  var DEFAULT_API_BASE_URL = "https://api.codeagent-mobile.com";
2640
2778
  var DEV_API_BASE_URL = "https://dev-api.codeagent-mobile.com";
@@ -2781,7 +2919,12 @@ var USER_EVENTS = {
2781
2919
  * toast when the review runs server-side (Inngest). Mobile-only surface,
2782
2920
  * produced by api-v2 (the CLI neither produces nor consumes it). Mirrored in
2783
2921
  * repo A. */
2784
- PR_REVIEW_LAUNCH: "pr_review_launch"
2922
+ PR_REVIEW_LAUNCH: "pr_review_launch",
2923
+ /** Agent Packs — full `PackRunState` republished by the backend on every
2924
+ * pipeline transition (stage start/done, pause, stall, completion). CLI
2925
+ * posts to /api/packs/events; mobile's pack.store renders the pipeline.
2926
+ * Mirrored in repo A's app-shared events.ts. */
2927
+ PACK_STATE: "pack_state"
2785
2928
  };
2786
2929
 
2787
2930
  // ../../packages/shared/src/preview-prompts.ts
@@ -2972,11 +3115,11 @@ function quiet(fn) {
2972
3115
  log.debug(TAG, "ignored sync error", err);
2973
3116
  }
2974
3117
  }
2975
- function rmIfExistsQuiet(path87) {
3118
+ function rmIfExistsQuiet(path89) {
2976
3119
  try {
2977
- fs2.rmSync(path87, { force: true });
3120
+ fs2.rmSync(path89, { force: true });
2978
3121
  } catch (err) {
2979
- log.debug(TAG, `rmIfExists failed for ${path87}`, err);
3122
+ log.debug(TAG, `rmIfExists failed for ${path89}`, err);
2980
3123
  }
2981
3124
  }
2982
3125
  function killQuiet(target, signal = "SIGTERM") {
@@ -3160,8 +3303,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
3160
3303
  return decodedFile;
3161
3304
  };
3162
3305
  }
3163
- function normalizeWindowsPath(path87) {
3164
- return path87.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3306
+ function normalizeWindowsPath(path89) {
3307
+ return path89.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3165
3308
  }
3166
3309
 
3167
3310
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -5641,9 +5784,9 @@ async function addSourceContext(frames) {
5641
5784
  LRU_FILE_CONTENTS_CACHE.reduce();
5642
5785
  return frames;
5643
5786
  }
5644
- function getContextLinesFromFile(path87, ranges, output) {
5787
+ function getContextLinesFromFile(path89, ranges, output) {
5645
5788
  return new Promise((resolve9) => {
5646
- const stream = (0, import_node_fs.createReadStream)(path87);
5789
+ const stream = (0, import_node_fs.createReadStream)(path89);
5647
5790
  const lineReaded = (0, import_node_readline.createInterface)({
5648
5791
  input: stream
5649
5792
  });
@@ -5658,7 +5801,7 @@ function getContextLinesFromFile(path87, ranges, output) {
5658
5801
  let rangeStart = range[0];
5659
5802
  let rangeEnd = range[1];
5660
5803
  function onStreamError() {
5661
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path87, 1);
5804
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path89, 1);
5662
5805
  lineReaded.close();
5663
5806
  lineReaded.removeAllListeners();
5664
5807
  destroyStreamAndResolve();
@@ -5719,8 +5862,8 @@ function clearLineContext(frame) {
5719
5862
  delete frame.context_line;
5720
5863
  delete frame.post_context;
5721
5864
  }
5722
- function shouldSkipContextLinesForFile(path87) {
5723
- return path87.startsWith("node:") || path87.endsWith(".min.js") || path87.endsWith(".min.cjs") || path87.endsWith(".min.mjs") || path87.startsWith("data:");
5865
+ function shouldSkipContextLinesForFile(path89) {
5866
+ return path89.startsWith("node:") || path89.endsWith(".min.js") || path89.endsWith(".min.cjs") || path89.endsWith(".min.mjs") || path89.startsWith("data:");
5724
5867
  }
5725
5868
  function shouldSkipContextLinesForFrame(frame) {
5726
5869
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -7874,7 +8017,7 @@ function readAnonId() {
7874
8017
  }
7875
8018
  function superProperties() {
7876
8019
  return {
7877
- cliVersion: true ? "2.61.90" : "0.0.0-dev",
8020
+ cliVersion: true ? "2.61.92" : "0.0.0-dev",
7878
8021
  nodeVersion: process.version,
7879
8022
  platform: process.platform,
7880
8023
  arch: process.arch,
@@ -8055,7 +8198,7 @@ var os4 = __toESM(require("os"));
8055
8198
  // package.json
8056
8199
  var package_default = {
8057
8200
  name: "codeam-cli",
8058
- version: "2.61.90",
8201
+ version: "2.61.92",
8059
8202
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
8060
8203
  type: "commonjs",
8061
8204
  main: "dist/index.js",
@@ -8893,6 +9036,27 @@ async function ensureHeadroomProxy(deps) {
8893
9036
  deps.spawnProxy();
8894
9037
  return "respawned";
8895
9038
  }
9039
+ async function ensureHeadroomProxyReady(deps, opts = {}) {
9040
+ if (!deps.isConfigured()) return true;
9041
+ if (await deps.probeAlive().catch(() => false)) return true;
9042
+ log.warn(
9043
+ "headroom-supervisor",
9044
+ "proxy :8787 not answering before a turn \u2014 force-respawning + waiting for readiness"
9045
+ );
9046
+ (deps.spawnProxyForce ?? deps.spawnProxy)();
9047
+ const sleep5 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
9048
+ const pollMs = opts.pollMs ?? 1500;
9049
+ const maxPolls = Math.max(1, Math.ceil((opts.timeoutMs ?? 6e4) / pollMs));
9050
+ for (let i = 0; i < maxPolls; i += 1) {
9051
+ await sleep5(pollMs);
9052
+ if (await deps.probeAlive().catch(() => false)) {
9053
+ log.info("headroom-supervisor", `proxy :8787 ready after ~${(i + 1) * pollMs / 1e3}s`);
9054
+ return true;
9055
+ }
9056
+ }
9057
+ log.warn("headroom-supervisor", "proxy :8787 still not ready after respawn wait \u2014 proceeding anyway");
9058
+ return false;
9059
+ }
8896
9060
  function isHeadroomConfiguredReal(homeDir2 = os6.homedir()) {
8897
9061
  if (process.env.HEADROOM_ENABLED === "1") return true;
8898
9062
  const csEnv = path6.join(homeDir2, ".codeam", "codespace-env.json");
@@ -8935,7 +9099,15 @@ function makeRealProxySupervisorDeps() {
8935
9099
  probeAlive: probeProxyAliveReal,
8936
9100
  proxyProcessAlive: () => isHeadroomProxyProcessAlive(),
8937
9101
  proxyStartupAgeMs: () => headroomProxyPidfileAgeMs(Date.now()),
8938
- spawnProxy: spawnProxyReal
9102
+ spawnProxy: spawnProxyReal,
9103
+ spawnProxyForce: () => spawnHeadroomProxy(
9104
+ {
9105
+ tag: "headroom-supervisor",
9106
+ spawnErrorMsg: (detail) => `force-respawn error (best-effort): ${detail}`,
9107
+ failureMsg: (detail) => `force-respawn failed (best-effort): ${detail}`
9108
+ },
9109
+ { force: true }
9110
+ )
8939
9111
  };
8940
9112
  }
8941
9113
 
@@ -9331,7 +9503,7 @@ var CommandRelayService = class _CommandRelayService {
9331
9503
  // fresh + clear the "CLI update available" banner after a self-update
9332
9504
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9333
9505
  // pair/reconnect). Older backends ignore the extra field.
9334
- ..."2.61.90" ? { ideVersion: "2.61.90" } : {}
9506
+ ..."2.61.92" ? { ideVersion: "2.61.92" } : {}
9335
9507
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9336
9508
  }
9337
9509
  /**
@@ -15940,8 +16112,8 @@ function pickLine(obj) {
15940
16112
  function toHunk(raw, groupSeverity) {
15941
16113
  if (!raw || typeof raw !== "object") return null;
15942
16114
  const o = raw;
15943
- const path87 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
15944
- if (!path87) return null;
16115
+ const path89 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
16116
+ if (!path89) return null;
15945
16117
  const message = asString(
15946
16118
  pick(o, [
15947
16119
  "comment",
@@ -15958,7 +16130,7 @@ function toHunk(raw, groupSeverity) {
15958
16130
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
15959
16131
  const locObj = pick(o, ["location"]) ?? o;
15960
16132
  return {
15961
- path: path87.trim(),
16133
+ path: path89.trim(),
15962
16134
  line: pickLine(o) ?? pickLine(locObj),
15963
16135
  severity,
15964
16136
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -16041,10 +16213,10 @@ function parsePlain(stdout) {
16041
16213
  for (const line of stdout.split(/\r?\n/)) {
16042
16214
  const m = line.match(HUNK_LINE_RE);
16043
16215
  if (!m) continue;
16044
- const [, path87, lineNo, sevToken, message] = m;
16045
- if (!path87 || !lineNo || !message) continue;
16216
+ const [, path89, lineNo, sevToken, message] = m;
16217
+ if (!path89 || !lineNo || !message) continue;
16046
16218
  hunks.push({
16047
- path: path87.trim(),
16219
+ path: path89.trim(),
16048
16220
  line: Number(lineNo),
16049
16221
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
16050
16222
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -20504,7 +20676,7 @@ async function autoUpgradeBeforeCriticalCommand() {
20504
20676
  if (process.env.NODE_ENV === "test") return;
20505
20677
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20506
20678
  if (process.env.CI) return;
20507
- const current2 = true ? "2.61.90" : null;
20679
+ const current2 = true ? "2.61.92" : null;
20508
20680
  if (!current2) return;
20509
20681
  const cache = readCache();
20510
20682
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20521,7 +20693,7 @@ function checkForUpdates() {
20521
20693
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20522
20694
  if (process.env.CI) return;
20523
20695
  if (!process.stdout.isTTY) return;
20524
- const current2 = true ? "2.61.90" : null;
20696
+ const current2 = true ? "2.61.92" : null;
20525
20697
  if (!current2) return;
20526
20698
  const cache = readCache();
20527
20699
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20541,7 +20713,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
20541
20713
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
20542
20714
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
20543
20715
  function currentCliVersion() {
20544
- return true ? "2.61.90" : null;
20716
+ return true ? "2.61.92" : null;
20545
20717
  }
20546
20718
  function runCmd(cmd, args2, timeoutMs) {
20547
20719
  return new Promise((resolve9) => {
@@ -25897,13 +26069,13 @@ function resolveGlobalNodeModulesDir(opts) {
25897
26069
  var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
25898
26070
  function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
25899
26071
  if (!nodeModulesDir) return 0;
25900
- const readdirSync13 = deps?.readdirSync ?? fs62.readdirSync;
26072
+ const readdirSync14 = deps?.readdirSync ?? fs62.readdirSync;
25901
26073
  const statSync17 = deps?.statSync ?? fs62.statSync;
25902
26074
  const rmSync9 = deps?.rmSync ?? fs62.rmSync;
25903
26075
  let removed = 0;
25904
26076
  let entries;
25905
26077
  try {
25906
- entries = readdirSync13(nodeModulesDir);
26078
+ entries = readdirSync14(nodeModulesDir);
25907
26079
  } catch {
25908
26080
  return 0;
25909
26081
  }
@@ -26786,11 +26958,11 @@ function resolveTokenValue(args2) {
26786
26958
  }
26787
26959
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
26788
26960
  if (fileFlag) {
26789
- const path87 = fileFlag.slice("--token-file=".length);
26961
+ const path89 = fileFlag.slice("--token-file=".length);
26790
26962
  try {
26791
- const content = fs63.readFileSync(path87, "utf8").trim();
26792
- if (content.length === 0) fail(`--token-file ${path87} is empty`);
26793
- rmIfExistsQuiet(path87);
26963
+ const content = fs63.readFileSync(path89, "utf8").trim();
26964
+ if (content.length === 0) fail(`--token-file ${path89} is empty`);
26965
+ rmIfExistsQuiet(path89);
26794
26966
  return content;
26795
26967
  } catch (err) {
26796
26968
  fail(`Could not read --token-file: ${err.message}`);
@@ -27436,14 +27608,14 @@ function defaultSdkDir() {
27436
27608
  return resolveSdkDirViaRequire();
27437
27609
  }
27438
27610
  function resolveClaudeNativeBinary(deps = {}) {
27439
- const existsSync28 = deps.existsSync ?? import_fs6.default.existsSync;
27611
+ const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
27440
27612
  const platformKey = deps.platformKey ?? currentPlatformKey();
27441
27613
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
27442
27614
  if (!sdkDir) return null;
27443
27615
  const scopeDir = import_path8.default.dirname(sdkDir);
27444
27616
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
27445
27617
  const candidate = import_path8.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
27446
- return existsSync28(candidate) ? candidate : null;
27618
+ return existsSync29(candidate) ? candidate : null;
27447
27619
  }
27448
27620
  var realSleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
27449
27621
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -27494,18 +27666,18 @@ async function waitForCommandOnPath(cmd, opts = {}) {
27494
27666
  return check();
27495
27667
  }
27496
27668
  function resolveCursorAgentBinary(deps = {}) {
27497
- const existsSync28 = deps.existsSync ?? import_fs6.default.existsSync;
27669
+ const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
27498
27670
  const platform3 = deps.platform ?? process.platform;
27499
27671
  const env = deps.env ?? process.env;
27500
27672
  if (platform3 === "win32") {
27501
27673
  const localAppData = env.LOCALAPPDATA;
27502
27674
  if (!localAppData) return null;
27503
27675
  const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
27504
- return existsSync28(exe) ? exe : null;
27676
+ return existsSync29(exe) ? exe : null;
27505
27677
  }
27506
27678
  const home = deps.homedir ?? import_os11.default.homedir();
27507
27679
  const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
27508
- return existsSync28(unix) ? unix : null;
27680
+ return existsSync29(unix) ? unix : null;
27509
27681
  }
27510
27682
  async function waitForCursorAgent(opts = {}) {
27511
27683
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -32934,6 +33106,7 @@ var AcpClient = class {
32934
33106
  if (!this.connection || !this.sessionId) {
32935
33107
  throw new Error("AcpClient.prompt called before start()");
32936
33108
  }
33109
+ await ensureHeadroomProxyReady(makeRealProxySupervisorDeps()).catch(() => void 0);
32937
33110
  const blocks = typeof input === "string" ? [{ type: "text", text: input }] : input;
32938
33111
  try {
32939
33112
  return await this.sendPromptOnce(blocks);
@@ -33048,6 +33221,28 @@ var AcpClient = class {
33048
33221
  * reply cleanly. The `finally` guarantees the guard clears even if the load
33049
33222
  * throws, so a failed recovery can't wedge streaming off.
33050
33223
  */
33224
+ /**
33225
+ * Start a BRAND-NEW conversation on the SAME running adapter process and make
33226
+ * it the active session. Agent Packs' stage boundary: each pipeline role runs
33227
+ * in a fresh conversation (fresh context — the reviewer must not see the
33228
+ * coder's conversation), so the pack runner calls this between stages instead
33229
+ * of respawning the agent. Same `session/new` the startup handshake and
33230
+ * {@link reestablishSession} send; callers own re-pointing the history anchor
33231
+ * (`AcpHistory.switchActiveSession` + `onActiveSessionChanged`), exactly like
33232
+ * the `resume_session` rail.
33233
+ */
33234
+ async newConversation() {
33235
+ if (!this.connection) {
33236
+ throw new Error("AcpClient.newConversation called before start()");
33237
+ }
33238
+ const ns = await this.connection.newSession({
33239
+ cwd: this.opts.cwd,
33240
+ mcpServers: this.opts.mcpServers ?? []
33241
+ });
33242
+ this.sessionId = ns.sessionId;
33243
+ log.info("acpClient", `newConversation \u2190 ok sid=${ns.sessionId.slice(0, 8)}`);
33244
+ return ns.sessionId;
33245
+ }
33051
33246
  async reestablishSession() {
33052
33247
  if (!this.connection) throw new Error("AcpClient.reestablishSession: no connection");
33053
33248
  const cwd = this.opts.cwd;
@@ -34529,7 +34724,7 @@ function defaultRunGit(cwd, args2) {
34529
34724
  });
34530
34725
  }
34531
34726
  async function discoverRepos(workingDir, maxDepth = 4) {
34532
- const fs77 = await import("fs/promises");
34727
+ const fs79 = await import("fs/promises");
34533
34728
  const out2 = [];
34534
34729
  await walk(workingDir, 0);
34535
34730
  return out2;
@@ -34537,7 +34732,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
34537
34732
  if (depth > maxDepth) return;
34538
34733
  let entries = [];
34539
34734
  try {
34540
- const dirents = await fs77.readdir(dir, { withFileTypes: true });
34735
+ const dirents = await fs79.readdir(dir, { withFileTypes: true });
34541
34736
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
34542
34737
  } catch {
34543
34738
  return;
@@ -35180,6 +35375,514 @@ async function postBudgetReached(opts, fetchImpl = fetch) {
35180
35375
  }
35181
35376
  }
35182
35377
 
35378
+ // src/packs/gates.ts
35379
+ var import_node_child_process30 = require("child_process");
35380
+ var fs71 = __toESM(require("fs"));
35381
+ var path77 = __toESM(require("path"));
35382
+ var defaultCommandRunner = (file, args2, cwd, timeoutMs) => new Promise((resolve9) => {
35383
+ (0, import_node_child_process30.execFile)(
35384
+ file,
35385
+ args2,
35386
+ { cwd, timeout: timeoutMs, maxBuffer: 4 * 1024 * 1024 },
35387
+ (err, stdout, stderr) => {
35388
+ let code = 0;
35389
+ if (err) {
35390
+ const rawCode = err.code;
35391
+ code = typeof rawCode === "number" ? rawCode : 1;
35392
+ }
35393
+ resolve9({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
35394
+ }
35395
+ );
35396
+ });
35397
+ var GIT_TIMEOUT_MS = 15e3;
35398
+ async function gitHead(run, cwd) {
35399
+ const res = await run("git", ["rev-parse", "HEAD"], cwd, GIT_TIMEOUT_MS);
35400
+ return res.code === 0 ? res.stdout.trim() : null;
35401
+ }
35402
+ async function canonicalCommit(run, cwd, sha) {
35403
+ const verify = await run("git", ["rev-parse", "--verify", `${sha}^{commit}`], cwd, GIT_TIMEOUT_MS);
35404
+ if (verify.code !== 0) return null;
35405
+ const short = await run("git", ["rev-parse", "--short=10", sha], cwd, GIT_TIMEOUT_MS);
35406
+ return short.code === 0 ? short.stdout.trim() : null;
35407
+ }
35408
+ async function diffStat(run, cwd, from, to) {
35409
+ const res = await run("git", ["diff", "--stat", `${from}..${to}`], cwd, GIT_TIMEOUT_MS);
35410
+ if (res.code !== 0) return "";
35411
+ const lines = res.stdout.trim().split("\n").filter(Boolean);
35412
+ return lines.length > 0 ? lines[lines.length - 1].trim() : "";
35413
+ }
35414
+ var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
35415
+ var CHECKS_TIMEOUT_MS = 5 * 6e4;
35416
+ function detectChecksCommand(cwd) {
35417
+ try {
35418
+ const cfg = JSON.parse(fs71.readFileSync(path77.join(cwd, ".codeam", "pack.json"), "utf8"));
35419
+ if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
35420
+ return cfg.checksCommand.trim();
35421
+ }
35422
+ } catch {
35423
+ }
35424
+ try {
35425
+ const pkg = JSON.parse(fs71.readFileSync(path77.join(cwd, "package.json"), "utf8"));
35426
+ const test = pkg.scripts?.test;
35427
+ if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
35428
+ return "npm test";
35429
+ }
35430
+ } catch {
35431
+ }
35432
+ return null;
35433
+ }
35434
+ async function runChecks(run, cwd, command2) {
35435
+ const res = await run("sh", ["-c", command2], cwd, CHECKS_TIMEOUT_MS);
35436
+ const combined = `${res.stdout}
35437
+ ${res.stderr}`.trim();
35438
+ const tail = combined.split("\n").slice(-12).join("\n").slice(-1500);
35439
+ return { command: command2, passed: res.code === 0, tail };
35440
+ }
35441
+
35442
+ // src/packs/run-store.ts
35443
+ var fs72 = __toESM(require("fs"));
35444
+ var path78 = __toESM(require("path"));
35445
+ var crypto5 = __toESM(require("crypto"));
35446
+ function packsDir(cwd) {
35447
+ return path78.join(cwd, ".codeam", "packs");
35448
+ }
35449
+ function runDir(cwd, runId) {
35450
+ return path78.join(packsDir(cwd), runId);
35451
+ }
35452
+ function newRunId() {
35453
+ return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
35454
+ }
35455
+ function writeJsonAtomic(file, value) {
35456
+ fs72.mkdirSync(path78.dirname(file), { recursive: true });
35457
+ const tmp = `${file}.tmp`;
35458
+ fs72.writeFileSync(tmp, JSON.stringify(value, null, 2));
35459
+ fs72.renameSync(tmp, file);
35460
+ }
35461
+ function saveRun(cwd, state) {
35462
+ writeJsonAtomic(path78.join(runDir(cwd, state.runId), "run.json"), state);
35463
+ }
35464
+ function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
35465
+ const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
35466
+ writeJsonAtomic(path78.join(runDir(cwd, runId), name), handoff);
35467
+ }
35468
+ function loadLatestRun(cwd) {
35469
+ try {
35470
+ const dir = packsDir(cwd);
35471
+ const entries = fs72.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
35472
+ for (let i = entries.length - 1; i >= 0; i--) {
35473
+ const file = path78.join(dir, entries[i], "run.json");
35474
+ try {
35475
+ const parsed = JSON.parse(fs72.readFileSync(file, "utf8"));
35476
+ if (parsed && typeof parsed.runId === "string") return parsed;
35477
+ } catch {
35478
+ }
35479
+ }
35480
+ } catch {
35481
+ }
35482
+ return null;
35483
+ }
35484
+ function ensureLedgerIgnored(cwd) {
35485
+ try {
35486
+ const gitDir = path78.join(cwd, ".git");
35487
+ if (!fs72.existsSync(gitDir)) return;
35488
+ const exclude = path78.join(gitDir, "info", "exclude");
35489
+ let existing = "";
35490
+ try {
35491
+ existing = fs72.readFileSync(exclude, "utf8");
35492
+ } catch {
35493
+ }
35494
+ if (existing.includes(".codeam/packs/")) return;
35495
+ fs72.mkdirSync(path78.dirname(exclude), { recursive: true });
35496
+ fs72.writeFileSync(exclude, `${existing.trimEnd()}
35497
+ .codeam/packs/
35498
+ `.trimStart());
35499
+ } catch {
35500
+ }
35501
+ }
35502
+
35503
+ // src/packs/events.ts
35504
+ async function postPackState(opts, state, fetchImpl = fetch) {
35505
+ const url2 = `${resolveApiBaseUrl()}/api/packs/events`;
35506
+ const body = JSON.stringify({ sessionId: opts.sessionId, pluginId: opts.pluginId, state });
35507
+ try {
35508
+ const makeHeaders = (token) => ({
35509
+ "Content-Type": "application/json",
35510
+ "X-Plugin-Auth-Token": token
35511
+ });
35512
+ const response = await fetchImpl(url2, {
35513
+ method: "POST",
35514
+ headers: makeHeaders(opts.pluginAuthToken),
35515
+ body
35516
+ });
35517
+ if (response.status === 401 || response.status === 403) {
35518
+ const freshToken = await fetchCurrentPluginAuthToken(
35519
+ opts.sessionId,
35520
+ opts.pluginId,
35521
+ opts.pollSecret
35522
+ );
35523
+ if (freshToken !== null) {
35524
+ await fetchImpl(url2, { method: "POST", headers: makeHeaders(freshToken), body });
35525
+ }
35526
+ }
35527
+ } catch {
35528
+ }
35529
+ }
35530
+
35531
+ // src/packs/runner.ts
35532
+ var NUDGE_PROMPT = "Your stage is not committed yet. Commit your completed work now (focused commits, ending with your role byline `By <role>.` on its own line), then summarize in 2-4 lines and stop. If you are blocked, say exactly what is blocking you instead.";
35533
+ var SUMMARY_MAX_CHARS = 600;
35534
+ function composeStagePrompt(pack, stageIndex, task, previous) {
35535
+ const stage = pack.stages[stageIndex];
35536
+ const pipeline2 = pack.stages.map((s, i) => i === stageIndex ? `[${s.name}]` : s.name).join(" \u2192 ");
35537
+ const parts = [
35538
+ stage.prompt,
35539
+ PACK_WORKFLOW_ARTICLE,
35540
+ `## Your pipeline position
35541
+ ${pack.name}: ${pipeline2} \u2014 you are stage ${stageIndex + 1} of ${pack.stages.length}. Your commit byline: \`By ${stage.role}.\``,
35542
+ `## Task
35543
+ ${task}`
35544
+ ];
35545
+ if (previous) {
35546
+ parts.push(
35547
+ `## Previous stage handoff (${previous.role})
35548
+ commit: ${previous.handoff.commit}
35549
+ ${previous.handoff.diffStat}
35550
+
35551
+ ${previous.handoff.summary}`
35552
+ );
35553
+ }
35554
+ return parts.join("\n\n");
35555
+ }
35556
+ function nowIso() {
35557
+ return (/* @__PURE__ */ new Date()).toISOString();
35558
+ }
35559
+ var PackRunner = class _PackRunner {
35560
+ constructor(deps, pack, initial) {
35561
+ this.deps = deps;
35562
+ this.pack = pack;
35563
+ this.state = initial;
35564
+ }
35565
+ deps;
35566
+ pack;
35567
+ state;
35568
+ control = "run";
35569
+ looping = false;
35570
+ static create(deps, packId, task, runId) {
35571
+ const pack = getPackDefinition(packId);
35572
+ if (!pack) throw new Error(`unknown pack: ${packId}`);
35573
+ const stages = pack.stages.map((s) => ({
35574
+ role: s.role,
35575
+ name: s.name,
35576
+ status: "pending"
35577
+ }));
35578
+ const state = {
35579
+ runId,
35580
+ packId: pack.id,
35581
+ task,
35582
+ status: "running",
35583
+ currentStage: 0,
35584
+ stages,
35585
+ startedAt: nowIso(),
35586
+ updatedAt: nowIso()
35587
+ };
35588
+ return new _PackRunner(deps, pack, state);
35589
+ }
35590
+ getState() {
35591
+ return this.state;
35592
+ }
35593
+ /** Persist + post the current state (ledger first — it's the truth). */
35594
+ async publish() {
35595
+ this.state = { ...this.state, updatedAt: nowIso() };
35596
+ try {
35597
+ this.deps.ledger.saveRun(this.state);
35598
+ } catch (err) {
35599
+ this.deps.log(`pack ledger save failed: ${err.message}`);
35600
+ }
35601
+ await this.deps.postState(this.state);
35602
+ }
35603
+ async settle(status2, stalledReason) {
35604
+ this.state = { ...this.state, status: status2, stalledReason };
35605
+ await this.publish();
35606
+ }
35607
+ // ── Control surface (relay `pack_action`) ────────────────────────────────
35608
+ async applyAction(action) {
35609
+ switch (action) {
35610
+ case "pause":
35611
+ this.control = "pause";
35612
+ if (this.state.status === "running") {
35613
+ this.state = { ...this.state, status: "paused" };
35614
+ await this.publish();
35615
+ }
35616
+ break;
35617
+ case "resume":
35618
+ this.control = "run";
35619
+ if (this.state.status === "paused" || this.state.status === "stalled") {
35620
+ this.state = { ...this.state, status: "running", stalledReason: void 0 };
35621
+ await this.publish();
35622
+ void this.run();
35623
+ }
35624
+ break;
35625
+ case "retry_stage": {
35626
+ const idx = this.state.currentStage;
35627
+ if (idx < this.state.stages.length) {
35628
+ const stages = this.state.stages.slice();
35629
+ stages[idx] = { role: stages[idx].role, name: stages[idx].name, status: "pending" };
35630
+ this.control = "run";
35631
+ this.state = { ...this.state, stages, status: "running", stalledReason: void 0 };
35632
+ await this.publish();
35633
+ void this.run();
35634
+ }
35635
+ break;
35636
+ }
35637
+ case "skip_stage": {
35638
+ const idx = this.state.currentStage;
35639
+ if (idx < this.state.stages.length) {
35640
+ const stages = this.state.stages.slice();
35641
+ stages[idx] = { ...stages[idx], status: "skipped" };
35642
+ this.control = "run";
35643
+ this.state = {
35644
+ ...this.state,
35645
+ stages,
35646
+ currentStage: idx + 1,
35647
+ status: "running",
35648
+ stalledReason: void 0
35649
+ };
35650
+ await this.publish();
35651
+ void this.run();
35652
+ }
35653
+ break;
35654
+ }
35655
+ case "abort":
35656
+ this.control = "abort";
35657
+ await this.deps.driver.cancel().catch(() => void 0);
35658
+ if (!this.looping) await this.settle("aborted");
35659
+ break;
35660
+ }
35661
+ return this.state;
35662
+ }
35663
+ // ── The loop ──────────────────────────────────────────────────────────────
35664
+ async run() {
35665
+ if (this.looping) return;
35666
+ this.looping = true;
35667
+ try {
35668
+ while (this.state.currentStage < this.state.stages.length) {
35669
+ if (this.control === "abort") {
35670
+ await this.settle("aborted");
35671
+ return;
35672
+ }
35673
+ if (this.control === "pause") {
35674
+ await this.settle("paused");
35675
+ return;
35676
+ }
35677
+ const advanced = await this.runStage(this.state.currentStage);
35678
+ if (!advanced) return;
35679
+ }
35680
+ await this.settle("completed");
35681
+ this.deps.log(`pack run ${this.state.runId} completed`);
35682
+ } catch (err) {
35683
+ await this.settle("failed", err.message).catch(() => void 0);
35684
+ } finally {
35685
+ this.looping = false;
35686
+ }
35687
+ }
35688
+ /** Run one stage to its handoff. True = advanced; false = run settled. */
35689
+ async runStage(index) {
35690
+ const stageDef = this.pack.stages[index];
35691
+ const startedMs = Date.now();
35692
+ const startSha = await this.deps.gates.head();
35693
+ let stages = this.state.stages.slice();
35694
+ stages[index] = { ...stages[index], status: "active" };
35695
+ this.state = { ...this.state, stages, status: "running" };
35696
+ try {
35697
+ const conversationId = await this.deps.driver.newConversation();
35698
+ stages = this.state.stages.slice();
35699
+ stages[index] = { ...stages[index], conversationId };
35700
+ this.state = { ...this.state, stages };
35701
+ await this.publish();
35702
+ this.deps.driver.mountSkills(stageDef.skillIds);
35703
+ const previous = this.previousHandoff(index);
35704
+ const prompt = composeStagePrompt(this.pack, index, this.state.task, previous);
35705
+ const displayLine = `\u25B6 ${this.pack.name} \u2014 stage ${index + 1}/${this.pack.stages.length}: ${stageDef.name}`;
35706
+ let reply = await this.deps.driver.runTurn(prompt, displayLine);
35707
+ if (this.control === "abort") {
35708
+ await this.settle("aborted");
35709
+ return false;
35710
+ }
35711
+ let endSha = await this.deps.gates.head();
35712
+ if (!endSha || endSha === startSha) {
35713
+ reply = await this.deps.driver.runTurn(NUDGE_PROMPT, "\u25B6 Waiting for the stage commit\u2026");
35714
+ endSha = await this.deps.gates.head();
35715
+ if (!endSha || endSha === startSha) {
35716
+ return this.stall(index, "stage produced no commit", reply);
35717
+ }
35718
+ }
35719
+ const commit = await this.deps.gates.canonicalCommit(endSha);
35720
+ if (!commit) return this.stall(index, "stage HEAD did not resolve to a commit", reply);
35721
+ const handoff = {
35722
+ commit,
35723
+ summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
35724
+ diffStat: startSha ? await this.deps.gates.diffStat(startSha, endSha) : "",
35725
+ checks: await this.deps.gates.runChecks() ?? void 0,
35726
+ durationMs: Date.now() - startedMs
35727
+ };
35728
+ stages = this.state.stages.slice();
35729
+ stages[index] = { ...stages[index], status: "done", handoff };
35730
+ this.state = { ...this.state, stages, currentStage: index + 1 };
35731
+ try {
35732
+ this.deps.ledger.saveStageHandoff(this.state.runId, index, stageDef.role, handoff);
35733
+ } catch (err) {
35734
+ this.deps.log(`pack handoff save failed: ${err.message}`);
35735
+ }
35736
+ await this.publish();
35737
+ return true;
35738
+ } catch (err) {
35739
+ if (this.control === "abort") {
35740
+ await this.settle("aborted");
35741
+ return false;
35742
+ }
35743
+ return this.stall(index, err.message);
35744
+ }
35745
+ }
35746
+ async stall(index, reason, lastReply) {
35747
+ const stages = this.state.stages.slice();
35748
+ stages[index] = { ...stages[index], status: "failed", error: reason };
35749
+ this.state = { ...this.state, stages };
35750
+ await this.settle("stalled", lastReply ? `${reason} \u2014 last reply: ${lastReply.slice(-300)}` : reason);
35751
+ this.deps.log(`pack run ${this.state.runId} stalled at stage ${index + 1}: ${reason}`);
35752
+ return false;
35753
+ }
35754
+ previousHandoff(index) {
35755
+ for (let i = index - 1; i >= 0; i--) {
35756
+ const s = this.state.stages[i];
35757
+ if (s.status === "done" && s.handoff) return { role: s.role, handoff: s.handoff };
35758
+ }
35759
+ return null;
35760
+ }
35761
+ };
35762
+
35763
+ // src/packs/active.ts
35764
+ var active = null;
35765
+ function setActivePackRunner(runner) {
35766
+ active = runner;
35767
+ }
35768
+ function getActivePackRunner() {
35769
+ return active;
35770
+ }
35771
+
35772
+ // src/packs/handlers.ts
35773
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "aborted", "failed"]);
35774
+ var PACK_ACTIONS = /* @__PURE__ */ new Set(["pause", "resume", "retry_stage", "skip_stage", "abort"]);
35775
+ function buildPackRunnerDeps(ctx) {
35776
+ const cwd = ctx.opts.cwd;
35777
+ const run = defaultCommandRunner;
35778
+ return {
35779
+ driver: {
35780
+ newConversation: async () => {
35781
+ const id = await ctx.client.newConversation();
35782
+ ctx.history.switchActiveSession(id);
35783
+ ctx.onActiveSessionChanged?.(id);
35784
+ return id;
35785
+ },
35786
+ runTurn: async (prompt, displayLine) => {
35787
+ await ctx.streaming.beginTurn();
35788
+ ctx.history.appendUserPrompt(displayLine);
35789
+ await ctx.client.prompt(prompt);
35790
+ const text = ctx.streaming.getCurrentText();
35791
+ await ctx.streaming.closeTurnWithInteractiveDetection();
35792
+ ctx.history.appendAgentReply(text);
35793
+ await ctx.history.flush();
35794
+ return text;
35795
+ },
35796
+ cancel: () => ctx.client.cancel(),
35797
+ mountSkills: (skillIds) => {
35798
+ for (const id of skillIds) {
35799
+ try {
35800
+ configureSkill("add", id);
35801
+ } catch (err) {
35802
+ log.warn("packs", `skill mount failed for ${id}: ${err.message}`);
35803
+ }
35804
+ }
35805
+ }
35806
+ },
35807
+ gates: {
35808
+ head: () => gitHead(run, cwd),
35809
+ canonicalCommit: (sha) => canonicalCommit(run, cwd, sha),
35810
+ diffStat: (from, to) => diffStat(run, cwd, from, to),
35811
+ runChecks: async () => {
35812
+ const command2 = detectChecksCommand(cwd);
35813
+ return command2 ? runChecks(run, cwd, command2) : null;
35814
+ }
35815
+ },
35816
+ ledger: {
35817
+ saveRun: (state) => saveRun(cwd, state),
35818
+ saveStageHandoff: (runId, index, role, handoff) => saveStageHandoff(cwd, runId, index, role, handoff)
35819
+ },
35820
+ postState: (state) => postPackState(
35821
+ {
35822
+ sessionId: ctx.opts.sessionId,
35823
+ pluginId: ctx.opts.pluginId,
35824
+ pluginAuthToken: ctx.opts.pluginAuthToken,
35825
+ pollSecret: ctx.opts.pollSecret
35826
+ },
35827
+ state
35828
+ ),
35829
+ log: (message) => log.info("packs", message)
35830
+ };
35831
+ }
35832
+ var packStartH = async (ctx) => {
35833
+ const payload = ctx.cmd.payload;
35834
+ const packId = typeof payload?.packId === "string" ? payload.packId : "";
35835
+ const task = typeof payload?.task === "string" ? payload.task.trim() : "";
35836
+ if (!isPackId(packId)) {
35837
+ await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: `unknown pack: ${packId || "(none)"}` });
35838
+ return;
35839
+ }
35840
+ if (task.length === 0) {
35841
+ await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: "pack_start requires a non-empty task" });
35842
+ return;
35843
+ }
35844
+ const existing = getActivePackRunner();
35845
+ if (existing && !TERMINAL_STATUSES.has(existing.getState().status)) {
35846
+ await ctx.relay.sendResult(ctx.cmd.id, "failed", {
35847
+ error: "a pack run is already active on this session \u2014 pause/abort it first",
35848
+ state: existing.getState()
35849
+ });
35850
+ return;
35851
+ }
35852
+ ensureLedgerIgnored(ctx.opts.cwd);
35853
+ const runner = PackRunner.create(buildPackRunnerDeps(ctx), packId, task, newRunId());
35854
+ setActivePackRunner(runner);
35855
+ log.info("packs", `pack_start ${packId} run=${runner.getState().runId}`);
35856
+ await ctx.relay.sendResult(ctx.cmd.id, "completed", {
35857
+ accepted: true,
35858
+ runId: runner.getState().runId,
35859
+ state: runner.getState()
35860
+ });
35861
+ void runner.run();
35862
+ };
35863
+ var packActionH = async (ctx) => {
35864
+ const payload = ctx.cmd.payload;
35865
+ const action = typeof payload?.action === "string" ? payload.action : "";
35866
+ if (!PACK_ACTIONS.has(action)) {
35867
+ await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: `unknown pack action: ${action || "(none)"}` });
35868
+ return;
35869
+ }
35870
+ const runner = getActivePackRunner();
35871
+ if (!runner) {
35872
+ await ctx.relay.sendResult(ctx.cmd.id, "failed", {
35873
+ error: "no active pack run in this session",
35874
+ state: loadLatestRun(ctx.opts.cwd)
35875
+ });
35876
+ return;
35877
+ }
35878
+ const state = await runner.applyAction(action);
35879
+ await ctx.relay.sendResult(ctx.cmd.id, "completed", { state });
35880
+ };
35881
+ var packStatusH = async (ctx) => {
35882
+ const state = getActivePackRunner()?.getState() ?? loadLatestRun(ctx.opts.cwd);
35883
+ await ctx.relay.sendResult(ctx.cmd.id, "completed", { state });
35884
+ };
35885
+
35183
35886
  // src/integrations/provision.ts
35184
35887
  function buildMcpServersForStart(ctx) {
35185
35888
  const manifest = readIntegrationsManifest();
@@ -35318,7 +36021,7 @@ async function detectRepoStack(cwd, runtime) {
35318
36021
  }
35319
36022
 
35320
36023
  // src/agents/acp/command-handlers.ts
35321
- var import_node_child_process30 = require("child_process");
36024
+ var import_node_child_process31 = require("child_process");
35322
36025
 
35323
36026
  // src/agents/acp/buildAcpPromptBlocks.ts
35324
36027
  var MIME_FROM_EXT = {
@@ -35355,35 +36058,35 @@ function buildAcpPromptBlocks(payload) {
35355
36058
  }
35356
36059
 
35357
36060
  // src/agents/agent-standard.ts
35358
- var fs72 = __toESM(require("fs"));
35359
- var path78 = __toESM(require("path"));
36061
+ var fs74 = __toESM(require("fs"));
36062
+ var path80 = __toESM(require("path"));
35360
36063
  var os57 = __toESM(require("os"));
35361
36064
  function ensureAgentStandard(homeDir2 = os57.homedir()) {
35362
36065
  try {
35363
- const file = path78.join(homeDir2, ".claude", "CLAUDE.md");
36066
+ const file = path80.join(homeDir2, ".claude", "CLAUDE.md");
35364
36067
  let existing = "";
35365
36068
  try {
35366
- existing = fs72.readFileSync(file, "utf8");
36069
+ existing = fs74.readFileSync(file, "utf8");
35367
36070
  } catch {
35368
36071
  }
35369
36072
  if (existing.includes(AGENT_STANDARD_MARKER)) return;
35370
- fs72.mkdirSync(path78.dirname(file), { recursive: true });
36073
+ fs74.mkdirSync(path80.dirname(file), { recursive: true });
35371
36074
  const next = existing.trim() ? `${existing.trimEnd()}
35372
36075
 
35373
36076
  ${AGENT_STANDARD_BLOCK}
35374
36077
  ` : `${AGENT_STANDARD_BLOCK}
35375
36078
  `;
35376
- fs72.writeFileSync(file, next);
36079
+ fs74.writeFileSync(file, next);
35377
36080
  } catch {
35378
36081
  }
35379
36082
  }
35380
36083
  var _agentStandardSeam = {
35381
36084
  isLocalSession: () => isLocalSession(),
35382
- markerPath: (sessionId) => path78.join(os57.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
35383
- exists: (p2) => fs72.existsSync(p2),
36085
+ markerPath: (sessionId) => path80.join(os57.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
36086
+ exists: (p2) => fs74.existsSync(p2),
35384
36087
  write: (p2) => {
35385
- fs72.mkdirSync(path78.dirname(p2), { recursive: true });
35386
- fs72.writeFileSync(p2, "");
36088
+ fs74.mkdirSync(path80.dirname(p2), { recursive: true });
36089
+ fs74.writeFileSync(p2, "");
35387
36090
  }
35388
36091
  };
35389
36092
  function isClaude(agent) {
@@ -36012,7 +36715,7 @@ async function prewarmNewMcpEntries(manifest, previousIds) {
36012
36715
  fresh.map(
36013
36716
  (e) => new Promise((resolve9) => {
36014
36717
  const mcp = e.delivery.mcp;
36015
- const child = (0, import_node_child_process30.execFile)(
36718
+ const child = (0, import_node_child_process31.execFile)(
36016
36719
  mcp.command,
36017
36720
  [...mcp.args, "--help"],
36018
36721
  { timeout: 9e4 },
@@ -36093,7 +36796,10 @@ var ACP_COMMAND_HANDLERS = {
36093
36796
  preview_start: previewH,
36094
36797
  preview_stop: previewH,
36095
36798
  save_preview_config: previewH,
36096
- skills_configure: skillsConfigureH2
36799
+ skills_configure: skillsConfigureH2,
36800
+ pack_start: packStartH,
36801
+ pack_action: packActionH,
36802
+ pack_status: packStatusH
36097
36803
  };
36098
36804
  async function dispatchAcpCommand(ctx) {
36099
36805
  const handler = ACP_COMMAND_HANDLERS[ctx.cmd.type];
@@ -38004,7 +38710,7 @@ function fetchQuotaUsage(runtime, historySvc) {
38004
38710
 
38005
38711
  // src/agents/claude/credential-sync.ts
38006
38712
  var import_chokidar2 = __toESM(require("chokidar"));
38007
- var crypto5 = __toESM(require("crypto"));
38713
+ var crypto6 = __toESM(require("crypto"));
38008
38714
  var CLAUDE_PUBLIC_AGENT_ID = "claude_code";
38009
38715
  function startClaudeCredentialSync(opts) {
38010
38716
  const push = opts.push ?? postCredentialSync;
@@ -38016,7 +38722,7 @@ function startClaudeCredentialSync(opts) {
38016
38722
  try {
38017
38723
  const tok = await read2();
38018
38724
  if (!tok || !tok.credential) return;
38019
- const hash = crypto5.createHash("sha256").update(tok.credential).digest("hex");
38725
+ const hash = crypto6.createHash("sha256").update(tok.credential).digest("hex");
38020
38726
  if (hash === lastHash) return;
38021
38727
  lastHash = hash;
38022
38728
  await push({
@@ -38053,8 +38759,8 @@ function startClaudeCredentialSync(opts) {
38053
38759
  }
38054
38760
 
38055
38761
  // src/beads/workflow-hint.ts
38056
- var fs73 = __toESM(require("fs"));
38057
- var path79 = __toESM(require("path"));
38762
+ var fs75 = __toESM(require("fs"));
38763
+ var path81 = __toESM(require("path"));
38058
38764
  var os58 = __toESM(require("os"));
38059
38765
  var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
38060
38766
  var BEADS_HINT = `${BEADS_HINT_MARKER}
@@ -38071,20 +38777,20 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
38071
38777
  ${BEADS_HINT_MARKER}`;
38072
38778
  function ensureBeadsWorkflowHint(homeDir2 = os58.homedir()) {
38073
38779
  try {
38074
- const file = path79.join(homeDir2, ".claude", "CLAUDE.md");
38780
+ const file = path81.join(homeDir2, ".claude", "CLAUDE.md");
38075
38781
  let existing = "";
38076
38782
  try {
38077
- existing = fs73.readFileSync(file, "utf8");
38783
+ existing = fs75.readFileSync(file, "utf8");
38078
38784
  } catch {
38079
38785
  }
38080
38786
  if (existing.includes(BEADS_HINT_MARKER)) return;
38081
- fs73.mkdirSync(path79.dirname(file), { recursive: true });
38787
+ fs75.mkdirSync(path81.dirname(file), { recursive: true });
38082
38788
  const next = existing.trim() ? `${existing.trimEnd()}
38083
38789
 
38084
38790
  ${BEADS_HINT}
38085
38791
  ` : `${BEADS_HINT}
38086
38792
  `;
38087
- fs73.writeFileSync(file, next);
38793
+ fs75.writeFileSync(file, next);
38088
38794
  } catch {
38089
38795
  }
38090
38796
  }
@@ -38456,7 +39162,7 @@ var AcpDriver = class {
38456
39162
  };
38457
39163
 
38458
39164
  // src/baton/transcript-mirror.ts
38459
- var fs74 = __toESM(require("fs"));
39165
+ var fs76 = __toESM(require("fs"));
38460
39166
  var TranscriptMirror = class {
38461
39167
  constructor(deps) {
38462
39168
  this.deps = deps;
@@ -38523,7 +39229,7 @@ var TranscriptMirror = class {
38523
39229
  }
38524
39230
  };
38525
39231
  function defaultWatch(file, onChange) {
38526
- const w3 = fs74.watch(file, { persistent: false }, () => onChange());
39232
+ const w3 = fs76.watch(file, { persistent: false }, () => onChange());
38527
39233
  return () => w3.close();
38528
39234
  }
38529
39235
 
@@ -38785,16 +39491,16 @@ function toEpochMs(ts) {
38785
39491
  }
38786
39492
 
38787
39493
  // src/agents/claude/onboarding.ts
38788
- var fs75 = __toESM(require("fs"));
39494
+ var fs77 = __toESM(require("fs"));
38789
39495
  var os60 = __toESM(require("os"));
38790
- var path80 = __toESM(require("path"));
39496
+ var path82 = __toESM(require("path"));
38791
39497
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
38792
39498
  function ensureClaudeOnboarded(cwd) {
38793
39499
  try {
38794
- const file = path80.join(os60.homedir(), ".claude.json");
39500
+ const file = path82.join(os60.homedir(), ".claude.json");
38795
39501
  let config = {};
38796
39502
  try {
38797
- config = JSON.parse(fs75.readFileSync(file, "utf8"));
39503
+ config = JSON.parse(fs77.readFileSync(file, "utf8"));
38798
39504
  } catch {
38799
39505
  }
38800
39506
  let changed = false;
@@ -38819,8 +39525,8 @@ function ensureClaudeOnboarded(cwd) {
38819
39525
  }
38820
39526
  }
38821
39527
  if (!changed) return;
38822
- fs75.mkdirSync(path80.dirname(file), { recursive: true });
38823
- fs75.writeFileSync(file, JSON.stringify(config, null, 2));
39528
+ fs77.mkdirSync(path82.dirname(file), { recursive: true });
39529
+ fs77.writeFileSync(file, JSON.stringify(config, null, 2));
38824
39530
  log.info(
38825
39531
  "claude",
38826
39532
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -39492,13 +40198,13 @@ var import_picocolors7 = __toESM(require("picocolors"));
39492
40198
  function status() {
39493
40199
  showIntro();
39494
40200
  const config = getConfig();
39495
- const active = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
40201
+ const active2 = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
39496
40202
  console.log(import_picocolors7.default.bold(" Status\n"));
39497
40203
  console.log(` Plugin ID ${import_picocolors7.default.dim(config.pluginId || "not generated yet")}`);
39498
40204
  console.log(` Sessions ${config.sessions.length} paired`);
39499
- if (active) {
39500
- console.log(` Active ${import_picocolors7.default.bold(active.userName)} ${import_picocolors7.default.cyan(active.plan)}`);
39501
- console.log(` Session ID ${import_picocolors7.default.dim(active.id)}`);
40205
+ if (active2) {
40206
+ console.log(` Active ${import_picocolors7.default.bold(active2.userName)} ${import_picocolors7.default.cyan(active2.plan)}`);
40207
+ console.log(` Session ID ${import_picocolors7.default.dim(active2.id)}`);
39502
40208
  } else {
39503
40209
  console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
39504
40210
  }
@@ -39550,7 +40256,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
39550
40256
  var import_child_process29 = require("child_process");
39551
40257
  var import_util4 = require("util");
39552
40258
  var import_picocolors9 = __toESM(require("picocolors"));
39553
- var path81 = __toESM(require("path"));
40259
+ var path83 = __toESM(require("path"));
39554
40260
  var execFileP6 = (0, import_util4.promisify)(import_child_process29.execFile);
39555
40261
  var MAX_BUFFER = 8 * 1024 * 1024;
39556
40262
  function resetStdinForChild() {
@@ -40039,7 +40745,7 @@ var GitHubCodespacesProvider = class {
40039
40745
  });
40040
40746
  }
40041
40747
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
40042
- const remoteDir = path81.posix.dirname(remotePath);
40748
+ const remoteDir = path83.posix.dirname(remotePath);
40043
40749
  const parts = [
40044
40750
  `mkdir -p ${shellQuote(remoteDir)}`,
40045
40751
  `cat > ${shellQuote(remotePath)}`
@@ -40109,7 +40815,7 @@ function shellQuote(s) {
40109
40815
  // src/services/providers/gitpod.ts
40110
40816
  var import_child_process30 = require("child_process");
40111
40817
  var import_util5 = require("util");
40112
- var path82 = __toESM(require("path"));
40818
+ var path84 = __toESM(require("path"));
40113
40819
  var import_picocolors10 = __toESM(require("picocolors"));
40114
40820
  var execFileP7 = (0, import_util5.promisify)(import_child_process30.execFile);
40115
40821
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -40349,7 +41055,7 @@ var GitpodProvider = class {
40349
41055
  });
40350
41056
  }
40351
41057
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
40352
- const remoteDir = path82.posix.dirname(remotePath);
41058
+ const remoteDir = path84.posix.dirname(remotePath);
40353
41059
  const parts = [
40354
41060
  `mkdir -p ${shellQuote2(remoteDir)}`,
40355
41061
  `cat > ${shellQuote2(remotePath)}`
@@ -40385,7 +41091,7 @@ function shellQuote2(s) {
40385
41091
  // src/services/providers/gitlab-workspaces.ts
40386
41092
  var import_child_process31 = require("child_process");
40387
41093
  var import_util6 = require("util");
40388
- var path83 = __toESM(require("path"));
41094
+ var path85 = __toESM(require("path"));
40389
41095
  var execFileP8 = (0, import_util6.promisify)(import_child_process31.execFile);
40390
41096
  var MAX_BUFFER3 = 8 * 1024 * 1024;
40391
41097
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -40645,7 +41351,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
40645
41351
  }
40646
41352
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
40647
41353
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
40648
- const remoteDir = path83.posix.dirname(remotePath);
41354
+ const remoteDir = path85.posix.dirname(remotePath);
40649
41355
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
40650
41356
  if (options.mode != null) {
40651
41357
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -40713,7 +41419,7 @@ function shellQuote3(s) {
40713
41419
  // src/services/providers/railway.ts
40714
41420
  var import_child_process32 = require("child_process");
40715
41421
  var import_util7 = require("util");
40716
- var path84 = __toESM(require("path"));
41422
+ var path86 = __toESM(require("path"));
40717
41423
  var execFileP9 = (0, import_util7.promisify)(import_child_process32.execFile);
40718
41424
  var MAX_BUFFER4 = 8 * 1024 * 1024;
40719
41425
  function resetStdinForChild4() {
@@ -40949,7 +41655,7 @@ var RailwayProvider = class {
40949
41655
  if (!projectId || !serviceId) {
40950
41656
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
40951
41657
  }
40952
- const remoteDir = path84.posix.dirname(remotePath);
41658
+ const remoteDir = path86.posix.dirname(remotePath);
40953
41659
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
40954
41660
  if (options.mode != null) {
40955
41661
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -41480,9 +42186,9 @@ async function probeCodeamPair(provider, workspace) {
41480
42186
  }
41481
42187
  async function stopWorkspaceFromLocal(target) {
41482
42188
  if (target.provider.id === "github-codespaces") {
41483
- const { execFile: execFile15 } = await import("child_process");
42189
+ const { execFile: execFile16 } = await import("child_process");
41484
42190
  const { promisify: promisify11 } = await import("util");
41485
- const execFileP10 = promisify11(execFile15);
42191
+ const execFileP10 = promisify11(execFile16);
41486
42192
  await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
41487
42193
  return;
41488
42194
  }
@@ -41595,8 +42301,8 @@ async function invite() {
41595
42301
  var import_node_dns = require("dns");
41596
42302
  var import_node_util5 = require("util");
41597
42303
  var import_node_crypto13 = require("crypto");
41598
- var fs76 = __toESM(require("fs"));
41599
- var path85 = __toESM(require("path"));
42304
+ var fs78 = __toESM(require("fs"));
42305
+ var path87 = __toESM(require("path"));
41600
42306
  var import_picocolors14 = __toESM(require("picocolors"));
41601
42307
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
41602
42308
  async function checkDns(apiBase2) {
@@ -41652,13 +42358,13 @@ async function checkHealth(apiBase2) {
41652
42358
  }
41653
42359
  }
41654
42360
  function checkConfigDir() {
41655
- const dir = path85.join(require("os").homedir(), ".codeam");
42361
+ const dir = path87.join(require("os").homedir(), ".codeam");
41656
42362
  try {
41657
- fs76.mkdirSync(dir, { recursive: true, mode: 448 });
41658
- const probe = path85.join(dir, ".doctor-probe");
41659
- fs76.writeFileSync(probe, "ok", { mode: 384 });
41660
- const read2 = fs76.readFileSync(probe, "utf8");
41661
- fs76.unlinkSync(probe);
42363
+ fs78.mkdirSync(dir, { recursive: true, mode: 448 });
42364
+ const probe = path87.join(dir, ".doctor-probe");
42365
+ fs78.writeFileSync(probe, "ok", { mode: 384 });
42366
+ const read2 = fs78.readFileSync(probe, "utf8");
42367
+ fs78.unlinkSync(probe);
41662
42368
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
41663
42369
  return {
41664
42370
  id: "config-dir",
@@ -41722,7 +42428,7 @@ function checkNodePty() {
41722
42428
  detail: "not required on this platform"
41723
42429
  };
41724
42430
  }
41725
- const vendoredPath = path85.join(__dirname, "vendor", "node-pty");
42431
+ const vendoredPath = path87.join(__dirname, "vendor", "node-pty");
41726
42432
  for (const target of [vendoredPath, "node-pty"]) {
41727
42433
  try {
41728
42434
  require(target);
@@ -41764,7 +42470,7 @@ function checkChokidar() {
41764
42470
  }
41765
42471
  async function doctor(args2 = []) {
41766
42472
  const json = args2.includes("--json");
41767
- const cliVersion = true ? "2.61.90" : "0.0.0-dev";
42473
+ const cliVersion = true ? "2.61.92" : "0.0.0-dev";
41768
42474
  const apiBase2 = resolveApiBaseUrl();
41769
42475
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
41770
42476
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -41961,7 +42667,7 @@ async function completion(args2) {
41961
42667
  }
41962
42668
 
41963
42669
  // src/integrations/mcp-run.ts
41964
- var import_node_child_process32 = require("child_process");
42670
+ var import_node_child_process33 = require("child_process");
41965
42671
  var import_node_fs12 = require("fs");
41966
42672
  var import_node_os14 = __toESM(require("os"));
41967
42673
  var import_node_path12 = __toESM(require("path"));
@@ -42036,7 +42742,7 @@ function resolveDelivery(id) {
42036
42742
  function commandExists(command2) {
42037
42743
  try {
42038
42744
  const probe = process.platform === "win32" ? "where" : "which";
42039
- (0, import_node_child_process32.execFileSync)(probe, [command2], { stdio: "ignore" });
42745
+ (0, import_node_child_process33.execFileSync)(probe, [command2], { stdio: "ignore" });
42040
42746
  return true;
42041
42747
  } catch {
42042
42748
  return false;
@@ -42069,7 +42775,7 @@ function ensureCommand(command2) {
42069
42775
  }
42070
42776
  if (command2 === "uvx") {
42071
42777
  try {
42072
- (0, import_node_child_process32.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
42778
+ (0, import_node_child_process33.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
42073
42779
  stdio: ["ignore", process.stderr, process.stderr],
42074
42780
  timeout: 18e4,
42075
42781
  env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
@@ -42078,7 +42784,7 @@ function ensureCommand(command2) {
42078
42784
  }
42079
42785
  if (resolveLauncherPath(command2) !== command2) return;
42080
42786
  try {
42081
- (0, import_node_child_process32.execSync)("python3 -m pip install --user --quiet uv", {
42787
+ (0, import_node_child_process33.execSync)("python3 -m pip install --user --quiet uv", {
42082
42788
  stdio: ["ignore", process.stderr, process.stderr],
42083
42789
  timeout: 18e4
42084
42790
  });
@@ -42155,7 +42861,7 @@ async function mcpRun(args2) {
42155
42861
  // src/commands/version.ts
42156
42862
  var import_picocolors15 = __toESM(require("picocolors"));
42157
42863
  function version2() {
42158
- const v = true ? "2.61.90" : "unknown";
42864
+ const v = true ? "2.61.92" : "unknown";
42159
42865
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
42160
42866
  }
42161
42867