@adhdev/daemon-standalone 1.0.29-rc.1 → 1.0.29-rc.3

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
@@ -33311,10 +33311,10 @@ var require_dist3 = __commonJS({
33311
33311
  }
33312
33312
  function getDaemonBuildInfo() {
33313
33313
  if (cached2) return cached2;
33314
- const commit = readInjected(true ? "97193d744d40d248ccdc0eb70e8170f4cccdf8a6" : void 0) ?? "unknown";
33315
- const commitShort = readInjected(true ? "97193d74" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33316
- const version2 = readInjected(true ? "1.0.29-rc.1" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33317
- const builtAt = readInjected(true ? "2026-07-31T22:51:04.932Z" : void 0);
33314
+ const commit = readInjected(true ? "8ee046ce7156a829d1038a65cb48221ca9bedb64" : void 0) ?? "unknown";
33315
+ const commitShort = readInjected(true ? "8ee046ce" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33316
+ const version2 = readInjected(true ? "1.0.29-rc.3" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33317
+ const builtAt = readInjected(true ? "2026-08-01T13:27:48.513Z" : void 0);
33318
33318
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
33319
33319
  return cached2;
33320
33320
  }
@@ -36155,20 +36155,40 @@ ${error48.message || ""}`;
36155
36155
  let hostDaemonId = readString3(raw?.hostDaemonId);
36156
36156
  let hostNodeId = readString3(raw?.hostNodeId);
36157
36157
  const hostAddress = readString3(raw?.hostAddress);
36158
+ let hostSynthesized = false;
36159
+ const nodes = Array.isArray(meshRecord?.nodes) ? meshRecord.nodes : [];
36160
+ const nodeDaemonIdOf = (node) => {
36161
+ const record2 = readObject(node);
36162
+ return readString3(record2?.daemonId) ?? readString3(record2?.daemon_id);
36163
+ };
36164
+ if (role === "host" && !hostDaemonId) {
36165
+ const declaredHostNode = nodes.find((n) => normalizeMeshDaemonRole(readObject(n)?.role) === "host");
36166
+ if (declaredHostNode) {
36167
+ const declaredDaemonId = nodeDaemonIdOf(declaredHostNode);
36168
+ if (declaredDaemonId) {
36169
+ hostDaemonId = declaredDaemonId;
36170
+ if (!hostNodeId) hostNodeId = readString3(readObject(declaredHostNode)?.id);
36171
+ }
36172
+ }
36173
+ }
36158
36174
  const localDaemonId = readString3(opts?.localDaemonId);
36159
- if (role === "host" && !hostDaemonId && localDaemonId) {
36175
+ const hasForeignDaemonNode = localDaemonId ? nodes.some((n) => {
36176
+ const nodeDaemonId = nodeDaemonIdOf(n);
36177
+ return nodeDaemonId ? !daemonIdsEquivalent(nodeDaemonId, localDaemonId) : false;
36178
+ }) : false;
36179
+ if (role === "host" && !hostDaemonId && !hostNodeId && localDaemonId && !hasForeignDaemonNode) {
36160
36180
  hostDaemonId = localDaemonId;
36161
- if (!hostNodeId && Array.isArray(meshRecord?.nodes)) {
36162
- const selfNode = meshRecord.nodes.find((n) => {
36163
- const nodeDaemonId = readString3(readObject(n)?.daemonId);
36164
- return nodeDaemonId ? daemonIdsEquivalent(nodeDaemonId, localDaemonId) : false;
36165
- });
36166
- const selfNodeId = readString3(readObject(selfNode)?.id);
36167
- if (selfNodeId) hostNodeId = selfNodeId;
36168
- }
36181
+ hostSynthesized = true;
36182
+ const selfNode = nodes.find((n) => {
36183
+ const nodeDaemonId = nodeDaemonIdOf(n);
36184
+ return nodeDaemonId ? daemonIdsEquivalent(nodeDaemonId, localDaemonId) : false;
36185
+ });
36186
+ const selfNodeId = readString3(readObject(selfNode)?.id);
36187
+ if (selfNodeId) hostNodeId = selfNodeId;
36169
36188
  }
36170
36189
  if (hostDaemonId) normalized.hostDaemonId = hostDaemonId;
36171
36190
  if (hostNodeId) normalized.hostNodeId = hostNodeId;
36191
+ if (hostSynthesized) normalized.hostSynthesized = true;
36172
36192
  if (hostAddress) normalized.hostAddress = hostAddress;
36173
36193
  if (pairing) {
36174
36194
  const status = pairing.status === "pairing" || pairing.status === "paired" || pairing.status === "rejected" || pairing.status === "revoked" ? pairing.status : "not_configured";
@@ -36235,6 +36255,7 @@ ${error48.message || ""}`;
36235
36255
  normalizeRepoIdentity: () => normalizeRepoIdentity,
36236
36256
  removeMagiKindPanel: () => removeMagiKindPanel,
36237
36257
  removeNode: () => removeNode,
36258
+ resolveScopedMeshId: () => resolveScopedMeshId,
36238
36259
  setDifficultyBrains: () => setDifficultyBrains,
36239
36260
  setMagiKindPanel: () => setMagiKindPanel,
36240
36261
  tokenIdForManualPairing: () => tokenIdForManualPairing,
@@ -36265,15 +36286,41 @@ ${error48.message || ""}`;
36265
36286
  }
36266
36287
  function migrateLoadedMeshConfig(config2) {
36267
36288
  let changed = false;
36289
+ if (foldLegacyTopLevelMeshSetting(config2, "magiKindPanels", "mesh_magi_kind_panel_set({ meshId, task_kind, slots })")) changed = true;
36290
+ if (foldLegacyTopLevelMeshSetting(config2, "difficultyBrains", "difficulty_brains_set({ meshId, difficultyBrains })")) changed = true;
36268
36291
  for (const mesh of config2.meshes) {
36269
36292
  if (!mesh || !Array.isArray(mesh.nodes)) continue;
36293
+ const brains = normalizeDifficultyBrainMap(mesh.difficultyBrains);
36294
+ const ownerBrains = Object.keys(brains).length > 0 ? brains : { ...DEFAULT_DIFFICULTY_BRAINS };
36270
36295
  for (const node of mesh.nodes) {
36271
- if (migrateProviderRolesToSlots(node?.policy)) changed = true;
36296
+ if (migrateProviderRolesToSlots(node?.policy, ownerBrains)) changed = true;
36272
36297
  }
36273
36298
  }
36274
36299
  return changed;
36275
36300
  }
36276
- function migrateProviderRolesToSlots(policy) {
36301
+ function foldLegacyTopLevelMeshSetting(config2, key2, rebindHint) {
36302
+ const root = config2;
36303
+ const legacy = root[key2];
36304
+ if (!legacy || typeof legacy !== "object" || Array.isArray(legacy)) {
36305
+ if (key2 in root) {
36306
+ delete root[key2];
36307
+ return true;
36308
+ }
36309
+ return false;
36310
+ }
36311
+ delete root[key2];
36312
+ const entryKeys = Object.keys(legacy);
36313
+ if (config2.meshes.length === 1 && entryKeys.length > 0) {
36314
+ const mesh = config2.meshes[0];
36315
+ mesh[key2] = { ...legacy, ...mesh[key2] ?? {} };
36316
+ } else if (entryKeys.length > 0) {
36317
+ console.warn(
36318
+ `[mesh-config] Dropped legacy top-level ${key2} (keys: ${entryKeys.join(", ")}) \u2014 ${config2.meshes.length} meshes are configured, so the owning mesh cannot be determined. Re-apply it per mesh with ${rebindHint}.`
36319
+ );
36320
+ }
36321
+ return true;
36322
+ }
36323
+ function migrateProviderRolesToSlots(policy, ownerDifficultyBrains) {
36277
36324
  if (!policy || typeof policy !== "object" || Array.isArray(policy)) return false;
36278
36325
  const p = policy;
36279
36326
  const rawRoles = p.providerRoles;
@@ -36296,12 +36343,7 @@ ${error48.message || ""}`;
36296
36343
  }
36297
36344
  p.slots = explicitSlots;
36298
36345
  } else if (roleCap.size) {
36299
- let difficultyBrains;
36300
- try {
36301
- difficultyBrains = getDifficultyBrains();
36302
- } catch {
36303
- difficultyBrains = void 0;
36304
- }
36346
+ const difficultyBrains = ownerDifficultyBrains;
36305
36347
  const priority = Array.isArray(p.providerPriority) ? p.providerPriority.map((t) => typeof t === "string" ? t.trim() : "").filter(Boolean) : [];
36306
36348
  const derived = deriveSlotsFromLegacy({ providerPriority: priority, difficultyBrains });
36307
36349
  const slots = derived.length ? derived : [...roleCap.values()].map((r) => ({ provider: r.provider }));
@@ -36640,6 +36682,7 @@ ${error48.message || ""}`;
36640
36682
  const idx = mesh.nodes.findIndex((n) => n.id === nodeId);
36641
36683
  if (idx === -1) return false;
36642
36684
  mesh.nodes.splice(idx, 1);
36685
+ pruneMagiKindPanelsForRemovedNode(mesh, nodeId);
36643
36686
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
36644
36687
  saveMeshConfig(config2);
36645
36688
  return true;
@@ -36696,7 +36739,8 @@ ${error48.message || ""}`;
36696
36739
  }
36697
36740
  return s2;
36698
36741
  }
36699
- function normalizeMagiSlots(slots) {
36742
+ function normalizeMagiSlots(slots, knownNodeIds) {
36743
+ const allowed = knownNodeIds ? new Set(knownNodeIds) : void 0;
36700
36744
  if (!Array.isArray(slots) || slots.length === 0) {
36701
36745
  throw new Error("invalid_magi_kind_panel: slots must be a non-empty array");
36702
36746
  }
@@ -36713,6 +36757,11 @@ ${error48.message || ""}`;
36713
36757
  throw new Error(`invalid_magi_kind_panel: slot[${idx}].provider is required`);
36714
36758
  }
36715
36759
  const nodeId = typeof s2.nodeId === "string" && s2.nodeId.trim() ? s2.nodeId.trim() : void 0;
36760
+ if (nodeId && allowed && !allowed.has(nodeId)) {
36761
+ throw new Error(
36762
+ `invalid_magi_kind_panel: slot[${idx}].nodeId '${nodeId}' is not a node of this mesh (known: ${[...allowed].join(", ") || "(none)"}). Pin a node from this mesh, or omit nodeId to let the fan-out pick any node offering the provider.`
36763
+ );
36764
+ }
36716
36765
  const model = typeof s2.model === "string" && s2.model.trim() ? s2.model.trim() : void 0;
36717
36766
  const capabilityTags = normalizeCapabilityTags(s2.capabilityTags);
36718
36767
  const n = normalizeReplicaCount(s2.n);
@@ -36725,32 +36774,51 @@ ${error48.message || ""}`;
36725
36774
  };
36726
36775
  });
36727
36776
  }
