@adhdev/daemon-core 0.9.82-rc.315 → 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.mjs CHANGED
@@ -35,6 +35,35 @@ function resolveNodeSchedulingPriority(nodePolicy) {
35
35
  const raw = Number(nodePolicy?.schedulingPriority);
36
36
  return Number.isFinite(raw) ? raw : 0;
37
37
  }
38
+ function resolveTaskAffinityRole(taskMode, policy) {
39
+ if (!taskMode) return null;
40
+ if (policy?.enabled === false) return null;
41
+ const override = policy?.byTaskMode && Object.prototype.hasOwnProperty.call(policy.byTaskMode, taskMode) ? policy.byTaskMode[taskMode] : void 0;
42
+ if (typeof override === "string") {
43
+ const trimmed = override.trim().toLowerCase();
44
+ return trimmed ? trimmed : null;
45
+ }
46
+ const fallback = DEFAULT_TASKMODE_ROLE_MAP[taskMode];
47
+ return fallback ?? null;
48
+ }
49
+ function resolveMeshRoleOptions(policy) {
50
+ const out = [...STANDARD_MESH_ROLES];
51
+ const seen = new Set(out);
52
+ const add = (raw) => {
53
+ if (typeof raw !== "string") return;
54
+ const role = raw.trim().toLowerCase();
55
+ if (!role || seen.has(role)) return;
56
+ seen.add(role);
57
+ out.push(role);
58
+ };
59
+ if (policy?.byTaskMode) {
60
+ for (const value of Object.values(policy.byTaskMode)) add(value);
61
+ }
62
+ if (Array.isArray(policy?.customRoles)) {
63
+ for (const value of policy.customRoles) add(value);
64
+ }
65
+ return out;
66
+ }
38
67
  function resolveAutoConvergeCodeChange(policy) {
39
68
  return policy?.autoConvergeCodeChange === true;
40
69
  }
@@ -65,7 +94,7 @@ function resolveProviderMaxParallel(nodePolicy, providerType) {
65
94
  if (!Number.isFinite(raw) || raw < 0) return void 0;
66
95
  return Math.floor(raw);
67
96
  }
