@adhdev/daemon-standalone 1.0.18-rc.8 → 1.0.18-rc.9

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.js CHANGED
@@ -30265,10 +30265,10 @@ var require_dist3 = __commonJS({
30265
30265
  }
30266
30266
  function getDaemonBuildInfo() {
30267
30267
  if (cached2) return cached2;
30268
- const commit = readInjected(true ? "ebf45e12869e32286272a11046f70914784f3f04" : void 0) ?? "unknown";
30269
- const commitShort = readInjected(true ? "ebf45e12" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
- const version2 = readInjected(true ? "1.0.18-rc.8" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
- const builtAt = readInjected(true ? "2026-07-22T04:23:14.120Z" : void 0);
30268
+ const commit = readInjected(true ? "3a1a0d16c0dd7ce3df15591fbe30b7e8638ab876" : void 0) ?? "unknown";
30269
+ const commitShort = readInjected(true ? "3a1a0d16" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
+ const version2 = readInjected(true ? "1.0.18-rc.9" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
+ const builtAt = readInjected(true ? "2026-07-22T05:27:46.385Z" : void 0);
30272
30272
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30273
30273
  return cached2;
30274
30274
  }
@@ -46595,6 +46595,33 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
46595
46595
  }
46596
46596
  return isWithinCloneBootstrapGrace(targetNodeId);
46597
46597
  }
46598
+ function resolveDeadTargetVerdict(components, meshId, mesh, task) {
46599
+ const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
46600
+ const targetSessionId = readNonEmptyString(task.targetSessionId);
46601
+ const targetNodeId = readNonEmptyString(task.targetNodeId);
46602
+ if (!targetSessionId && !targetNodeId) return NOT_DEAD;
46603
+ const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
46604
+ if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
46605
+ const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
46606
+ if (targetNodeId) {
46607
+ const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
46608
+ if (!nodePresent) {
46609
+ if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
46610
+ return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
46611
+ }
46612
+ }
46613
+ if (targetSessionId) {
46614
+ const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
46615
+ const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
46616
+ if (nodeIsLocal) {
46617
+ const verdict = resolveSessionBusyVerdict(components, targetSessionId);
46618
+ if (verdict === "UNKNOWN") {
46619
+ return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
46620
+ }
46621
+ }
46622
+ }
46623
+ return NOT_DEAD;
46624
+ }
46598
46625
  function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
46599
46626
  const dedupKey = `${meshId}:${taskId}`;
46600
46627
  if (!lastActionableSkipNotified.delete(dedupKey)) return;
@@ -47112,6 +47139,21 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
47112
47139
  continue;
47113
47140
  }
47114
47141
  if (task.targetSessionId) {
47142
+ const deadTarget = resolveDeadTargetVerdict(components, meshId, mesh, task);
47143
+ if (deadTarget.dead) {
47144
+ const requeued = requeueTask(meshId, task.id, {
47145
+ reason: deadTarget.reason,
47146
+ clearTargetSession: true,
47147
+ // Keep the node pin if only the SESSION died on a still-live node; clear it
47148
+ // when the NODE itself is absent (nothing to pin to).
47149
+ clearTargetNode: deadTarget.nodeDead
47150
+ });
47151
+ if (requeued) {
47152
+ LOG2.warn("MeshQueue", `DEAD-TARGET-SELFHEAL: task ${task.id} (mesh ${meshId}) was pinned to a dead target (${deadTarget.reason}); requeued${deadTarget.nodeDead ? " and unpinned node" : ""} (requeueCount=${requeued.requeueCount ?? "?"}, status=${requeued.status}).`);
47153
+ }
47154
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_dead_requeued" });
47155
+ continue;
47156
+ }
47115
47157
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
47116
47158
  continue;
47117
47159
  }
@@ -47707,6 +47749,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
47707
47749
  var ACTIONABLE_SKIP_REASON_PREFIXES;
47708
47750
  var TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON;
47709
47751
  var lastActionableSkipNotified;
47752
+ var DEAD_TARGET_GRACE_MS;
47710
47753
  var init_mesh_queue_assignment = __esm2({
47711
47754
  "src/mesh/mesh-queue-assignment.ts"() {
47712
47755
  "use strict";
@@ -47768,6 +47811,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
47768
47811
  ];
47769
47812
  TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
47770
47813
  lastActionableSkipNotified = /* @__PURE__ */ new Map();
47814
+ DEAD_TARGET_GRACE_MS = 6e4;
47771
47815
  }
47772
47816
  });
47773
47817
  function readSettings(state) {
@@ -73248,6 +73292,40 @@ ${formatManifestValidationIssues2(validation.issues)}`,
73248
73292
  var POINTER_NAME = ".adhdev-current";
73249
73293
  var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
73250
73294
  var DEFAULT_HEALTH_PORT = 19222;
73295
+ function fetchLocalJson(port, pathname) {
73296
+ return new Promise((resolve27) => {
73297
+ const req = http2.get(`http://127.0.0.1:${port}${pathname}`, { timeout: 1500 }, (res) => {
73298
+ let body = "";
73299
+ res.setEncoding("utf8");
73300
+ res.on("data", (chunk) => {
73301
+ body += chunk;
73302
+ });
73303
+ res.on("end", () => resolve27({ ok: res.statusCode === 200, body }));
73304
+ });
73305
+ req.on("timeout", () => req.destroy());
73306
+ req.on("error", () => resolve27({ ok: false, body: "" }));
73307
+ });
73308
+ }
73309
+ async function fetchLocalHealth(port) {
73310
+ const { ok, body } = await fetchLocalJson(port, "/health");
73311
+ if (!ok) return { ok: false };
73312
+ try {
73313
+ const pid = Number(JSON.parse(body)?.pid);
73314
+ return { ok: true, pid: Number.isFinite(pid) ? pid : void 0 };
73315
+ } catch {
73316
+ return { ok: false };
73317
+ }
73318
+ }
73319
+ async function fetchLocalStatusVersion(port) {
73320
+ const { ok, body } = await fetchLocalJson(port, "/api/v1/status");
73321
+ if (!ok) return void 0;
73322
+ try {
73323
+ const version2 = JSON.parse(body)?.status?.version;
73324
+ return typeof version2 === "string" ? version2 : void 0;
73325
+ } catch {
73326
+ return void 0;
73327
+ }
73328
+ }
73251
73329
  var ADHDEV_OWNED_MARKERS = [
73252
73330
  "session-host-daemon",
73253
73331
  "node_modules/adhdev",
@@ -73525,6 +73603,8 @@ exec "${portableNode}" "${cliEntry}" "$@"
73525
73603
  }