36728
- function listMagiKindPanels() {
36729
- return loadMeshConfig().magiKindPanels ?? {};
36777
+ function resolveScopedMeshId(config2) {
36778
+ const meshes = (config2 ?? loadMeshConfig({ persistMigrations: false })).meshes;
36779
+ return meshes.length === 1 ? meshes[0].id : void 0;
36780
+ }
36781
+ function resolveScopedMesh(config2, meshId) {
36782
+ const id = meshId?.trim() || resolveScopedMeshId(config2);
36783
+ if (!id) return void 0;
36784
+ return config2.meshes.find((m) => m.id === id);
36785
+ }
36786
+ function listMagiKindPanels(meshId) {
36787
+ const config2 = loadMeshConfig();
36788
+ return resolveScopedMesh(config2, meshId)?.magiKindPanels ?? {};
36730
36789
  }
36731
- function listMagiKindPanelsReadOnly() {
36732
- return loadMeshConfig({ persistMigrations: false }).magiKindPanels ?? {};
36790
+ function listMagiKindPanelsReadOnly(meshId) {
36791
+ const config2 = loadMeshConfig({ persistMigrations: false });
36792
+ return resolveScopedMesh(config2, meshId)?.magiKindPanels ?? {};
36733
36793
  }
36734
- function getMagiKindPanel(kind) {
36794
+ function getMagiKindPanel(kind, meshId) {
36735
36795
  let key2;
36736
36796
  try {
36737
36797
  key2 = normalizeMagiTaskKindKey(kind);
36738
36798
  } catch {
36739
36799
  return void 0;
36740
36800
  }
36741
- return loadMeshConfig().magiKindPanels?.[key2];
36801
+ const config2 = loadMeshConfig();
36802
+ return resolveScopedMesh(config2, meshId)?.magiKindPanels?.[key2];
36742
36803
  }
36743
- function setMagiKindPanel(kind, slots) {
36804
+ function setMagiKindPanel(kind, slots, meshId) {
36744
36805
  const key2 = normalizeMagiTaskKindKey(kind);
36745
- const normalized = normalizeMagiSlots(slots);
36746
36806
  const stored = loadMeshConfig();
36747
- const map3 = stored.magiKindPanels ?? {};
36807
+ const mesh = resolveScopedMesh(stored, meshId);
36808
+ if (!mesh) {
36809
+ throw new Error(
36810
+ meshId?.trim() ? `invalid_magi_kind_panel: mesh '${meshId.trim()}' not found` : `magi_kind_panel_mesh_ambiguous: this machine hosts ${stored.meshes.length} meshes, so a MAGI kind-panel write must name its mesh explicitly (meshId). Panels are per mesh.`
36811
+ );
36812
+ }
36813
+ const normalized = normalizeMagiSlots(slots, mesh.nodes.map((n) => n.id));
36814
+ const map3 = mesh.magiKindPanels ?? {};
36748
36815
  map3[key2] = normalized;
36749
- stored.magiKindPanels = map3;
36816
+ mesh.magiKindPanels = map3;
36817
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
36750
36818
  saveMeshConfig(stored);
36751
36819
  return normalized;
36752
36820
  }
36753
- function removeMagiKindPanel(kind) {
36821
+ function removeMagiKindPanel(kind, meshId) {
36754
36822
  let key2;
36755
36823
  try {
36756
36824
  key2 = normalizeMagiTaskKindKey(kind);
@@ -36758,21 +36826,47 @@ ${error48.message || ""}`;
36758
36826
  return false;
36759
36827
  }
36760
36828
  const stored = loadMeshConfig();
36761
- if (!stored.magiKindPanels || !stored.magiKindPanels[key2]) return false;
36762
- delete stored.magiKindPanels[key2];
36829
+ const mesh = resolveScopedMesh(stored, meshId);
36830
+ if (!mesh?.magiKindPanels?.[key2]) return false;
36831
+ delete mesh.magiKindPanels[key2];
36832
+ if (Object.keys(mesh.magiKindPanels).length === 0) delete mesh.magiKindPanels;
36833
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
36763
36834
  saveMeshConfig(stored);
36764
36835
  return true;
36765
36836
  }
36766
- function getDifficultyBrains() {
36767
- const stored = loadMeshConfig().difficultyBrains;
36837
+ function pruneMagiKindPanelsForRemovedNode(mesh, nodeId) {
36838
+ const panels = mesh.magiKindPanels;
36839
+ if (!panels) return false;
36840
+ let changed = false;
36841
+ for (const [kind, slots] of Object.entries(panels)) {
36842
+ if (!Array.isArray(slots)) continue;
36843
+ const kept = slots.filter((slot) => slot.nodeId !== nodeId);
36844
+ if (kept.length === slots.length) continue;
36845
+ changed = true;
36846
+ if (kept.length === 0) delete panels[kind];
36847
+ else panels[kind] = kept;
36848
+ }
36849
+ if (changed && Object.keys(panels).length === 0) delete mesh.magiKindPanels;
36850
+ return changed;
36851
+ }
36852
+ function getDifficultyBrains(meshId) {
36853
+ const config2 = loadMeshConfig();
36854
+ const stored = resolveScopedMesh(config2, meshId)?.difficultyBrains;
36768
36855
  const normalized = normalizeDifficultyBrainMap(stored);
36769
36856
  return Object.keys(normalized).length > 0 ? normalized : { ...DEFAULT_DIFFICULTY_BRAINS };
36770
36857
  }
36771
- function setDifficultyBrains(map3) {
36858
+ function setDifficultyBrains(map3, meshId) {
36772
36859
  const normalized = normalizeDifficultyBrainMap(map3);
36773
36860
  const stored = loadMeshConfig();
36774
- if (Object.keys(normalized).length > 0) stored.difficultyBrains = normalized;
36775
- else delete stored.difficultyBrains;
36861
+ const mesh = resolveScopedMesh(stored, meshId);
36862
+ if (!mesh) {
36863
+ throw new Error(
36864
+ meshId?.trim() ? `invalid_difficulty_brains: mesh '${meshId.trim()}' not found` : `difficulty_brains_mesh_ambiguous: this machine hosts ${stored.meshes.length} meshes, so a difficulty-brain write must name its mesh explicitly (meshId). Presets are per mesh \u2014 they decide which model a task runs on, so writing to the wrong mesh changes what it costs.`
36865
+ );
36866
+ }
36867
+ if (Object.keys(normalized).length > 0) mesh.difficultyBrains = normalized;
36868
+ else delete mesh.difficultyBrains;
36869
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
36776
36870
  saveMeshConfig(stored);
36777
36871
  return normalized;
36778
36872
  }
@@ -36808,12 +36902,12 @@ ${error48.message || ""}`;
36808
36902
  return true;
36809
36903
  });
36810
36904
  }
36811
- function resolveNodeCapabilitySlots(node) {
36905
+ function resolveNodeCapabilitySlots(node, meshId) {
36812
36906
  const explicit = normalizeNodeCapabilitySlots(node?.policy?.slots);
36813
36907
  if (explicit.length) return explicit;
36814
36908
  let difficultyBrains;
36815
36909
  try {
36816
- difficultyBrains = getDifficultyBrains();
36910
+ difficultyBrains = getDifficultyBrains(meshId);
36817
36911
  } catch {
36818
36912
  difficultyBrains = void 0;
36819
36913
  }
@@ -40828,7 +40922,7 @@ Next step: ${nextStep}`;
40828
40922
  const taskDifficulty = isMeshTaskDifficulty(opts?.difficulty) ? opts.difficulty : void 0;
40829
40923
  if (isMeshTaskDifficulty(opts?.difficulty)) {
40830
40924
  try {
40831
- const preset = getDifficultyBrains()[opts.difficulty];
40925
+ const preset = getDifficultyBrains(meshId)[opts.difficulty];
40832
40926
  if (preset) {
40833
40927
  if (!effectiveModel && preset.model) effectiveModel = preset.model;
40834
40928
  if (!effectiveThinkingLevel && preset.thinkingLevel) effectiveThinkingLevel = preset.thinkingLevel;
@@ -54047,6 +54141,77 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54047
54141
  ]);
54048
54142
  }
54049
54143
  });
54144
+ function normalizeLiteral(model) {
54145
+ return model.toLowerCase().replace(/[_/\\().,]+/g, " ").replace(/-+/g, " ").replace(/\s+/g, " ").trim();
54146
+ }
54147
+ function canonicalizeModelName(model) {
54148
+ if (typeof model !== "string") return void 0;
54149
+ const literal2 = normalizeLiteral(model);
54150
+ if (!literal2) return void 0;
54151
+ const tokens = literal2.split(" ").filter((t) => t && !MODIFIER_WORDS.has(t));
54152
+ const family = CLAUDE_FAMILIES.find((f) => tokens.includes(f));
54153
+ let version2;
54154
+ if (family) {
54155
+ const after = tokens.slice(tokens.indexOf(family) + 1).filter((t) => /^\d+$/.test(t));
54156
+ if (after.length) version2 = after.join(".");
54157
+ else {
54158
+ const dotted = tokens.find((t) => /^\d+(\.\d+)+$/.test(t));
54159
+ if (dotted) version2 = dotted;
54160
+ }
54161
+ }
54162
+ return { family, version: version2, literal: literal2 };
54163
+ }
54164
+ function modelNamesEquivalent(a, b) {
54165
+ const ca = canonicalizeModelName(a);
54166
+ const cb = canonicalizeModelName(b);
54167
+ if (!ca || !cb) return false;
54168
+ if (ca.family && cb.family) {
54169
+ if (ca.family !== cb.family) return false;
54170
+ if (ca.version && cb.version) return ca.version === cb.version;
54171
+ return true;
54172
+ }
54173
+ if (ca.family || cb.family) return false;
54174
+ return ca.literal === cb.literal;
54175
+ }
54176
+ function isModelAllowedBySlot(model, slot) {
54177
+ if (!slot) return true;
54178
+ const declared = typeof slot.model === "string" ? slot.model.trim() : "";
54179
+ const requested = typeof model === "string" ? model.trim() : "";
54180
+ if (!declared) return !requested;
54181
+ if (!requested) return true;
54182
+ return modelNamesEquivalent(requested, declared);
54183
+ }
54184
+ function decideSlotForModel(input) {
54185
+ const { requestedModel, slots } = input;
54186
+ const declaring = slots.filter((s2) => isModelAllowedBySlot(requestedModel, s2.slot));
54187
+ if (!declaring.length) {
54188
+ const declaredModels = slots.map((s2) => typeof s2.slot.model === "string" && s2.slot.model.trim() ? s2.slot.model.trim() : "(provider default)").filter((v, i, a) => a.indexOf(v) === i);
54189
+ return { outcome: "notify", reason: SLOT_MODEL_ABSENT_SKIP_REASON, declaredModels };
54190
+ }
54191
+ const free = declaring.find((s2) => s2.available);
54192
+ if (free) {
54193
+ const declared = typeof free.slot.model === "string" && free.slot.model.trim() ? free.slot.model.trim() : void 0;
54194
+ return { outcome: "run", slot: free.slot, model: declared };
54195
+ }
54196
+ return {
54197
+ outcome: "wait",
54198
+ reason: SLOT_MODEL_BUSY_SKIP_REASON,
54199
+ busySlots: declaring.map((s2) => s2.slot)
54200
+ };
54201
+ }
54202
+ var CLAUDE_FAMILIES;
54203
+ var MODIFIER_WORDS;
54204
+ var SLOT_MODEL_BUSY_SKIP_REASON;
54205
+ var SLOT_MODEL_ABSENT_SKIP_REASON;
54206
+ var init_slot_model_enforcement = __esm2({
54207
+ "src/mesh/slot-model-enforcement.ts"() {
54208
+ "use strict";
54209
+ CLAUDE_FAMILIES = ["opus", "sonnet", "haiku"];
54210
+ MODIFIER_WORDS = /* @__PURE__ */ new Set(["thinking", "latest", "preview", "claude", "anthropic"]);
54211
+ SLOT_MODEL_BUSY_SKIP_REASON = "slot_for_model_busy";
54212
+ SLOT_MODEL_ABSENT_SKIP_REASON = "no_slot_declares_requested_model";
54213
+ }
54214
+ });
54050
54215
  function encodeDuplicateMeshDispatchCode(holderSessionId) {
54051
54216
  const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
54052
54217
  return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
@@ -54395,7 +54560,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54395
54560
  return false;
54396
54561
  }
54397
54562
  const capabilityTags = buildMeshNodeCapabilityTags(node, providerType);
54398
- const providerMaxParallel = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), providerType);
54563
+ const providerMaxParallel = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), providerType);
54399
54564
  const nodeIsWorktree = node?.isLocalWorktree === true;
54400
54565
  const assignedTranscriptProfile = resolveClaimingSessionTranscriptProfile(components, sessionId);
54401
54566
  const task = claimNextTask(meshId, nodeId, sessionId, capabilityTags, {
@@ -54696,6 +54861,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54696
54861
  summary: "the node's workspace is dirty, so auto-launch is blocked to avoid clobbering uncommitted changes",
54697
54862
  nextAction: "Clean or commit the node's working tree (or fast-forward it); the task will then auto-assign."
54698
54863
  };
54864
+ if (reason === SLOT_MODEL_ABSENT_SKIP_REASON) return {
54865
+ summary: "no capability slot on the node declares the model this task resolved to (its difficulty\u2192brain preset picked a model the node was never configured to run)",
54866
+ nextAction: "Re-enqueue with a difficulty/model the node's slots declare, target a node that declares this model, or add a slot for it. The task is NOT run on a substitute model \u2014 an undeclared model is never launched."
54867
+ };
54699
54868
  return {
54700
54869
  summary: `it cannot be dispatched (${reason})`,
54701
54870
  nextAction: "Inspect the node/mesh state with mesh_status and resolve the blocker, or re-enqueue the task."
@@ -54887,8 +55056,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54887
55056
  }
54888
55057
  return score;
54889
55058
  }
54890
- function bestSlotForTask(node, task) {
54891
- const slots = resolveNodeCapabilitySlots(node);
55059
+ function bestSlotForTask(node, task, meshId) {
55060
+ const slots = resolveNodeCapabilitySlots(node, meshId);
54892
55061
  if (!slots.length) return null;
54893
55062
  let best = null;
54894
55063
  for (const slot of slots) {
@@ -54897,8 +55066,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54897
55066
  }
54898
55067
  return best;
54899
55068
  }
54900
- function nodeFitnessForTask(node, task) {
54901
- return bestSlotForTask(node, task)?.score ?? 0;
55069
+ function nodeFitnessForTask(node, task, meshId) {
55070
+ return bestSlotForTask(node, task, meshId)?.score ?? 0;
54902
55071
  }
54903
55072
  function orderEligibleNodes(meshId, strategy, nodes, opts) {
54904
55073
  if (strategy === "first_eligible" || nodes.length <= 1) {
@@ -54907,7 +55076,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54907
55076
  if (strategy === "fitness" && opts?.task) {
54908
55077
  const task = opts.task;
54909
55078
  return [...nodes].sort((a, b) => {
54910
- const fitDelta = nodeFitnessForTask(b.node, task) - nodeFitnessForTask(a.node, task);
55079
+ const fitDelta = nodeFitnessForTask(b.node, task, meshId) - nodeFitnessForTask(a.node, task, meshId);
54911
55080
  if (fitDelta !== 0) return fitDelta;
54912
55081
  const prioDelta = resolveNodeSchedulingPriority(b.node?.policy) - resolveNodeSchedulingPriority(a.node?.policy);
54913
55082
  if (prioDelta !== 0) return prioDelta;
@@ -54936,6 +55105,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
54936
55105
  function activeProviderAssignedCount(meshId, nodeId, providerType) {
54937
55106
  return getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId) && task.assignedProviderType === providerType).length;
54938
55107
  }
55108
+ function slotHasCapacity(meshId, nodeId, node, slot) {
55109
+ const providerType = typeof slot.provider === "string" ? slot.provider.trim() : "";
55110
+ if (!providerType) return false;
55111
+ const cap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), providerType);
55112
+ if (cap === void 0) return true;
55113
+ return activeProviderAssignedCount(meshId, nodeId, providerType) < cap;
55114
+ }
54939
55115
  function sessionHasActiveAssignment(meshId, sessionId) {
54940
55116
  if (getQueue(meshId, { status: ["assigned"] }).some((task) => sessionIdsEquivalent(task.assignedSessionId, sessionId))) {
54941
55117
  return true;
@@ -55073,10 +55249,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55073
55249
  retractActionableSkipIfPreviouslyNotified(meshId, taskId);
55074
55250
  }
55075
55251
  }
55076
- async function resolveUsableProvider(components, nodeId, node, requiredTags, task) {
55252
+ async function resolveUsableProvider(components, nodeId, node, meshId, requiredTags, task) {
55077
55253
  const providerLoader = components.providerLoader;
55078
55254
  if (!providerLoader) return { reason: "provider_loader_unavailable" };
55079
- const slots = resolveNodeCapabilitySlots(node);
55255
+ const slots = resolveNodeCapabilitySlots(node, meshId);
55080
55256
  if (!slots.length) return { reason: "missing_provider_priority" };
55081
55257
  const orderedSlots = task ? [...slots].sort((a, b) => scoreSlotForTask(b, task) - scoreSlotForTask(a, task)) : slots;
55082
55258
  const failed = [];
@@ -55110,7 +55286,12 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55110
55286
  return {
55111
55287
  providerType: normalizedType,
55112
55288
  ...slot.model ? { model: slot.model } : {},
55113
- ...slot.thinkingLevel ? { thinkingLevel: slot.thinkingLevel } : {}
55289
+ ...slot.thinkingLevel ? { thinkingLevel: slot.thinkingLevel } : {},
55290
+ // The slot that won selection. Returned so the caller can enforce
55291
+ // "the launch model must be one this slot declares" — a preset
55292
+ // model must not widen what the operator configured. See
55293
+ // slot-model-enforcement.ts.
55294
+ slot
55114
55295
  };
55115
55296
  }
55116
55297
  failed.push(`${requestedType}: not detected`);
@@ -55247,7 +55428,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55247
55428
  if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
55248
55429
  if (task.taskMode === "convergence" && node?.isLocalWorktree === true) return false;
55249
55430
  if (task.requiredTags?.length) {
55250
- const slotProviders = resolveNodeCapabilitySlots(node).map((s2) => s2.provider).filter(Boolean);
55431
+ const slotProviders = resolveNodeCapabilitySlots(node, meshId).map((s2) => s2.provider).filter(Boolean);
55251
55432
  const priorities = slotProviders.length ? slotProviders : normalizeProviderPriority2(node?.policy);
55252
55433
  const providerCandidates = priorities.length ? priorities : [void 0];
55253
55434
  return providerCandidates.some(
@@ -55336,18 +55517,36 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55336
55517
  }
55337
55518
  autoLaunchInProgress.add(launchKey);
55338
55519
  try {
55339
- const resolved = await resolveUsableProvider(components, nodeId, node, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
55520
+ const resolved = await resolveUsableProvider(components, nodeId, node, meshId, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
55340
55521
  if (!resolved.providerType) {
55341
55522
  markSkip(nodeId, resolved.reason || "provider_unusable");
55342
55523
  continue;
55343
55524
  }
55344
- const rawEffectiveModel = typeof task.model === "string" && task.model.trim() ? task.model.trim() : resolved.model;
55525
+ const requestedModel = typeof task.model === "string" && task.model.trim() ? task.model.trim() : resolved.model;
55345
55526
  const effectiveThinkingLevel = typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? task.thinkingLevel.trim() : resolved.thinkingLevel;
55527
+ const slotDecision = decideSlotForModel({
55528
+ requestedModel,
55529
+ slots: resolveNodeCapabilitySlots(node, meshId).map((slot) => ({
55530
+ slot,
55531
+ available: slotHasCapacity(meshId, nodeId, node, slot)
55532
+ }))
55533
+ });
55534
+ if (slotDecision.outcome === "wait") {
55535
+ LOG2.info("MeshQueue", `SLOT MODEL GUARD: model '${requestedModel}' is declared on node ${nodeId} but every matching slot is at its maxParallel cap (task ${task.id}); leaving the task queued until a slot goes idle`);
55536
+ markSkip(nodeId, slotDecision.reason, { providerType: resolved.providerType });
55537
+ continue;
55538
+ }
55539
+ if (slotDecision.outcome === "notify") {
55540
+ LOG2.warn("MeshQueue", `SLOT MODEL GUARD: no slot on node ${nodeId} declares model '${requestedModel}' (declared: ${slotDecision.declaredModels.join(", ") || "none"}) for task ${task.id}; not launching \u2014 surfacing to the coordinator to re-drive`);
55541
+ markSkip(nodeId, slotDecision.reason, { providerType: resolved.providerType });
55542
+ continue;
55543
+ }
55544
+ const rawEffectiveModel = slotDecision.model;
55346
55545
  const effectiveModel = isModelCompatibleWithProvider(rawEffectiveModel, resolved.providerType) ? rawEffectiveModel : void 0;
55347
55546
  if (rawEffectiveModel && effectiveModel === void 0) {
55348
55547
  LOG2.info("MeshQueue", `CODEX-400 GUARD: dropped incompatible launch model '${rawEffectiveModel}' for non-Anthropic provider '${resolved.providerType}' on node ${nodeId} (task ${task.id}); provider will use its own default model`);
55349
55548
  }
55350
- const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), resolved.providerType);
55549
+ const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node, meshId), resolved.providerType);
55351
55550
  if (providerCap !== void 0 && activeProviderAssignedCount(meshId, nodeId, resolved.providerType) >= providerCap) {
55352
55551
  markSkip(nodeId, "max_provider_parallel_reached", { providerType: resolved.providerType });
55353
55552
  continue;
@@ -55441,7 +55640,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55441
55640
  const requiredTags = Array.isArray(task.requiredTags) ? task.requiredTags.filter((t) => !!t) : [];
55442
55641
  const routingDecision = {
55443
55642
  source: "autoLaunch",
55444
- fitnessScore: nodeFitnessForTask(node, { difficulty: task.difficulty, requiredTags: task.requiredTags }),
55643
+ fitnessScore: nodeFitnessForTask(node, { difficulty: task.difficulty, requiredTags: task.requiredTags }, meshId),
55445
55644
  ...skippedCandidates.length ? { skippedCandidates } : {},
55446
55645
  requiredTagsResult: {
55447
55646
  required: requiredTags,
@@ -55885,6 +56084,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55885
56084
  init_mesh_clone_grace();
55886
56085
  init_mesh_task_inflight();
55887
56086
  init_model_provider_compat();
56087
+ init_slot_model_enforcement();
55888
56088
  init_mesh_turn_ledger();
55889
56089
  init_mesh_duplicate_dispatch();
55890
56090
  IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
@@ -55917,7 +56117,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
55917
56117
  "provider_loader_unavailable",
55918
56118
  "provider_priority_unusable",
55919
56119
  "provider_unusable",
55920
- "dirty_workspace"
56120
+ "dirty_workspace",
56121
+ // SLOT MODEL GUARD (absent): no slot on the node declares the task's model.
56122
+ // Permanent — no amount of waiting produces a slot, so the coordinator must
56123
+ // re-drive (adjust difficulty, target another node, ask the owner). Its
56124
+ // busy counterpart SLOT_MODEL_BUSY_SKIP_REASON is deliberately NOT listed:
56125
+ // that one clears on its own when the slot goes idle.
56126
+ SLOT_MODEL_ABSENT_SKIP_REASON
55921
56127
  ];
55922
56128
  TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
55923
56129
  lastActionableSkipNotified = /* @__PURE__ */ new Map();
@@ -71152,6 +71358,7 @@ ${lastSnapshot}`;
71152
71358
  buildChatMessageSignature: () => buildChatMessageSignature,
71153
71359
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
71154
71360
  buildClaudeInteractiveToolResult: () => buildClaudeInteractiveToolResult,
71361
+ buildCloudStatusReportPayload: () => buildCloudStatusReportPayload,
71155
71362
  buildCompactStaleDirectWorkSummary: () => buildCompactStaleDirectWorkSummary,
71156
71363
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
71157
71364
  buildIdleReminderMessage: () => buildIdleReminderMessage,
@@ -71451,6 +71658,7 @@ ${lastSnapshot}`;
71451
71658
  resolveNotBefore: () => resolveNotBefore,
71452
71659
  resolveProviderChannel: () => resolveProviderChannel,
71453
71660
  resolveProviderMaxParallel: () => resolveProviderMaxParallel,
71661
+ resolveScopedMeshId: () => resolveScopedMeshId,
71454
71662
  resolveSessionHostAppName: () => resolveSessionHostAppName,
71455
71663
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
71456
71664
  resolveSessionTurnPresentation: () => resolveSessionTurnPresentation,
@@ -73026,7 +73234,7 @@ ${lastSnapshot}`;
73026
73234
  const bootstrapLoaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
73027
73235
  let magiKindPanels = {};
73028
73236
  try {
73029
- magiKindPanels = listMagiKindPanelsReadOnly();
73237
+ magiKindPanels = listMagiKindPanelsReadOnly(typeof mesh?.id === "string" ? mesh.id : void 0);
73030
73238
  } catch {
73031
73239
  magiKindPanels = {};
73032
73240
  }
@@ -87981,6 +88189,48 @@ ${body}
87981
88189
  }
87982
88190
  return screenText;
87983
88191
  }
88192
+ /**
88193
+ * Is `reread` a re-render of the SAME picker page as `landed`?
88194
+ *
88195
+ * Guards the return-pass screenText swap in captureClaudeTuiPrompt, which
88196
+ * replaces a page's entire raw screen and therefore must never be handed a
88197
+ * frame belonging to a different question.
88198
+ *
88199
+ * WHAT WE COMPARE — the question line, via the same parser the capture
88200
+ * itself uses (readFocusedClaudeTuiQuestion). Rationale:
88201
+ * - The question text is the one field that is per-page, always rendered
88202
+ * (it is the parse anchor — a page without it yields no question at all),
88203
+ * and stable across the redraw we are waiting on. The redraw races the
88204
+ * option-row GLYPH COLUMN, not the question line.
88205
+ * - The header is NOT usable on its own: on the headered variant every page
88206
+ * renders the identical nav line, and `page.header` is assigned by index
88207
+ * from that shared line rather than read from the page body — so it is
88208
+ * equal across pages by construction and would accept any frame.
88209
+ * - The option-label set is rejected as the primary key: it is drawn in the
88210
+ * very region that is mid-redraw, and rows can be clipped or scrolled out
88211
+ * of the captured frame (the same truncation that forced the headerless
88212
+ * parser to stop requiring the freeform escape hatch). Comparing it would
88213
+ * reject legitimate repairs — exactly the frames this pass exists to fix.
88214
+ *
88215
+ * STRICTNESS — deliberately asymmetric, because the two error directions are
88216
+ * not equally costly. Wrongly ALLOWING a swap corrupts a question into a
88217
+ * duplicate of another (the reported user-visible defect). Wrongly BLOCKING
88218
+ * one merely leaves the forward-pass capture in place — at worst a
88219
+ * multi-select page stays flagged single-select, which the live status-tick
88220
+ * upgrade (maybeUpgradeClaudeTuiMultiSelect) then repairs anyway. So this
88221
+ * blocks only on POSITIVE EVIDENCE of a different page: if either side fails
88222
+ * to parse we return true and defer to the pre-existing glyph gate, keeping
88223
+ * behaviour identical to before for every frame whose identity we cannot
88224
+ * read. Comparison is whitespace-normalised so a reflow or trailing-pad
88225
+ * difference does not read as a different question.
88226
+ */
88227
+ claudeTuiPagesLookLikeSameQuestion(landed, reread) {
88228
+ const landedQuestion = readFocusedClaudeTuiQuestion(landed.screenText);
88229
+ const rereadQuestion = readFocusedClaudeTuiQuestion(reread);
88230
+ if (!landedQuestion || !rereadQuestion) return true;
88231
+ const normalize4 = (text) => text.replace(/\s+/g, " ").trim();
88232
+ return normalize4(landedQuestion.question) === normalize4(rereadQuestion.question);
88233
+ }
87984
88234
  async captureClaudeTuiPrompt(firstScreen, headers) {
87985
88235
  const pages = [{ screenText: firstScreen, header: headers[0] }];
87986
88236
  for (let index = 1; index < headers.length; index += 1) {
@@ -87993,7 +88243,7 @@ ${body}
87993
88243
  await new Promise((resolve29) => setTimeout(resolve29, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
87994
88244
  const reread = await this.snapshotSettledClaudeTuiPage();
87995
88245
  const landed = pages[index - 1];
87996
- if (landed && !detectClaudeTuiMultiSelect(landed.screenText) && detectClaudeTuiMultiSelect(reread)) {
88246
+ if (landed && !detectClaudeTuiMultiSelect(landed.screenText) && detectClaudeTuiMultiSelect(reread) && this.claudeTuiPagesLookLikeSameQuestion(landed, reread)) {
87997
88247
  landed.screenText = reread;
87998
88248
  }
87999
88249
  }
@@ -101184,19 +101434,37 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
101184
101434
  }
101185
101435
  },
101186
101436
  // ─── MAGI kind → panel bindings (MAGI-KIND-PANEL, machine-local config) ───
101187
- // Per-task_kind slot lists in ~/.adhdev/meshes.json `magiKindPanels` — the SOLE
101188
- // MAGI panel-resolution surface (the former named-panel magi_panel_* handlers were
101189
- // removed). Owner-only gating: intentionally NOT listed in
101437
+ // Per-task_kind slot lists stored PER MESH in ~/.adhdev/meshes.json
101438
+ // (`meshes[].magiKindPanels`) — the SOLE MAGI panel-resolution surface (the former
101439
+ // named-panel magi_panel_* handlers were removed). `meshId` is optional on all three
101440
+ // so existing callers keep working: it resolves to the sole mesh on a single-mesh
101441
+ // machine, and is REQUIRED (loud error, never a silent pick) when several meshes
101442
+ // exist. Owner-only gating: intentionally NOT listed in
101190
101443
  // canPeerUsePrivilegedShareCommand (daemon-cloud data-channel-router), so a peer
101191
101444
  // holding ANY share permission hits its `default → false` branch — identical
101192
101445
  // owner-only gating to create_mesh / update_mesh / list_meshes. A trusted peer (no
101193
101446
  // permission = the owner) passes the top `!permission → true` guard. set/remove are
101194
101447
  // WRITE commands; list is read-only. normalizeMagiSlots (inside setMagiKindPanel)
101195
- // surfaces invalid_magi_kind_panel: … messages verbatim for the editor.
101196
- magi_kind_panel_list: async (_ctx, _args) => {
101448
+ // surfaces invalid_magi_kind_panel: … messages verbatim for the editor, including
101449
+ // a nodeId that is not a member of the target mesh.
101450
+ magi_kind_panel_list: async (_ctx, args) => {
101451
+ const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
101197
101452
  try {
101198
- const { listMagiKindPanels: listMagiKindPanels2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101199
- return { success: true, kindPanels: listMagiKindPanels2() };
101453
+ const { listMagiKindPanels: listMagiKindPanels2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101454
+ const meshId = requestedMeshId || resolveScopedMeshId2();
101455
+ return {
101456
+ success: true,
101457
+ kindPanels: listMagiKindPanels2(requestedMeshId || void 0),
101458
+ scope: {
101459
+ kind: "mesh",
101460
+ storage: "machine_local",
101461
+ meshId: meshId ?? null,
101462
+ resolvedFrom: requestedMeshId ? "explicit" : meshId ? "sole_mesh" : "ambiguous",
101463
+ ...requestedMeshId || meshId ? {} : {
101464
+ note: "Several meshes are configured and no meshId was given, so no panels could be read. Pass meshId."
101465
+ }
101466
+ }
101467
+ };
101200
101468
  } catch (e) {
101201
101469
  return { success: false, error: e.message };
101202
101470
  }
@@ -101204,10 +101472,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
101204
101472
  magi_kind_panel_set: async (_ctx, args) => {
101205
101473
  const kind = typeof args?.kind === "string" ? args.kind.trim() : "";
101206
101474
  if (!kind) return { success: false, error: "invalid_magi_kind_panel: task_kind is required" };
101475
+ const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
101207
101476
  try {
101208
- const { setMagiKindPanel: setMagiKindPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101209
- const slots = setMagiKindPanel2(kind, args?.slots);
101210
- return { success: true, kind, slots };
101477
+ const { setMagiKindPanel: setMagiKindPanel2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101478
+ const slots = setMagiKindPanel2(kind, args?.slots, requestedMeshId || void 0);
101479
+ const meshId = requestedMeshId || resolveScopedMeshId2();
101480
+ return { success: true, kind, slots, meshId: meshId ?? null };
101211
101481
  } catch (e) {
101212
101482
  return { success: false, error: e.message };
101213
101483
  }
@@ -101215,30 +101485,52 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
101215
101485
  magi_kind_panel_remove: async (_ctx, args) => {
101216
101486
  const kind = typeof args?.kind === "string" ? args.kind.trim() : "";
101217
101487
  if (!kind) return { success: false, error: "invalid_magi_kind_panel: task_kind is required" };
101488
+ const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
101218
101489
  try {
101219
- const { removeMagiKindPanel: removeMagiKindPanel2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101220
- const removed = removeMagiKindPanel2(kind);
101221
- return { success: true, removed };
101490
+ const { removeMagiKindPanel: removeMagiKindPanel2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101491
+ const removed = removeMagiKindPanel2(kind, requestedMeshId || void 0);
101492
+ const meshId = requestedMeshId || resolveScopedMeshId2();
101493
+ return { success: true, removed, meshId: meshId ?? null };
101222
101494
  } catch (e) {
101223
101495
  return { success: false, error: e.message };
101224
101496
  }
101225
101497
  },
101226
- // ─── Brain routing: per-difficulty brain presets (machine-local) ───
101227
- // getDifficultyBrains returns the seeded defaults when nothing is configured,
101228
- // so the editor always shows a usable mapping. set replaces the whole map.
101229
- difficulty_brains_get: async (_ctx, _args) => {
101498
+ // ─── Brain routing: per-difficulty brain presets (PER MESH, machine-local) ───
101499
+ // getDifficultyBrains returns the seeded defaults when the mesh has nothing
101500
+ // configured, so the editor always shows a usable mapping. set replaces the whole
101501
+ // map for ONE mesh. `meshId` is optional and resolves to the sole mesh, so
101502
+ // existing callers keep working; with several meshes a write must name its mesh
101503
+ // (these presets choose the model a task runs on — writing to the wrong mesh
101504
+ // changes what that mesh costs).
101505
+ difficulty_brains_get: async (_ctx, args) => {
101506
+ const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
101230
101507
  try {
101231
- const { getDifficultyBrains: getDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101232
- return { success: true, difficultyBrains: getDifficultyBrains2() };
101508
+ const { getDifficultyBrains: getDifficultyBrains2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101509
+ const meshId = requestedMeshId || resolveScopedMeshId2();
101510
+ return {
101511
+ success: true,
101512
+ difficultyBrains: getDifficultyBrains2(requestedMeshId || void 0),
101513
+ scope: {
101514
+ kind: "mesh",
101515
+ storage: "machine_local",
101516
+ meshId: meshId ?? null,
101517
+ resolvedFrom: requestedMeshId ? "explicit" : meshId ? "sole_mesh" : "ambiguous",
101518
+ ...requestedMeshId || meshId ? {} : {
101519
+ note: "Several meshes are configured and no meshId was given, so these are the shipped defaults, not any mesh's saved presets. Pass meshId."
101520
+ }
101521
+ }
101522
+ };
101233
101523
  } catch (e) {
101234
101524
  return { success: false, error: e.message };
101235
101525
  }
101236
101526
  },
101237
101527
  difficulty_brains_set: async (_ctx, args) => {
101528
+ const requestedMeshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
101238
101529
  try {
101239
- const { setDifficultyBrains: setDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101240
- const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains);
101241
- return { success: true, difficultyBrains };
101530
+ const { setDifficultyBrains: setDifficultyBrains2, resolveScopedMeshId: resolveScopedMeshId2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
101531
+ const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains, requestedMeshId || void 0);
101532
+ const meshId = requestedMeshId || resolveScopedMeshId2();
101533
+ return { success: true, difficultyBrains, meshId: meshId ?? null };
101242
101534
  } catch (e) {
101243
101535
  return { success: false, error: e.message };
101244
101536
  }
@@ -102889,10 +103181,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
102889
103181
  return void 0;
102890
103182
  }
102891
103183
  };
102892
- const loadMagiKindPanelsBestEffort = async () => {
103184
+ const loadMagiKindPanelsBestEffort = async (forMeshId) => {
102893
103185
  try {
102894
103186
  const { listMagiKindPanels: listMagiKindPanels2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
102895
- return listMagiKindPanels2();
103187
+ return listMagiKindPanels2(forMeshId);
102896
103188
  } catch {
102897
103189
  return void 0;
102898
103190
  }
@@ -102994,7 +103286,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
102994
103286
  if (coordinatorSetup.kind === "cli_command") {
102995
103287
  let cliCmdSystemPrompt = "";
102996
103288
  try {
102997
- cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
103289
+ cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort(meshId) });
102998
103290
  } catch (error48) {
102999
103291
  const message = error48?.message || String(error48);
103000
103292
  LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
@@ -103191,7 +103483,7 @@ ${ptyResult.output.slice(-2e3)}`);
103191
103483
  }
103192
103484
  let systemPrompt = "";
103193
103485
  try {
103194
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort() });
103486
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh: effectiveMesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildEffectiveOperatingNotes(mesh.id), magiKindPanels: await loadMagiKindPanelsBestEffort(meshId) });
103195
103487
  } catch (error48) {
103196
103488
  const message = error48?.message || String(error48);
103197
103489
  LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
@@ -109175,6 +109467,32 @@ ${e?.stderr || ""}`;
109175
109467
  init_logger();
109176
109468
  init_runtime_defaults();
109177
109469
  init_snapshot();
109470
+ function buildCloudStatusReportPayload(sessions, p2p, timestamp2) {
109471
+ const list = Array.isArray(sessions) ? sessions : [];
109472
+ return {
109473
+ sessions: list.map((raw) => {
109474
+ const session = raw || {};
109475
+ return {
109476
+ id: session.id,
109477
+ parentId: session.parentId ?? null,
109478
+ providerType: session.providerType,
109479
+ providerName: session.providerName || session.providerType,
109480
+ kind: session.kind,
109481
+ transport: session.transport,
109482
+ status: session.status,
109483
+ workspace: session.workspace ?? null,
109484
+ cdpConnected: session.cdpConnected,
109485
+ // Forward surfaceHidden/muted so the server can gate push notifications
109486
+ // for coordinator-hidden and user-muted sessions (the WS path is the
109487
+ // only one the server sees). Both are plain booleans, not content.
109488
+ surfaceHidden: session.surfaceHidden,
109489
+ muted: session.muted
109490
+ };
109491
+ }),
109492
+ p2p,
109493
+ timestamp: timestamp2
109494
+ };
109495
+ }
109178
109496
  var DaemonStatusReporter = class {
109179
109497
  deps;
109180
109498
  log;
@@ -109388,28 +109706,7 @@ ${e?.stderr || ""}`;
109388
109706
  }
109389
109707
  if (opts?.p2pOnly) return;
109390
109708
  if (!serverConnected || !serverConn) return;
109391
- const payloadSessions = Array.isArray(payload.sessions) ? payload.sessions : [];
109392
- const wsPayload = {
109393
- sessions: payloadSessions.map((session) => ({
109394
- id: session.id,
109395
- parentId: session.parentId,
109396
- providerType: session.providerType,
109397
- providerName: session.providerName || session.providerType,
109398
- kind: session.kind,
109399
- transport: session.transport,
109400
- status: session.status,
109401
- workspace: session.workspace ?? null,
109402
- title: session.title,
109403
- cdpConnected: session.cdpConnected,
109404
- summaryMetadata: session.summaryMetadata,
109405
- settings: session.settings,
109406
- // Forward surfaceHidden so the server can gate push notifications for
109407
- // coordinator-hidden sessions (the WS path is the only one the server sees).
109408
- surfaceHidden: session.surfaceHidden
109409
- })),
109410
- p2p: payload.p2p,
109411
- timestamp: now
109412
- };
109709
+ const wsPayload = buildCloudStatusReportPayload(payload.sessions, payload.p2p, now);
109413
109710
  const wsHash = this.simpleHash(JSON.stringify({
109414
109711
  ...wsPayload,
109415
109712
  timestamp: void 0