@adhdev/daemon-core 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.mjs CHANGED
@@ -437,10 +437,10 @@ function readInjected(value) {
437
437
  }
438
438
  function getDaemonBuildInfo() {
439
439
  if (cached) return cached;
440
- const commit = readInjected(true ? "ebf45e12869e32286272a11046f70914784f3f04" : void 0) ?? "unknown";
441
- const commitShort = readInjected(true ? "ebf45e12" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
- const version = readInjected(true ? "1.0.18-rc.8" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
- const builtAt = readInjected(true ? "2026-07-22T04:22:40.678Z" : void 0);
440
+ const commit = readInjected(true ? "3a1a0d16c0dd7ce3df15591fbe30b7e8638ab876" : void 0) ?? "unknown";
441
+ const commitShort = readInjected(true ? "3a1a0d16" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
+ const version = readInjected(true ? "1.0.18-rc.9" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
+ const builtAt = readInjected(true ? "2026-07-22T05:27:14.328Z" : void 0);
444
444
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
445
445
  return cached;
446
446
  }
@@ -16642,6 +16642,33 @@ function isTargetNodeTransientlyUnresolved(mesh, task) {
16642
16642
  }
16643
16643
  return isWithinCloneBootstrapGrace(targetNodeId);
16644
16644
  }
16645
+ function resolveDeadTargetVerdict(components, meshId, mesh, task) {
16646
+ const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
16647
+ const targetSessionId = readNonEmptyString(task.targetSessionId);
16648
+ const targetNodeId = readNonEmptyString(task.targetNodeId);
16649
+ if (!targetSessionId && !targetNodeId) return NOT_DEAD;
16650
+ const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
16651
+ if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
16652
+ const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
16653
+ if (targetNodeId) {
16654
+ const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
16655
+ if (!nodePresent) {
16656
+ if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
16657
+ return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
16658
+ }
16659
+ }
16660
+ if (targetSessionId) {
16661
+ const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
16662
+ const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
16663
+ if (nodeIsLocal) {
16664
+ const verdict = resolveSessionBusyVerdict(components, targetSessionId);
16665
+ if (verdict === "UNKNOWN") {
16666
+ return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
16667
+ }
16668
+ }
16669
+ }
16670
+ return NOT_DEAD;
16671
+ }
16645
16672
  function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
16646
16673
  const dedupKey = `${meshId}:${taskId}`;
16647
16674
  if (!lastActionableSkipNotified.delete(dedupKey)) return;
@@ -17159,6 +17186,21 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
17159
17186
  continue;
17160
17187
  }
17161
17188
  if (task.targetSessionId) {
17189
+ const deadTarget = resolveDeadTargetVerdict(components, meshId, mesh, task);
17190
+ if (deadTarget.dead) {
17191
+ const requeued = requeueTask(meshId, task.id, {
17192
+ reason: deadTarget.reason,
17193
+ clearTargetSession: true,
17194
+ // Keep the node pin if only the SESSION died on a still-live node; clear it
17195
+ // when the NODE itself is absent (nothing to pin to).
17196
+ clearTargetNode: deadTarget.nodeDead
17197
+ });
17198
+ if (requeued) {
17199
+ LOG.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}).`);
17200
+ }
17201
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_dead_requeued" });
17202
+ continue;
17203
+ }
17162
17204
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
17163
17205
  continue;
17164
17206
  }
@@ -17730,7 +17772,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
17730
17772
  });
17731
17773
  });
17732
17774
  }
17733
- var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS, continuousAutoFastForwardLastScan, autoFastForwardWorkspaceLease, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
17775
+ var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS, continuousAutoFastForwardLastScan, autoFastForwardWorkspaceLease, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified, DEAD_TARGET_GRACE_MS;
17734
17776
  var init_mesh_queue_assignment = __esm({
17735
17777
  "src/mesh/mesh-queue-assignment.ts"() {
17736
17778
  "use strict";
@@ -17791,6 +17833,7 @@ var init_mesh_queue_assignment = __esm({
17791
17833
  ];
17792
17834
  TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
17793
17835
  lastActionableSkipNotified = /* @__PURE__ */ new Map();
17836
+ DEAD_TARGET_GRACE_MS = 6e4;
17794
17837
  }
17795
17838
  });
17796
17839
 
@@ -42968,6 +43011,40 @@ async function stopOwnedProcessesForPrefixes(options) {
42968
43011
  var POINTER_NAME = ".adhdev-current";
42969
43012
  var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
42970
43013
  var DEFAULT_HEALTH_PORT = 19222;
43014
+ function fetchLocalJson(port, pathname) {
43015
+ return new Promise((resolve27) => {
43016
+ const req = http2.get(`http://127.0.0.1:${port}${pathname}`, { timeout: 1500 }, (res) => {
43017
+ let body = "";
43018
+ res.setEncoding("utf8");
43019
+ res.on("data", (chunk) => {
43020
+ body += chunk;
43021
+ });
43022
+ res.on("end", () => resolve27({ ok: res.statusCode === 200, body }));
43023
+ });
43024
+ req.on("timeout", () => req.destroy());
43025
+ req.on("error", () => resolve27({ ok: false, body: "" }));
43026
+ });
43027
+ }
43028
+ async function fetchLocalHealth(port) {
43029
+ const { ok, body } = await fetchLocalJson(port, "/health");
43030
+ if (!ok) return { ok: false };
43031
+ try {
43032
+ const pid = Number(JSON.parse(body)?.pid);
43033
+ return { ok: true, pid: Number.isFinite(pid) ? pid : void 0 };
43034
+ } catch {
43035
+ return { ok: false };
43036
+ }
43037
+ }
43038
+ async function fetchLocalStatusVersion(port) {
43039
+ const { ok, body } = await fetchLocalJson(port, "/api/v1/status");
43040
+ if (!ok) return void 0;
43041
+ try {
43042
+ const version = JSON.parse(body)?.status?.version;
43043
+ return typeof version === "string" ? version : void 0;
43044
+ } catch {
43045
+ return void 0;
43046
+ }
43047
+ }
42971
43048
  var ADHDEV_OWNED_MARKERS = [
42972
43049
  "session-host-daemon",
42973
43050
  "node_modules/adhdev",
@@ -43245,6 +43322,8 @@ async function performWindowsAtomicUpgrade(options) {
43245
43322
  }
43246
43323
  }