73526
73604
  }
73527
73605
  function createDefaultWindowsAtomicHooks(options) {
73606
+ const healthPort = options.healthPort ?? DEFAULT_HEALTH_PORT;
73607
+ const healthTimeoutMs = options.healthTimeoutMs ?? 3e4;
73528
73608
  return {
73529
73609
  install: (stagedPrefix, portableNode) => {
73530
73610
  const env2 = {
@@ -73535,7 +73615,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
73535
73615
  };
73536
73616
  const pathKey = Object.keys(env2).find((key2) => key2.toLowerCase() === "path") || "Path";
73537
73617
  env2[pathKey] = `${path20.dirname(portableNode)};${env2[pathKey] || ""}`;
73538
- (0, import_child_process6.execFileSync)(portableNode, [
73618
+ const installOutput = String((0, import_child_process6.execFileSync)(portableNode, [
73539
73619
  options.npmCliPath,
73540
73620
  "install",
73541
73621
  "-g",
@@ -73550,7 +73630,8 @@ exec "${portableNode}" "${cliEntry}" "$@"
73550
73630
  maxBuffer: 20 * 1024 * 1024,
73551
73631
  windowsHide: true,
73552
73632
  env: env2
73553
- });
73633
+ }));
73634
+ if (installOutput.trim()) options.log(installOutput.trim());
73554
73635
  },
73555
73636
  restart: (portableNode, stagedCliEntry) => {
73556
73637
  const restartArgv = options.restartArgv.map((arg, index) => index === 0 ? stagedCliEntry : arg);
@@ -73577,28 +73658,12 @@ exec "${portableNode}" "${cliEntry}" "$@"
73577
73658
  child.unref();
73578
73659
  },
73579
73660
  waitForHealth: async (pid, targetVersion) => {
73580
- const deadline = Date.now() + 3e4;
73661
+ const deadline = Date.now() + healthTimeoutMs;
73581
73662
  while (Date.now() < deadline) {
73582
- const result = await new Promise((resolve27) => {
73583
- const req = http2.get(`http://127.0.0.1:${DEFAULT_HEALTH_PORT}/health`, { timeout: 1500 }, (res) => {
73584
- let body = "";
73585
- res.setEncoding("utf8");
73586
- res.on("data", (chunk) => {
73587
- body += chunk;
73588
- });
73589
- res.on("end", () => {
73590
- let responsePid;
73591
- try {
73592
- responsePid = Number(JSON.parse(body)?.pid);
73593
- } catch {
73594
- }
73595
- resolve27({ ok: res.statusCode === 200, pid: responsePid, body });
73596
- });
73597
- });
73598
- req.on("timeout", () => req.destroy());
73599
- req.on("error", () => resolve27({ ok: false }));
73600
- });
73601
- if (result.ok && result.pid === pid && result.body?.includes(targetVersion)) return true;
73663
+ const liveness = await fetchLocalHealth(healthPort);
73664
+ const alive = liveness.ok && liveness.pid === pid;
73665
+ const version2 = alive ? await fetchLocalStatusVersion(healthPort) : void 0;
73666
+ if (alive && version2 === targetVersion) return true;
73602
73667
  await new Promise((resolve27) => setTimeout(resolve27, 500));
73603
73668
  }
73604
73669
  return false;
@@ -74025,22 +74090,31 @@ ${body}
74025
74090
  `Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
74026
74091
  );
74027
74092
  }
74028
- await performWindowsAtomicUpgrade({
74029
- layout: windowsInstallerLayout,
74030
- packageName: payload.packageName,
74031
- targetVersion: payload.targetVersion,
74032
- portableNode,
74033
- excludePids: upgradePids,
74034
- hooks: createDefaultWindowsAtomicHooks({
74093
+ try {
74094
+ await performWindowsAtomicUpgrade({
74095
+ layout: windowsInstallerLayout,
74035
74096
  packageName: payload.packageName,
74036
74097
  targetVersion: payload.targetVersion,
74037
- npmCliPath,
74038
- restartArgv,
74039
- cwd: payload.cwd || process.cwd(),
74040
- env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
74041
- log: appendUpgradeLog
74042
- })
74043
- });
74098
+ portableNode,
74099
+ excludePids: upgradePids,
74100
+ hooks: createDefaultWindowsAtomicHooks({
74101
+ packageName: payload.packageName,
74102
+ targetVersion: payload.targetVersion,
74103
+ npmCliPath,
74104
+ restartArgv,
74105
+ cwd: payload.cwd || process.cwd(),
74106
+ env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
74107
+ log: appendUpgradeLog
74108
+ })
74109
+ });
74110
+ } catch (error48) {
74111
+ emitUpgradeFailureNotice([
74112
+ `adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error48?.message || String(error48)}`,
74113
+ `Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
74114
+ "See daemon-upgrade.log for the full install/health trace. The next daemon start will retry."
74115
+ ]);
74116
+ throw error48;
74117
+ }
74044
74118
  try {
74045
74119
  fs15.unlinkSync(getUpgradeFailureNoticePath());
74046
74120
  } catch {