@adhdev/daemon-core 0.9.82-rc.316 → 0.9.82-rc.317

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
@@ -353,10 +353,10 @@ function readInjected(value) {
353
353
  }
354
354
  function getDaemonBuildInfo() {
355
355
  if (cached) return cached;
356
- const commit = readInjected(true ? "930909642b3f28668483159d3a8f39d0a796c61a" : void 0) ?? "unknown";
357
- const commitShort = readInjected(true ? "93090964" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
358
- const version = readInjected(true ? "0.9.82-rc.316" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
359
- const builtAt = readInjected(true ? "2026-06-18T07:23:07.242Z" : void 0);
356
+ const commit = readInjected(true ? "b4484284652748bf8096f40a00eb5cb463963576" : void 0) ?? "unknown";
357
+ const commitShort = readInjected(true ? "b4484284" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
358
+ const version = readInjected(true ? "0.9.82-rc.317" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
359
+ const builtAt = readInjected(true ? "2026-06-18T08:55:18.955Z" : void 0);
360
360
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
361
361
  return cached;
362
362
  }
@@ -682,14 +682,79 @@ function emptyStatus(workspace, lastCheckedAt, error) {
682
682
  async function getSubmoduleStatuses(repo, options) {
683
683
  if (!repo.repoRoot) return [];
684
684
  try {
685
- const result = await runGit(repo, ["submodule", "status"], options);
686
- const submodules = parseSubmoduleStatusOutput(result.stdout, repo.repoRoot, options.submoduleIgnorePaths);
685
+ const submodules = await deriveSubmoduleGitlinkStatuses(repo, options);
687
686
  await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
688
687
  return submodules;
689
688
  } catch {
690
689
  return [];
691
690
  }
692
691
  }
692
+ async function deriveSubmoduleGitlinkStatuses(repo, options) {
693
+ if (!repo.repoRoot) return [];
694
+ const paths = await readSubmodulePaths(repo, options);
695
+ const ignoreSet = new Set(options.submoduleIgnorePaths || []);
696
+ const lastCheckedAt = Date.now();
697
+ const entries = await Promise.all(
698
+ paths.filter((path41) => !ignoreSet.has(path41)).map(async (path41) => {
699
+ const repoPath = repo.repoRoot + "/" + path41;
700
+ const expected = await readGitlinkExpectedSha(repo, path41, options);
701
+ const actual = await readSubmoduleHeadSha(repo, repoPath, options);
702
+ const outOfSync = actual === null ? true : expected !== null && expected !== actual;
703
+ return {
704
+ path: path41,
705
+ // Prefer the recorded gitlink SHA (matches the legacy column); fall back
706
+ // to the checked-out SHA so the field is never empty when both are known.
707
+ commit: expected ?? actual ?? "",
708
+ repoPath,
709
+ dirty: false,
710
+ outOfSync,
711
+ lastCheckedAt
712
+ };
713
+ })
714
+ );
715
+ return entries;
716
+ }
717
+ async function readSubmodulePaths(repo, options) {
718
+ if (!repo.repoRoot) return [];
719
+ const gitmodulesPath = repo.repoRoot + "/.gitmodules";
720
+ try {
721
+ const result = await runGit(
722
+ repo,
723
+ ["config", "--file", gitmodulesPath, "--get-regexp", "^submodule\\..*\\.path$"],
724
+ options
725
+ );
726
+ const paths = [];
727
+ for (const line of result.stdout.split("\n")) {
728
+ const spaceIdx = line.indexOf(" ");
729
+ if (spaceIdx < 0) continue;
730
+ const value = line.slice(spaceIdx + 1).trim();
731
+ if (value) paths.push(value);
732
+ }
733
+ return paths;
734
+ } catch {
735
+ return [];
736
+ }
737
+ }
738
+ async function readGitlinkExpectedSha(repo, submodulePath, options) {
739
+ try {
740
+ const result = await runGit(repo, ["ls-tree", "HEAD", submodulePath], options);
741
+ const line = result.stdout.split("\n").find((l) => l.trim().length > 0);
742
+ if (!line) return null;
743
+ const match = line.match(/^\s*\d+\s+commit\s+([0-9a-f]{40})\b/);
744
+ return match ? match[1] : null;
745
+ } catch {
746
+ return null;
747
+ }
748
+ }
749
+ async function readSubmoduleHeadSha(repo, repoPath, options) {
750
+ try {
751
+ const result = await runGit(repo, ["rev-parse", "HEAD"], { ...options, cwd: repoPath });
752
+ const sha = result.stdout.trim();
753
+ return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
754
+ } catch {
755
+ return null;
756
+ }
757
+ }
693
758
  async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
694
759
  try {
695
760
  const result = await runGit(repo, ["status", "--porcelain=v2", "--branch"], {
@@ -704,28 +769,6 @@ async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
704
769
  submodule.error = formatGitError(error);
705
770
  }
706
771
  }
707
- function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
708
- const submodules = [];
709
- const ignoreSet = new Set(ignorePaths || []);
710
- for (const line of output.split("\n")) {
711
- if (!line.trim()) continue;
712
- const match = line.match(/^([\-+U\s])([0-9a-f]{40})\s+(\S+)(?:\s+\(([^)]+)\))?/);
713
- if (!match) continue;
714
- const prefix = match[1];
715
- const commit = match[2];
716
- const path41 = match[3];
717
- if (ignoreSet.has(path41)) continue;
718
- submodules.push({
719
- path: path41,
720
- commit,
721
- repoPath: repoRoot + "/" + path41,
722
- dirty: prefix === "U",
723
- outOfSync: prefix === "-" || prefix === "+",
724
- lastCheckedAt: Date.now()
725
- });
726
- }
727
- return submodules;
728
- }
729
772
  var lastKnownGoodStatus, DAEMON_RUNTIME_PACKAGES, WEB_ONLY_PACKAGES;
730
773
  var init_git_status = __esm({
731
774
  "src/git/git-status.ts"() {
@@ -3955,6 +3998,18 @@ var init_mesh_runtime_store = __esm({
3955
3998
  `).get(meshId, nodeId);
3956
3999
  return row?.count ?? 0;
3957
4000
  }
4001
+ /**
4002
+ * O(1) count of queue tasks in 'pending' status for a mesh. A COUNT(*) over the
4003
+ * indexed status column, so it avoids JSON.parse-ing every queue row — used as a
4004
+ * cheap guard before the reconcile loop runs a full triggerMeshQueue scan.
4005
+ */
4006
+ pendingQueueTaskCount(meshId) {
4007
+ const row = this.db.prepare(`
4008
+ SELECT COUNT(*) as count FROM mesh_queue
4009
+ WHERE mesh_id = ? AND status = 'pending'
4010
+ `).get(meshId);
4011
+ return row?.count ?? 0;
4012
+ }
3958
4013
  /**
3959
4014
  * Read the current per-mesh round-robin cursor (0 when unset). Used to rotate
3960
4015
  * the tie-break winner among nodes tied at the least load.
@@ -8888,7 +8943,7 @@ async function triggerMeshQueue(components, meshId) {
8888
8943
  }
8889
8944
  const remoteCandidates = [];
8890
8945
  for (const idle of remoteSessions) {
8891
- const node = mesh.nodes.find((n) => n.id === idle.nodeId);
8946
+ const node = mesh.nodes.find((n) => meshNodeIdMatches(n, idle.nodeId));
8892
8947
  if (node) {
8893
8948
  remoteIdleSessionsChecked += 1;
8894
8949
  remoteCandidates.push({ nodeId: idle.nodeId, sessionId: idle.sessionId, providerType: idle.providerType, origin: "remote", node });
@@ -9692,6 +9747,21 @@ async function runMeshReconcileTick(components) {
9692
9747
  }
9693
9748
  }
9694
9749
  }
9750
+ for (const mesh of listMeshes()) {
9751
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
9752
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
9753
+ if (store) {
9754
+ try {
9755
+ if (store.pendingQueueTaskCount(mesh.id) === 0) continue;
9756
+ } catch {
9757
+ }
9758
+ }
9759
+ try {
9760
+ await triggerMeshQueue(components, mesh.id);
9761
+ } catch (e) {
9762
+ LOG.warn("MeshReconcile", `Pending-claim recovery trigger failed for mesh ${mesh.id}: ${e?.message || e}`);
9763
+ }
9764
+ }
9695
9765
  const coordinators = findLiveCoordinators(components);
9696
9766
  if (coordinators.length === 0) {
9697
9767
  return;
@@ -43297,7 +43367,15 @@ var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
43297
43367
  function readMeshConnectionState(connection) {
43298
43368
  return readStringValue(connection?.state);
43299
43369
  }
43370
+ function isMeshConnectionDefinitivelyDown(connection) {
43371
+ if (!connection) return true;
43372
+ const state = readMeshConnectionState(connection);
43373
+ return state === "failed" || state === "closed" || state === "disconnected";
43374
+ }
43300
43375
  async function probeRemoteMeshGitStatusWithRetry(args) {
43376
+ if (args.getConnection && isMeshConnectionDefinitivelyDown(args.getConnection(args.daemonId))) {
43377
+ return null;
43378
+ }
43301
43379
  for (let attempt = 0; attempt <= MESH_DIRECT_PROBE_MAX_RETRIES; attempt += 1) {
43302
43380
  if (attempt > 0) {
43303
43381
  const connection = args.getConnection?.(args.daemonId);