43247
43324
  function createDefaultWindowsAtomicHooks(options) {
43325
+ const healthPort = options.healthPort ?? DEFAULT_HEALTH_PORT;
43326
+ const healthTimeoutMs = options.healthTimeoutMs ?? 3e4;
43248
43327
  return {
43249
43328
  install: (stagedPrefix, portableNode) => {
43250
43329
  const env = {
@@ -43255,7 +43334,7 @@ function createDefaultWindowsAtomicHooks(options) {
43255
43334
  };
43256
43335
  const pathKey = Object.keys(env).find((key2) => key2.toLowerCase() === "path") || "Path";
43257
43336
  env[pathKey] = `${path20.dirname(portableNode)};${env[pathKey] || ""}`;
43258
- execFileSync4(portableNode, [
43337
+ const installOutput = String(execFileSync4(portableNode, [
43259
43338
  options.npmCliPath,
43260
43339
  "install",
43261
43340
  "-g",
@@ -43270,7 +43349,8 @@ function createDefaultWindowsAtomicHooks(options) {
43270
43349
  maxBuffer: 20 * 1024 * 1024,
43271
43350
  windowsHide: true,
43272
43351
  env
43273
- });
43352
+ }));
43353
+ if (installOutput.trim()) options.log(installOutput.trim());
43274
43354
  },
43275
43355
  restart: (portableNode, stagedCliEntry) => {
43276
43356
  const restartArgv = options.restartArgv.map((arg, index) => index === 0 ? stagedCliEntry : arg);
@@ -43297,28 +43377,12 @@ function createDefaultWindowsAtomicHooks(options) {
43297
43377
  child.unref();
43298
43378
  },
43299
43379
  waitForHealth: async (pid, targetVersion) => {
43300
- const deadline = Date.now() + 3e4;
43380
+ const deadline = Date.now() + healthTimeoutMs;
43301
43381
  while (Date.now() < deadline) {
43302
- const result = await new Promise((resolve27) => {
43303
- const req = http2.get(`http://127.0.0.1:${DEFAULT_HEALTH_PORT}/health`, { timeout: 1500 }, (res) => {
43304
- let body = "";
43305
- res.setEncoding("utf8");
43306
- res.on("data", (chunk) => {
43307
- body += chunk;
43308
- });
43309
- res.on("end", () => {
43310
- let responsePid;
43311
- try {
43312
- responsePid = Number(JSON.parse(body)?.pid);
43313
- } catch {
43314
- }
43315
- resolve27({ ok: res.statusCode === 200, pid: responsePid, body });
43316
- });
43317
- });
43318
- req.on("timeout", () => req.destroy());
43319
- req.on("error", () => resolve27({ ok: false }));
43320
- });
43321
- if (result.ok && result.pid === pid && result.body?.includes(targetVersion)) return true;
43382
+ const liveness = await fetchLocalHealth(healthPort);
43383
+ const alive = liveness.ok && liveness.pid === pid;
43384
+ const version = alive ? await fetchLocalStatusVersion(healthPort) : void 0;
43385
+ if (alive && version === targetVersion) return true;
43322
43386
  await new Promise((resolve27) => setTimeout(resolve27, 500));
43323
43387
  }
43324
43388
  return false;
@@ -43747,22 +43811,31 @@ async function runDaemonUpgradeHelper(payload) {
43747
43811
  `Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
43748
43812
  );
43749
43813
  }
43750
- await performWindowsAtomicUpgrade({
43751
- layout: windowsInstallerLayout,
43752
- packageName: payload.packageName,
43753
- targetVersion: payload.targetVersion,
43754
- portableNode,
43755
- excludePids: upgradePids,
43756
- hooks: createDefaultWindowsAtomicHooks({
43814
+ try {
43815
+ await performWindowsAtomicUpgrade({
43816
+ layout: windowsInstallerLayout,
43757
43817
  packageName: payload.packageName,
43758
43818
  targetVersion: payload.targetVersion,
43759
- npmCliPath,
43760
- restartArgv,
43761
- cwd: payload.cwd || process.cwd(),
43762
- env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
43763
- log: appendUpgradeLog
43764
- })
43765
- });
43819
+ portableNode,
43820
+ excludePids: upgradePids,
43821
+ hooks: createDefaultWindowsAtomicHooks({
43822
+ packageName: payload.packageName,
43823
+ targetVersion: payload.targetVersion,
43824
+ npmCliPath,
43825
+ restartArgv,
43826
+ cwd: payload.cwd || process.cwd(),
43827
+ env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
43828
+ log: appendUpgradeLog
43829
+ })
43830
+ });
43831
+ } catch (error) {
43832
+ emitUpgradeFailureNotice([
43833
+ `adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error?.message || String(error)}`,
43834
+ `Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
43835
+ "See daemon-upgrade.log for the full install/health trace. The next daemon start will retry."
43836
+ ]);
43837
+ throw error;
43838
+ }
43766
43839
  try {
43767
43840
  fs15.unlinkSync(getUpgradeFailureNoticePath());
43768
43841
  } catch {