68
- var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, DEFAULT_MESH_POLICY;
97
+ var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, STANDARD_MESH_ROLES, DEFAULT_TASKMODE_ROLE_MAP, DEFAULT_MESH_POLICY;
69
98
  var init_repo_mesh_types = __esm({
70
99
  "src/repo-mesh-types.ts"() {
71
100
  "use strict";
@@ -78,6 +107,14 @@ var init_repo_mesh_types = __esm({
78
107
  DEFAULT_MESH_SCHEDULING_STRATEGY = "first_eligible";
79
108
  MESH_CONVERGE_REFINE_TAG = "converge=refine";
80
109
  MESH_CONVERGE_FAST_FORWARD_TAG = "converge=fast_forward";
110
+ STANDARD_MESH_ROLES = ["investigator", "coder", "validator", "converger"];
111
+ DEFAULT_TASKMODE_ROLE_MAP = {
112
+ live_debug_readonly: "investigator",
113
+ code_change: "coder",
114
+ launch_app: "coder",
115
+ validation: "validator",
116
+ convergence: "converger"
117
+ };
81
118
  DEFAULT_MESH_POLICY = {
82
119
  requirePreTaskCheckpoint: false,
83
120
  requirePostTaskCheckpoint: true,
@@ -311,10 +348,10 @@ function readInjected(value) {
311
348
  }
312
349
  function getDaemonBuildInfo() {
313
350
  if (cached) return cached;
314
- const commit = readInjected(true ? "e28347641639c9d0a1e46a6141e3cfed2bc90ac2" : void 0) ?? "unknown";
315
- const commitShort = readInjected(true ? "e2834764" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
- const version = readInjected(true ? "0.9.82-rc.315" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
- const builtAt = readInjected(true ? "2026-06-18T05:47:44.462Z" : void 0);
351
+ const commit = readInjected(true ? "b4484284652748bf8096f40a00eb5cb463963576" : void 0) ?? "unknown";
352
+ const commitShort = readInjected(true ? "b4484284" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
353
+ const version = readInjected(true ? "0.9.82-rc.317" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
354
+ const builtAt = readInjected(true ? "2026-06-18T08:55:18.955Z" : void 0);
318
355
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
319
356
  return cached;
320
357
  }
@@ -640,14 +677,79 @@ function emptyStatus(workspace, lastCheckedAt, error) {
640
677
  async function getSubmoduleStatuses(repo, options) {
641
678
  if (!repo.repoRoot) return [];
642
679
  try {
643
- const result = await runGit(repo, ["submodule", "status"], options);
644
- const submodules = parseSubmoduleStatusOutput(result.stdout, repo.repoRoot, options.submoduleIgnorePaths);
680
+ const submodules = await deriveSubmoduleGitlinkStatuses(repo, options);
645
681
  await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
646
682
  return submodules;
647
683
  } catch {
648
684
  return [];
649
685
  }
650
686
  }
687
+ async function deriveSubmoduleGitlinkStatuses(repo, options) {
688
+ if (!repo.repoRoot) return [];
689
+ const paths = await readSubmodulePaths(repo, options);
690
+ const ignoreSet = new Set(options.submoduleIgnorePaths || []);
691
+ const lastCheckedAt = Date.now();
692
+ const entries = await Promise.all(
693
+ paths.filter((path41) => !ignoreSet.has(path41)).map(async (path41) => {
694
+ const repoPath = repo.repoRoot + "/" + path41;
695
+ const expected = await readGitlinkExpectedSha(repo, path41, options);
696
+ const actual = await readSubmoduleHeadSha(repo, repoPath, options);
697
+ const outOfSync = actual === null ? true : expected !== null && expected !== actual;
698
+ return {
699
+ path: path41,
700
+ // Prefer the recorded gitlink SHA (matches the legacy column); fall back
701
+ // to the checked-out SHA so the field is never empty when both are known.
702
+ commit: expected ?? actual ?? "",
703
+ repoPath,
704
+ dirty: false,
705
+ outOfSync,
706
+ lastCheckedAt
707
+ };
708
+ })
709
+ );
710
+ return entries;
711
+ }
712
+ async function readSubmodulePaths(repo, options) {
713
+ if (!repo.repoRoot) return [];
714
+ const gitmodulesPath = repo.repoRoot + "/.gitmodules";
715
+ try {
716
+ const result = await runGit(
717
+ repo,
718
+ ["config", "--file", gitmodulesPath, "--get-regexp", "^submodule\\..*\\.path$"],
719
+ options
720
+ );
721
+ const paths = [];
722
+ for (const line of result.stdout.split("\n")) {
723
+ const spaceIdx = line.indexOf(" ");
724
+ if (spaceIdx < 0) continue;
725
+ const value = line.slice(spaceIdx + 1).trim();
726
+ if (value) paths.push(value);
727
+ }
728
+ return paths;
729
+ } catch {
730
+ return [];
731
+ }
732
+ }
733
+ async function readGitlinkExpectedSha(repo, submodulePath, options) {
734
+ try {
735
+ const result = await runGit(repo, ["ls-tree", "HEAD", submodulePath], options);
736
+ const line = result.stdout.split("\n").find((l) => l.trim().length > 0);
737
+ if (!line) return null;
738
+ const match = line.match(/^\s*\d+\s+commit\s+([0-9a-f]{40})\b/);
739
+ return match ? match[1] : null;
740
+ } catch {
741
+ return null;
742
+ }
743
+ }
744
+ async function readSubmoduleHeadSha(repo, repoPath, options) {
745
+ try {
746
+ const result = await runGit(repo, ["rev-parse", "HEAD"], { ...options, cwd: repoPath });
747
+ const sha = result.stdout.trim();
748
+ return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
749
+ } catch {
750
+ return null;
751
+ }
752
+ }
651
753
  async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
652
754
  try {
653
755
  const result = await runGit(repo, ["status", "--porcelain=v2", "--branch"], {
@@ -662,28 +764,6 @@ async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
662
764
  submodule.error = formatGitError(error);
663
765
  }
664
766
  }
665
- function parseSubmoduleStatusOutput(output, repoRoot, ignorePaths) {
666
- const submodules = [];
667
- const ignoreSet = new Set(ignorePaths || []);
668
- for (const line of output.split("\n")) {
669
- if (!line.trim()) continue;
670
- const match = line.match(/^([\-+U\s])([0-9a-f]{40})\s+(\S+)(?:\s+\(([^)]+)\))?/);
671
- if (!match) continue;
672
- const prefix = match[1];
673
- const commit = match[2];
674
- const path41 = match[3];
675
- if (ignoreSet.has(path41)) continue;
676
- submodules.push({
677
- path: path41,
678
- commit,
679
- repoPath: repoRoot + "/" + path41,
680
- dirty: prefix === "U",
681
- outOfSync: prefix === "-" || prefix === "+",
682
- lastCheckedAt: Date.now()
683
- });
684
- }
685
- return submodules;
686
- }
687
767
  var lastKnownGoodStatus, DAEMON_RUNTIME_PACKAGES, WEB_ONLY_PACKAGES;
688
768
  var init_git_status = __esm({
689
769
  "src/git/git-status.ts"() {
@@ -1575,8 +1655,61 @@ function mergeMeshPolicy(base, patch) {
1575
1655
  } else {
1576
1656
  delete policy.autoConvergeCodeChange;
1577
1657
  }
1658
+ const normalizedAffinity = normalizeTaskAffinityPolicy(policy.taskAffinity);
1659
+ if (normalizedAffinity) {
1660
+ policy.taskAffinity = normalizedAffinity;
1661
+ } else {
1662
+ delete policy.taskAffinity;
1663
+ }
1578
1664
  return policy;
1579
1665
  }
1666
+ function normalizeTaskAffinityPolicy(value) {
1667
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
1668
+ const record = value;
1669
+ const out = {};
1670
+ let hasContent = false;
1671
+ if (typeof record.enabled === "boolean") {
1672
+ out.enabled = record.enabled;
1673
+ if (record.enabled === false) hasContent = true;
1674
+ else delete out.enabled;
1675
+ }
1676
+ if (record.byTaskMode && typeof record.byTaskMode === "object" && !Array.isArray(record.byTaskMode)) {
1677
+ const byTaskMode = {};
1678
+ for (const [mode, raw] of Object.entries(record.byTaskMode)) {
1679
+ const modeKey = mode.trim();
1680
+ if (!modeKey) continue;
1681
+ if (typeof raw !== "string") continue;
1682
+ const role = raw.trim().toLowerCase();
1683
+ byTaskMode[modeKey] = role;
1684
+ if (role && !STANDARD_MESH_ROLES.includes(role)) {
1685
+ try {
1686
+ console.warn(`[mesh] task_affinity.byTaskMode.${modeKey}: custom role "${role}" is not a standard mesh role (${STANDARD_MESH_ROLES.join("/")}); routing still applies`);
1687
+ } catch {
1688
+ }
1689
+ }
1690
+ }
1691
+ if (Object.keys(byTaskMode).length > 0) {
1692
+ out.byTaskMode = byTaskMode;
1693
+ hasContent = true;
1694
+ }
1695
+ }
1696
+ if (Array.isArray(record.customRoles)) {
1697
+ const seen = /* @__PURE__ */ new Set();
1698
+ const customRoles = [];
1699
+ for (const raw of record.customRoles) {
1700
+ if (typeof raw !== "string") continue;
1701
+ const role = raw.trim().toLowerCase();
1702
+ if (!role || seen.has(role)) continue;
1703
+ seen.add(role);
1704
+ customRoles.push(role);
1705
+ }
1706
+ if (customRoles.length > 0) {
1707
+ out.customRoles = customRoles;
1708
+ hasContent = true;
1709
+ }
1710
+ }
1711
+ return hasContent ? out : void 0;
1712
+ }
1580
1713
  function normalizeAutoFastForwardPolicy(value) {
1581
1714
  const record = value && typeof value === "object" && !Array.isArray(value) ? value : {};
1582
1715
  const maxBehind = Number(record.maxBehind);
@@ -2867,6 +3000,7 @@ __export(mesh_work_queue_exports, {
2867
3000
  recordTaskAutoLaunch: () => recordTaskAutoLaunch,
2868
3001
  requeueTask: () => requeueTask,
2869
3002
  resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
3003
+ resolveTaskAffinityRequiredTags: () => resolveTaskAffinityRequiredTags,
2870
3004
  updateDirectDispatchStatus: () => updateDirectDispatchStatus,
2871
3005
  updateSessionTaskStatus: () => updateSessionTaskStatus,
2872
3006
  updateTaskStatus: () => updateTaskStatus,
@@ -3006,6 +3140,31 @@ function resolveConvergeRequiredTags(meshId, taskMode, explicitRequiredTags, opt
3006
3140
  if (!optedIn) return explicitRequiredTags;
3007
3141
  return normalizeMeshCapabilityTags([...explicitRequiredTags, MESH_CONVERGE_REFINE_TAG]);
3008
3142
  }
3143
+ function meshHasNodeAdvertisingRole(nodes, role) {
3144
+ if (!Array.isArray(nodes) || nodes.length === 0) return false;
3145
+ const wanted = `role=${role}`;
3146
+ return nodes.some((node) => buildMeshNodeCapabilityTags(node).includes(wanted));
3147
+ }
3148
+ function resolveTaskAffinityRequiredTags(meshId, taskMode, explicitRequiredTags, opts) {
3149
+ if (typeof opts?.targetNodeId === "string" && opts.targetNodeId.trim()) return explicitRequiredTags;
3150
+ if (opts?.callerSpecifiedRequiredTags === true) return explicitRequiredTags;
3151
+ let mesh;
3152
+ try {
3153
+ mesh = getMesh(meshId);
3154
+ } catch {
3155
+ return explicitRequiredTags;
3156
+ }
3157
+ const role = resolveTaskAffinityRole(taskMode, mesh?.policy?.taskAffinity);
3158
+ if (!role) return explicitRequiredTags;
3159
+ if (!meshHasNodeAdvertisingRole(mesh?.nodes, role)) {
3160
+ try {
3161
+ console.warn(`[mesh] task_affinity: no node advertises role=${role} for taskMode=${taskMode} in mesh ${meshId}; skipping injection (least_loaded fallback)`);
3162
+ } catch {
3163
+ }
3164
+ return explicitRequiredTags;
3165
+ }
3166
+ return normalizeMeshCapabilityTags([...explicitRequiredTags, `role=${role}`]);
3167
+ }
3009
3168
  function withQueueLock(_meshId, fn) {
3010
3169
  return MeshRuntimeStore.getInstance().transaction(fn);
3011
3170
  }
@@ -3056,6 +3215,20 @@ function enqueueTask(meshId, message, opts) {
3056
3215
  throw new Error(`duplicate_task_id: task '${id}' already exists in mesh '${meshId}'`);
3057
3216
  }
3058
3217
  assertNoDependencyCycle(meshId, id, dependsOn);
3218
+ const callerTags = normalizeMeshCapabilityTags(opts?.requiredTags);
3219
+ const callerSpecifiedRequiredTags = callerTags.length > 0;
3220
+ let resolvedRequiredTags = resolveConvergeRequiredTags(
3221
+ meshId,
3222
+ modeValidation.taskMode,
3223
+ callerTags,
3224
+ { targetNodeId: opts?.targetNodeId }
3225
+ );
3226
+ resolvedRequiredTags = resolveTaskAffinityRequiredTags(
3227
+ meshId,
3228
+ modeValidation.taskMode,
3229
+ resolvedRequiredTags,
3230
+ { targetNodeId: opts?.targetNodeId, callerSpecifiedRequiredTags }
3231
+ );
3059
3232
  const entry = {
3060
3233
  id,
3061
3234
  meshId,
@@ -3064,15 +3237,7 @@ function enqueueTask(meshId, message, opts) {
3064
3237
  taskMode: modeValidation.taskMode,
3065
3238
  targetNodeId: opts?.targetNodeId,
3066
3239
  targetSessionId: opts?.targetSessionId,
3067
- // Convergence routing (opt-in): auto-inject converge=refine for code_change
3068
- // tasks so they hard-filter onto refine-capable worktree nodes. No-op unless
3069
- // the mesh opts in; explicit target_node_id / required_tags are preserved.
3070
- requiredTags: resolveConvergeRequiredTags(
3071
- meshId,
3072
- modeValidation.taskMode,
3073
- normalizeMeshCapabilityTags(opts?.requiredTags),
3074
- { targetNodeId: opts?.targetNodeId }
3075
- ),
3240
+ requiredTags: resolvedRequiredTags,
3076
3241
  ...dependsOn.length > 0 ? { dependsOn } : {},
3077
3242
  ...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
3078
3243
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -3827,6 +3992,18 @@ var init_mesh_runtime_store = __esm({
3827
3992
  `).get(meshId, nodeId);
3828
3993
  return row?.count ?? 0;
3829
3994
  }
3995
+ /**
3996
+ * O(1) count of queue tasks in 'pending' status for a mesh. A COUNT(*) over the
3997
+ * indexed status column, so it avoids JSON.parse-ing every queue row — used as a
3998
+ * cheap guard before the reconcile loop runs a full triggerMeshQueue scan.
3999
+ */
4000
+ pendingQueueTaskCount(meshId) {
4001
+ const row = this.db.prepare(`
4002
+ SELECT COUNT(*) as count FROM mesh_queue
4003
+ WHERE mesh_id = ? AND status = 'pending'
4004
+ `).get(meshId);
4005
+ return row?.count ?? 0;
4006
+ }
3830
4007
  /**
3831
4008
  * Read the current per-mesh round-robin cursor (0 when unset). Used to rotate
3832
4009
  * the tie-break winner among nodes tied at the least load.
@@ -8760,7 +8937,7 @@ async function triggerMeshQueue(components, meshId) {
8760
8937
  }
8761
8938
  const remoteCandidates = [];
8762
8939
  for (const idle of remoteSessions) {
8763
- const node = mesh.nodes.find((n) => n.id === idle.nodeId);
8940
+ const node = mesh.nodes.find((n) => meshNodeIdMatches(n, idle.nodeId));
8764
8941
  if (node) {
8765
8942
  remoteIdleSessionsChecked += 1;
8766
8943
  remoteCandidates.push({ nodeId: idle.nodeId, sessionId: idle.sessionId, providerType: idle.providerType, origin: "remote", node });
@@ -9563,6 +9740,21 @@ async function runMeshReconcileTick(components) {
9563
9740
  }
9564
9741
  }
9565
9742
  }
9743
+ for (const mesh of listMeshes()) {
9744
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
9745
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
9746
+ if (store) {
9747
+ try {
9748
+ if (store.pendingQueueTaskCount(mesh.id) === 0) continue;
9749
+ } catch {
9750
+ }
9751
+ }
9752
+ try {
9753
+ await triggerMeshQueue(components, mesh.id);
9754
+ } catch (e) {
9755
+ LOG.warn("MeshReconcile", `Pending-claim recovery trigger failed for mesh ${mesh.id}: ${e?.message || e}`);
9756
+ }
9757
+ }
9566
9758
  const coordinators = findLiveCoordinators(components);
9567
9759
  if (coordinators.length === 0) {
9568
9760
  return;
@@ -10959,8 +11151,24 @@ function findBinary(name) {
10959
11151
  }
10960
11152
  const isWin = os12.platform() === "win32";
10961
11153
  const paths = (process.env.PATH || "").split(path17.delimiter);
11154
+ const extraDirs = [];
11155
+ if (isWin) {
11156
+ if (process.env.APPDATA) extraDirs.push(path17.join(process.env.APPDATA, "npm"));
11157
+ try {
11158
+ extraDirs.push(path17.dirname(process.execPath));
11159
+ } catch {
11160
+ }
11161
+ } else {
11162
+ extraDirs.push(path17.join(os12.homedir(), ".npm-global", "bin"));
11163
+ extraDirs.push("/usr/local/bin", "/opt/homebrew/bin");
11164
+ try {
11165
+ extraDirs.push(path17.dirname(process.execPath));
11166
+ } catch {
11167
+ }
11168
+ }
11169
+ const searchDirs = [...paths, ...extraDirs];
10962
11170
  const exes = isWin ? [".exe", ".cmd", ".bat", ""] : [""];
10963
- for (const p of paths) {
11171
+ for (const p of searchDirs) {
10964
11172
  if (!p) continue;
10965
11173
  for (const ext of exes) {
10966
11174
  const fullPath = path17.join(p, trimmed + ext);
@@ -14357,6 +14565,37 @@ ${lastSnapshot}`;
14357
14565
  if (!this.ptyProcess || typeof this.ptyProcess.getMetadata !== "function") return null;
14358
14566
  return this.ptyProcess.getMetadata();
14359
14567
  }
14568
+ /**
14569
+ * Launch metadata for the dashboard Session info panel. Re-derives the spawn plan
14570
+ * (pure — same inputs the live PTY was spawned with) so the dashboard sees the
14571
+ * resolved binary, full arg vector, and cwd without us having to persist it.
14572
+ * extraEnv values are intentionally dropped (keys only) so secrets passed at
14573
+ * launch time never reach the dashboard.
14574
+ */
14575
+ getLaunchInfo() {
14576
+ let command;
14577
+ let args = [...this.extraArgs];
14578
+ try {
14579
+ const plan = resolveCliSpawnPlan({
14580
+ provider: this.provider,
14581
+ runtimeSettings: this.runtimeSettings,
14582
+ workingDir: this.workingDir,
14583
+ extraArgs: this.extraArgs,
14584
+ extraEnv: this.extraEnv
14585
+ });
14586
+ command = plan.binaryPath;
14587
+ args = plan.allArgs;
14588
+ } catch {
14589
+ }
14590
+ return {
14591
+ command,
14592
+ args,
14593
+ extraArgs: [...this.extraArgs],
14594
+ cwd: this.workingDir,
14595
+ extraEnvKeys: Object.keys(this.extraEnv || {}),
14596
+ providerSessionId: this.providerSessionId || void 0
14597
+ };
14598
+ }
14360
14599
  updateRuntimeMeta(meta, replace = false) {
14361
14600
  const nextProviderSessionId = typeof meta?.providerSessionId === "string" ? meta.providerSessionId.trim() : "";
14362
14601
  if (nextProviderSessionId) {
@@ -18588,8 +18827,8 @@ async function detectIDEs(providerLoader) {
18588
18827
  if (existsSync16(bundledCli)) resolvedCli = bundledCli;
18589
18828
  }
18590
18829
  if (!resolvedCli && appPath && os30 === "win32") {
18591
- const { dirname: dirname14 } = await import("path");
18592
- const appDir = dirname14(appPath);
18830
+ const { dirname: dirname15 } = await import("path");
18831
+ const appDir = dirname15(appPath);
18593
18832
  const candidates = [
18594
18833
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
18595
18834
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -41197,7 +41436,7 @@ init_mesh_refine_status();
41197
41436
 
41198
41437
  // src/mesh/mesh-init.ts
41199
41438
  import { existsSync as existsSync35, mkdirSync as mkdirSync15, writeFileSync as writeFileSync17 } from "fs";
41200
- import { dirname as dirname7, join as join37 } from "path";
41439
+ import { dirname as dirname8, join as join37 } from "path";
41201
41440
  var MESH_INIT_REFINE_CONFIG_PATH = MESH_REFINE_CONFIG_LOCATIONS[0];
41202
41441
  var MESH_INIT_WORKTREE_BOOTSTRAP_CONFIG_PATH = MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS[0];
41203
41442
  var CANDIDATE_STALE_INPUTS = [
@@ -41212,7 +41451,7 @@ var CANDIDATE_STALE_INPUTS = [
41212
41451
  ];
41213
41452
  function writeConfigFile(workspace, relativePath, config) {
41214
41453
  const target = join37(workspace, relativePath);
41215
- mkdirSync15(dirname7(target), { recursive: true });
41454
+ mkdirSync15(dirname8(target), { recursive: true });
41216
41455
  writeFileSync17(target, `${JSON.stringify(config, null, 2)}
41217
41456
  `, "utf-8");
41218
41457
  return target;
@@ -42776,7 +43015,15 @@ var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
42776
43015
  function readMeshConnectionState(connection) {
42777
43016
  return readStringValue(connection?.state);
42778
43017
  }
43018
+ function isMeshConnectionDefinitivelyDown(connection) {
43019
+ if (!connection) return true;
43020
+ const state = readMeshConnectionState(connection);
43021
+ return state === "failed" || state === "closed" || state === "disconnected";
43022
+ }
42779
43023
  async function probeRemoteMeshGitStatusWithRetry(args) {
43024
+ if (args.getConnection && isMeshConnectionDefinitivelyDown(args.getConnection(args.daemonId))) {
43025
+ return null;
43026
+ }
42780
43027
  for (let attempt = 0; attempt <= MESH_DIRECT_PROBE_MAX_RETRIES; attempt += 1) {
42781
43028
  if (attempt > 0) {
42782
43029
  const connection = args.getConnection?.(args.daemonId);
@@ -46757,6 +47004,7 @@ ${hintLines.join("\n")}` : "",
46757
47004
  if (!target && !coord) return { success: false, error: "Session not found", sessionId };
46758
47005
  const adapter = target ? this.deps.cliManager.findAdapter(target.providerType, { instanceKey: sessionId })?.adapter : void 0;
46759
47006
  const runtimeMeta = adapter && typeof adapter.getRuntimeMetadata === "function" ? adapter.getRuntimeMetadata() : void 0;
47007
+ const launchInfo = adapter && typeof adapter.getLaunchInfo === "function" ? adapter.getLaunchInfo() : void 0;
46760
47008
  const providerType = target?.providerType || coord?.cliType || "";
46761
47009
  const providerMetaForSession = providerType ? this.deps.providerLoader.resolve?.(providerType) || this.deps.providerLoader.getMeta(providerType) : void 0;
46762
47010
  return {
@@ -46768,8 +47016,11 @@ ${hintLines.join("\n")}` : "",
46768
47016
  transport: target?.transport,
46769
47017
  workspace: target?.workspace || coord?.workspace,
46770
47018
  spawnedAtMs: target?.spawnedAtMs || coord?.startedAt,
46771
- providerSessionId: target?.providerSessionId,
46772
- runtimeMetadata: runtimeMeta
47019
+ // providerSessionId now comes from the live adapter's launch info
47020
+ // (the registry target never carried it — it was always undefined).
47021
+ providerSessionId: launchInfo?.providerSessionId || target?.providerSessionId,
47022
+ runtimeMetadata: runtimeMeta,
47023
+ launch: launchInfo
46773
47024
  },
46774
47025
  coordinator: coord ? {
46775
47026
  meshId: coord.meshId,
@@ -48610,7 +48861,7 @@ ${ptyResult.output.slice(-2e3)}`);
48610
48861
  };
48611
48862
  }
48612
48863
  const { existsSync: existsSync44, readFileSync: readFileSync35, writeFileSync: writeFileSync23, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
48613
- const { dirname: dirname14 } = await import("path");
48864
+ const { dirname: dirname15 } = await import("path");
48614
48865
  const mcpConfigPath = coordinatorSetup.configPath;
48615
48866
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
48616
48867
  let hermesBaseConfig = null;
@@ -48645,7 +48896,7 @@ ${ptyResult.output.slice(-2e3)}`);
48645
48896
  };
48646
48897
  }
48647
48898
  try {
48648
- mkdirSync21(dirname14(mcpConfigPath), { recursive: true });
48899
+ mkdirSync21(dirname15(mcpConfigPath), { recursive: true });
48649
48900
  } catch (error) {
48650
48901
  const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
48651
48902
  LOG.error("MeshCoordinator", message);
@@ -48655,7 +48906,7 @@ ${ptyResult.output.slice(-2e3)}`);
48655
48906
  const hadExistingMcpConfig = existsSync44(mcpConfigPath);
48656
48907
  let existingMcpConfig = hermesBaseConfig?.config || {};
48657
48908
  if (hermesBaseConfig) {
48658
- copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname14(mcpConfigPath));
48909
+ copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname15(mcpConfigPath));
48659
48910
  }
48660
48911
  if (hadExistingMcpConfig) {
48661
48912
  try {
@@ -48693,7 +48944,7 @@ ${ptyResult.output.slice(-2e3)}`);
48693
48944
  const cliArgs = [];
48694
48945
  const launchEnv = {};
48695
48946
  if (configFormat === "hermes_config_yaml") {
48696
- launchEnv.HERMES_HOME = dirname14(mcpConfigPath);
48947
+ launchEnv.HERMES_HOME = dirname15(mcpConfigPath);
48697
48948
  launchEnv.HERMES_IGNORE_USER_CONFIG = "";
48698
48949
  }
48699
48950
  let autoImportContextFilePath;
@@ -57718,11 +57969,11 @@ init_parse_session();
57718
57969
  // src/providers/sdk/v1/fixture-tooling/replay.ts
57719
57970
  init_provider_cli_shared();
57720
57971
  import { readFileSync as readFileSync33 } from "fs";
57721
- import { dirname as dirname12, resolve as resolve22 } from "path";
57972
+ import { dirname as dirname13, resolve as resolve22 } from "path";
57722
57973
 
57723
57974
  // src/providers/sdk/v1/validators/taint.ts
57724
57975
  import { readFileSync as readFileSync34, existsSync as existsSync43 } from "fs";
57725
- import { resolve as resolve23, dirname as dirname13, join as join44 } from "path";
57976
+ import { resolve as resolve23, dirname as dirname14, join as join44 } from "path";
57726
57977
 
57727
57978
  // src/providers/sdk/v1/validators/index.ts
57728
57979
  init_manifest();
@@ -57827,6 +58078,7 @@ export {
57827
58078
  DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS,
57828
58079
  DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS,
57829
58080
  DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS,
58081
+ DEFAULT_TASKMODE_ROLE_MAP,
57830
58082
  DEV_SERVER_PORT,
57831
58083
  DaemonAgentStreamManager,
57832
58084
  DaemonCdpInitializer,
@@ -57866,6 +58118,7 @@ export {
57866
58118
  RawTerminalAttachment,
57867
58119
  STALE_TERMINAL_REFINE_WINDOW_MS,
57868
58120
  STANDALONE_CDP_SCAN_INTERVAL_MS,
58121
+ STANDARD_MESH_ROLES,
57869
58122
  SessionHostPtyTransportFactory,
57870
58123
  TerminalAdapter,
57871
58124
  TurnSnapshotTracker,
@@ -58099,9 +58352,12 @@ export {
58099
58352
  resolveGitRepository,
58100
58353
  resolveMeshHostStatus,
58101
58354
  resolveMeshRefineValidationPlan,
58355
+ resolveMeshRoleOptions,
58102
58356
  resolveNodeSchedulingPriority,
58103
58357
  resolveSessionHostAppName,
58104
58358
  resolveSessionHostAppNameResolution,
58359
+ resolveTaskAffinityRequiredTags,
58360
+ resolveTaskAffinityRole,
58105
58361
  resolveWorktreePath,
58106
58362
  runAsyncBatch,
58107
58363
  runGit,