@adhdev/daemon-core 0.9.82-rc.114 → 0.9.82-rc.115

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.
package/dist/index.mjs CHANGED
@@ -1053,6 +1053,7 @@ function addNode(meshId, opts) {
1053
1053
  isLocalWorktree: opts.isLocalWorktree,
1054
1054
  worktreeBranch: opts.worktreeBranch,
1055
1055
  clonedFromNodeId: opts.clonedFromNodeId,
1056
+ worktreeBootstrap: opts.worktreeBootstrap,
1056
1057
  role: opts.role
1057
1058
  };
1058
1059
  mesh.nodes.push(node);
@@ -1079,6 +1080,7 @@ function updateNode(meshId, nodeId, opts) {
1079
1080
  if (!node) return void 0;
1080
1081
  if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
1081
1082
  if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
1083
+ if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
1082
1084
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1083
1085
  saveMeshConfig(config);
1084
1086
  return node;
@@ -1291,8 +1293,8 @@ __export(mesh_ledger_exports, {
1291
1293
  readLedgerEntries: () => readLedgerEntries,
1292
1294
  readLedgerSlice: () => readLedgerSlice
1293
1295
  });
1294
- import { appendFileSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, statSync as statSync2, renameSync } from "fs";
1295
- import { join as join6 } from "path";
1296
+ import { appendFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, statSync as statSync2, renameSync } from "fs";
1297
+ import { join as join7 } from "path";
1296
1298
  import { randomUUID as randomUUID4 } from "crypto";
1297
1299
  import { EventEmitter } from "events";
1298
1300
  function isIntentionalCleanupStopEntry(entry) {
@@ -1301,19 +1303,19 @@ function isIntentionalCleanupStopEntry(entry) {
1301
1303
  return payload.intentional === true && (payload.reason === "operator_cleanup" || payload.intentionalStopReason === "operator_cleanup" || payload.source === "mesh_cleanup_sessions" || payload.source === "mesh_remove_node");
1302
1304
  }
1303
1305
  function getLedgerDir() {
1304
- const dir = join6(getConfigDir(), LEDGER_DIR_NAME);
1305
- if (!existsSync6(dir)) {
1306
+ const dir = join7(getConfigDir(), LEDGER_DIR_NAME);
1307
+ if (!existsSync7(dir)) {
1306
1308
  mkdirSync3(dir, { recursive: true, mode: 448 });
1307
1309
  }
1308
1310
  return dir;
1309
1311
  }
1310
1312
  function getLedgerPath(meshId) {
1311
1313
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1312
- return join6(getLedgerDir(), `${safe}.jsonl`);
1314
+ return join7(getLedgerDir(), `${safe}.jsonl`);
1313
1315
  }
1314
1316
  function getRotatedPath(meshId, index) {
1315
1317
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1316
- return join6(getLedgerDir(), `${safe}.${index}.jsonl`);
1318
+ return join7(getLedgerDir(), `${safe}.${index}.jsonl`);
1317
1319
  }
1318
1320
  function readNonEmptyString(value) {
1319
1321
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -1435,7 +1437,7 @@ function appendLedgerEntry(meshId, partial) {
1435
1437
  ...partial
1436
1438
  };
1437
1439
  const filePath = getLedgerPath(meshId);
1438
- if (existsSync6(filePath)) {
1440
+ if (existsSync7(filePath)) {
1439
1441
  try {
1440
1442
  const stat2 = statSync2(filePath);
1441
1443
  if (stat2.size >= MAX_FILE_SIZE_BYTES) {
@@ -1502,10 +1504,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
1502
1504
  }
1503
1505
  function readLedgerEntries(meshId, opts) {
1504
1506
  const filePath = getLedgerPath(meshId);
1505
- if (!existsSync6(filePath)) return [];
1507
+ if (!existsSync7(filePath)) return [];
1506
1508
  let content;
1507
1509
  try {
1508
- content = readFileSync4(filePath, "utf-8");
1510
+ content = readFileSync5(filePath, "utf-8");
1509
1511
  } catch {
1510
1512
  return [];
1511
1513
  }
@@ -1677,7 +1679,7 @@ function getSessionRecoveryContext(meshId, opts) {
1677
1679
  }
1678
1680
  function rotateLedgerFile(meshId, currentPath) {
1679
1681
  let index = 1;
1680
- while (existsSync6(getRotatedPath(meshId, index))) {
1682
+ while (existsSync7(getRotatedPath(meshId, index))) {
1681
1683
  index++;
1682
1684
  if (index > 10) break;
1683
1685
  }
@@ -1702,8 +1704,8 @@ var init_mesh_ledger = __esm({
1702
1704
  });
1703
1705
 
1704
1706
  // src/mesh/beads-db.ts
1705
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5 } from "fs";
1706
- import { dirname as dirname2, join as join7 } from "path";
1707
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync6 } from "fs";
1708
+ import { dirname as dirname2, join as join8 } from "path";
1707
1709
  import { createRequire } from "module";
1708
1710
  function loadDatabaseCtor() {
1709
1711
  if (DatabaseCtor) return DatabaseCtor;
@@ -1715,7 +1717,7 @@ function safeMeshId(meshId) {
1715
1717
  return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1716
1718
  }
1717
1719
  function legacyQueuePath(meshId) {
1718
- return join7(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
1720
+ return join8(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
1719
1721
  }
1720
1722
  var DatabaseCtor, BeadsDB;
1721
1723
  var init_beads_db = __esm({
@@ -1728,7 +1730,7 @@ var init_beads_db = __esm({
1728
1730
  migratedMeshIds = /* @__PURE__ */ new Set();
1729
1731
  constructor(dbPath) {
1730
1732
  const dir = dirname2(dbPath);
1731
- if (!existsSync7(dir)) mkdirSync4(dir, { recursive: true });
1733
+ if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
1732
1734
  this.db = new (loadDatabaseCtor())(dbPath);
1733
1735
  this.db.pragma("journal_mode = WAL");
1734
1736
  this.db.pragma("synchronous = NORMAL");
@@ -1738,7 +1740,7 @@ var init_beads_db = __esm({
1738
1740
  }
1739
1741
  static getInstance() {
1740
1742
  if (!this.instance) {
1741
- this.instance = new _BeadsDB(join7(getLedgerDir(), "beads.db"));
1743
+ this.instance = new _BeadsDB(join8(getLedgerDir(), "beads.db"));
1742
1744
  }
1743
1745
  return this.instance;
1744
1746
  }
@@ -1779,9 +1781,9 @@ var init_beads_db = __esm({
1779
1781
  const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
1780
1782
  if (count.count > 0) return;
1781
1783
  const path28 = legacyQueuePath(meshId);
1782
- if (!existsSync7(path28)) return;
1784
+ if (!existsSync8(path28)) return;
1783
1785
  try {
1784
- const entries = JSON.parse(readFileSync5(path28, "utf-8"));
1786
+ const entries = JSON.parse(readFileSync6(path28, "utf-8"));
1785
1787
  if (!Array.isArray(entries)) return;
1786
1788
  const insert = this.db.prepare(`
1787
1789
  INSERT OR REPLACE INTO mesh_queue (
@@ -2120,7 +2122,7 @@ var init_mesh_work_queue = __esm({
2120
2122
  import { exec } from "child_process";
2121
2123
  import * as os2 from "os";
2122
2124
  import * as path8 from "path";
2123
- import { existsSync as existsSync8 } from "fs";
2125
+ import { existsSync as existsSync9 } from "fs";
2124
2126
  function parseVersion(raw) {
2125
2127
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
2126
2128
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -2144,24 +2146,24 @@ function resolveCommandPath(command) {
2144
2146
  if (isExplicitCommandPath(trimmed)) {
2145
2147
  const expanded = expandHome(trimmed);
2146
2148
  const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
2147
- return existsSync8(candidate) ? candidate : null;
2149
+ return existsSync9(candidate) ? candidate : null;
2148
2150
  }
2149
2151
  return null;
2150
2152
  }
2151
2153
  function execAsync(cmd, timeoutMs = 5e3) {
2152
- return new Promise((resolve16) => {
2154
+ return new Promise((resolve17) => {
2153
2155
  const child = exec(cmd, {
2154
2156
  encoding: "utf-8",
2155
2157
  timeout: timeoutMs,
2156
2158
  ...process.platform === "win32" ? { windowsHide: true } : {}
2157
2159
  }, (err, stdout) => {
2158
2160
  if (err || !stdout?.trim()) {
2159
- resolve16(null);
2161
+ resolve17(null);
2160
2162
  } else {
2161
- resolve16(stdout.trim());
2163
+ resolve17(stdout.trim());
2162
2164
  }
2163
2165
  });
2164
- child.on("error", () => resolve16(null));
2166
+ child.on("error", () => resolve17(null));
2165
2167
  });
2166
2168
  }
2167
2169
  async function detectCLIs(providerLoader, options) {
@@ -2531,10 +2533,10 @@ __export(mesh_events_exports, {
2531
2533
  triggerMeshQueue: () => triggerMeshQueue,
2532
2534
  tryAssignQueueTask: () => tryAssignQueueTask
2533
2535
  });
2534
- import { appendFileSync as appendFileSync2, existsSync as existsSync10, readFileSync as readFileSync6, unlinkSync as unlinkSync2 } from "fs";
2535
- import { join as join10 } from "path";
2536
+ import { appendFileSync as appendFileSync2, existsSync as existsSync11, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
2537
+ import { join as join11 } from "path";
2536
2538
  function readWorkerResultMetadata(event) {
2537
- return readRecord(event.workerResult) || readRecord(event.meshWorkerResult) || readRecord(event.structuredResult);
2539
+ return readRecord2(event.workerResult) || readRecord2(event.meshWorkerResult) || readRecord2(event.structuredResult);
2538
2540
  }
2539
2541
  function sweepExpiredRemoteIdleSessions() {
2540
2542
  const now = Date.now();
@@ -2543,9 +2545,9 @@ function sweepExpiredRemoteIdleSessions() {
2543
2545
  }
2544
2546
  }
2545
2547
  function readRefineJobId(event) {
2546
- const metadata = readRecord(event.metadataEvent) || event;
2547
- const result = readRecord(metadata.result);
2548
- const refineJob = readRecord(result?.refineJob);
2548
+ const metadata = readRecord2(event.metadataEvent) || event;
2549
+ const result = readRecord2(metadata.result);
2550
+ const refineJob = readRecord2(result?.refineJob);
2549
2551
  return readNonEmptyString2(metadata.jobId) || readNonEmptyString2(refineJob?.jobId);
2550
2552
  }
2551
2553
  function buildRefineTerminalEventFingerprint(meshId, eventName, metadataEvent) {
@@ -2561,10 +2563,10 @@ function hasPendingRefineTerminalEventDuplicate(event) {
2561
2563
  );
2562
2564
  }
2563
2565
  function buildPendingEventFingerprint(event) {
2564
- const metadata = readRecord(event.metadataEvent) || {};
2566
+ const metadata = readRecord2(event.metadataEvent) || {};
2565
2567
  const sessionId = resolveEventSessionId(metadata);
2566
2568
  const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
2567
- const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord(metadata.payload)?.taskId);
2569
+ const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord2(metadata.payload)?.taskId);
2568
2570
  const jobId = readRefineJobId(event);
2569
2571
  const timestamp = metadata.timestamp !== void 0 && metadata.timestamp !== null ? String(metadata.timestamp) : "";
2570
2572
  return [
@@ -2585,7 +2587,7 @@ function hasPendingCoordinatorEventDuplicate(event) {
2585
2587
  }
2586
2588
  function getPendingEventsPath(meshId) {
2587
2589
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
2588
- return join10(getLedgerDir(), `${safe}.pending-events.jsonl`);
2590
+ return join11(getLedgerDir(), `${safe}.pending-events.jsonl`);
2589
2591
  }
2590
2592
  function queuePendingMeshCoordinatorEvent(event) {
2591
2593
  try {
@@ -2607,9 +2609,9 @@ function queuePendingMeshCoordinatorEvent(event) {
2607
2609
  function drainPendingMeshCoordinatorEvents(meshId) {
2608
2610
  if (!meshId) return [];
2609
2611
  const path28 = getPendingEventsPath(meshId);
2610
- if (!existsSync10(path28)) return [];
2612
+ if (!existsSync11(path28)) return [];
2611
2613
  try {
2612
- const raw = readFileSync6(path28, "utf-8");
2614
+ const raw = readFileSync7(path28, "utf-8");
2613
2615
  try {
2614
2616
  unlinkSync2(path28);
2615
2617
  } catch {
@@ -2628,9 +2630,9 @@ function drainPendingMeshCoordinatorEvents(meshId) {
2628
2630
  function getPendingMeshCoordinatorEvents(meshId) {
2629
2631
  if (!meshId) return [];
2630
2632
  const path28 = getPendingEventsPath(meshId);
2631
- if (!existsSync10(path28)) return [];
2633
+ if (!existsSync11(path28)) return [];
2632
2634
  try {
2633
- const raw = readFileSync6(path28, "utf-8");
2635
+ const raw = readFileSync7(path28, "utf-8");
2634
2636
  return raw.split("\n").filter(Boolean).flatMap((line) => {
2635
2637
  try {
2636
2638
  return [JSON.parse(line)];
@@ -2645,7 +2647,7 @@ function getPendingMeshCoordinatorEvents(meshId) {
2645
2647
  function clearPendingMeshCoordinatorEvents(meshId) {
2646
2648
  if (!meshId) return;
2647
2649
  const path28 = getPendingEventsPath(meshId);
2648
- if (existsSync10(path28)) try {
2650
+ if (existsSync11(path28)) try {
2649
2651
  unlinkSync2(path28);
2650
2652
  } catch {
2651
2653
  }
@@ -2653,7 +2655,7 @@ function clearPendingMeshCoordinatorEvents(meshId) {
2653
2655
  function readNonEmptyString2(value) {
2654
2656
  return typeof value === "string" && value.trim() ? value.trim() : "";
2655
2657
  }
2656
- function readRecord(value) {
2658
+ function readRecord2(value) {
2657
2659
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2658
2660
  }
2659
2661
  function resolveEventSessionId(event, fallback) {
@@ -3093,10 +3095,10 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
3093
3095
  }
3094
3096
  if (args.event === "refine:completed") {
3095
3097
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
3096
- const result = readRecord(args.metadataEvent.result);
3097
- const validationSummary = readRecord(result?.validationSummary);
3098
- const patchEquivalence = readRecord(result?.patchEquivalence);
3099
- const finalConvergence = readRecord(result?.finalBranchConvergenceState);
3098
+ const result = readRecord2(args.metadataEvent.result);
3099
+ const validationSummary = readRecord2(result?.validationSummary);
3100
+ const patchEquivalence = readRecord2(result?.patchEquivalence);
3101
+ const finalConvergence = readRecord2(result?.finalBranchConvergenceState);
3100
3102
  const validationStatus = readNonEmptyString2(validationSummary?.status);
3101
3103
  const patchStatus = readNonEmptyString2(patchEquivalence?.status) || (patchEquivalence?.equivalent === true ? "passed" : "");
3102
3104
  const into = readNonEmptyString2(result?.into);
@@ -3117,10 +3119,10 @@ Next step: ${nextStep}`;
3117
3119
  }
3118
3120
  if (args.event === "refine:failed") {
3119
3121
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
3120
- const result = readRecord(args.metadataEvent.result);
3121
- const validationSummary = readRecord(result?.validationSummary);
3122
- const patchEquivalence = readRecord(result?.patchEquivalence);
3123
- const finalConvergence = readRecord(result?.finalBranchConvergenceState);
3122
+ const result = readRecord2(args.metadataEvent.result);
3123
+ const validationSummary = readRecord2(result?.validationSummary);
3124
+ const patchEquivalence = readRecord2(result?.patchEquivalence);
3125
+ const finalConvergence = readRecord2(result?.finalBranchConvergenceState);
3124
3126
  const code = readNonEmptyString2(result?.code);
3125
3127
  const error = readNonEmptyString2(result?.error);
3126
3128
  const validationStatus = readNonEmptyString2(validationSummary?.status);
@@ -5209,7 +5211,7 @@ ${lastSnapshot}`;
5209
5211
  `[${this.cliType}] Waiting for interactive prompt: status=${status} stableMs=${stableMs} recentOutputMs=${recentlyOutput} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
5210
5212
  );
5211
5213
  }
5212
- await new Promise((resolve16) => setTimeout(resolve16, 50));
5214
+ await new Promise((resolve17) => setTimeout(resolve17, 50));
5213
5215
  }
5214
5216
  const finalScreenText = this.terminalScreen.getText() || "";
5215
5217
  LOG.warn(
@@ -6436,7 +6438,7 @@ ${lastSnapshot}`;
6436
6438
  const deadline = Date.now() + 1e4;
6437
6439
  while (this.startupParseGate && Date.now() < deadline) {
6438
6440
  this.resolveStartupState("send_wait");
6439
- await new Promise((resolve16) => setTimeout(resolve16, 50));
6441
+ await new Promise((resolve17) => setTimeout(resolve17, 50));
6440
6442
  }
6441
6443
  }
6442
6444
  const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
@@ -6533,13 +6535,13 @@ ${lastSnapshot}`;
6533
6535
  }
6534
6536
  this.responseEpoch += 1;
6535
6537
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
6536
- await new Promise((resolve16, reject) => {
6538
+ await new Promise((resolve17, reject) => {
6537
6539
  let resolved = false;
6538
6540
  const completion = {
6539
6541
  resolveOnce: () => {
6540
6542
  if (resolved) return;
6541
6543
  resolved = true;
6542
- resolve16();
6544
+ resolve17();
6543
6545
  },
6544
6546
  rejectOnce: (error) => {
6545
6547
  if (resolved) return;
@@ -6697,17 +6699,17 @@ ${lastSnapshot}`;
6697
6699
  }
6698
6700
  }
6699
6701
  waitForStopped(timeoutMs) {
6700
- return new Promise((resolve16) => {
6702
+ return new Promise((resolve17) => {
6701
6703
  const startedAt = Date.now();
6702
6704
  const timer = setInterval(() => {
6703
6705
  if (!this.ptyProcess || this.currentStatus === "stopped") {
6704
6706
  clearInterval(timer);
6705
- resolve16(true);
6707
+ resolve17(true);
6706
6708
  return;
6707
6709
  }
6708
6710
  if (Date.now() - startedAt >= timeoutMs) {
6709
6711
  clearInterval(timer);
6710
- resolve16(false);
6712
+ resolve17(false);
6711
6713
  }
6712
6714
  }, 100);
6713
6715
  });
@@ -8057,10 +8059,17 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
8057
8059
  } catch (err) {
8058
8060
  const output = (err?.stdout || "") + (err?.stderr || "");
8059
8061
  if (/nothing to commit/i.test(output)) {
8060
- throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
8061
- stdout: err?.stdout,
8062
- stderr: err?.stderr
8063
- });
8062
+ return {
8063
+ workspace: repo.workspace,
8064
+ repoRoot,
8065
+ isGitRepo: true,
8066
+ message: fullMsg,
8067
+ status: "skipped",
8068
+ skipped: true,
8069
+ noop: true,
8070
+ reason: "nothing_to_commit",
8071
+ lastCheckedAt: Date.now()
8072
+ };
8064
8073
  }
8065
8074
  throw err;
8066
8075
  }
@@ -8070,6 +8079,7 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
8070
8079
  isGitRepo: true,
8071
8080
  commit: commitSha,
8072
8081
  message: fullMsg,
8082
+ status: "created",
8073
8083
  lastCheckedAt: Date.now()
8074
8084
  };
8075
8085
  }
@@ -8773,6 +8783,7 @@ var MESH_REFINE_CONFIG_SCHEMA = {
8773
8783
  category: { enum: [...MESH_REFINE_VALIDATION_CATEGORIES, "custom"] },
8774
8784
  cwd: { type: "string" },
8775
8785
  timeoutMs: { type: "number", minimum: 1e3, maximum: 6e5 },
8786
+ outputLimitBytes: { type: "number", minimum: 1024, maximum: 1048576 },
8776
8787
  env: { type: "object", additionalProperties: { type: "string" } }
8777
8788
  }
8778
8789
  }
@@ -8790,6 +8801,7 @@ var MESH_REFINE_CONFIG_SCHEMA = {
8790
8801
  category: { enum: [...MESH_REFINE_VALIDATION_CATEGORIES, "custom"] },
8791
8802
  cwd: { type: "string" },
8792
8803
  timeoutMs: { type: "number", minimum: 1e3, maximum: 6e5 },
8804
+ outputLimitBytes: { type: "number", minimum: 1024, maximum: 1048576 },
8793
8805
  env: { type: "object", additionalProperties: { type: "string" } }
8794
8806
  }
8795
8807
  }
@@ -8798,7 +8810,7 @@ var MESH_REFINE_CONFIG_SCHEMA = {
8798
8810
  }
8799
8811
  }
8800
8812
  };
8801
- function isRecord(value) {
8813
+ function isMeshConfigRecord(value) {
8802
8814
  return !!value && typeof value === "object" && !Array.isArray(value);
8803
8815
  }
8804
8816
  function tokenizeCommandString(command) {
@@ -8813,8 +8825,8 @@ function tokenizeCommandString(command) {
8813
8825
  function validateCategory(value) {
8814
8826
  return typeof value === "string" && [...MESH_REFINE_VALIDATION_CATEGORIES, "custom"].includes(value) ? value : "custom";
8815
8827
  }
8816
- function normalizeCommandConfig(entry, source) {
8817
- if (!isRecord(entry) || typeof entry.command !== "string") {
8828
+ function normalizeMeshCommandConfig(entry, source) {
8829
+ if (!isMeshConfigRecord(entry) || typeof entry.command !== "string") {
8818
8830
  return { rejected: { source, reason: "validation command must be an object with a command string" } };
8819
8831
  }
8820
8832
  const commandText = entry.command.trim();
@@ -8841,7 +8853,10 @@ function normalizeCommandConfig(entry, source) {
8841
8853
  if (entry.timeoutMs !== void 0 && (typeof entry.timeoutMs !== "number" || !Number.isFinite(entry.timeoutMs) || entry.timeoutMs < 1e3 || entry.timeoutMs > 6e5)) {
8842
8854
  return { rejected: { source, command: commandText, reason: "timeoutMs must be between 1000 and 600000" } };
8843
8855
  }
8844
- if (entry.env !== void 0 && (!isRecord(entry.env) || !Object.values(entry.env).every((value) => typeof value === "string"))) {
8856
+ if (entry.outputLimitBytes !== void 0 && (typeof entry.outputLimitBytes !== "number" || !Number.isFinite(entry.outputLimitBytes) || entry.outputLimitBytes < 1024 || entry.outputLimitBytes > 1048576)) {
8857
+ return { rejected: { source, command: commandText, reason: "outputLimitBytes must be between 1024 and 1048576" } };
8858
+ }
8859
+ if (entry.env !== void 0 && (!isMeshConfigRecord(entry.env) || !Object.values(entry.env).every((value) => typeof value === "string"))) {
8845
8860
  return { rejected: { source, command: commandText, reason: "env must be an object of string values" } };
8846
8861
  }
8847
8862
  return {
@@ -8853,10 +8868,12 @@ function normalizeCommandConfig(entry, source) {
8853
8868
  source,
8854
8869
  ...typeof entry.cwd === "string" && entry.cwd.trim() ? { cwd: entry.cwd.trim() } : {},
8855
8870
  ...typeof entry.timeoutMs === "number" ? { timeoutMs: entry.timeoutMs } : {},
8856
- ...isRecord(entry.env) ? { env: entry.env } : {}
8871
+ ...typeof entry.outputLimitBytes === "number" ? { outputLimitBytes: entry.outputLimitBytes } : {},
8872
+ ...isMeshConfigRecord(entry.env) ? { env: entry.env } : {}
8857
8873
  }
8858
8874
  };
8859
8875
  }
8876
+ var isRecord = isMeshConfigRecord;
8860
8877
  function validateMeshRefineConfig(config, source = "inline") {
8861
8878
  const errors = [];
8862
8879
  const bootstrapCommands = [];
@@ -8875,14 +8892,14 @@ function validateMeshRefineConfig(config, source = "inline") {
8875
8892
  if (rawBootstrapCommands !== void 0 && !Array.isArray(rawBootstrapCommands)) errors.push("validation.bootstrapCommands must be an array");
8876
8893
  if (Array.isArray(rawBootstrapCommands)) {
8877
8894
  rawBootstrapCommands.forEach((entry, index) => {
8878
- const normalized = normalizeCommandConfig(entry, `${source}:validation.bootstrapCommands[${index}]`);
8895
+ const normalized = normalizeMeshCommandConfig(entry, `${source}:validation.bootstrapCommands[${index}]`);
8879
8896
  if (normalized.command) bootstrapCommands.push(normalized.command);
8880
8897
  if (normalized.rejected) rejectedCommands.push(normalized.rejected);
8881
8898
  });
8882
8899
  }
8883
8900
  if (Array.isArray(rawCommands)) {
8884
8901
  rawCommands.forEach((entry, index) => {
8885
- const normalized = normalizeCommandConfig(entry, `${source}:validation.commands[${index}]`);
8902
+ const normalized = normalizeMeshCommandConfig(entry, `${source}:validation.commands[${index}]`);
8886
8903
  if (normalized.command) commands.push(normalized.command);
8887
8904
  if (normalized.rejected) rejectedCommands.push(normalized.rejected);
8888
8905
  });
@@ -8994,6 +9011,190 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
8994
9011
  };
8995
9012
  }
8996
9013
 
9014
+ // src/mesh/worktree-bootstrap-config.ts
9015
+ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
9016
+ import { join as join6, resolve as pathResolve } from "path";
9017
+ import { execFile as execFile3 } from "child_process";
9018
+ import { promisify as promisify3 } from "util";
9019
+ import * as yaml2 from "js-yaml";
9020
+ var MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
9021
+ ".adhdev/worktree_bootstrap.json",
9022
+ ".adhdev/worktree_bootstrap.yaml",
9023
+ ".adhdev/worktree_bootstrap.yml",
9024
+ ".adhdev/worktree-bootstrap.json",
9025
+ ".adhdev/worktree-bootstrap.yaml",
9026
+ ".adhdev/worktree-bootstrap.yml"
9027
+ ];
9028
+ var MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA = {
9029
+ $schema: "https://json-schema.org/draft/2020-12/schema",
9030
+ title: "ADHDev Repo Mesh Worktree Bootstrap Config",
9031
+ type: "object",
9032
+ additionalProperties: false,
9033
+ required: ["version"],
9034
+ properties: {
9035
+ version: { const: 1 },
9036
+ enabled: { type: "boolean", default: true },
9037
+ runOnClone: { type: "boolean", default: true },
9038
+ required: { type: "boolean", default: true },
9039
+ staleInputs: { type: "array", maxItems: 16, items: { type: "string", minLength: 1 } },
9040
+ commands: {
9041
+ type: "array",
9042
+ minItems: 1,
9043
+ maxItems: 4,
9044
+ items: {
9045
+ type: "object",
9046
+ additionalProperties: false,
9047
+ required: ["command"],
9048
+ properties: {
9049
+ command: { type: "string", minLength: 1 },
9050
+ args: { type: "array", items: { type: "string" } },
9051
+ category: { enum: ["typecheck", "test", "lint", "build", "custom"] },
9052
+ cwd: { type: "string" },
9053
+ timeoutMs: { type: "number", minimum: 1e3, maximum: 6e5 },
9054
+ outputLimitBytes: { type: "number", minimum: 1024, maximum: 1048576 },
9055
+ env: { type: "object", additionalProperties: { type: "string" } }
9056
+ }
9057
+ }
9058
+ }
9059
+ }
9060
+ };
9061
+ var DEFAULT_TIMEOUT_MS2 = 12e4;
9062
+ var DEFAULT_OUTPUT_LIMIT_BYTES = 128 * 1024;
9063
+ var OUTPUT_SUMMARY_CHARS = 2e3;
9064
+ function parseConfigText2(path28, text) {
9065
+ if (/\.json$/i.test(path28)) return JSON.parse(text);
9066
+ return yaml2.load(text);
9067
+ }
9068
+ function truncateOutput(value) {
9069
+ const text = typeof value === "string" ? value : value == null ? "" : String(value);
9070
+ if (text.length <= OUTPUT_SUMMARY_CHARS) return text;
9071
+ return `${text.slice(0, OUTPUT_SUMMARY_CHARS)}
9072
+ [truncated ${text.length - OUTPUT_SUMMARY_CHARS} chars]`;
9073
+ }
9074
+ function validateMeshWorktreeBootstrapConfig(config, source = "inline") {
9075
+ const errors = [];
9076
+ const commands = [];
9077
+ const rejectedCommands = [];
9078
+ if (!isMeshConfigRecord(config)) return { valid: false, errors: ["config must be an object"], commands, rejectedCommands };
9079
+ if (config.version !== 1) errors.push("version must be 1");
9080
+ if (config.enabled !== void 0 && typeof config.enabled !== "boolean") errors.push("enabled must be a boolean when provided");
9081
+ if (config.runOnClone !== void 0 && typeof config.runOnClone !== "boolean") errors.push("runOnClone must be a boolean when provided");
9082
+ if (config.required !== void 0 && typeof config.required !== "boolean") errors.push("required must be a boolean when provided");
9083
+ if (config.staleInputs !== void 0 && (!Array.isArray(config.staleInputs) || !config.staleInputs.every((input) => typeof input === "string" && input.trim()))) {
9084
+ errors.push("staleInputs must be an array of non-empty strings when provided");
9085
+ }
9086
+ if (config.commands !== void 0 && !Array.isArray(config.commands)) errors.push("commands must be an array");
9087
+ if (Array.isArray(config.commands)) {
9088
+ config.commands.forEach((entry, index) => {
9089
+ const normalized = normalizeMeshCommandConfig(entry, `${source}:commands[${index}]`);
9090
+ if (normalized.command) commands.push(normalized.command);
9091
+ if (normalized.rejected) rejectedCommands.push(normalized.rejected);
9092
+ });
9093
+ }
9094
+ if (config.enabled !== false && config.runOnClone !== false && commands.length === 0) errors.push("commands must contain at least one command when bootstrap is enabled");
9095
+ if (rejectedCommands.length) errors.push("one or more bootstrap commands are invalid");
9096
+ return { valid: errors.length === 0, errors, commands, rejectedCommands };
9097
+ }
9098
+ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
9099
+ const inline = mesh?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrap;
9100
+ if (inline !== void 0) {
9101
+ const validation = validateMeshWorktreeBootstrapConfig(inline, "mesh.policy.worktreeBootstrapConfig");
9102
+ if (!validation.valid) return { source: "mesh.policy.worktreeBootstrapConfig", sourceType: "invalid", error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
9103
+ return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
9104
+ }
9105
+ for (const relative3 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
9106
+ const configPath = join6(workspace, relative3);
9107
+ if (!existsSync6(configPath)) continue;
9108
+ try {
9109
+ const parsed = parseConfigText2(configPath, readFileSync4(configPath, "utf-8"));
9110
+ const validation = validateMeshWorktreeBootstrapConfig(parsed, relative3);
9111
+ if (!validation.valid) return { source: relative3, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
9112
+ return { config: parsed, source: relative3, sourceType: "repo_file", path: configPath };
9113
+ } catch (error) {
9114
+ return { source: relative3, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
9115
+ }
9116
+ }
9117
+ return { source: "unavailable", sourceType: "unavailable", error: `No worktree bootstrap config found. Checked: ${MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS.join(", ")}` };
9118
+ }
9119
+ async function runMeshWorktreeBootstrap(mesh, workspace) {
9120
+ const loaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
9121
+ if (!loaded.config) {
9122
+ return { status: "not_configured", required: false, configSource: loaded.source, configSourceType: loaded.sourceType, error: loaded.error };
9123
+ }
9124
+ const required = loaded.config.required !== false;
9125
+ if (loaded.config.enabled === false || loaded.config.runOnClone === false) {
9126
+ return { status: "disabled", required, configSource: loaded.path || loaded.source, configSourceType: loaded.sourceType };
9127
+ }
9128
+ const validation = validateMeshWorktreeBootstrapConfig(loaded.config, loaded.source);
9129
+ if (!validation.valid) {
9130
+ return { status: "failed", required, configSource: loaded.path || loaded.source, configSourceType: "invalid", error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")), commandsRun: [] };
9131
+ }
9132
+ const execFileAsync3 = promisify3(execFile3);
9133
+ const state = {
9134
+ status: "running",
9135
+ required,
9136
+ configSource: loaded.path || loaded.source,
9137
+ configSourceType: loaded.sourceType,
9138
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
9139
+ commandsRun: [],
9140
+ staleInputs: loaded.config.staleInputs
9141
+ };
9142
+ for (const command of validation.commands) {
9143
+ const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
9144
+ const startedAt = Date.now();
9145
+ state.lastCommand = command.displayCommand;
9146
+ try {
9147
+ const result = await execFileAsync3(command.command, command.args, {
9148
+ cwd,
9149
+ encoding: "utf8",
9150
+ timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
9151
+ maxBuffer: command.outputLimitBytes || DEFAULT_OUTPUT_LIMIT_BYTES,
9152
+ env: { ...process.env, CI: process.env.CI || "1", ...command.env || {} },
9153
+ windowsHide: true
9154
+ });
9155
+ state.commandsRun?.push({
9156
+ command: command.command,
9157
+ args: command.args,
9158
+ displayCommand: command.displayCommand,
9159
+ category: command.category,
9160
+ source: command.source,
9161
+ cwd,
9162
+ passed: true,
9163
+ durationMs: Date.now() - startedAt,
9164
+ exitCode: 0,
9165
+ stdout: truncateOutput(result.stdout),
9166
+ stderr: truncateOutput(result.stderr)
9167
+ });
9168
+ } catch (error) {
9169
+ const exitCode = typeof error?.code === "number" ? error.code : null;
9170
+ state.status = "failed";
9171
+ state.exitCode = exitCode;
9172
+ state.error = error?.message || String(error);
9173
+ state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
9174
+ state.commandsRun?.push({
9175
+ command: command.command,
9176
+ args: command.args,
9177
+ displayCommand: command.displayCommand,
9178
+ category: command.category,
9179
+ source: command.source,
9180
+ cwd,
9181
+ passed: false,
9182
+ durationMs: Date.now() - startedAt,
9183
+ exitCode,
9184
+ signal: typeof error?.signal === "string" ? error.signal : null,
9185
+ timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
9186
+ stdout: truncateOutput(error?.stdout),
9187
+ stderr: truncateOutput(error?.stderr || error?.message)
9188
+ });
9189
+ return state;
9190
+ }
9191
+ }
9192
+ state.status = "ready";
9193
+ state.exitCode = 0;
9194
+ state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
9195
+ return state;
9196
+ }
9197
+
8997
9198
  // src/mesh/mesh-sync.ts
8998
9199
  init_mesh_config();
8999
9200
  async function syncMeshes(transport) {
@@ -9645,6 +9846,134 @@ function buildMeshActiveWork(opts) {
9645
9846
  }
9646
9847
  return { activeWork: records, staleDirectWork, staleDirectWorkNote, terminalDirectWork, summary };
9647
9848
  }
9849
+ function buildCompactStaleDirectWorkSummary(staleDirectWork, opts = {}) {
9850
+ const sampleLimit = Math.max(0, Math.min(10, Math.floor(opts.sampleLimit ?? 3)));
9851
+ const reasonCounts = {};
9852
+ for (const entry of staleDirectWork) {
9853
+ const reason = entry.staleReason || "unknown";
9854
+ reasonCounts[reason] = (reasonCounts[reason] || 0) + 1;
9855
+ }
9856
+ return {
9857
+ count: staleDirectWork.length,
9858
+ sampleLimit,
9859
+ sample: staleDirectWork.slice(0, sampleLimit).map((entry) => ({
9860
+ taskId: entry.taskId,
9861
+ status: entry.status,
9862
+ nodeId: entry.nodeId,
9863
+ sessionId: entry.sessionId,
9864
+ taskTitle: entry.taskTitle,
9865
+ createdAt: entry.createdAt,
9866
+ staleReason: entry.staleReason
9867
+ })),
9868
+ reasonCounts,
9869
+ detailHint: opts.detailHint || "Stale direct records are historical recovery evidence only. Use mesh_task_history for full ledger details, or request includeStaleDirectWorkDetails when supported by the caller.",
9870
+ ...opts.note ? { note: opts.note } : {}
9871
+ };
9872
+ }
9873
+
9874
+ // src/mesh/mesh-refine-status.ts
9875
+ function readString3(value) {
9876
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
9877
+ }
9878
+ function readRecord(value) {
9879
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
9880
+ }
9881
+ function eventStatus(event, fallback) {
9882
+ if (event === "refine:accepted") return "accepted";
9883
+ if (event === "refine:completed") return "completed";
9884
+ if (event === "refine:failed") return "failed";
9885
+ if (fallback === "completed" || fallback === "failed" || fallback === "accepted") return fallback;
9886
+ return void 0;
9887
+ }
9888
+ function ledgerStatus(kind, fallback) {
9889
+ if (kind === "task_completed") return "completed";
9890
+ if (kind === "task_failed") return "failed";
9891
+ if (fallback === "accepted") return "accepted";
9892
+ return "running";
9893
+ }
9894
+ function instructionForStatus(status) {
9895
+ if (status === "accepted") return "Refine job is accepted; wait for asyncRefineJobs or pendingCoordinatorEvents to report running/completed/failed.";
9896
+ if (status === "running") return "Refine job is running; do not poll the ledger repeatedly. Watch asyncRefineJobs or pendingCoordinatorEvents for the terminal result.";
9897
+ if (status === "completed") return "Refine job completed; inspect branch convergence and cleanup evidence before reporting final merge state.";
9898
+ return "Refine job failed; inspect result/finalBranchConvergenceState in mesh_task_history, fix the blocker, then rerun mesh_refine_node when ready.";
9899
+ }
9900
+ function mergeJob(jobs, patch) {
9901
+ const jobId = readString3(patch.jobId);
9902
+ if (!jobId) return;
9903
+ const previous = jobs.get(jobId);
9904
+ const status = patch.status || previous?.status || "running";
9905
+ const definedPatch = Object.fromEntries(
9906
+ Object.entries(patch).filter(([, value]) => value !== void 0)
9907
+ );
9908
+ jobs.set(jobId, {
9909
+ ...previous,
9910
+ ...definedPatch,
9911
+ jobId,
9912
+ status,
9913
+ instruction: instructionForStatus(status)
9914
+ });
9915
+ }
9916
+ function buildMeshAsyncRefineJobs(args) {
9917
+ const jobs = /* @__PURE__ */ new Map();
9918
+ for (const entry of args.ledgerEntries || []) {
9919
+ const payload = readRecord(entry.payload);
9920
+ if (payload?.source !== "refine_mesh_node_async_job") continue;
9921
+ const refineJob = readRecord(payload.refineJob);
9922
+ const result = readRecord(payload.result);
9923
+ const finalState = readRecord(payload.finalBranchConvergenceState) || readRecord(result?.finalBranchConvergenceState);
9924
+ const jobId = readString3(refineJob?.jobId);
9925
+ if (!jobId) continue;
9926
+ const status = ledgerStatus(entry.kind, readString3(refineJob?.status));
9927
+ mergeJob(jobs, {
9928
+ jobId,
9929
+ interactionId: readString3(refineJob?.interactionId),
9930
+ status,
9931
+ meshId: readString3(refineJob?.meshId) || args.meshId,
9932
+ nodeId: readString3(refineJob?.nodeId) || entry.nodeId,
9933
+ targetNodeId: readString3(refineJob?.nodeId) || entry.nodeId,
9934
+ targetDaemonId: readString3(refineJob?.targetDaemonId),
9935
+ workspace: readString3(refineJob?.workspace),
9936
+ branch: readString3(result?.branch) || readString3(finalState?.branch),
9937
+ into: readString3(result?.into) || readString3(finalState?.baseBranch),
9938
+ startedAt: readString3(refineJob?.startedAt),
9939
+ completedAt: readString3(refineJob?.completedAt),
9940
+ retryOfJobId: readString3(refineJob?.retryOfJobId) || readString3(payload.retryOfJobId),
9941
+ lastLedgerKind: entry.kind,
9942
+ lastUpdatedAt: entry.timestamp
9943
+ });
9944
+ }
9945
+ for (const event of args.pendingEvents || []) {
9946
+ const metadata = readRecord(event.metadataEvent);
9947
+ if (metadata?.source !== "refine_mesh_node_async_job") continue;
9948
+ const result = readRecord(metadata.result);
9949
+ const finalState = readRecord(result?.finalBranchConvergenceState);
9950
+ const jobId = readString3(metadata.jobId);
9951
+ if (!jobId) continue;
9952
+ const status = eventStatus(event.event, readString3(metadata.status));
9953
+ mergeJob(jobs, {
9954
+ jobId,
9955
+ interactionId: readString3(metadata.interactionId),
9956
+ ...status ? { status } : {},
9957
+ meshId: readString3(metadata.meshId) || event.meshId || args.meshId,
9958
+ nodeId: readString3(metadata.nodeId) || event.nodeId,
9959
+ targetNodeId: readString3(metadata.nodeId) || event.nodeId,
9960
+ targetDaemonId: readString3(metadata.targetDaemonId),
9961
+ workspace: readString3(metadata.workspace) || event.workspace,
9962
+ branch: readString3(result?.branch) || readString3(finalState?.branch),
9963
+ into: readString3(result?.into) || readString3(finalState?.baseBranch),
9964
+ startedAt: readString3(metadata.startedAt),
9965
+ completedAt: readString3(metadata.completedAt),
9966
+ retryOfJobId: readString3(metadata.retryOfJobId),
9967
+ lastEvent: event.event,
9968
+ lastUpdatedAt: new Date(event.queuedAt).toISOString()
9969
+ });
9970
+ }
9971
+ return Array.from(jobs.values()).sort((a, b) => {
9972
+ const aTime = new Date(a.lastUpdatedAt || a.startedAt || "").getTime();
9973
+ const bTime = new Date(b.lastUpdatedAt || b.startedAt || "").getTime();
9974
+ return (Number.isFinite(bTime) ? bTime : 0) - (Number.isFinite(aTime) ? aTime : 0);
9975
+ });
9976
+ }
9648
9977
 
9649
9978
  // src/index.ts
9650
9979
  init_mesh_host_ownership();
@@ -9762,8 +10091,8 @@ var P2pRelayFailureError = class extends Error {
9762
10091
 
9763
10092
  // src/config/state-store.ts
9764
10093
  init_config();
9765
- import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
9766
- import { join as join11 } from "path";
10094
+ import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "fs";
10095
+ import { join as join12 } from "path";
9767
10096
  var DEFAULT_STATE = {
9768
10097
  recentActivity: [],
9769
10098
  savedProviderSessions: [],
@@ -9776,7 +10105,7 @@ function isPlainObject2(value) {
9776
10105
  return !!value && typeof value === "object" && !Array.isArray(value);
9777
10106
  }
9778
10107
  function getStatePath() {
9779
- return join11(getConfigDir(), "state.json");
10108
+ return join12(getConfigDir(), "state.json");
9780
10109
  }
9781
10110
  function normalizeState(raw) {
9782
10111
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -9812,11 +10141,11 @@ function normalizeState(raw) {
9812
10141
  }
9813
10142
  function loadState() {
9814
10143
  const statePath = getStatePath();
9815
- if (!existsSync11(statePath)) {
10144
+ if (!existsSync12(statePath)) {
9816
10145
  return { ...DEFAULT_STATE };
9817
10146
  }
9818
10147
  try {
9819
- const raw = readFileSync7(statePath, "utf-8");
10148
+ const raw = readFileSync8(statePath, "utf-8");
9820
10149
  return normalizeState(JSON.parse(raw));
9821
10150
  } catch {
9822
10151
  return { ...DEFAULT_STATE };
@@ -9833,11 +10162,11 @@ function resetState() {
9833
10162
 
9834
10163
  // src/detection/ide-detector.ts
9835
10164
  import { exec as exec2 } from "child_process";
9836
- import { promisify as promisify3 } from "util";
9837
- import { existsSync as existsSync12, statSync as statSync4 } from "fs";
10165
+ import { promisify as promisify4 } from "util";
10166
+ import { existsSync as existsSync13, statSync as statSync4 } from "fs";
9838
10167
  import { platform as platform2, homedir as homedir5 } from "os";
9839
10168
  import * as path10 from "path";
9840
- var execAsync2 = promisify3(exec2);
10169
+ var execAsync2 = promisify4(exec2);
9841
10170
  var BUILTIN_IDE_DEFINITIONS = [];
9842
10171
  var registeredIDEs = /* @__PURE__ */ new Map();
9843
10172
  function registerIDEDefinition(def) {
@@ -9859,7 +10188,7 @@ function findCliCommand(command) {
9859
10188
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
9860
10189
  const candidate = trimmed.startsWith("~") ? path10.join(homedir5(), trimmed.slice(1)) : trimmed;
9861
10190
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
9862
- return existsSync12(resolved) ? resolved : null;
10191
+ return existsSync13(resolved) ? resolved : null;
9863
10192
  }
9864
10193
  const isWin = platform2() === "win32";
9865
10194
  const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
@@ -9869,7 +10198,7 @@ function findCliCommand(command) {
9869
10198
  for (const ext of exes) {
9870
10199
  const fullPath = path10.join(p, trimmed + ext);
9871
10200
  try {
9872
- if (existsSync12(fullPath)) {
10201
+ if (existsSync13(fullPath)) {
9873
10202
  const stat2 = statSync4(fullPath);
9874
10203
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
9875
10204
  return fullPath;
@@ -9899,9 +10228,9 @@ function checkPathExists(paths) {
9899
10228
  if (normalized.includes("*")) {
9900
10229
  const username = home.split(/[\\/]/).pop() || "";
9901
10230
  const resolved = normalized.replace("*", username);
9902
- if (existsSync12(resolved)) return resolved;
10231
+ if (existsSync13(resolved)) return resolved;
9903
10232
  } else {
9904
- if (existsSync12(normalized)) return normalized;
10233
+ if (existsSync13(normalized)) return normalized;
9905
10234
  }
9906
10235
  }
9907
10236
  return null;
@@ -9915,7 +10244,7 @@ async function detectIDEs(providerLoader) {
9915
10244
  let resolvedCli = cliPath;
9916
10245
  if (!resolvedCli && appPath && os22 === "darwin") {
9917
10246
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
9918
- if (existsSync12(bundledCli)) resolvedCli = bundledCli;
10247
+ if (existsSync13(bundledCli)) resolvedCli = bundledCli;
9919
10248
  }
9920
10249
  if (!resolvedCli && appPath && os22 === "win32") {
9921
10250
  const { dirname: dirname9 } = await import("path");
@@ -9928,7 +10257,7 @@ async function detectIDEs(providerLoader) {
9928
10257
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
9929
10258
  ];
9930
10259
  for (const c of candidates) {
9931
- if (existsSync12(c)) {
10260
+ if (existsSync13(c)) {
9932
10261
  resolvedCli = c;
9933
10262
  break;
9934
10263
  }
@@ -9956,8 +10285,8 @@ init_cli_detector();
9956
10285
  // src/system/host-memory.ts
9957
10286
  import * as os4 from "os";
9958
10287
  import { exec as exec3 } from "child_process";
9959
- import { promisify as promisify4 } from "util";
9960
- var execAsync3 = promisify4(exec3);
10288
+ import { promisify as promisify5 } from "util";
10289
+ var execAsync3 = promisify5(exec3);
9961
10290
  var cachedDarwinAvail = null;
9962
10291
  var darwinMemoryInterval = null;
9963
10292
  async function updateDarwinMemoryCache() {
@@ -10244,7 +10573,7 @@ var DaemonCdpManager = class {
10244
10573
  * Returns multiple entries if multiple IDE windows are open on same port
10245
10574
  */
10246
10575
  static listAllTargets(port) {
10247
- return new Promise((resolve16) => {
10576
+ return new Promise((resolve17) => {
10248
10577
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
10249
10578
  let data = "";
10250
10579
  res.on("data", (chunk) => data += chunk.toString());
@@ -10260,16 +10589,16 @@ var DaemonCdpManager = class {
10260
10589
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
10261
10590
  );
10262
10591
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
10263
- resolve16(mainPages.length > 0 ? mainPages : fallbackPages);
10592
+ resolve17(mainPages.length > 0 ? mainPages : fallbackPages);
10264
10593
  } catch {
10265
- resolve16([]);
10594
+ resolve17([]);
10266
10595
  }
10267
10596
  });
10268
10597
  });
10269
- req.on("error", () => resolve16([]));
10598
+ req.on("error", () => resolve17([]));
10270
10599
  req.setTimeout(2e3, () => {
10271
10600
  req.destroy();
10272
- resolve16([]);
10601
+ resolve17([]);
10273
10602
  });
10274
10603
  });
10275
10604
  }
@@ -10309,7 +10638,7 @@ var DaemonCdpManager = class {
10309
10638
  }
10310
10639
  }
10311
10640
  findTargetOnPort(port) {
10312
- return new Promise((resolve16) => {
10641
+ return new Promise((resolve17) => {
10313
10642
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
10314
10643
  let data = "";
10315
10644
  res.on("data", (chunk) => data += chunk.toString());
@@ -10320,7 +10649,7 @@ var DaemonCdpManager = class {
10320
10649
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
10321
10650
  );
10322
10651
  if (pages.length === 0) {
10323
- resolve16(targets.find((t) => t.webSocketDebuggerUrl) || null);
10652
+ resolve17(targets.find((t) => t.webSocketDebuggerUrl) || null);
10324
10653
  return;
10325
10654
  }
10326
10655
  const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -10339,25 +10668,25 @@ var DaemonCdpManager = class {
10339
10668
  this._targetId = selected.target.id;
10340
10669
  }
10341
10670
  this._pageTitle = selected.target.title || "";
10342
- resolve16(selected.target);
10671
+ resolve17(selected.target);
10343
10672
  return;
10344
10673
  }
10345
10674
  if (previousTargetId) {
10346
10675
  this.log(`[CDP] Target ${previousTargetId} not found in page list`);
10347
- resolve16(null);
10676
+ resolve17(null);
10348
10677
  return;
10349
10678
  }
10350
10679
  this._pageTitle = list[0]?.title || "";
10351
- resolve16(list[0]);
10680
+ resolve17(list[0]);
10352
10681
  } catch {
10353
- resolve16(null);
10682
+ resolve17(null);
10354
10683
  }
10355
10684
  });
10356
10685
  });
10357
- req.on("error", () => resolve16(null));
10686
+ req.on("error", () => resolve17(null));
10358
10687
  req.setTimeout(2e3, () => {
10359
10688
  req.destroy();
10360
- resolve16(null);
10689
+ resolve17(null);
10361
10690
  });
10362
10691
  });
10363
10692
  }
@@ -10368,7 +10697,7 @@ var DaemonCdpManager = class {
10368
10697
  this.extensionProviders = providers;
10369
10698
  }
10370
10699
  connectToTarget(wsUrl) {
10371
- return new Promise((resolve16) => {
10700
+ return new Promise((resolve17) => {
10372
10701
  this.ws = new WebSocket(wsUrl);
10373
10702
  this.ws.on("open", async () => {
10374
10703
  this._connected = true;
@@ -10378,17 +10707,17 @@ var DaemonCdpManager = class {
10378
10707
  }
10379
10708
  this.connectBrowserWs().catch(() => {
10380
10709
  });
10381
- resolve16(true);
10710
+ resolve17(true);
10382
10711
  });
10383
10712
  this.ws.on("message", (data) => {
10384
10713
  try {
10385
10714
  const msg = JSON.parse(data.toString());
10386
10715
  if (msg.id && this.pending.has(msg.id)) {
10387
- const { resolve: resolve17, reject } = this.pending.get(msg.id);
10716
+ const { resolve: resolve18, reject } = this.pending.get(msg.id);
10388
10717
  this.pending.delete(msg.id);
10389
10718
  this.failureCount = 0;
10390
10719
  if (msg.error) reject(new Error(msg.error.message));
10391
- else resolve17(msg.result);
10720
+ else resolve18(msg.result);
10392
10721
  } else if (msg.method === "Runtime.executionContextCreated") {
10393
10722
  this.contexts.add(msg.params.context.id);
10394
10723
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -10411,7 +10740,7 @@ var DaemonCdpManager = class {
10411
10740
  this.ws.on("error", (err) => {
10412
10741
  this.log(`[CDP] WebSocket error: ${err.message}`);
10413
10742
  this._connected = false;
10414
- resolve16(false);
10743
+ resolve17(false);
10415
10744
  });
10416
10745
  });
10417
10746
  }
@@ -10425,7 +10754,7 @@ var DaemonCdpManager = class {
10425
10754
  return;
10426
10755
  }
10427
10756
  this.log(`[CDP] Connecting browser WS for target discovery...`);
10428
- await new Promise((resolve16, reject) => {
10757
+ await new Promise((resolve17, reject) => {
10429
10758
  this.browserWs = new WebSocket(browserWsUrl);
10430
10759
  this.browserWs.on("open", async () => {
10431
10760
  this._browserConnected = true;
@@ -10435,16 +10764,16 @@ var DaemonCdpManager = class {
10435
10764
  } catch (e) {
10436
10765
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
10437
10766
  }
10438
- resolve16();
10767
+ resolve17();
10439
10768
  });
10440
10769
  this.browserWs.on("message", (data) => {
10441
10770
  try {
10442
10771
  const msg = JSON.parse(data.toString());
10443
10772
  if (msg.id && this.browserPending.has(msg.id)) {
10444
- const { resolve: resolve17, reject: reject2 } = this.browserPending.get(msg.id);
10773
+ const { resolve: resolve18, reject: reject2 } = this.browserPending.get(msg.id);
10445
10774
  this.browserPending.delete(msg.id);
10446
10775
  if (msg.error) reject2(new Error(msg.error.message));
10447
- else resolve17(msg.result);
10776
+ else resolve18(msg.result);
10448
10777
  }
10449
10778
  } catch {
10450
10779
  }
@@ -10464,31 +10793,31 @@ var DaemonCdpManager = class {
10464
10793
  }
10465
10794
  }
10466
10795
  getBrowserWsUrl() {
10467
- return new Promise((resolve16) => {
10796
+ return new Promise((resolve17) => {
10468
10797
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
10469
10798
  let data = "";
10470
10799
  res.on("data", (chunk) => data += chunk.toString());
10471
10800
  res.on("end", () => {
10472
10801
  try {
10473
10802
  const info = JSON.parse(data);
10474
- resolve16(info.webSocketDebuggerUrl || null);
10803
+ resolve17(info.webSocketDebuggerUrl || null);
10475
10804
  } catch {
10476
- resolve16(null);
10805
+ resolve17(null);
10477
10806
  }
10478
10807
  });
10479
10808
  });
10480
- req.on("error", () => resolve16(null));
10809
+ req.on("error", () => resolve17(null));
10481
10810
  req.setTimeout(3e3, () => {
10482
10811
  req.destroy();
10483
- resolve16(null);
10812
+ resolve17(null);
10484
10813
  });
10485
10814
  });
10486
10815
  }
10487
10816
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
10488
- return new Promise((resolve16, reject) => {
10817
+ return new Promise((resolve17, reject) => {
10489
10818
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
10490
10819
  const id = this.browserMsgId++;
10491
- this.browserPending.set(id, { resolve: resolve16, reject });
10820
+ this.browserPending.set(id, { resolve: resolve17, reject });
10492
10821
  this.browserWs.send(JSON.stringify({ id, method, params }));
10493
10822
  setTimeout(() => {
10494
10823
  if (this.browserPending.has(id)) {
@@ -10528,11 +10857,11 @@ var DaemonCdpManager = class {
10528
10857
  }
10529
10858
  // ─── CDP Protocol ────────────────────────────────────────
10530
10859
  sendInternal(method, params = {}, timeoutMs = 15e3) {
10531
- return new Promise((resolve16, reject) => {
10860
+ return new Promise((resolve17, reject) => {
10532
10861
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
10533
10862
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
10534
10863
  const id = this.msgId++;
10535
- this.pending.set(id, { resolve: resolve16, reject });
10864
+ this.pending.set(id, { resolve: resolve17, reject });
10536
10865
  this.ws.send(JSON.stringify({ id, method, params }));
10537
10866
  setTimeout(() => {
10538
10867
  if (this.pending.has(id)) {
@@ -10781,7 +11110,7 @@ var DaemonCdpManager = class {
10781
11110
  const browserWs = this.browserWs;
10782
11111
  let msgId = this.browserMsgId;
10783
11112
  const sendWs = (method, params = {}, sessionId) => {
10784
- return new Promise((resolve16, reject) => {
11113
+ return new Promise((resolve17, reject) => {
10785
11114
  const mid = msgId++;
10786
11115
  this.browserMsgId = msgId;
10787
11116
  const handler = (raw) => {
@@ -10790,7 +11119,7 @@ var DaemonCdpManager = class {
10790
11119
  if (msg.id === mid) {
10791
11120
  browserWs.removeListener("message", handler);
10792
11121
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
10793
- else resolve16(msg.result);
11122
+ else resolve17(msg.result);
10794
11123
  }
10795
11124
  } catch {
10796
11125
  }
@@ -10991,14 +11320,14 @@ var DaemonCdpManager = class {
10991
11320
  if (!ws || ws.readyState !== WebSocket.OPEN) {
10992
11321
  throw new Error("CDP not connected");
10993
11322
  }
10994
- return new Promise((resolve16, reject) => {
11323
+ return new Promise((resolve17, reject) => {
10995
11324
  const id = getNextId();
10996
11325
  pendingMap.set(id, {
10997
11326
  resolve: (result) => {
10998
11327
  if (result?.result?.subtype === "error") {
10999
11328
  reject(new Error(result.result.description));
11000
11329
  } else {
11001
- resolve16(result?.result?.value);
11330
+ resolve17(result?.result?.value);
11002
11331
  }
11003
11332
  },
11004
11333
  reject
@@ -11030,10 +11359,10 @@ var DaemonCdpManager = class {
11030
11359
  throw new Error("CDP not connected");
11031
11360
  }
11032
11361
  const sendViaSession = (method, params = {}) => {
11033
- return new Promise((resolve16, reject) => {
11362
+ return new Promise((resolve17, reject) => {
11034
11363
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
11035
11364
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
11036
- pendingMap.set(id, { resolve: resolve16, reject });
11365
+ pendingMap.set(id, { resolve: resolve17, reject });
11037
11366
  ws.send(JSON.stringify({ id, sessionId, method, params }));
11038
11367
  setTimeout(() => {
11039
11368
  if (pendingMap.has(id)) {
@@ -16135,7 +16464,7 @@ function getSendChatInputEnvelope(args) {
16135
16464
  return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
16136
16465
  }
16137
16466
  function sleep(ms) {
16138
- return new Promise((resolve16) => setTimeout(resolve16, ms));
16467
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
16139
16468
  }
16140
16469
  async function waitOnceForFreshHermesCliStart(adapter, log) {
16141
16470
  if (adapter.cliType !== "hermes-cli") return;
@@ -16922,7 +17251,7 @@ function getCliVisibleTranscriptCount(adapter) {
16922
17251
  async function getStableExtensionBaseline(h) {
16923
17252
  const first = await readExtensionChatState(h);
16924
17253
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
16925
- await new Promise((resolve16) => setTimeout(resolve16, 150));
17254
+ await new Promise((resolve17) => setTimeout(resolve17, 150));
16926
17255
  const second = await readExtensionChatState(h);
16927
17256
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
16928
17257
  }
@@ -16930,7 +17259,7 @@ async function verifyExtensionSendObserved(h, before) {
16930
17259
  const beforeCount = getStateMessageCount(before);
16931
17260
  const beforeSignature = getStateLastSignature(before);
16932
17261
  for (let attempt = 0; attempt < 12; attempt += 1) {
16933
- await new Promise((resolve16) => setTimeout(resolve16, 250));
17262
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
16934
17263
  const state = await readExtensionChatState(h);
16935
17264
  if (state?.status === "waiting_approval") return true;
16936
17265
  const afterCount = getStateMessageCount(state);
@@ -18819,7 +19148,7 @@ async function executeProviderScript(h, args, scriptName) {
18819
19148
  const enterCount = cliCommand.enterCount || 1;
18820
19149
  await adapter.writeRaw(cliCommand.text + "\r");
18821
19150
  for (let i = 1; i < enterCount; i += 1) {
18822
- await new Promise((resolve16) => setTimeout(resolve16, 50));
19151
+ await new Promise((resolve17) => setTimeout(resolve17, 50));
18823
19152
  await adapter.writeRaw("\r");
18824
19153
  }
18825
19154
  }
@@ -19508,7 +19837,7 @@ var DaemonCommandHandler = class {
19508
19837
  try {
19509
19838
  const http3 = await import("http");
19510
19839
  const postData = JSON.stringify(body);
19511
- const result = await new Promise((resolve16, reject) => {
19840
+ const result = await new Promise((resolve17, reject) => {
19512
19841
  const req = http3.request({
19513
19842
  hostname: "127.0.0.1",
19514
19843
  port: 19280,
@@ -19520,9 +19849,9 @@ var DaemonCommandHandler = class {
19520
19849
  res.on("data", (chunk) => data += chunk);
19521
19850
  res.on("end", () => {
19522
19851
  try {
19523
- resolve16(JSON.parse(data));
19852
+ resolve17(JSON.parse(data));
19524
19853
  } catch {
19525
- resolve16({ raw: data });
19854
+ resolve17({ raw: data });
19526
19855
  }
19527
19856
  });
19528
19857
  });
@@ -19540,15 +19869,15 @@ var DaemonCommandHandler = class {
19540
19869
  if (!providerType) return { success: false, error: "providerType required" };
19541
19870
  try {
19542
19871
  const http3 = await import("http");
19543
- const result = await new Promise((resolve16, reject) => {
19872
+ const result = await new Promise((resolve17, reject) => {
19544
19873
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
19545
19874
  let data = "";
19546
19875
  res.on("data", (chunk) => data += chunk);
19547
19876
  res.on("end", () => {
19548
19877
  try {
19549
- resolve16(JSON.parse(data));
19878
+ resolve17(JSON.parse(data));
19550
19879
  } catch {
19551
- resolve16({ raw: data });
19880
+ resolve17({ raw: data });
19552
19881
  }
19553
19882
  });
19554
19883
  }).on("error", reject);
@@ -19562,7 +19891,7 @@ var DaemonCommandHandler = class {
19562
19891
  try {
19563
19892
  const http3 = await import("http");
19564
19893
  const postData = JSON.stringify(args || {});
19565
- const result = await new Promise((resolve16, reject) => {
19894
+ const result = await new Promise((resolve17, reject) => {
19566
19895
  const req = http3.request({
19567
19896
  hostname: "127.0.0.1",
19568
19897
  port: 19280,
@@ -19574,9 +19903,9 @@ var DaemonCommandHandler = class {
19574
19903
  res.on("data", (chunk) => data += chunk);
19575
19904
  res.on("end", () => {
19576
19905
  try {
19577
- resolve16(JSON.parse(data));
19906
+ resolve17(JSON.parse(data));
19578
19907
  } catch {
19579
- resolve16({ raw: data });
19908
+ resolve17({ raw: data });
19580
19909
  }
19581
19910
  });
19582
19911
  });
@@ -19598,7 +19927,7 @@ init_config();
19598
19927
  import * as os13 from "os";
19599
19928
  import * as path18 from "path";
19600
19929
  import * as crypto4 from "crypto";
19601
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "fs";
19930
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "fs";
19602
19931
  import { execFileSync } from "child_process";
19603
19932
  import chalk from "chalk";
19604
19933
 
@@ -19820,7 +20149,7 @@ async function waitForCliAdapterReady(adapter, options) {
19820
20149
  if (status === "stopped") {
19821
20150
  throw new Error("CLI runtime stopped before it became ready");
19822
20151
  }
19823
- await new Promise((resolve16) => setTimeout(resolve16, pollMs));
20152
+ await new Promise((resolve17) => setTimeout(resolve17, pollMs));
19824
20153
  }
19825
20154
  throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
19826
20155
  }
@@ -20197,7 +20526,7 @@ var CliProviderInstance = class {
20197
20526
  const enterCount = cliCommand.enterCount || 1;
20198
20527
  await this.adapter.writeRaw(cliCommand.text + "\r");
20199
20528
  for (let i = 1; i < enterCount; i += 1) {
20200
- await new Promise((resolve16) => setTimeout(resolve16, 50));
20529
+ await new Promise((resolve17) => setTimeout(resolve17, 50));
20201
20530
  await this.adapter.writeRaw("\r");
20202
20531
  }
20203
20532
  }
@@ -21598,13 +21927,13 @@ var AcpProviderInstance = class {
21598
21927
  }
21599
21928
  this.currentStatus = "waiting_approval";
21600
21929
  this.detectStatusTransition();
21601
- const approved = await new Promise((resolve16) => {
21602
- this.permissionResolvers.push(resolve16);
21930
+ const approved = await new Promise((resolve17) => {
21931
+ this.permissionResolvers.push(resolve17);
21603
21932
  setTimeout(() => {
21604
- const idx = this.permissionResolvers.indexOf(resolve16);
21933
+ const idx = this.permissionResolvers.indexOf(resolve17);
21605
21934
  if (idx >= 0) {
21606
21935
  this.permissionResolvers.splice(idx, 1);
21607
- resolve16(false);
21936
+ resolve17(false);
21608
21937
  }
21609
21938
  }, 3e5);
21610
21939
  });
@@ -22215,7 +22544,7 @@ function commandExists(command) {
22215
22544
  const trimmed = command.trim();
22216
22545
  if (!trimmed) return false;
22217
22546
  if (isExplicitCommand(trimmed)) {
22218
- return existsSync16(expandExecutable(trimmed));
22547
+ return existsSync17(expandExecutable(trimmed));
22219
22548
  }
22220
22549
  try {
22221
22550
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -22313,7 +22642,7 @@ async function waitForZeroMessageStartingLaunch(adapter) {
22313
22642
  } catch {
22314
22643
  return false;
22315
22644
  }
22316
- await new Promise((resolve16) => setTimeout(resolve16, ZERO_MESSAGE_STARTING_SEND_WAIT_MS));
22645
+ await new Promise((resolve17) => setTimeout(resolve17, ZERO_MESSAGE_STARTING_SEND_WAIT_MS));
22317
22646
  try {
22318
22647
  return hasZeroMessageStartingLaunch(adapter);
22319
22648
  } catch {
@@ -24386,8 +24715,8 @@ var ProviderLoader = class _ProviderLoader {
24386
24715
  }
24387
24716
  const https = __require("https");
24388
24717
  const { exec: exec7 } = __require("child_process");
24389
- const { promisify: promisify6 } = __require("util");
24390
- const execAsync5 = promisify6(exec7);
24718
+ const { promisify: promisify7 } = __require("util");
24719
+ const execAsync5 = promisify7(exec7);
24391
24720
  const metaPath = path19.join(this.upstreamDir, _ProviderLoader.META_FILE);
24392
24721
  let prevEtag = "";
24393
24722
  let prevTimestamp = 0;
@@ -24405,7 +24734,7 @@ var ProviderLoader = class _ProviderLoader {
24405
24734
  return { updated: false };
24406
24735
  }
24407
24736
  try {
24408
- const etag = await new Promise((resolve16, reject) => {
24737
+ const etag = await new Promise((resolve17, reject) => {
24409
24738
  const options = {
24410
24739
  method: "HEAD",
24411
24740
  hostname: "github.com",
@@ -24423,7 +24752,7 @@ var ProviderLoader = class _ProviderLoader {
24423
24752
  headers: { "User-Agent": "adhdev-launcher" },
24424
24753
  timeout: 1e4
24425
24754
  }, (res2) => {
24426
- resolve16(res2.headers.etag || res2.headers["last-modified"] || "");
24755
+ resolve17(res2.headers.etag || res2.headers["last-modified"] || "");
24427
24756
  });
24428
24757
  req2.on("error", reject);
24429
24758
  req2.on("timeout", () => {
@@ -24432,7 +24761,7 @@ var ProviderLoader = class _ProviderLoader {
24432
24761
  });
24433
24762
  req2.end();
24434
24763
  } else {
24435
- resolve16(res.headers.etag || res.headers["last-modified"] || "");
24764
+ resolve17(res.headers.etag || res.headers["last-modified"] || "");
24436
24765
  }
24437
24766
  });
24438
24767
  req.on("error", reject);
@@ -24496,7 +24825,7 @@ var ProviderLoader = class _ProviderLoader {
24496
24825
  downloadFile(url, destPath) {
24497
24826
  const https = __require("https");
24498
24827
  const http3 = __require("http");
24499
- return new Promise((resolve16, reject) => {
24828
+ return new Promise((resolve17, reject) => {
24500
24829
  const doRequest = (reqUrl, redirectCount = 0) => {
24501
24830
  if (redirectCount > 5) {
24502
24831
  reject(new Error("Too many redirects"));
@@ -24516,7 +24845,7 @@ var ProviderLoader = class _ProviderLoader {
24516
24845
  res.pipe(ws);
24517
24846
  ws.on("finish", () => {
24518
24847
  ws.close();
24519
- resolve16();
24848
+ resolve17();
24520
24849
  });
24521
24850
  ws.on("error", reject);
24522
24851
  });
@@ -25019,10 +25348,10 @@ function findMacAppProcessPids(psOutput, appPaths) {
25019
25348
 
25020
25349
  // src/launch.ts
25021
25350
  async function execQuiet(command, options = {}) {
25022
- return new Promise((resolve16) => {
25351
+ return new Promise((resolve17) => {
25023
25352
  exec4(command, options, (error, stdout) => {
25024
- if (error) return resolve16("");
25025
- resolve16(stdout.toString());
25353
+ if (error) return resolve17("");
25354
+ resolve17(stdout.toString());
25026
25355
  });
25027
25356
  });
25028
25357
  }
@@ -25103,17 +25432,17 @@ async function findFreePort(ports) {
25103
25432
  throw new Error("No free port found");
25104
25433
  }
25105
25434
  function checkPortFree(port) {
25106
- return new Promise((resolve16) => {
25435
+ return new Promise((resolve17) => {
25107
25436
  const server = net.createServer();
25108
25437
  server.unref();
25109
- server.on("error", () => resolve16(false));
25438
+ server.on("error", () => resolve17(false));
25110
25439
  server.listen(port, "127.0.0.1", () => {
25111
- server.close(() => resolve16(true));
25440
+ server.close(() => resolve17(true));
25112
25441
  });
25113
25442
  });
25114
25443
  }
25115
25444
  async function isCdpActive(port) {
25116
- return new Promise((resolve16) => {
25445
+ return new Promise((resolve17) => {
25117
25446
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
25118
25447
  timeout: 2e3
25119
25448
  }, (res) => {
@@ -25122,16 +25451,16 @@ async function isCdpActive(port) {
25122
25451
  res.on("end", () => {
25123
25452
  try {
25124
25453
  const info = JSON.parse(data);
25125
- resolve16(!!info["WebKit-Version"] || !!info["Browser"]);
25454
+ resolve17(!!info["WebKit-Version"] || !!info["Browser"]);
25126
25455
  } catch {
25127
- resolve16(false);
25456
+ resolve17(false);
25128
25457
  }
25129
25458
  });
25130
25459
  });
25131
- req.on("error", () => resolve16(false));
25460
+ req.on("error", () => resolve17(false));
25132
25461
  req.on("timeout", () => {
25133
25462
  req.destroy();
25134
- resolve16(false);
25463
+ resolve17(false);
25135
25464
  });
25136
25465
  });
25137
25466
  }
@@ -25606,12 +25935,12 @@ cleanOldFiles();
25606
25935
 
25607
25936
  // src/commands/router.ts
25608
25937
  init_logger();
25609
- import * as yaml2 from "js-yaml";
25938
+ import * as yaml3 from "js-yaml";
25610
25939
 
25611
25940
  // src/commands/mesh-coordinator.ts
25612
25941
  import { createHash as createHash3 } from "crypto";
25613
25942
  import * as os17 from "os";
25614
- import { isAbsolute as isAbsolute11, join as join22, resolve as resolve13 } from "path";
25943
+ import { isAbsolute as isAbsolute11, join as join23, resolve as resolve13 } from "path";
25615
25944
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
25616
25945
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev";
25617
25946
  var HERMES_CLI_TYPE = "hermes-cli";
@@ -25633,7 +25962,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
25633
25962
  reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
25634
25963
  };
25635
25964
  }
25636
- const configPath = join22(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
25965
+ const configPath = join23(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
25637
25966
  if (!configPath.trim()) {
25638
25967
  return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
25639
25968
  }
@@ -25753,14 +26082,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
25753
26082
  const key = `${meshId || "mesh"}
25754
26083
  ${resolve13(workspace || os17.tmpdir())}`;
25755
26084
  const hash = createHash3("sha256").update(key).digest("hex").slice(0, 16);
25756
- return join22(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
26085
+ return join23(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
25757
26086
  }
25758
26087
  function resolveMcpConfigPath(configPath, workspace) {
25759
26088
  const trimmed = configPath.trim();
25760
26089
  if (trimmed === "~") return os17.homedir();
25761
- if (trimmed.startsWith("~/")) return join22(os17.homedir(), trimmed.slice(2));
26090
+ if (trimmed.startsWith("~/")) return join23(os17.homedir(), trimmed.slice(2));
25762
26091
  if (isAbsolute11(trimmed)) return trimmed;
25763
- return join22(workspace, trimmed);
26092
+ return join23(workspace, trimmed);
25764
26093
  }
25765
26094
  function resolveAdhdevMcpServerLaunch(options) {
25766
26095
  const command = resolveAdhdevCommand(options.adhdevMcpCommand);
@@ -25793,6 +26122,88 @@ function resolveMcpPort(explicitPort) {
25793
26122
  init_mesh_events();
25794
26123
  init_mesh_host_ownership();
25795
26124
 
26125
+ // src/mesh/preview-freshness.ts
26126
+ import { execFileSync as execFileSync2 } from "child_process";
26127
+ import { existsSync as existsSync20, readFileSync as readFileSync13 } from "fs";
26128
+ import { resolve as resolve14 } from "path";
26129
+ var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
26130
+ function runGit2(repoRoot, args) {
26131
+ try {
26132
+ return execFileSync2("git", args, {
26133
+ cwd: repoRoot,
26134
+ encoding: "utf8",
26135
+ stdio: ["ignore", "pipe", "ignore"],
26136
+ timeout: 5e3
26137
+ }).trim();
26138
+ } catch {
26139
+ return "";
26140
+ }
26141
+ }
26142
+ function readRecord3(repoRoot) {
26143
+ const path28 = resolve14(repoRoot, PREVIEW_DEPLOY_RECORD);
26144
+ if (!existsSync20(path28)) return null;
26145
+ try {
26146
+ const parsed = JSON.parse(readFileSync13(path28, "utf8"));
26147
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
26148
+ } catch {
26149
+ return null;
26150
+ }
26151
+ }
26152
+ function normalizeCommit(value) {
26153
+ return typeof value === "string" && /^[0-9a-f]{7,40}$/i.test(value.trim()) ? value.trim() : null;
26154
+ }
26155
+ function readTargetFreshness(record, currentCommit) {
26156
+ const targets = record?.targets && typeof record.targets === "object" && !Array.isArray(record.targets) ? record.targets : {};
26157
+ const result = {};
26158
+ for (const targetName of ["npm", "server", "web"]) {
26159
+ const targetRecord = targets[targetName] && typeof targets[targetName] === "object" && !Array.isArray(targets[targetName]) ? targets[targetName] : {};
26160
+ const commit = normalizeCommit(targetRecord.commit);
26161
+ result[targetName] = {
26162
+ commit,
26163
+ deployedAt: typeof targetRecord.deployedAt === "string" ? targetRecord.deployedAt : void 0,
26164
+ status: commit && currentCommit ? commit === currentCommit ? "fresh" : "stale" : "unknown"
26165
+ };
26166
+ }
26167
+ return result;
26168
+ }
26169
+ function readCurrentMainCommit(repoRoot) {
26170
+ const originMain = runGit2(repoRoot, ["rev-parse", "--verify", "origin/main^{commit}"]);
26171
+ if (originMain) {
26172
+ return { currentMainCommit: originMain, currentMainCommitSource: "origin/main" };
26173
+ }
26174
+ const head = runGit2(repoRoot, ["rev-parse", "--verify", "HEAD"]);
26175
+ if (head) {
26176
+ return { currentMainCommit: head, currentMainCommitSource: "HEAD" };
26177
+ }
26178
+ return { currentMainCommit: null, currentMainCommitSource: "unknown" };
26179
+ }
26180
+ function buildPreviewFreshness(repoRoot) {
26181
+ const current = readCurrentMainCommit(repoRoot);
26182
+ const record = readRecord3(repoRoot);
26183
+ const lastPreviewCommit = normalizeCommit(record?.lastPreviewCommit);
26184
+ const targets = readTargetFreshness(record, current.currentMainCommit);
26185
+ let status = "unknown";
26186
+ let nextAction = "Run npm run deploy:preview from the current main commit, then smoke preview.";
26187
+ if (lastPreviewCommit && current.currentMainCommit) {
26188
+ status = lastPreviewCommit === current.currentMainCommit ? "fresh" : "stale";
26189
+ nextAction = status === "fresh" ? "No preview deploy action needed." : "Run npm run deploy:preview from origin/main, then smoke preview.";
26190
+ } else if (!current.currentMainCommit) {
26191
+ nextAction = "Resolve the current main commit before judging preview freshness.";
26192
+ }
26193
+ return {
26194
+ status,
26195
+ lastPreviewCommit,
26196
+ currentMainCommit: current.currentMainCommit,
26197
+ currentMainCommitSource: current.currentMainCommitSource,
26198
+ recordPath: PREVIEW_DEPLOY_RECORD,
26199
+ lastDeployedAt: typeof record?.updatedAt === "string" ? record.updatedAt : void 0,
26200
+ lastTarget: typeof record?.target === "string" ? record.target : void 0,
26201
+ previewVersion: typeof record?.previewVersion === "string" ? record.previewVersion : void 0,
26202
+ targets,
26203
+ nextAction
26204
+ };
26205
+ }
26206
+
25796
26207
  // src/status/snapshot.ts
25797
26208
  init_config();
25798
26209
  import * as os18 from "os";
@@ -26107,7 +26518,7 @@ function buildStatusSnapshot(options) {
26107
26518
  }
26108
26519
 
26109
26520
  // src/commands/upgrade-helper.ts
26110
- import { execFileSync as execFileSync2 } from "child_process";
26521
+ import { execFileSync as execFileSync3 } from "child_process";
26111
26522
  import { spawn as spawn3 } from "child_process";
26112
26523
  import * as fs10 from "fs";
26113
26524
  import * as os19 from "os";
@@ -26227,7 +26638,7 @@ function getNpmExecOptions(platform10 = process.platform) {
26227
26638
  }
26228
26639
  function execNpmCommandSync(args, options = {}, surface) {
26229
26640
  const execOptions = surface?.execOptions || getNpmExecOptions();
26230
- return execFileSync2(
26641
+ return execFileSync3(
26231
26642
  surface?.npmExecutable || "npm",
26232
26643
  [...surface?.npmArgsPrefix || [], ...args],
26233
26644
  {
@@ -26240,7 +26651,7 @@ function execNpmCommandSync(args, options = {}, surface) {
26240
26651
  function killPid(pid) {
26241
26652
  try {
26242
26653
  if (process.platform === "win32") {
26243
- execFileSync2("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
26654
+ execFileSync3("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
26244
26655
  } else {
26245
26656
  process.kill(pid, "SIGTERM");
26246
26657
  }
@@ -26252,7 +26663,7 @@ function killPid(pid) {
26252
26663
  function getWindowsProcessCommandLine(pid) {
26253
26664
  const pidFilter = `ProcessId=${pid}`;
26254
26665
  try {
26255
- const psOut = execFileSync2("powershell.exe", [
26666
+ const psOut = execFileSync3("powershell.exe", [
26256
26667
  "-NoProfile",
26257
26668
  "-NonInteractive",
26258
26669
  "-ExecutionPolicy",
@@ -26264,7 +26675,7 @@ function getWindowsProcessCommandLine(pid) {
26264
26675
  } catch {
26265
26676
  }
26266
26677
  try {
26267
- const wmicOut = execFileSync2("wmic", [
26678
+ const wmicOut = execFileSync3("wmic", [
26268
26679
  "process",
26269
26680
  "where",
26270
26681
  pidFilter,
@@ -26280,7 +26691,7 @@ function getProcessCommandLine(pid) {
26280
26691
  if (!Number.isFinite(pid) || pid <= 0) return null;
26281
26692
  if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
26282
26693
  try {
26283
- const text = execFileSync2("ps", ["-o", "command=", "-p", String(pid)], {
26694
+ const text = execFileSync3("ps", ["-o", "command=", "-p", String(pid)], {
26284
26695
  encoding: "utf8",
26285
26696
  timeout: 3e3,
26286
26697
  stdio: ["ignore", "pipe", "ignore"]
@@ -26299,7 +26710,7 @@ async function waitForPidExit(pid, timeoutMs) {
26299
26710
  while (Date.now() - start < timeoutMs) {
26300
26711
  try {
26301
26712
  process.kill(pid, 0);
26302
- await new Promise((resolve16) => setTimeout(resolve16, 250));
26713
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
26303
26714
  } catch {
26304
26715
  return;
26305
26716
  }
@@ -26396,7 +26807,7 @@ async function runDaemonUpgradeHelper(payload) {
26396
26807
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
26397
26808
  const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
26398
26809
  appendUpgradeLog(`Installing ${spec}`);
26399
- const installOutput = execFileSync2(
26810
+ const installOutput = execFileSync3(
26400
26811
  installCommand.command,
26401
26812
  installCommand.args,
26402
26813
  {
@@ -26410,7 +26821,7 @@ async function runDaemonUpgradeHelper(payload) {
26410
26821
  appendUpgradeLog(installOutput.trim());
26411
26822
  }
26412
26823
  if (process.platform === "win32") {
26413
- await new Promise((resolve16) => setTimeout(resolve16, 500));
26824
+ await new Promise((resolve17) => setTimeout(resolve17, 500));
26414
26825
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
26415
26826
  appendUpgradeLog("Post-install staging cleanup complete");
26416
26827
  }
@@ -26447,8 +26858,9 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
26447
26858
  // src/commands/router.ts
26448
26859
  init_mesh_work_queue();
26449
26860
  import { homedir as homedir19, hostname as osHostname } from "os";
26450
- import { basename as pathBasename, join as pathJoin, resolve as pathResolve } from "path";
26861
+ import { basename as pathBasename, join as pathJoin, resolve as pathResolve2 } from "path";
26451
26862
  import * as fs11 from "fs";
26863
+ import { execFileSync as execFileSync4 } from "child_process";
26452
26864
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
26453
26865
  var CHANNEL_SERVER_URL = {
26454
26866
  stable: "https://api.adhf.dev",
@@ -27160,6 +27572,16 @@ function finalizeMeshNodeStatus(args) {
27160
27572
  if (machineStatus) status.machineStatus = machineStatus;
27161
27573
  }
27162
27574
  synthesizeMeshNodeFreshnessFromConnection(status);
27575
+ const bootstrap = readObjectRecord(node?.worktreeBootstrap);
27576
+ if (node?.isLocalWorktree && readStringValue(bootstrap.status)) {
27577
+ status.worktreeBootstrap = bootstrap;
27578
+ if (bootstrap.status === "failed" && bootstrap.required !== false) {
27579
+ status.launchReady = false;
27580
+ status.launchBlockedReason = "worktree_bootstrap_failed";
27581
+ status.launchBlockedMessage = readStringValue(bootstrap.error) || "Required worktree bootstrap failed; resolve it before launching an agent into this node.";
27582
+ return;
27583
+ }
27584
+ }
27163
27585
  const connectionState = readStringValue(readObjectRecord(status.connection).state);
27164
27586
  status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
27165
27587
  }
@@ -27301,6 +27723,40 @@ function collectLiveMeshSessionRecords(args) {
27301
27723
  }
27302
27724
  return matches;
27303
27725
  }
27726
+ function buildHistoricalMeshSessions(args) {
27727
+ const liveNodeIds = /* @__PURE__ */ new Set();
27728
+ const liveWorkspaces = /* @__PURE__ */ new Set();
27729
+ for (const node of args.nodes || []) {
27730
+ const nodeId = readStringValue(node?.id, node?.nodeId);
27731
+ const workspace = readStringValue(node?.workspace);
27732
+ if (nodeId) liveNodeIds.add(nodeId);
27733
+ if (workspace) liveWorkspaces.add(workspace);
27734
+ }
27735
+ const sessions = [];
27736
+ for (const record of args.liveSessionRecords || []) {
27737
+ const meta = readObjectRecord(record?.meta);
27738
+ const recordMeshId = readStringValue(meta.meshNodeFor, meta.meshCoordinatorFor);
27739
+ if (recordMeshId !== args.meshId) continue;
27740
+ const recordNodeId = readStringValue(meta.meshNodeId);
27741
+ const workspace = readStringValue(record?.workspace);
27742
+ const removedNode = !!recordNodeId && !liveNodeIds.has(recordNodeId);
27743
+ const orphanedWorkspace = !!workspace && !liveWorkspaces.has(workspace) && meta.meshCoordinatorFor !== args.meshId;
27744
+ if (!removedNode && !orphanedWorkspace) continue;
27745
+ sessions.push({
27746
+ ...summarizeMeshSessionRecord(record),
27747
+ classification: removedNode ? "removedNode" : "orphanedSession",
27748
+ historical: true,
27749
+ meshNodeId: recordNodeId || null,
27750
+ reason: removedNode ? "Session is tagged to a mesh node that is no longer in live membership." : "Session workspace is no longer attached to a live mesh node."
27751
+ });
27752
+ }
27753
+ if (sessions.length === 0) return void 0;
27754
+ return {
27755
+ count: sessions.length,
27756
+ sessions: sessions.slice(0, 5),
27757
+ instruction: "These sessions are separated from normal node activeSessions because their mesh node/workspace is no longer live. Use mesh_cleanup_sessions only if cleanup is intended."
27758
+ };
27759
+ }
27304
27760
  function applyCachedInlineMeshNodeStatus(status, node, options) {
27305
27761
  const cachedStatus = readObjectRecord(node?.cachedStatus);
27306
27762
  const liveGit = buildInlineMeshTransitGitStatus(node);
@@ -27386,14 +27842,14 @@ function resolveRefineryAutoPublishSubmoduleMainCommits(mesh, workspace) {
27386
27842
  return { enabled: false };
27387
27843
  }
27388
27844
  async function computeGitPatchId(cwd, fromRef, toRef) {
27389
- const { execFileSync: execFileSync3 } = await import("child_process");
27390
- const diff = execFileSync3("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
27845
+ const { execFileSync: execFileSync5 } = await import("child_process");
27846
+ const diff = execFileSync5("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
27391
27847
  cwd,
27392
27848
  encoding: "utf8",
27393
27849
  maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
27394
27850
  });
27395
27851
  if (!diff.trim()) return "";
27396
- const patchId = execFileSync3("git", ["patch-id", "--stable"], {
27852
+ const patchId = execFileSync5("git", ["patch-id", "--stable"], {
27397
27853
  cwd,
27398
27854
  input: diff,
27399
27855
  encoding: "utf8",
@@ -27404,8 +27860,8 @@ async function computeGitPatchId(cwd, fromRef, toRef) {
27404
27860
  async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
27405
27861
  const startedAt = Date.now();
27406
27862
  try {
27407
- const { execFileSync: execFileSync3 } = await import("child_process");
27408
- const git = (args) => execFileSync3("git", args, {
27863
+ const { execFileSync: execFileSync5 } = await import("child_process");
27864
+ const git = (args) => execFileSync5("git", args, {
27409
27865
  cwd: repoRoot,
27410
27866
  encoding: "utf8",
27411
27867
  maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
@@ -27449,6 +27905,135 @@ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead)
27449
27905
  durationMs: Date.now() - startedAt,
27450
27906
  error: e?.message || String(e),
27451
27907
  stdout: truncateValidationOutput(e?.stdout),
27908
+ stderr: truncateValidationOutput(e?.stderr),
27909
+ actionableHint: buildPatchEquivalenceSubmoduleConflictHint(
27910
+ repoRoot,
27911
+ baseHead,
27912
+ branchHead,
27913
+ `${e?.message || ""}
27914
+ ${e?.stdout || ""}
27915
+ ${e?.stderr || ""}`
27916
+ )
27917
+ };
27918
+ }
27919
+ }
27920
+ function buildPatchEquivalenceSubmoduleConflictHint(repoRoot, baseHead, branchHead, output) {
27921
+ if (!/(submodule|160000)/i.test(output) || !/(conflict|failed to merge)/i.test(output)) return void 0;
27922
+ const conflicts = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path28) => ({
27923
+ path: path28,
27924
+ baseCommit: readTreeObject(repoRoot, baseHead, path28),
27925
+ branchCommit: readTreeObject(repoRoot, branchHead, path28)
27926
+ }));
27927
+ if (conflicts.length === 0) return void 0;
27928
+ return {
27929
+ kind: "submodule_conflict",
27930
+ message: "Refinery could not synthesize a safe merge tree because the branch and base point the same submodule path at different commits.",
27931
+ conflicts,
27932
+ nextSteps: [
27933
+ "Inspect the listed submodule path in both base and branch: baseCommit is the commit currently recorded by the base workspace, branchCommit is the commit recorded by the worktree branch.",
27934
+ "Resolve the submodule first by checking out or creating the intended submodule commit, then commit the chosen gitlink in the root branch.",
27935
+ "Ensure the chosen submodule commit is reachable from the configured submodule remote main branch, then rerun mesh_refine_node."
27936
+ ]
27937
+ };
27938
+ }
27939
+ function readChangedGitlinkPaths(repoRoot, fromRef, toRef) {
27940
+ try {
27941
+ const output = execFileSync4("git", ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
27942
+ cwd: repoRoot,
27943
+ encoding: "utf8",
27944
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
27945
+ });
27946
+ const paths = /* @__PURE__ */ new Set();
27947
+ for (const line of output.split("\n")) {
27948
+ if (!line.trim()) continue;
27949
+ const metaAndPath = line.split(" ");
27950
+ const meta = metaAndPath[0] || "";
27951
+ const path28 = metaAndPath[metaAndPath.length - 1]?.trim();
27952
+ if (!path28) continue;
27953
+ const parts = meta.split(/\s+/);
27954
+ if (parts[0]?.includes("160000") || parts[1]?.includes("160000")) {
27955
+ paths.add(path28);
27956
+ }
27957
+ }
27958
+ return [...paths].sort();
27959
+ } catch {
27960
+ return [];
27961
+ }
27962
+ }
27963
+ function readTreeObject(repoRoot, ref, path28) {
27964
+ try {
27965
+ const output = execFileSync4("git", ["ls-tree", ref, "--", path28], {
27966
+ cwd: repoRoot,
27967
+ encoding: "utf8",
27968
+ maxBuffer: 1024 * 1024
27969
+ }).trim();
27970
+ const match = output.match(/\bcommit\s+([0-9a-f]{40})\b/i);
27971
+ return match?.[1];
27972
+ } catch {
27973
+ return void 0;
27974
+ }
27975
+ }
27976
+ async function alignRefinerySubmodulesAfterMerge(repoRoot, previousBaseHead, currentHead, options = {}) {
27977
+ const startedAt = Date.now();
27978
+ const changedGitlinkPaths = readChangedGitlinkPaths(repoRoot, previousBaseHead, currentHead).filter((path28) => !(options.submoduleIgnorePaths || []).includes(path28));
27979
+ const preStatus = await getGitRepoStatus(repoRoot, {
27980
+ includeSubmodules: true,
27981
+ submoduleIgnorePaths: options.submoduleIgnorePaths,
27982
+ timeoutMs: 15e3
27983
+ });
27984
+ const outOfSyncPaths = (preStatus.submodules || []).filter((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error).map((submodule) => submodule.path);
27985
+ const updatePaths = [.../* @__PURE__ */ new Set([...changedGitlinkPaths, ...outOfSyncPaths])].sort();
27986
+ if (updatePaths.length === 0) {
27987
+ return {
27988
+ status: "skipped",
27989
+ changedGitlinkPaths,
27990
+ outOfSyncPaths,
27991
+ updatedPaths: [],
27992
+ verifiedPaths: [],
27993
+ durationMs: Date.now() - startedAt,
27994
+ reason: "no_changed_or_out_of_sync_submodules"
27995
+ };
27996
+ }
27997
+ const commandArgs = ["submodule", "update", "--init", "--recursive", "--", ...updatePaths];
27998
+ try {
27999
+ const { execFile: execFile4 } = await import("child_process");
28000
+ const { promisify: promisify7 } = await import("util");
28001
+ const execFileAsync3 = promisify7(execFile4);
28002
+ const result = await execFileAsync3("git", commandArgs, {
28003
+ cwd: repoRoot,
28004
+ encoding: "utf8",
28005
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES,
28006
+ timeout: 6e4
28007
+ });
28008
+ const postStatus = await getGitRepoStatus(repoRoot, {
28009
+ includeSubmodules: true,
28010
+ submoduleIgnorePaths: options.submoduleIgnorePaths,
28011
+ timeoutMs: 15e3
28012
+ });
28013
+ const remaining = (postStatus.submodules || []).filter((submodule) => updatePaths.includes(submodule.path) && (submodule.dirty || submodule.outOfSync || !!submodule.error));
28014
+ return {
28015
+ status: remaining.length === 0 ? "passed" : "failed",
28016
+ changedGitlinkPaths,
28017
+ outOfSyncPaths,
28018
+ updatedPaths: updatePaths,
28019
+ verifiedPaths: updatePaths.filter((path28) => !remaining.some((submodule) => submodule.path === path28)),
28020
+ durationMs: Date.now() - startedAt,
28021
+ command: `git ${commandArgs.join(" ")}`,
28022
+ stdout: truncateValidationOutput(result.stdout),
28023
+ stderr: truncateValidationOutput(result.stderr),
28024
+ ...remaining.length > 0 ? { error: `Submodule checkout remained out of sync after update: ${remaining.map((entry) => entry.path).join(", ")}` } : {}
28025
+ };
28026
+ } catch (e) {
28027
+ return {
28028
+ status: "failed",
28029
+ changedGitlinkPaths,
28030
+ outOfSyncPaths,
28031
+ updatedPaths: updatePaths,
28032
+ verifiedPaths: [],
28033
+ durationMs: Date.now() - startedAt,
28034
+ command: `git ${commandArgs.join(" ")}`,
28035
+ error: e?.message || String(e),
28036
+ stdout: truncateValidationOutput(e?.stdout),
27452
28037
  stderr: truncateValidationOutput(e?.stderr)
27453
28038
  };
27454
28039
  }
@@ -27457,10 +28042,10 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27457
28042
  const startedAt = Date.now();
27458
28043
  const entries = [];
27459
28044
  try {
27460
- const { execFile: execFile3 } = await import("child_process");
27461
- const { promisify: promisify6 } = await import("util");
27462
- const execFileAsync3 = promisify6(execFile3);
27463
- const runGit2 = async (cwd, args) => {
28045
+ const { execFile: execFile4 } = await import("child_process");
28046
+ const { promisify: promisify7 } = await import("util");
28047
+ const execFileAsync3 = promisify7(execFile4);
28048
+ const runGit3 = async (cwd, args) => {
27464
28049
  const { stdout } = await execFileAsync3("git", args, {
27465
28050
  cwd,
27466
28051
  encoding: "utf8",
@@ -27471,8 +28056,8 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27471
28056
  return String(stdout || "");
27472
28057
  };
27473
28058
  const verifyRemoteMainContainsCommit = async (submodulePath, commit, branch = "main") => {
27474
- await runGit2(submodulePath, ["-c", "protocol.file.allow=always", "fetch", "origin", `refs/heads/${branch}:refs/remotes/origin/${branch}`]);
27475
- await runGit2(submodulePath, ["merge-base", "--is-ancestor", commit, `refs/remotes/origin/${branch}`]);
28059
+ await runGit3(submodulePath, ["-c", "protocol.file.allow=always", "fetch", "origin", `refs/heads/${branch}:refs/remotes/origin/${branch}`]);
28060
+ await runGit3(submodulePath, ["merge-base", "--is-ancestor", commit, `refs/remotes/origin/${branch}`]);
27476
28061
  };
27477
28062
  const publishCommitToRemoteMain = async (submodulePath, commit, branch = "main") => {
27478
28063
  const refspec = `${commit}:refs/heads/${branch}`;
@@ -27488,21 +28073,21 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27488
28073
  const importCommitFromWorktreeSubmodule = async (submodulePath, worktreeSubmodulePath, commit) => {
27489
28074
  if (!fs11.existsSync(worktreeSubmodulePath)) return false;
27490
28075
  try {
27491
- await runGit2(worktreeSubmodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
28076
+ await runGit3(worktreeSubmodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
27492
28077
  } catch {
27493
28078
  return false;
27494
28079
  }
27495
- await runGit2(submodulePath, ["-c", "protocol.file.allow=always", "fetch", worktreeSubmodulePath, commit]);
27496
- await runGit2(submodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
28080
+ await runGit3(submodulePath, ["-c", "protocol.file.allow=always", "fetch", worktreeSubmodulePath, commit]);
28081
+ await runGit3(submodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
27497
28082
  return true;
27498
28083
  };
27499
- const treeOutput = await runGit2(repoRoot, ["ls-tree", "-r", "-z", mergedTree]);
28084
+ const treeOutput = await runGit3(repoRoot, ["ls-tree", "-r", "-z", mergedTree]);
27500
28085
  const gitlinks = treeOutput.split("\0").filter(Boolean).map((record) => {
27501
28086
  const match = /^160000\s+commit\s+([0-9a-f]{40})\t(.+)$/.exec(record);
27502
28087
  return match ? { commit: match[1], path: match[2] } : null;
27503
28088
  }).filter((entry) => !!entry);
27504
28089
  for (const gitlink of gitlinks) {
27505
- const submodulePath = pathResolve(repoRoot, gitlink.path);
28090
+ const submodulePath = pathResolve2(repoRoot, gitlink.path);
27506
28091
  const entry = {
27507
28092
  path: gitlink.path,
27508
28093
  commit: gitlink.commit,
@@ -27522,7 +28107,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27522
28107
  }
27523
28108
  entry.checkedLocal = true;
27524
28109
  try {
27525
- await runGit2(submodulePath, ["cat-file", "-e", `${gitlink.commit}^{commit}`]);
28110
+ await runGit3(submodulePath, ["cat-file", "-e", `${gitlink.commit}^{commit}`]);
27526
28111
  entry.localReachable = true;
27527
28112
  } catch {
27528
28113
  entry.localReachable = false;
@@ -27530,7 +28115,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27530
28115
  try {
27531
28116
  const imported = await importCommitFromWorktreeSubmodule(
27532
28117
  submodulePath,
27533
- pathResolve(options.worktreeRoot, gitlink.path),
28118
+ pathResolve2(options.worktreeRoot, gitlink.path),
27534
28119
  gitlink.commit
27535
28120
  );
27536
28121
  if (imported) {
@@ -27546,7 +28131,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
27546
28131
  entry.remote = "origin";
27547
28132
  let remoteUrl = "";
27548
28133
  try {
27549
- remoteUrl = (await runGit2(submodulePath, ["remote", "get-url", "origin"])).trim();
28134
+ remoteUrl = (await runGit3(submodulePath, ["remote", "get-url", "origin"])).trim();
27550
28135
  if (!remoteUrl) throw new Error("origin remote has no URL");
27551
28136
  entry.remoteUrl = remoteUrl;
27552
28137
  } catch {
@@ -27661,9 +28246,9 @@ function buildMeshRefineValidationPlan(mesh, workspace) {
27661
28246
  };
27662
28247
  }
27663
28248
  async function runMeshRefineValidationGate(mesh, workspace) {
27664
- const { execFile: execFile3 } = await import("child_process");
27665
- const { promisify: promisify6 } = await import("util");
27666
- const execFileAsync3 = promisify6(execFile3);
28249
+ const { execFile: execFile4 } = await import("child_process");
28250
+ const { promisify: promisify7 } = await import("util");
28251
+ const execFileAsync3 = promisify7(execFile4);
27667
28252
  const selection = resolveMeshRefineValidationPlan(mesh, workspace);
27668
28253
  const summary = {
27669
28254
  status: "skipped",
@@ -27707,14 +28292,14 @@ async function runMeshRefineValidationGate(mesh, workspace) {
27707
28292
  };
27708
28293
  for (const candidate of selection.bootstrapCommands) {
27709
28294
  const startedAt = Date.now();
27710
- const cwd = candidate.cwd ? pathResolve(workspace, candidate.cwd) : workspace;
28295
+ const cwd = candidate.cwd ? pathResolve2(workspace, candidate.cwd) : workspace;
27711
28296
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
27712
28297
  try {
27713
28298
  const result = await execFileAsync3(candidate.command, candidate.args, {
27714
28299
  cwd,
27715
28300
  encoding: "utf8",
27716
28301
  timeout,
27717
- maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
28302
+ maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
27718
28303
  env: { ...process.env, CI: process.env.CI || "1", ...candidate.env || {} }
27719
28304
  });
27720
28305
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
@@ -27733,7 +28318,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
27733
28318
  }
27734
28319
  for (const candidate of selection.commands) {
27735
28320
  const startedAt = Date.now();
27736
- const cwd = candidate.cwd ? pathResolve(workspace, candidate.cwd) : workspace;
28321
+ const cwd = candidate.cwd ? pathResolve2(workspace, candidate.cwd) : workspace;
27737
28322
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
27738
28323
  if (selection.bootstrapCommands.length === 0 && isPackageManagerValidation(candidate) && dependenciesLikelyMissing(cwd)) {
27739
28324
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, {
@@ -27753,7 +28338,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
27753
28338
  cwd,
27754
28339
  encoding: "utf8",
27755
28340
  timeout,
27756
- maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
28341
+ maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
27757
28342
  env: { ...process.env, CI: process.env.CI || "1", ...candidate.env || {} }
27758
28343
  });
27759
28344
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
@@ -27778,7 +28363,7 @@ async function runMeshRefineValidationGate(mesh, workspace) {
27778
28363
  return summary;
27779
28364
  }
27780
28365
  function loadYamlModule() {
27781
- return yaml2;
28366
+ return yaml3;
27782
28367
  }
27783
28368
  function getMcpServersKey(format) {
27784
28369
  return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
@@ -27801,7 +28386,7 @@ function loadHermesCoordinatorBaseConfig(targetConfigPath) {
27801
28386
  const sourceHome = resolveHermesUserHome();
27802
28387
  const sourceConfigPath = pathJoin(sourceHome, "config.yaml");
27803
28388
  if (!fs11.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
27804
- if (pathResolve(sourceConfigPath) === pathResolve(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
28389
+ if (pathResolve2(sourceConfigPath) === pathResolve2(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
27805
28390
  const parsed = parseMeshCoordinatorMcpConfig(fs11.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
27806
28391
  const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
27807
28392
  return { config: baseConfig, sourceHome, sourceConfigPath };
@@ -27835,7 +28420,7 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
27835
28420
  return sanitized;
27836
28421
  }
27837
28422
  function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
27838
- if (pathResolve(sourceHome) === pathResolve(targetHome)) return;
28423
+ if (pathResolve2(sourceHome) === pathResolve2(targetHome)) return;
27839
28424
  for (const fileName of [".env", "auth.json"]) {
27840
28425
  const sourcePath = pathJoin(sourceHome, fileName);
27841
28426
  const targetPath = pathJoin(targetHome, fileName);
@@ -28220,7 +28805,7 @@ var DaemonCommandRouter = class {
28220
28805
  }
28221
28806
  const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
28222
28807
  const normalizePath = (value) => {
28223
- const resolved = pathResolve(value);
28808
+ const resolved = pathResolve2(value);
28224
28809
  try {
28225
28810
  return fs11.realpathSync(resolved);
28226
28811
  } catch {
@@ -28294,10 +28879,10 @@ var DaemonCommandRouter = class {
28294
28879
  if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
28295
28880
  return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
28296
28881
  }
28297
- const { execFile: execFile3 } = await import("child_process");
28298
- const { promisify: promisify6 } = await import("util");
28299
- const execFileAsync3 = promisify6(execFile3);
28300
- const runGit2 = async (gitArgs, cwd) => {
28882
+ const { execFile: execFile4 } = await import("child_process");
28883
+ const { promisify: promisify7 } = await import("util");
28884
+ const execFileAsync3 = promisify7(execFile4);
28885
+ const runGit3 = async (gitArgs, cwd) => {
28301
28886
  const { stdout } = await execFileAsync3("git", gitArgs, {
28302
28887
  cwd,
28303
28888
  encoding: "utf8",
@@ -28309,14 +28894,14 @@ var DaemonCommandRouter = class {
28309
28894
  };
28310
28895
  let head = "";
28311
28896
  try {
28312
- head = await runGit2(["rev-parse", "HEAD"], args.workspace);
28897
+ head = await runGit3(["rev-parse", "HEAD"], args.workspace);
28313
28898
  } catch (e) {
28314
28899
  return { allow: false, error: `could not resolve worktree HEAD: ${e?.message || e}` };
28315
28900
  }
28316
28901
  if (!head) return { allow: false, error: "worktree HEAD is empty" };
28317
28902
  const candidateRefs = [];
28318
28903
  try {
28319
- const defaultBranch = await runGit2(["branch", "--show-current"], args.repoRoot);
28904
+ const defaultBranch = await runGit3(["branch", "--show-current"], args.repoRoot);
28320
28905
  if (defaultBranch) {
28321
28906
  candidateRefs.push(defaultBranch, `origin/${defaultBranch}`);
28322
28907
  }
@@ -28330,13 +28915,13 @@ var DaemonCommandRouter = class {
28330
28915
  seen.add(ref);
28331
28916
  let commit = "";
28332
28917
  try {
28333
- commit = await runGit2(["rev-parse", "--verify", `${ref}^{commit}`], args.repoRoot);
28918
+ commit = await runGit3(["rev-parse", "--verify", `${ref}^{commit}`], args.repoRoot);
28334
28919
  } catch {
28335
28920
  continue;
28336
28921
  }
28337
28922
  checkedRefs.push(ref);
28338
28923
  try {
28339
- await runGit2(["merge-base", "--is-ancestor", head, commit], args.repoRoot);
28924
+ await runGit3(["merge-base", "--is-ancestor", head, commit], args.repoRoot);
28340
28925
  return { allow: true, status: "merged_to_default_ref", source: "git_merge_base", ref };
28341
28926
  } catch {
28342
28927
  }
@@ -28728,9 +29313,9 @@ var DaemonCommandRouter = class {
28728
29313
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
28729
29314
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
28730
29315
  if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
28731
- const { execFile: execFile3 } = await import("child_process");
28732
- const { promisify: promisify6 } = await import("util");
28733
- const execFileAsync3 = promisify6(execFile3);
29316
+ const { execFile: execFile4 } = await import("child_process");
29317
+ const { promisify: promisify7 } = await import("util");
29318
+ const execFileAsync3 = promisify7(execFile4);
28734
29319
  const resolveStarted = Date.now();
28735
29320
  const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
28736
29321
  const branch = branchStdout.trim();
@@ -28797,7 +29382,8 @@ var DaemonCommandRouter = class {
28797
29382
  equivalent: patchEquivalence.equivalent,
28798
29383
  expectedPatchId: patchEquivalence.expectedPatchId,
28799
29384
  actualPatchId: patchEquivalence.actualPatchId,
28800
- error: patchEquivalence.error
29385
+ error: patchEquivalence.error,
29386
+ actionableHint: patchEquivalence.actionableHint
28801
29387
  });
28802
29388
  if (!patchEquivalence.equivalent) {
28803
29389
  return {
@@ -28956,6 +29542,49 @@ var DaemonCommandRouter = class {
28956
29542
  }
28957
29543
  };
28958
29544
  }
29545
+ const submoduleAlignmentStarted = Date.now();
29546
+ const submoduleAlignment = await alignRefinerySubmodulesAfterMerge(repoRoot, baseHead, "HEAD", {
29547
+ submoduleIgnorePaths: Array.isArray(sourceNode?.policy?.submoduleIgnorePaths) ? sourceNode.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0
29548
+ });
29549
+ if (submoduleAlignment.status !== "skipped") {
29550
+ recordMeshRefineStage(refineStages, "submodule_alignment", submoduleAlignment.status, submoduleAlignmentStarted, {
29551
+ changedGitlinkPaths: submoduleAlignment.changedGitlinkPaths,
29552
+ outOfSyncPaths: submoduleAlignment.outOfSyncPaths,
29553
+ updatedPaths: submoduleAlignment.updatedPaths,
29554
+ verifiedPaths: submoduleAlignment.verifiedPaths,
29555
+ command: submoduleAlignment.command,
29556
+ error: submoduleAlignment.error
29557
+ });
29558
+ }
29559
+ if (submoduleAlignment.status === "failed") {
29560
+ return {
29561
+ success: false,
29562
+ code: "post_merge_submodule_alignment_failed",
29563
+ error: "Refinery merge completed but post-merge submodule checkout alignment failed; run the reported git submodule update command and re-check base workspace status.",
29564
+ merged: true,
29565
+ branch,
29566
+ into: baseBranch,
29567
+ validationSummary,
29568
+ patchEquivalence,
29569
+ submoduleReachability,
29570
+ submoduleAlignment,
29571
+ mergeResult,
29572
+ refineStages,
29573
+ finalBranchConvergenceState: {
29574
+ branch: baseBranch,
29575
+ mergedBranch: branch,
29576
+ baseBranch,
29577
+ merged: true,
29578
+ removed: false,
29579
+ validation: "passed",
29580
+ patchEquivalence: "passed",
29581
+ submoduleReachability: "passed",
29582
+ submoduleAlignment: "failed",
29583
+ status: "post_merge_alignment_failed",
29584
+ nextStep: submoduleAlignment.command || "Run git submodule update --init --recursive for the reported path(s), then re-check base workspace status."
29585
+ }
29586
+ };
29587
+ }
28959
29588
  const cleanupStarted = Date.now();
28960
29589
  const removeResult = await this.execute("remove_mesh_node", {
28961
29590
  meshId,
@@ -28975,7 +29604,7 @@ var DaemonCommandRouter = class {
28975
29604
  appendLedgerEntry2(meshId, {
28976
29605
  kind: "node_removed",
28977
29606
  nodeId,
28978
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence, submoduleReachability }
29607
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence, submoduleReachability, submoduleAlignment }
28979
29608
  });
28980
29609
  recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
28981
29610
  } catch (e) {
@@ -28990,6 +29619,7 @@ var DaemonCommandRouter = class {
28990
29619
  removed: removeResult?.success !== false,
28991
29620
  validation: "passed",
28992
29621
  patchEquivalence: "passed",
29622
+ submoduleAlignment: submoduleAlignment.status,
28993
29623
  status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
28994
29624
  };
28995
29625
  if (removeResult?.success === false) {
@@ -29004,6 +29634,7 @@ var DaemonCommandRouter = class {
29004
29634
  validationSummary,
29005
29635
  patchEquivalence,
29006
29636
  submoduleReachability,
29637
+ submoduleAlignment,
29007
29638
  mergeResult,
29008
29639
  refineStages,
29009
29640
  ...ledgerError ? { ledgerError } : {},
@@ -29019,6 +29650,7 @@ var DaemonCommandRouter = class {
29019
29650
  validationSummary,
29020
29651
  patchEquivalence,
29021
29652
  submoduleReachability,
29653
+ submoduleAlignment,
29022
29654
  mergeResult,
29023
29655
  refineStages,
29024
29656
  ...ledgerError ? { ledgerError } : {},
@@ -30101,6 +30733,12 @@ var DaemonCommandRouter = class {
30101
30733
  success: true,
30102
30734
  schema: MESH_REFINE_CONFIG_SCHEMA,
30103
30735
  locations: MESH_REFINE_CONFIG_LOCATIONS,
30736
+ worktreeBootstrap: {
30737
+ schema: MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
30738
+ locations: MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
30739
+ sourceOfTruth: "repo worktree bootstrap config",
30740
+ runBehavior: "When present and enabled, clone_mesh_node runs commands after submodule initialization and records status on the worktree node."
30741
+ },
30104
30742
  sourceOfTruth: "repo mesh/refine config",
30105
30743
  heuristicRole: "suggestions_only_not_execution_path"
30106
30744
  };
@@ -30295,8 +30933,8 @@ var DaemonCommandRouter = class {
30295
30933
  const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
30296
30934
  if (initSubmodules) {
30297
30935
  try {
30298
- const { runGit: runGit2 } = await Promise.resolve().then(() => (init_git_executor(), git_executor_exports));
30299
- await runGit2(
30936
+ const { runGit: runGit3 } = await Promise.resolve().then(() => (init_git_executor(), git_executor_exports));
30937
+ await runGit3(
30300
30938
  { workspace: result.worktreePath, repoRoot: result.worktreePath, isGitRepo: true },
30301
30939
  ["submodule", "update", "--init", "--recursive"],
30302
30940
  { timeoutMs: 12e4 }
@@ -30305,12 +30943,35 @@ var DaemonCommandRouter = class {
30305
30943
  console.warn("[mesh] Submodule init failed for worktree:", subErr.message);
30306
30944
  }
30307
30945
  }
30946
+ const bootstrapState = await runMeshWorktreeBootstrap(mesh, result.worktreePath);
30947
+ node.worktreeBootstrap = bootstrapState;
30948
+ if (!meshRecord.inline) {
30949
+ try {
30950
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
30951
+ updateNode2(meshId, node.id, { worktreeBootstrap: bootstrapState });
30952
+ this.invalidateAggregateMeshStatus(meshId);
30953
+ } catch {
30954
+ }
30955
+ }
30308
30956
  try {
30309
30957
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
30310
30958
  appendLedgerEntry2(meshId, {
30311
30959
  kind: "node_cloned",
30312
30960
  nodeId: node.id,
30313
- payload: { sourceNodeId, branch: result.branch, worktreePath: result.worktreePath, submodulesInitialized: initSubmodules }
30961
+ payload: {
30962
+ sourceNodeId,
30963
+ branch: result.branch,
30964
+ worktreePath: result.worktreePath,
30965
+ submodulesInitialized: initSubmodules,
30966
+ worktreeBootstrap: {
30967
+ status: bootstrapState.status,
30968
+ required: bootstrapState.required,
30969
+ configSource: bootstrapState.configSource,
30970
+ configSourceType: bootstrapState.configSourceType,
30971
+ lastCommand: bootstrapState.lastCommand,
30972
+ exitCode: bootstrapState.exitCode
30973
+ }
30974
+ }
30314
30975
  });
30315
30976
  } catch {
30316
30977
  }
@@ -30318,7 +30979,8 @@ var DaemonCommandRouter = class {
30318
30979
  success: true,
30319
30980
  node,
30320
30981
  worktreePath: result.worktreePath,
30321
- branch: result.branch
30982
+ branch: result.branch,
30983
+ worktreeBootstrap: bootstrapState
30322
30984
  };
30323
30985
  } catch (e) {
30324
30986
  return { success: false, error: e.message };
@@ -30546,7 +31208,7 @@ ${block2}`);
30546
31208
  workspace
30547
31209
  };
30548
31210
  }
30549
- const { existsSync: existsSync26, readFileSync: readFileSync19, writeFileSync: writeFileSync14, copyFileSync: copyFileSync4, mkdirSync: mkdirSync18 } = await import("fs");
31211
+ const { existsSync: existsSync28, readFileSync: readFileSync21, writeFileSync: writeFileSync14, copyFileSync: copyFileSync4, mkdirSync: mkdirSync18 } = await import("fs");
30550
31212
  const { dirname: dirname9 } = await import("path");
30551
31213
  const mcpConfigPath = coordinatorSetup.configPath;
30552
31214
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -30589,14 +31251,14 @@ ${block2}`);
30589
31251
  if (hermesManualFallback) return returnManualFallback(message);
30590
31252
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
30591
31253
  }
30592
- const hadExistingMcpConfig = existsSync26(mcpConfigPath);
31254
+ const hadExistingMcpConfig = existsSync28(mcpConfigPath);
30593
31255
  let existingMcpConfig = hermesBaseConfig?.config || {};
30594
31256
  if (hermesBaseConfig) {
30595
31257
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
30596
31258
  }
30597
31259
  if (hadExistingMcpConfig) {
30598
31260
  try {
30599
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync19(mcpConfigPath, "utf-8"), configFormat);
31261
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync21(mcpConfigPath, "utf-8"), configFormat);
30600
31262
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
30601
31263
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
30602
31264
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -30708,6 +31370,7 @@ ${block2}`);
30708
31370
  const queueSummary = getMeshQueueStats2(meshId);
30709
31371
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
30710
31372
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
31373
+ const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
30711
31374
  const ledgerSummary = getLedgerSummary2(meshId);
30712
31375
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
30713
31376
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
@@ -30970,6 +31633,20 @@ ${block2}`);
30970
31633
  nodeStatuses.push(status);
30971
31634
  }
30972
31635
  const pendingCoordinatorEvents = drainPendingMeshCoordinatorEvents(meshId);
31636
+ const previewFreshness = (() => {
31637
+ const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs11.existsSync(candidate));
31638
+ return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
31639
+ })();
31640
+ const asyncRefineJobs = buildMeshAsyncRefineJobs({
31641
+ meshId,
31642
+ ledgerEntries: asyncRefineLedgerEntries,
31643
+ pendingEvents: pendingCoordinatorEvents
31644
+ });
31645
+ const historicalSessions = buildHistoricalMeshSessions({
31646
+ meshId,
31647
+ nodes: mesh.nodes || [],
31648
+ liveSessionRecords: liveMeshSessions
31649
+ });
30973
31650
  const statusResult = {
30974
31651
  success: true,
30975
31652
  meshId: mesh.id,
@@ -31001,12 +31678,15 @@ ${block2}`);
31001
31678
  partialNodeFailures: effectiveDirectTruth.unavailableNodeIds
31002
31679
  }
31003
31680
  } : {},
31004
- historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
31681
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary", "historicalSessions"]
31005
31682
  },
31006
31683
  branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
31684
+ ...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
31007
31685
  nodes: nodeStatuses,
31008
31686
  queue: { tasks: queue, summary: queueSummary },
31009
31687
  ledger: { entries: ledgerEntries, summary: ledgerSummary },
31688
+ ...asyncRefineJobs.length > 0 ? { asyncRefineJobs } : {},
31689
+ ...historicalSessions ? { historicalSessions } : {},
31010
31690
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {}
31011
31691
  };
31012
31692
  const { pendingCoordinatorEvents: _pendingCoordinatorEvents, ...cacheableStatusResult } = statusResult;
@@ -31657,7 +32337,7 @@ var ProviderStreamAdapter = class {
31657
32337
  const beforeCount = this.messageCount(before);
31658
32338
  const beforeSignature = this.lastMessageSignature(before);
31659
32339
  for (let attempt = 0; attempt < 12; attempt += 1) {
31660
- await new Promise((resolve16) => setTimeout(resolve16, 250));
32340
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
31661
32341
  let state;
31662
32342
  try {
31663
32343
  state = await this.readChat(evaluate);
@@ -31679,7 +32359,7 @@ var ProviderStreamAdapter = class {
31679
32359
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
31680
32360
  return first;
31681
32361
  }
31682
- await new Promise((resolve16) => setTimeout(resolve16, 150));
32362
+ await new Promise((resolve17) => setTimeout(resolve17, 150));
31683
32363
  const second = await this.readChat(evaluate);
31684
32364
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
31685
32365
  }
@@ -31830,7 +32510,7 @@ var ProviderStreamAdapter = class {
31830
32510
  if (typeof data.error === "string" && data.error.trim()) return false;
31831
32511
  }
31832
32512
  for (let attempt = 0; attempt < 6; attempt += 1) {
31833
- await new Promise((resolve16) => setTimeout(resolve16, 250));
32513
+ await new Promise((resolve17) => setTimeout(resolve17, 250));
31834
32514
  const state = await this.readChat(evaluate);
31835
32515
  const title = this.getStateTitle(state);
31836
32516
  if (this.titlesMatch(title, sessionId)) return true;
@@ -32758,13 +33438,13 @@ var VersionArchive = class {
32758
33438
  }
32759
33439
  };
32760
33440
  async function runCommand(cmd, timeout = 1e4) {
32761
- return new Promise((resolve16) => {
33441
+ return new Promise((resolve17) => {
32762
33442
  exec5(cmd, {
32763
33443
  encoding: "utf-8",
32764
33444
  timeout
32765
33445
  }, (error, stdout) => {
32766
- if (error) return resolve16(null);
32767
- resolve16(stdout.trim());
33446
+ if (error) return resolve17(null);
33447
+ resolve17(stdout.trim());
32768
33448
  });
32769
33449
  });
32770
33450
  }
@@ -34453,7 +35133,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
34453
35133
  return { target, instance, adapter };
34454
35134
  }
34455
35135
  function sleep2(ms) {
34456
- return new Promise((resolve16) => setTimeout(resolve16, ms));
35136
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
34457
35137
  }
34458
35138
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
34459
35139
  const startedAt = Date.now();
@@ -36708,15 +37388,15 @@ var DevServer = class _DevServer {
36708
37388
  this.json(res, 500, { error: e.message });
36709
37389
  }
36710
37390
  });
36711
- return new Promise((resolve16, reject) => {
37391
+ return new Promise((resolve17, reject) => {
36712
37392
  this.server.listen(port, "127.0.0.1", () => {
36713
37393
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
36714
- resolve16();
37394
+ resolve17();
36715
37395
  });
36716
37396
  this.server.on("error", (e) => {
36717
37397
  if (e.code === "EADDRINUSE") {
36718
37398
  this.log(`Port ${port} in use, skipping dev server`);
36719
- resolve16();
37399
+ resolve17();
36720
37400
  } else {
36721
37401
  reject(e);
36722
37402
  }
@@ -36798,20 +37478,20 @@ var DevServer = class _DevServer {
36798
37478
  child.stderr?.on("data", (d) => {
36799
37479
  stderr += d.toString().slice(0, 2e3);
36800
37480
  });
36801
- await new Promise((resolve16) => {
37481
+ await new Promise((resolve17) => {
36802
37482
  const timer = setTimeout(() => {
36803
37483
  child.kill();
36804
- resolve16();
37484
+ resolve17();
36805
37485
  }, 3e3);
36806
37486
  child.on("exit", () => {
36807
37487
  clearTimeout(timer);
36808
- resolve16();
37488
+ resolve17();
36809
37489
  });
36810
37490
  child.stdout?.once("data", () => {
36811
37491
  setTimeout(() => {
36812
37492
  child.kill();
36813
37493
  clearTimeout(timer);
36814
- resolve16();
37494
+ resolve17();
36815
37495
  }, 500);
36816
37496
  });
36817
37497
  });
@@ -37314,14 +37994,14 @@ var DevServer = class _DevServer {
37314
37994
  child.stderr?.on("data", (d) => {
37315
37995
  stderr += d.toString();
37316
37996
  });
37317
- await new Promise((resolve16) => {
37997
+ await new Promise((resolve17) => {
37318
37998
  const timer = setTimeout(() => {
37319
37999
  child.kill();
37320
- resolve16();
38000
+ resolve17();
37321
38001
  }, timeout);
37322
38002
  child.on("exit", () => {
37323
38003
  clearTimeout(timer);
37324
- resolve16();
38004
+ resolve17();
37325
38005
  });
37326
38006
  });
37327
38007
  const elapsed = Date.now() - start;
@@ -37991,14 +38671,14 @@ data: ${JSON.stringify(msg.data)}
37991
38671
  res.end(JSON.stringify(data, null, 2));
37992
38672
  }
37993
38673
  async readBody(req) {
37994
- return new Promise((resolve16) => {
38674
+ return new Promise((resolve17) => {
37995
38675
  let body = "";
37996
38676
  req.on("data", (chunk) => body += chunk);
37997
38677
  req.on("end", () => {
37998
38678
  try {
37999
- resolve16(JSON.parse(body));
38679
+ resolve17(JSON.parse(body));
38000
38680
  } catch {
38001
- resolve16({});
38681
+ resolve17({});
38002
38682
  }
38003
38683
  });
38004
38684
  });
@@ -38541,7 +39221,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS, requiredRe
38541
39221
  const deadline = Date.now() + timeoutMs;
38542
39222
  while (Date.now() < deadline) {
38543
39223
  if (await canConnect(endpoint, requiredRequestTypes)) return;
38544
- await new Promise((resolve16) => setTimeout(resolve16, STARTUP_POLL_MS));
39224
+ await new Promise((resolve17) => setTimeout(resolve17, STARTUP_POLL_MS));
38545
39225
  }
38546
39226
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
38547
39227
  }
@@ -38592,7 +39272,7 @@ function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
38592
39272
 
38593
39273
  // src/installer.ts
38594
39274
  import { exec as exec6 } from "child_process";
38595
- import { promisify as promisify5 } from "util";
39275
+ import { promisify as promisify6 } from "util";
38596
39276
  var EXTENSION_CATALOG = [
38597
39277
  // AI Agent extensions
38598
39278
  {
@@ -38679,7 +39359,7 @@ var EXTENSION_CATALOG = [
38679
39359
  apiKeyName: "OpenAI/Anthropic API key"
38680
39360
  }
38681
39361
  ];
38682
- var execAsync4 = promisify5(exec6);
39362
+ var execAsync4 = promisify6(exec6);
38683
39363
  async function isExtensionInstalled(ide, marketplaceId) {
38684
39364
  if (!ide.cliCommand) return false;
38685
39365
  try {
@@ -38721,10 +39401,10 @@ async function installExtension(ide, extension) {
38721
39401
  const buffer = Buffer.from(await res.arrayBuffer());
38722
39402
  const fs17 = await import("fs");
38723
39403
  fs17.writeFileSync(vsixPath, buffer);
38724
- return new Promise((resolve16) => {
39404
+ return new Promise((resolve17) => {
38725
39405
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
38726
39406
  exec6(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
38727
- resolve16({
39407
+ resolve17({
38728
39408
  extensionId: extension.id,
38729
39409
  marketplaceId: extension.marketplaceId,
38730
39410
  success: !error,
@@ -38737,11 +39417,11 @@ async function installExtension(ide, extension) {
38737
39417
  } catch (e) {
38738
39418
  }
38739
39419
  }
38740
- return new Promise((resolve16) => {
39420
+ return new Promise((resolve17) => {
38741
39421
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
38742
39422
  exec6(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
38743
39423
  if (error) {
38744
- resolve16({
39424
+ resolve17({
38745
39425
  extensionId: extension.id,
38746
39426
  marketplaceId: extension.marketplaceId,
38747
39427
  success: false,
@@ -38749,7 +39429,7 @@ async function installExtension(ide, extension) {
38749
39429
  error: stderr || error.message
38750
39430
  });
38751
39431
  } else {
38752
- resolve16({
39432
+ resolve17({
38753
39433
  extensionId: extension.id,
38754
39434
  marketplaceId: extension.marketplaceId,
38755
39435
  success: true,
@@ -39123,6 +39803,8 @@ export {
39123
39803
  MAX_LEDGER_SLICE_LIMIT,
39124
39804
  MESH_REFINE_CONFIG_LOCATIONS,
39125
39805
  MESH_REFINE_CONFIG_SCHEMA,
39806
+ MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
39807
+ MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
39126
39808
  MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
39127
39809
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
39128
39810
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
@@ -39143,10 +39825,12 @@ export {
39143
39825
  buildChatMessage,
39144
39826
  buildChatMessageSignature,
39145
39827
  buildChatTailDeliverySignature,
39828
+ buildCompactStaleDirectWorkSummary,
39146
39829
  buildCoordinatorSystemPrompt,
39147
39830
  buildMachineInfo,
39148
39831
  buildMeshActiveWork,
39149
39832
  buildMeshActiveWorkSummary,
39833
+ buildMeshAsyncRefineJobs,
39150
39834
  buildMeshHostRequiredFailure,
39151
39835
  buildMeshLedgerReconciliationEvidence,
39152
39836
  buildMeshLedgerReplicaEvidence,
@@ -39255,6 +39939,7 @@ export {
39255
39939
  listWorktrees,
39256
39940
  loadConfig,
39257
39941
  loadMeshRefineConfig,
39942
+ loadMeshWorktreeBootstrapConfig,
39258
39943
  loadState,
39259
39944
  logCommand,
39260
39945
  markSetupComplete,
@@ -39306,6 +39991,7 @@ export {
39306
39991
  resolveWorktreePath,
39307
39992
  runAsyncBatch,
39308
39993
  runGit,
39994
+ runMeshWorktreeBootstrap,
39309
39995
  saveConfig,
39310
39996
  saveState,
39311
39997
  setDebugRuntimeConfig,
@@ -39327,6 +40013,7 @@ export {
39327
40013
  updateTaskStatus,
39328
40014
  upsertSavedProviderSession,
39329
40015
  validateMeshRefineConfig,
39330
- validateMeshTaskModeRequest
40016
+ validateMeshTaskModeRequest,
40017
+ validateMeshWorktreeBootstrapConfig
39331
40018
  };
39332
40019
  //# sourceMappingURL=index.mjs.map