@adhdev/daemon-core 1.0.18-rc.17 → 1.0.18-rc.19

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
@@ -184,7 +184,7 @@ function mergeAndNormalizePolicy(base, patch) {
184
184
  }
185
185
  return policy;
186
186
  }
187
- function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
187
+ function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider, repoConfig, providerType) {
188
188
  let enabled = true;
189
189
  if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
190
190
  enabled = nodePolicy.delegatedWorkerAutoApprove;
@@ -194,14 +194,17 @@ function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
194
194
  if (!enabled) return false;
195
195
  const modes = provider?.autoApproveModes;
196
196
  if (!modes) return true;
197
- const defaultMode = modes.modes.find((mode) => mode.id === modes.default);
198
- if (!defaultMode || defaultMode.strategy === "post-boot-command") return false;
197
+ const requestedModeRaw = typeof providerType === "string" ? repoConfig?.providerDefaults?.autoApproveModes?.[providerType.trim()] : void 0;
198
+ const requestedModeId = typeof requestedModeRaw === "string" && requestedModeRaw.trim() ? requestedModeRaw.trim() : "";
199
+ const requestedMode = requestedModeId ? modes.modes.find((mode) => mode.id === requestedModeId) : void 0;
200
+ const selectedMode = requestedMode ?? modes.modes.find((mode) => mode.id === modes.default);
201
+ if (!selectedMode || selectedMode.strategy === "post-boot-command") return false;
199
202
  const dangerousAllowed = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
200
- if (deriveAutoApproveModeRisk(defaultMode) === "dangerous" && !dangerousAllowed) {
203
+ if (deriveAutoApproveModeRisk(selectedMode) === "dangerous" && !dangerousAllowed) {
201
204
  const ptyFallback = modes.modes.find((mode) => mode.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(mode) !== "dangerous");
202
205
  return ptyFallback?.id || false;
203
206
  }
204
- return defaultMode.id;
207
+ return selectedMode.id;
205
208
  }
206
209
  function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
207
210
  if (typeof nodePolicy?.delegatedWorkerDangerousModeAllow === "boolean") {
@@ -209,8 +212,8 @@ function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
209
212
  }
210
213
  return meshPolicy?.delegatedWorkerDangerousModeAllow === true;
211
214
  }
212
- function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider) {
213
- const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider);
215
+ function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider, repoConfig, providerType) {
216
+ const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider, repoConfig, providerType);
214
217
  const delegatedWorkerDangerousModeAllow = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
215
218
  return typeof resolved === "string" ? { autoApprove: void 0, autoApproveMode: resolved, delegatedWorkerDangerousModeAllow } : { autoApprove: resolved, autoApproveMode: void 0, delegatedWorkerDangerousModeAllow };
216
219
  }
@@ -310,6 +313,267 @@ var init_repo_mesh_types = __esm({
310
313
  }
311
314
  });
312
315
 
316
+ // src/config/mesh-json-config.ts
317
+ var mesh_json_config_exports = {};
318
+ __export(mesh_json_config_exports, {
319
+ MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
320
+ MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
321
+ MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE: () => MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
322
+ applyRepoMeshConfig: () => applyRepoMeshConfig,
323
+ buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
324
+ loadRepoMeshJsonConfig: () => loadRepoMeshJsonConfig,
325
+ mergeEffectiveCoordinatorConfig: () => mergeEffectiveCoordinatorConfig,
326
+ mergeEffectiveOperatingNotes: () => mergeEffectiveOperatingNotes,
327
+ normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
328
+ serializeMeshJsonConfigScaffold: () => serializeMeshJsonConfigScaffold
329
+ });
330
+ function isRecord(value) {
331
+ return !!value && typeof value === "object" && !Array.isArray(value);
332
+ }
333
+ function parseConfigText(path46, text) {
334
+ if (/\.json$/i.test(path46)) return JSON.parse(text);
335
+ return yaml.load(text);
336
+ }
337
+ function normalizeOperatingNote(value) {
338
+ if (!isRecord(value)) return null;
339
+ const text = typeof value.text === "string" ? value.text.trim() : "";
340
+ if (!text) return null;
341
+ const category = value.category === "provider_quirk" || value.category === "pattern_to_avoid" || value.category === "recovery_lesson" ? value.category : void 0;
342
+ return {
343
+ text,
344
+ ...category ? { category } : {},
345
+ ...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {},
346
+ ...typeof value.sourceCoordinator === "string" ? { sourceCoordinator: value.sourceCoordinator } : {},
347
+ // Operating-notes lifecycle: a repo-declared note may pin itself or set an
348
+ // explicit expiry, same as a runtime-recorded one. Phase 2 (b)/(c): it may
349
+ // also declare supersedes/subjectKey to retire an earlier note or group
350
+ // same-subject notes for folding.
351
+ ...value.pinned === true ? { pinned: true } : {},
352
+ ...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {},
353
+ ...typeof value.supersedes === "string" ? { supersedes: value.supersedes } : {},
354
+ ...typeof value.subjectKey === "string" ? { subjectKey: value.subjectKey } : {}
355
+ };
356
+ }
357
+ function normalizeRepoMeshDeclarativeConfig(parsed) {
358
+ const errors = [];
359
+ if (!isRecord(parsed)) return { valid: false, errors: ["config must be an object"] };
360
+ if (parsed.version !== 1) {
361
+ return { valid: false, errors: [`version must be 1 (got ${JSON.stringify(parsed.version)})`] };
362
+ }
363
+ const config = { version: 1 };
364
+ if (parsed.coordinator !== void 0) {
365
+ if (isRecord(parsed.coordinator)) {
366
+ const coord = {};
367
+ const c = parsed.coordinator;
368
+ if (typeof c.systemPromptOverride === "string") coord.systemPromptOverride = c.systemPromptOverride;
369
+ if (typeof c.systemPromptAppend === "string") coord.systemPromptAppend = c.systemPromptAppend;
370
+ if (Number.isFinite(Number(c.maxPromptChars))) coord.maxPromptChars = Number(c.maxPromptChars);
371
+ config.coordinator = coord;
372
+ } else {
373
+ errors.push("coordinator must be an object when provided");
374
+ }
375
+ }
376
+ if (parsed.operatingNotes !== void 0) {
377
+ if (Array.isArray(parsed.operatingNotes)) {
378
+ const notes = parsed.operatingNotes.map(normalizeOperatingNote).filter((n) => n !== null);
379
+ if (notes.length) config.operatingNotes = notes;
380
+ } else {
381
+ errors.push("operatingNotes must be an array when provided");
382
+ }
383
+ }
384
+ if (parsed.limits !== void 0) {
385
+ if (isRecord(parsed.limits)) {
386
+ const limits = {};
387
+ if (Number.isFinite(Number(parsed.limits.maxNoteChars))) limits.maxNoteChars = Number(parsed.limits.maxNoteChars);
388
+ if (Number.isFinite(Number(parsed.limits.maxNotes))) limits.maxNotes = Number(parsed.limits.maxNotes);
389
+ if (Object.keys(limits).length) config.limits = limits;
390
+ } else {
391
+ errors.push("limits must be an object when provided");
392
+ }
393
+ }
394
+ if (parsed.providerDefaults !== void 0) {
395
+ if (isRecord(parsed.providerDefaults)) {
396
+ const pd = {};
397
+ const rawModes = parsed.providerDefaults.autoApproveModes;
398
+ if (rawModes !== void 0) {
399
+ if (isRecord(rawModes)) {
400
+ const modes = {};
401
+ for (const [providerType, modeId] of Object.entries(rawModes)) {
402
+ const type = typeof providerType === "string" ? providerType.trim() : "";
403
+ const id = typeof modeId === "string" ? modeId.trim() : "";
404
+ if (type && id) modes[type] = id;
405
+ }
406
+ if (Object.keys(modes).length) pd.autoApproveModes = modes;
407
+ } else {
408
+ errors.push("providerDefaults.autoApproveModes must be an object when provided");
409
+ }
410
+ }
411
+ if (Object.keys(pd).length) config.providerDefaults = pd;
412
+ } else {
413
+ errors.push("providerDefaults must be an object when provided");
414
+ }
415
+ }
416
+ return { valid: true, config, errors };
417
+ }
418
+ function loadRepoMeshJsonConfig(workspace) {
419
+ const bases = [];
420
+ const ws = typeof workspace === "string" ? workspace.trim() : "";
421
+ if (ws) bases.push(ws);
422
+ let cwd = "";
423
+ try {
424
+ cwd = process.cwd();
425
+ } catch {
426
+ }
427
+ if (cwd && cwd !== ws) bases.push(cwd);
428
+ for (const base of bases) {
429
+ for (const relative5 of MESH_JSON_CONFIG_LOCATIONS) {
430
+ const configPath = (0, import_path.join)(base, relative5);
431
+ if (!(0, import_fs.existsSync)(configPath)) continue;
432
+ try {
433
+ const parsed = parseConfigText(configPath, (0, import_fs.readFileSync)(configPath, "utf-8"));
434
+ const result = normalizeRepoMeshDeclarativeConfig(parsed);
435
+ if (!result.valid || !result.config) {
436
+ return { source: relative5, sourceType: "invalid", path: configPath, error: result.errors.join("; ") };
437
+ }
438
+ return { config: result.config, source: relative5, sourceType: "repo_file", path: configPath };
439
+ } catch (error) {
440
+ return { source: relative5, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
441
+ }
442
+ }
443
+ }
444
+ return {
445
+ source: "unavailable",
446
+ sourceType: "unavailable",
447
+ error: `No repo mesh config found. Checked: ${MESH_JSON_CONFIG_LOCATIONS.join(", ")}`
448
+ };
449
+ }
450
+ function mergeEffectiveCoordinatorConfig(repoCoord, localCoord) {
451
+ const out = { ...localCoord || {} };
452
+ const localOverride = localCoord?.systemPromptOverride?.trim();
453
+ const repoOverride = repoCoord?.systemPromptOverride?.trim();
454
+ if (localOverride) {
455
+ out.systemPromptOverride = localCoord.systemPromptOverride;
456
+ } else if (repoOverride) {
457
+ out.systemPromptOverride = repoCoord.systemPromptOverride;
458
+ } else {
459
+ delete out.systemPromptOverride;
460
+ }
461
+ const repoAppend = repoCoord?.systemPromptAppend?.trim() ? repoCoord.systemPromptAppend.trim() : "";
462
+ const localAppendRaw = localCoord?.systemPromptAppend ?? localCoord?.systemPromptSuffix;
463
+ const localAppend = localAppendRaw?.trim() ? localAppendRaw.trim() : "";
464
+ const stacked = [repoAppend, localAppend].filter(Boolean).join("\n\n");
465
+ if (stacked) {
466
+ out.systemPromptAppend = stacked;
467
+ delete out.systemPromptSuffix;
468
+ }
469
+ return out;
470
+ }
471
+ function mergeEffectiveOperatingNotes(repoNotes, ledgerNotes) {
472
+ const usable = (notes) => Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
473
+ const repo = usable(repoNotes);
474
+ const ledger = usable(ledgerNotes);
475
+ const ledgerTexts = new Set(ledger.map((n) => n.text.trim()));
476
+ const repoKept = repo.filter((n) => !ledgerTexts.has(n.text.trim()));
477
+ const merged = [...repoKept, ...ledger];
478
+ return merged.length ? merged : void 0;
479
+ }
480
+ function applyRepoMeshConfig(mesh, repoConfig) {
481
+ if (!repoConfig) return mesh;
482
+ return {
483
+ ...mesh,
484
+ coordinator: mergeEffectiveCoordinatorConfig(repoConfig.coordinator, mesh.coordinator)
485
+ };
486
+ }
487
+ function buildMeshJsonConfigScaffold(mesh) {
488
+ const scaffold = { version: 1 };
489
+ const coord = {};
490
+ const override = mesh.coordinator?.systemPromptOverride;
491
+ if (typeof override === "string" && override.trim()) coord.systemPromptOverride = override;
492
+ const append = mesh.coordinator?.systemPromptAppend ?? mesh.coordinator?.systemPromptSuffix;
493
+ if (typeof append === "string" && append.trim()) coord.systemPromptAppend = append;
494
+ if (Object.keys(coord).length) scaffold.coordinator = coord;
495
+ return scaffold;
496
+ }
497
+ function serializeMeshJsonConfigScaffold(config) {
498
+ return JSON.stringify(config, null, 2);
499
+ }
500
+ var import_fs, import_path, yaml, MESH_JSON_CONFIG_LOCATIONS, MESH_JSON_CONFIG_SCHEMA, MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE;
501
+ var init_mesh_json_config = __esm({
502
+ "src/config/mesh-json-config.ts"() {
503
+ "use strict";
504
+ import_fs = require("fs");
505
+ import_path = require("path");
506
+ yaml = __toESM(require("js-yaml"));
507
+ MESH_JSON_CONFIG_LOCATIONS = [
508
+ ".adhdev/mesh.json",
509
+ ".adhdev/mesh.yaml",
510
+ ".adhdev/mesh.yml"
511
+ ];
512
+ MESH_JSON_CONFIG_SCHEMA = {
513
+ $schema: "https://json-schema.org/draft/2020-12/schema",
514
+ title: "ADHDev Repo Mesh Declarative Config",
515
+ type: "object",
516
+ additionalProperties: false,
517
+ required: ["version"],
518
+ properties: {
519
+ version: { const: 1 },
520
+ coordinator: {
521
+ type: "object",
522
+ additionalProperties: false,
523
+ properties: {
524
+ systemPromptOverride: { type: "string" },
525
+ systemPromptAppend: { type: "string" },
526
+ maxPromptChars: { type: "number", minimum: 1 }
527
+ }
528
+ },
529
+ operatingNotes: {
530
+ type: "array",
531
+ maxItems: 200,
532
+ items: {
533
+ type: "object",
534
+ additionalProperties: false,
535
+ required: ["text"],
536
+ properties: {
537
+ text: { type: "string", minLength: 1 },
538
+ category: { enum: ["provider_quirk", "pattern_to_avoid", "recovery_lesson"] },
539
+ createdAt: { type: "string" },
540
+ sourceCoordinator: { type: "string" }
541
+ }
542
+ }
543
+ },
544
+ limits: {
545
+ type: "object",
546
+ additionalProperties: false,
547
+ properties: {
548
+ maxNoteChars: { type: "number", minimum: 1 },
549
+ maxNotes: { type: "number", minimum: 1 }
550
+ }
551
+ },
552
+ providerDefaults: {
553
+ type: "object",
554
+ additionalProperties: false,
555
+ properties: {
556
+ // providerType → requested auto-approve mode ID. Mode IDs are
557
+ // validated against the live provider spec at resolve time; an
558
+ // unknown ID is ignored (provider default is used), so the schema
559
+ // only constrains the shape (string→string), not the ID values.
560
+ autoApproveModes: {
561
+ type: "object",
562
+ additionalProperties: { type: "string" }
563
+ }
564
+ }
565
+ }
566
+ }
567
+ };
568
+ MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE = {
569
+ autoApproveModes: {
570
+ "claude-cli": "accept-edits",
571
+ "codex-cli": "auto"
572
+ }
573
+ };
574
+ }
575
+ });
576
+
313
577
  // src/git/git-executor.ts
314
578
  var git_executor_exports = {};
315
579
  __export(git_executor_exports, {
@@ -526,10 +790,10 @@ function readInjected(value) {
526
790
  }
527
791
  function getDaemonBuildInfo() {
528
792
  if (cached) return cached;
529
- const commit = readInjected(true ? "eeb3e1474488eb5543c443270208f3ca8958a86a" : void 0) ?? "unknown";
530
- const commitShort = readInjected(true ? "eeb3e147" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
531
- const version = readInjected(true ? "1.0.18-rc.17" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
532
- const builtAt = readInjected(true ? "2026-07-23T03:30:50.962Z" : void 0);
793
+ const commit = readInjected(true ? "957753ce64d49cf4222cb2675d7d919871d3f009" : void 0) ?? "unknown";
794
+ const commitShort = readInjected(true ? "957753ce" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
795
+ const version = readInjected(true ? "1.0.18-rc.19" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
796
+ const builtAt = readInjected(true ? "2026-07-23T07:07:10.469Z" : void 0);
533
797
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
534
798
  return cached;
535
799
  }
@@ -541,14 +805,14 @@ var init_build_info = __esm({
541
805
  });
542
806
 
543
807
  // src/git/change-impact-config.ts
544
- function isRecord(value) {
808
+ function isRecord2(value) {
545
809
  return !!value && typeof value === "object" && !Array.isArray(value);
546
810
  }
547
811
  function isStringArray(value) {
548
812
  return Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0);
549
813
  }
550
814
  function validateTarget(value, key2, errors) {
551
- if (!isRecord(value)) {
815
+ if (!isRecord2(value)) {
552
816
  errors.push(`impactTargets.${key2} must be an object`);
553
817
  return void 0;
554
818
  }
@@ -564,7 +828,7 @@ function validateTarget(value, key2, errors) {
564
828
  }
565
829
  function validateChangeImpactConfig(raw, source = "inline") {
566
830
  const errors = [];
567
- if (!isRecord(raw)) {
831
+ if (!isRecord2(raw)) {
568
832
  return { valid: false, errors: [`${source}: config must be an object`] };
569
833
  }
570
834
  const config = {};
@@ -581,7 +845,7 @@ function validateChangeImpactConfig(raw, source = "inline") {
581
845
  else errors.push("nonRuntimeRootFilePatterns must be an array of non-empty strings");
582
846
  }
583
847
  if (raw.impactTargets !== void 0) {
584
- if (!isRecord(raw.impactTargets)) {
848
+ if (!isRecord2(raw.impactTargets)) {
585
849
  errors.push("impactTargets must be an object");
586
850
  } else {
587
851
  const targets = {};
@@ -603,23 +867,23 @@ function validateChangeImpactConfig(raw, source = "inline") {
603
867
  }
604
868
  return { valid: errors.length === 0, errors, config: errors.length === 0 ? config : void 0 };
605
869
  }
606
- function parseConfigText(path46, text) {
870
+ function parseConfigText2(path46, text) {
607
871
  if (/\.json$/i.test(path46)) return JSON.parse(text);
608
- return yaml.load(text);
872
+ return yaml2.load(text);
609
873
  }
610
874
  function loadChangeImpactConfig(repoRoot) {
611
875
  for (const relative5 of CHANGE_IMPACT_CONFIG_LOCATIONS) {
612
- const configPath = (0, import_path.join)(repoRoot, relative5);
613
- if (!(0, import_fs.existsSync)(configPath)) continue;
876
+ const configPath = (0, import_path2.join)(repoRoot, relative5);
877
+ if (!(0, import_fs2.existsSync)(configPath)) continue;
614
878
  try {
615
- const text = (0, import_fs.readFileSync)(configPath, "utf-8");
879
+ const text = (0, import_fs2.readFileSync)(configPath, "utf-8");
616
880
  let mtimeMs = 0;
617
881
  try {
618
- mtimeMs = (0, import_fs.statSync)(configPath).mtimeMs;
882
+ mtimeMs = (0, import_fs2.statSync)(configPath).mtimeMs;
619
883
  } catch {
620
884
  mtimeMs = text.length;
621
885
  }
622
- const parsed = parseConfigText(configPath, text);
886
+ const parsed = parseConfigText2(configPath, text);
623
887
  const validation = validateChangeImpactConfig(parsed, relative5);
624
888
  if (!validation.valid) {
625
889
  return {
@@ -678,7 +942,7 @@ function globToRegExp(pattern) {
678
942
  }
679
943
  function listPackageDirs(packagesRoot) {
680
944
  try {
681
- return (0, import_fs.readdirSync)(packagesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
945
+ return (0, import_fs2.readdirSync)(packagesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
682
946
  } catch {
683
947
  return [];
684
948
  }
@@ -688,10 +952,10 @@ function suggestChangeImpactConfig(repoRoot) {
688
952
  const daemon = /* @__PURE__ */ new Set();
689
953
  const web = /* @__PURE__ */ new Set();
690
954
  const unclassified = [];
691
- const roots = ["packages", (0, import_path.join)("oss", "packages")];
955
+ const roots = ["packages", (0, import_path2.join)("oss", "packages")];
692
956
  for (const rel of roots) {
693
- const packagesRoot = (0, import_path.join)(repoRoot, rel);
694
- if (!(0, import_fs.existsSync)(packagesRoot)) continue;
957
+ const packagesRoot = (0, import_path2.join)(repoRoot, rel);
958
+ if (!(0, import_fs2.existsSync)(packagesRoot)) continue;
695
959
  for (const name of listPackageDirs(packagesRoot)) {
696
960
  if (/(^web[-.]|[-.]web$)/i.test(name) || /dashboard|frontend|ui$/i.test(name)) {
697
961
  web.add(name);
@@ -733,13 +997,13 @@ function suggestChangeImpactConfig(repoRoot) {
733
997
  discoveredPackages: { daemon: daemonRuntimePackages, web: webOnlyPackages, unclassified }
734
998
  };
735
999
  }
736
- var import_fs, import_path, yaml, CHANGE_IMPACT_CONFIG_LOCATIONS, CHANGE_IMPACT_CONFIG_SCHEMA;
1000
+ var import_fs2, import_path2, yaml2, CHANGE_IMPACT_CONFIG_LOCATIONS, CHANGE_IMPACT_CONFIG_SCHEMA;
737
1001
  var init_change_impact_config = __esm({
738
1002
  "src/git/change-impact-config.ts"() {
739
1003
  "use strict";
740
- import_fs = require("fs");
741
- import_path = require("path");
742
- yaml = __toESM(require("js-yaml"));
1004
+ import_fs2 = require("fs");
1005
+ import_path2 = require("path");
1006
+ yaml2 = __toESM(require("js-yaml"));
743
1007
  CHANGE_IMPACT_CONFIG_LOCATIONS = [
744
1008
  ".adhdev/change-impact.json",
745
1009
  ".adhdev/change-impact.yaml",
@@ -1824,25 +2088,25 @@ function ensureMachineId(config) {
1824
2088
  }
1825
2089
  function getConfigDir() {
1826
2090
  const override = process.env.ADHDEV_CONFIG_DIR;
1827
- const dir = override && override.trim() ? override.trim() : (0, import_path2.join)((0, import_os.homedir)(), ".adhdev");
1828
- if (!(0, import_fs2.existsSync)(dir)) {
1829
- (0, import_fs2.mkdirSync)(dir, { recursive: true });
2091
+ const dir = override && override.trim() ? override.trim() : (0, import_path3.join)((0, import_os.homedir)(), ".adhdev");
2092
+ if (!(0, import_fs3.existsSync)(dir)) {
2093
+ (0, import_fs3.mkdirSync)(dir, { recursive: true });
1830
2094
  }
1831
2095
  return dir;
1832
2096
  }
1833
2097
  function getDaemonDataDir() {
1834
- const dir = (0, import_path2.join)(getConfigDir(), "daemon");
1835
- if (!(0, import_fs2.existsSync)(dir)) {
1836
- (0, import_fs2.mkdirSync)(dir, { recursive: true });
2098
+ const dir = (0, import_path3.join)(getConfigDir(), "daemon");
2099
+ if (!(0, import_fs3.existsSync)(dir)) {
2100
+ (0, import_fs3.mkdirSync)(dir, { recursive: true });
1837
2101
  }
1838
2102
  return dir;
1839
2103
  }
1840
2104
  function getConfigPath() {
1841
- return (0, import_path2.join)(getConfigDir(), "config.json");
2105
+ return (0, import_path3.join)(getConfigDir(), "config.json");
1842
2106
  }
1843
2107
  function migrateStateToStateFile(raw) {
1844
- const statePath = (0, import_path2.join)(getConfigDir(), "state.json");
1845
- if ((0, import_fs2.existsSync)(statePath)) return;
2108
+ const statePath = (0, import_path3.join)(getConfigDir(), "state.json");
2109
+ if ((0, import_fs3.existsSync)(statePath)) return;
1846
2110
  const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
1847
2111
  const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
1848
2112
  const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
@@ -1862,11 +2126,11 @@ function migrateStateToStateFile(raw) {
1862
2126
  sessionReads: mergedReads,
1863
2127
  sessionReadMarkers: cleanedMarkers
1864
2128
  };
1865
- (0, import_fs2.writeFileSync)(statePath, JSON.stringify(state, null, 2), { encoding: "utf-8", mode: 384 });
2129
+ (0, import_fs3.writeFileSync)(statePath, JSON.stringify(state, null, 2), { encoding: "utf-8", mode: 384 });
1866
2130
  }
1867
2131
  function loadConfig() {
1868
2132
  const configPath = getConfigPath();
1869
- if (!(0, import_fs2.existsSync)(configPath)) {
2133
+ if (!(0, import_fs3.existsSync)(configPath)) {
1870
2134
  const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
1871
2135
  try {
1872
2136
  saveConfig(initialized.config);
@@ -1875,7 +2139,7 @@ function loadConfig() {
1875
2139
  return initialized.config;
1876
2140
  }
1877
2141
  try {
1878
- const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
2142
+ const raw = (0, import_fs3.readFileSync)(configPath, "utf-8");
1879
2143
  const parsed = JSON.parse(raw);
1880
2144
  migrateStateToStateFile(parsed);
1881
2145
  const normalizedInput = normalizeConfig(parsed);
@@ -1897,12 +2161,12 @@ function saveConfig(config) {
1897
2161
  const configPath = getConfigPath();
1898
2162
  const dir = getConfigDir();
1899
2163
  const normalized = normalizeConfig(config);
1900
- if (!(0, import_fs2.existsSync)(dir)) {
1901
- (0, import_fs2.mkdirSync)(dir, { recursive: true, mode: 448 });
2164
+ if (!(0, import_fs3.existsSync)(dir)) {
2165
+ (0, import_fs3.mkdirSync)(dir, { recursive: true, mode: 448 });
1902
2166
  }
1903
- (0, import_fs2.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
2167
+ (0, import_fs3.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
1904
2168
  try {
1905
- (0, import_fs2.chmodSync)(configPath, 384);
2169
+ (0, import_fs3.chmodSync)(configPath, 384);
1906
2170
  } catch {
1907
2171
  }
1908
2172
  }
@@ -1929,13 +2193,13 @@ function isSetupComplete() {
1929
2193
  function resetConfig() {
1930
2194
  saveConfig({ ...DEFAULT_CONFIG });
1931
2195
  }
1932
- var import_os, import_path2, import_fs2, import_crypto, DEFAULT_CONFIG, MACHINE_ID_PREFIX;
2196
+ var import_os, import_path3, import_fs3, import_crypto, DEFAULT_CONFIG, MACHINE_ID_PREFIX;
1933
2197
  var init_config = __esm({
1934
2198
  "src/config/config.ts"() {
1935
2199
  "use strict";
1936
2200
  import_os = require("os");
1937
- import_path2 = require("path");
1938
- import_fs2 = require("fs");
2201
+ import_path3 = require("path");
2202
+ import_fs3 = require("fs");
1939
2203
  import_crypto = require("crypto");
1940
2204
  DEFAULT_CONFIG = {
1941
2205
  serverUrl: "https://api.adhf.dev",
@@ -3367,13 +3631,13 @@ __export(mesh_config_exports, {
3367
3631
  updateNode: () => updateNode
3368
3632
  });
3369
3633
  function getMeshConfigPath() {
3370
- return (0, import_path3.join)(getConfigDir(), "meshes.json");
3634
+ return (0, import_path4.join)(getConfigDir(), "meshes.json");
3371
3635
  }
3372
3636
  function loadMeshConfig() {
3373
3637
  const path46 = getMeshConfigPath();
3374
- if (!(0, import_fs3.existsSync)(path46)) return { meshes: [] };
3638
+ if (!(0, import_fs4.existsSync)(path46)) return { meshes: [] };
3375
3639
  try {
3376
- const raw = JSON.parse((0, import_fs3.readFileSync)(path46, "utf-8"));
3640
+ const raw = JSON.parse((0, import_fs4.readFileSync)(path46, "utf-8"));
3377
3641
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
3378
3642
  const config = raw;
3379
3643
  const migrated = migrateLoadedMeshConfig(config);
@@ -3451,7 +3715,7 @@ function normalizeCapabilityTags(value) {
3451
3715
  }
3452
3716
  function saveMeshConfig(config) {
3453
3717
  const path46 = getMeshConfigPath();
3454
- (0, import_fs3.writeFileSync)(path46, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
3718
+ (0, import_fs4.writeFileSync)(path46, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
3455
3719
  }
3456
3720
  function normalizeRepoIdentity(remoteUrl) {
3457
3721
  let identity = remoteUrl.trim();
@@ -3880,12 +4144,12 @@ function setDifficultyBrains(map) {
3880
4144
  saveMeshConfig(stored);
3881
4145
  return normalized;
3882
4146
  }
3883
- var import_fs3, import_path3, import_crypto3, mergeMeshPolicy, MAGI_KIND_PANEL_KINDS, MAX_MAGI_KIND_SLOTS;
4147
+ var import_fs4, import_path4, import_crypto3, mergeMeshPolicy, MAGI_KIND_PANEL_KINDS, MAX_MAGI_KIND_SLOTS;
3884
4148
  var init_mesh_config = __esm({
3885
4149
  "src/config/mesh-config.ts"() {
3886
4150
  "use strict";
3887
- import_fs3 = require("fs");
3888
- import_path3 = require("path");
4151
+ import_fs4 = require("fs");
4152
+ import_path4 = require("path");
3889
4153
  import_crypto3 = require("crypto");
3890
4154
  init_hash();
3891
4155
  init_config();
@@ -5202,9 +5466,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
5202
5466
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
5203
5467
  if (coordinatorDaemonId) {
5204
5468
  const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
5205
- return (0, import_path4.join)(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
5469
+ return (0, import_path5.join)(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
5206
5470
  }
5207
- return (0, import_path4.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
5471
+ return (0, import_path5.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
5208
5472
  }
5209
5473
  function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
5210
5474
  if (!meshId) return [];
@@ -5213,9 +5477,9 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
5213
5477
  const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
5214
5478
  const events = [];
5215
5479
  for (const path46 of paths) {
5216
- if (!(0, import_fs4.existsSync)(path46)) continue;
5480
+ if (!(0, import_fs5.existsSync)(path46)) continue;
5217
5481
  try {
5218
- const raw = (0, import_fs4.readFileSync)(path46, "utf-8");
5482
+ const raw = (0, import_fs5.readFileSync)(path46, "utf-8");
5219
5483
  const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
5220
5484
  try {
5221
5485
  return [JSON.parse(line)];
@@ -5305,9 +5569,9 @@ function prunePendingMeshCoordinatorEventsRetention() {
5305
5569
  }
5306
5570
  function trimPendingEventsIfNeeded(path46) {
5307
5571
  try {
5308
- if (!(0, import_fs4.existsSync)(path46)) return;
5309
- if ((0, import_fs4.statSync)(path46).size <= MAX_PENDING_EVENTS_BYTES) return;
5310
- const lines = (0, import_fs4.readFileSync)(path46, "utf-8").split("\n").filter(Boolean);
5572
+ if (!(0, import_fs5.existsSync)(path46)) return;
5573
+ if ((0, import_fs5.statSync)(path46).size <= MAX_PENDING_EVENTS_BYTES) return;
5574
+ const lines = (0, import_fs5.readFileSync)(path46, "utf-8").split("\n").filter(Boolean);
5311
5575
  if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
5312
5576
  const dropped = lines.slice(0, lines.length - MAX_PENDING_EVENTS_KEEP);
5313
5577
  for (const line of dropped) {
@@ -5343,7 +5607,7 @@ function trimPendingEventsIfNeeded(path46) {
5343
5607
  LOG.warn("MeshEvents", `Failed to ledger-record trim-dropped ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
5344
5608
  }
5345
5609
  }
5346
- (0, import_fs4.writeFileSync)(path46, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
5610
+ (0, import_fs5.writeFileSync)(path46, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
5347
5611
  } catch {
5348
5612
  }
5349
5613
  }
@@ -5455,7 +5719,7 @@ function persistPendingMeshCoordinatorEvent(event) {
5455
5719
  try {
5456
5720
  const path46 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
5457
5721
  trimPendingEventsIfNeeded(path46);
5458
- (0, import_fs4.appendFileSync)(path46, JSON.stringify(event) + "\n", "utf-8");
5722
+ (0, import_fs5.appendFileSync)(path46, JSON.stringify(event) + "\n", "utf-8");
5459
5723
  } catch (e) {
5460
5724
  if (!sqliteOk) throw e;
5461
5725
  LOG.warn("MeshEvents", `JSONL append failed for mesh ${event.meshId}; SQLite holds the event: ${e?.message || e}`);
@@ -5469,20 +5733,20 @@ function persistPendingMeshCoordinatorEvent(event) {
5469
5733
  function atomicDrainFile(path46) {
5470
5734
  const tmpPath = `${path46}.draining`;
5471
5735
  try {
5472
- (0, import_fs4.renameSync)(path46, tmpPath);
5736
+ (0, import_fs5.renameSync)(path46, tmpPath);
5473
5737
  } catch {
5474
5738
  return null;
5475
5739
  }
5476
5740
  try {
5477
- const content = (0, import_fs4.readFileSync)(tmpPath, "utf-8");
5741
+ const content = (0, import_fs5.readFileSync)(tmpPath, "utf-8");
5478
5742
  try {
5479
- (0, import_fs4.unlinkSync)(tmpPath);
5743
+ (0, import_fs5.unlinkSync)(tmpPath);
5480
5744
  } catch {
5481
5745
  }
5482
5746
  return content;
5483
5747
  } catch {
5484
5748
  try {
5485
- (0, import_fs4.unlinkSync)(tmpPath);
5749
+ (0, import_fs5.unlinkSync)(tmpPath);
5486
5750
  } catch {
5487
5751
  }
5488
5752
  return null;
@@ -5491,16 +5755,16 @@ function atomicDrainFile(path46) {
5491
5755
  function selectiveDrainFile(path46, predicate) {
5492
5756
  const tmpPath = `${path46}.draining`;
5493
5757
  try {
5494
- (0, import_fs4.renameSync)(path46, tmpPath);
5758
+ (0, import_fs5.renameSync)(path46, tmpPath);
5495
5759
  } catch {
5496
5760
  return [];
5497
5761
  }
5498
5762
  let content;
5499
5763
  try {
5500
- content = (0, import_fs4.readFileSync)(tmpPath, "utf-8");
5764
+ content = (0, import_fs5.readFileSync)(tmpPath, "utf-8");
5501
5765
  } catch {
5502
5766
  try {
5503
- (0, import_fs4.unlinkSync)(tmpPath);
5767
+ (0, import_fs5.unlinkSync)(tmpPath);
5504
5768
  } catch {
5505
5769
  }
5506
5770
  return [];
@@ -5523,12 +5787,12 @@ function selectiveDrainFile(path46, predicate) {
5523
5787
  }
5524
5788
  try {
5525
5789
  if (keptLines.length > 0) {
5526
- (0, import_fs4.writeFileSync)(path46, keptLines.join("\n") + "\n", "utf-8");
5790
+ (0, import_fs5.writeFileSync)(path46, keptLines.join("\n") + "\n", "utf-8");
5527
5791
  }
5528
- (0, import_fs4.unlinkSync)(tmpPath);
5792
+ (0, import_fs5.unlinkSync)(tmpPath);
5529
5793
  } catch {
5530
5794
  try {
5531
- if ((0, import_fs4.existsSync)(tmpPath) && !(0, import_fs4.existsSync)(path46)) (0, import_fs4.renameSync)(tmpPath, path46);
5795
+ if ((0, import_fs5.existsSync)(tmpPath) && !(0, import_fs5.existsSync)(path46)) (0, import_fs5.renameSync)(tmpPath, path46);
5532
5796
  } catch {
5533
5797
  }
5534
5798
  return [];
@@ -5756,18 +6020,18 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
5756
6020
  }
5757
6021
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
5758
6022
  for (const path46 of paths) {
5759
- if ((0, import_fs4.existsSync)(path46)) try {
5760
- (0, import_fs4.unlinkSync)(path46);
6023
+ if ((0, import_fs5.existsSync)(path46)) try {
6024
+ (0, import_fs5.unlinkSync)(path46);
5761
6025
  } catch {
5762
6026
  }
5763
6027
  }
5764
6028
  }
5765
- var import_fs4, import_path4, import_crypto5, REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, loggedSqlitePendingDrainFailure, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP, PENDING_EVENTS_DRAINED_RETENTION_MS, PENDING_EVENTS_UNDRAINED_RETENTION_MS;
6029
+ var import_fs5, import_path5, import_crypto5, REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, loggedSqlitePendingDrainFailure, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP, PENDING_EVENTS_DRAINED_RETENTION_MS, PENDING_EVENTS_UNDRAINED_RETENTION_MS;
5766
6030
  var init_mesh_events_pending = __esm({
5767
6031
  "src/mesh/mesh-events-pending.ts"() {
5768
6032
  "use strict";
5769
- import_fs4 = require("fs");
5770
- import_path4 = require("path");
6033
+ import_fs5 = require("fs");
6034
+ import_path5 = require("path");
5771
6035
  import_crypto5 = require("crypto");
5772
6036
  init_logger();
5773
6037
  init_config();
@@ -7118,15 +7382,15 @@ function safeMeshId(meshId) {
7118
7382
  return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
7119
7383
  }
7120
7384
  function legacyQueuePath(meshId) {
7121
- return (0, import_path5.join)(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
7385
+ return (0, import_path6.join)(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
7122
7386
  }
7123
7387
  function cleanupStrayRootRuntimeDb(canonicalPath) {
7124
7388
  try {
7125
- const strayPath = (0, import_path5.join)(getConfigDir(), "mesh-runtime.db");
7389
+ const strayPath = (0, import_path6.join)(getConfigDir(), "mesh-runtime.db");
7126
7390
  if (strayPath === canonicalPath) return;
7127
- if (!(0, import_fs5.existsSync)(strayPath)) return;
7128
- if ((0, import_fs5.statSync)(strayPath).size !== 0) return;
7129
- (0, import_fs5.unlinkSync)(strayPath);
7391
+ if (!(0, import_fs6.existsSync)(strayPath)) return;
7392
+ if ((0, import_fs6.statSync)(strayPath).size !== 0) return;
7393
+ (0, import_fs6.unlinkSync)(strayPath);
7130
7394
  if (!loggedStrayCleanup) {
7131
7395
  loggedStrayCleanup = true;
7132
7396
  LOG.info("MeshRuntimeStore", `Removed stray 0-byte root mesh-runtime.db at ${strayPath}`);
@@ -7140,17 +7404,17 @@ function cleanupStrayRootRuntimeDb(canonicalPath) {
7140
7404
  }
7141
7405
  function meshRuntimeStorePath() {
7142
7406
  const dir = getLedgerDir();
7143
- const nextPath = (0, import_path5.join)(dir, "mesh-runtime.db");
7407
+ const nextPath = (0, import_path6.join)(dir, "mesh-runtime.db");
7144
7408
  cleanupStrayRootRuntimeDb(nextPath);
7145
- if ((0, import_fs5.existsSync)(nextPath)) return nextPath;
7146
- const legacyPath = (0, import_path5.join)(dir, "beads.db");
7147
- if (!(0, import_fs5.existsSync)(legacyPath)) return nextPath;
7409
+ if ((0, import_fs6.existsSync)(nextPath)) return nextPath;
7410
+ const legacyPath = (0, import_path6.join)(dir, "beads.db");
7411
+ if (!(0, import_fs6.existsSync)(legacyPath)) return nextPath;
7148
7412
  try {
7149
- (0, import_fs5.renameSync)(legacyPath, nextPath);
7413
+ (0, import_fs6.renameSync)(legacyPath, nextPath);
7150
7414
  for (const suffix of ["-wal", "-shm"]) {
7151
7415
  const legacyCompanion = `${legacyPath}${suffix}`;
7152
- if ((0, import_fs5.existsSync)(legacyCompanion)) {
7153
- (0, import_fs5.renameSync)(legacyCompanion, `${nextPath}${suffix}`);
7416
+ if ((0, import_fs6.existsSync)(legacyCompanion)) {
7417
+ (0, import_fs6.renameSync)(legacyCompanion, `${nextPath}${suffix}`);
7154
7418
  }
7155
7419
  }
7156
7420
  } catch (err) {
@@ -7161,7 +7425,7 @@ function meshRuntimeStorePath() {
7161
7425
  `Legacy beads.db\u2192mesh-runtime.db migration failed; using existing DB in-place to avoid data loss: ${err?.message || err}`
7162
7426
  );
7163
7427
  }
7164
- return (0, import_fs5.existsSync)(nextPath) ? nextPath : legacyPath;
7428
+ return (0, import_fs6.existsSync)(nextPath) ? nextPath : legacyPath;
7165
7429
  }
7166
7430
  return nextPath;
7167
7431
  }
@@ -7180,12 +7444,12 @@ function pruneMeshRuntimeRetention() {
7180
7444
  return { ledger: 0, toolCalls: 0, terminalQueue: 0 };
7181
7445
  }
7182
7446
  }
7183
- var import_fs5, import_path5, DatabaseCtor, loggedMigrationFailure, loggedStrayCleanup, MeshRuntimeStore, MESH_EVENT_LEDGER_RETENTION_MS, MESH_TOOL_CALL_LOG_RETENTION_MS, MESH_TERMINAL_QUEUE_RETENTION_MS;
7447
+ var import_fs6, import_path6, DatabaseCtor, loggedMigrationFailure, loggedStrayCleanup, MeshRuntimeStore, MESH_EVENT_LEDGER_RETENTION_MS, MESH_TOOL_CALL_LOG_RETENTION_MS, MESH_TERMINAL_QUEUE_RETENTION_MS;
7184
7448
  var init_mesh_runtime_store = __esm({
7185
7449
  "src/mesh/mesh-runtime-store.ts"() {
7186
7450
  "use strict";
7187
- import_fs5 = require("fs");
7188
- import_path5 = require("path");
7451
+ import_fs6 = require("fs");
7452
+ import_path6 = require("path");
7189
7453
  init_logger();
7190
7454
  init_load_better_sqlite3();
7191
7455
  init_config();
@@ -7216,8 +7480,8 @@ var init_mesh_runtime_store = __esm({
7216
7480
  static WAL_MAX_BYTES = 50 * 1024 * 1024;
7217
7481
  // 50 MB
7218
7482
  constructor(dbPath) {
7219
- const dir = (0, import_path5.dirname)(dbPath);
7220
- if (!(0, import_fs5.existsSync)(dir)) (0, import_fs5.mkdirSync)(dir, { recursive: true });
7483
+ const dir = (0, import_path6.dirname)(dbPath);
7484
+ if (!(0, import_fs6.existsSync)(dir)) (0, import_fs6.mkdirSync)(dir, { recursive: true });
7221
7485
  this.dbPath = dbPath;
7222
7486
  this.db = new (loadDatabaseCtor())(dbPath);
7223
7487
  this.db.pragma("journal_mode = WAL");
@@ -7596,8 +7860,8 @@ var init_mesh_runtime_store = __esm({
7596
7860
  this.walWriteCounter = 0;
7597
7861
  try {
7598
7862
  const walPath = `${this.dbPath}-wal`;
7599
- if (!(0, import_fs5.existsSync)(walPath)) return;
7600
- const size = (0, import_fs5.statSync)(walPath).size;
7863
+ if (!(0, import_fs6.existsSync)(walPath)) return;
7864
+ const size = (0, import_fs6.statSync)(walPath).size;
7601
7865
  if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
7602
7866
  process.stderr.write(
7603
7867
  `[adhdev-mesh] WAL file ${Math.round(size / 1024 / 1024)}MB exceeds threshold; forcing checkpoint
@@ -7613,9 +7877,9 @@ var init_mesh_runtime_store = __esm({
7613
7877
  const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
7614
7878
  if (count.count > 0) return;
7615
7879
  const path46 = legacyQueuePath(meshId);
7616
- if (!(0, import_fs5.existsSync)(path46)) return;
7880
+ if (!(0, import_fs6.existsSync)(path46)) return;
7617
7881
  try {
7618
- const entries = JSON.parse((0, import_fs5.readFileSync)(path46, "utf-8"));
7882
+ const entries = JSON.parse((0, import_fs6.readFileSync)(path46, "utf-8"));
7619
7883
  if (!Array.isArray(entries)) return;
7620
7884
  const insert = this.db.prepare(`
7621
7885
  INSERT OR REPLACE INTO mesh_queue (
@@ -9066,41 +9330,41 @@ function isNoteExpired(note, now) {
9066
9330
  return now - created >= ttlDays * MS_PER_DAY;
9067
9331
  }
9068
9332
  function getLedgerDir() {
9069
- const dir = (0, import_path6.join)(getConfigDir(), LEDGER_DIR_NAME);
9070
- if (!(0, import_fs6.existsSync)(dir)) {
9071
- (0, import_fs6.mkdirSync)(dir, { recursive: true, mode: 448 });
9333
+ const dir = (0, import_path7.join)(getConfigDir(), LEDGER_DIR_NAME);
9334
+ if (!(0, import_fs7.existsSync)(dir)) {
9335
+ (0, import_fs7.mkdirSync)(dir, { recursive: true, mode: 448 });
9072
9336
  }
9073
9337
  return dir;
9074
9338
  }
9075
9339
  function getLedgerPath(meshId) {
9076
9340
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
9077
- return (0, import_path6.join)(getLedgerDir(), `${safe}.jsonl`);
9341
+ return (0, import_path7.join)(getLedgerDir(), `${safe}.jsonl`);
9078
9342
  }
9079
9343
  function getRotatedPath(meshId, index) {
9080
9344
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
9081
- return (0, import_path6.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
9345
+ return (0, import_path7.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
9082
9346
  }
9083
9347
  function getArchivePath(meshId) {
9084
9348
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
9085
- return (0, import_path6.join)(getLedgerDir(), `${safe}.archive.jsonl`);
9349
+ return (0, import_path7.join)(getLedgerDir(), `${safe}.archive.jsonl`);
9086
9350
  }
9087
9351
  function getRotatedArchivePath(meshId, index) {
9088
9352
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
9089
- return (0, import_path6.join)(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
9353
+ return (0, import_path7.join)(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
9090
9354
  }
9091
9355
  function getArchivedCountsPath(meshId) {
9092
9356
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
9093
- return (0, import_path6.join)(getLedgerDir(), `${safe}.archived-counts.json`);
9357
+ return (0, import_path7.join)(getLedgerDir(), `${safe}.archived-counts.json`);
9094
9358
  }
9095
9359
  function rotateArchiveFile(meshId, archivePath) {
9096
9360
  let index = 1;
9097
- while ((0, import_fs6.existsSync)(getRotatedArchivePath(meshId, index))) {
9361
+ while ((0, import_fs7.existsSync)(getRotatedArchivePath(meshId, index))) {
9098
9362
  index++;
9099
9363
  if (index > 5) break;
9100
9364
  }
9101
9365
  if (index > 5) index = 5;
9102
9366
  try {
9103
- (0, import_fs6.renameSync)(archivePath, getRotatedArchivePath(meshId, index));
9367
+ (0, import_fs7.renameSync)(archivePath, getRotatedArchivePath(meshId, index));
9104
9368
  } catch (e) {
9105
9369
  process.stderr.write(`[adhdev-mesh] Archive rotation failed for mesh ${meshId}: ${e?.message || e}
9106
9370
  `);
@@ -9108,9 +9372,9 @@ function rotateArchiveFile(meshId, archivePath) {
9108
9372
  }
9109
9373
  function readArchivedCounts(meshId) {
9110
9374
  const path46 = getArchivedCountsPath(meshId);
9111
- if (!(0, import_fs6.existsSync)(path46)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
9375
+ if (!(0, import_fs7.existsSync)(path46)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
9112
9376
  try {
9113
- return JSON.parse((0, import_fs6.readFileSync)(path46, "utf-8"));
9377
+ return JSON.parse((0, import_fs7.readFileSync)(path46, "utf-8"));
9114
9378
  } catch {
9115
9379
  return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
9116
9380
  }
@@ -9126,7 +9390,7 @@ function updateArchivedCounts(meshId, archived) {
9126
9390
  counts.totalArchived += archived.length;
9127
9391
  counts.lastArchivedAt = (/* @__PURE__ */ new Date()).toISOString();
9128
9392
  try {
9129
- (0, import_fs6.writeFileSync)(getArchivedCountsPath(meshId), JSON.stringify(counts), { encoding: "utf-8", mode: 384 });
9393
+ (0, import_fs7.writeFileSync)(getArchivedCountsPath(meshId), JSON.stringify(counts), { encoding: "utf-8", mode: 384 });
9130
9394
  } catch {
9131
9395
  }
9132
9396
  }
@@ -9149,7 +9413,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
9149
9413
  }
9150
9414
  function compactLedger(meshId) {
9151
9415
  const filePath = getLedgerPath(meshId);
9152
- if (!(0, import_fs6.existsSync)(filePath)) return { archivedCount: 0, retainedCount: 0 };
9416
+ if (!(0, import_fs7.existsSync)(filePath)) return { archivedCount: 0, retainedCount: 0 };
9153
9417
  const cutoff = Date.now() - ARCHIVE_TERMINAL_OLDER_THAN_MS;
9154
9418
  const entries = readLedgerEntries(meshId);
9155
9419
  const keep = [];
@@ -9164,11 +9428,11 @@ function compactLedger(meshId) {
9164
9428
  if (archive.length === 0) return { archivedCount: 0, retainedCount: keep.length };
9165
9429
  const archivePath = getArchivePath(meshId);
9166
9430
  try {
9167
- if ((0, import_fs6.existsSync)(archivePath) && (0, import_fs6.statSync)(archivePath).size > 50 * 1024 * 1024) {
9431
+ if ((0, import_fs7.existsSync)(archivePath) && (0, import_fs7.statSync)(archivePath).size > 50 * 1024 * 1024) {
9168
9432
  rotateArchiveFile(meshId, archivePath);
9169
9433
  }
9170
9434
  const archiveLines = archive.map((e) => JSON.stringify(e)).join("\n") + "\n";
9171
- (0, import_fs6.appendFileSync)(archivePath, archiveLines, { encoding: "utf-8", mode: 384 });
9435
+ (0, import_fs7.appendFileSync)(archivePath, archiveLines, { encoding: "utf-8", mode: 384 });
9172
9436
  updateArchivedCounts(meshId, archive);
9173
9437
  } catch (e) {
9174
9438
  process.stderr.write(`[adhdev-mesh] Ledger archive write failed for mesh ${meshId}: ${e?.message || e}
@@ -9177,7 +9441,7 @@ function compactLedger(meshId) {
9177
9441
  }
9178
9442
  try {
9179
9443
  const keepLines = keep.length ? keep.map((e) => JSON.stringify(e)).join("\n") + "\n" : "";
9180
- (0, import_fs6.writeFileSync)(filePath, keepLines, { encoding: "utf-8", mode: 384 });
9444
+ (0, import_fs7.writeFileSync)(filePath, keepLines, { encoding: "utf-8", mode: 384 });
9181
9445
  invalidateLedgerCache(meshId);
9182
9446
  } catch (e) {
9183
9447
  process.stderr.write(`[adhdev-mesh] Ledger compaction rewrite failed for mesh ${meshId}: ${e?.message || e}
@@ -9355,9 +9619,9 @@ function appendLedgerEntry(meshId, partial) {
9355
9619
  ...partial
9356
9620
  };
9357
9621
  const filePath = getLedgerPath(meshId);
9358
- if ((0, import_fs6.existsSync)(filePath)) {
9622
+ if ((0, import_fs7.existsSync)(filePath)) {
9359
9623
  try {
9360
- const stat2 = (0, import_fs6.statSync)(filePath);
9624
+ const stat2 = (0, import_fs7.statSync)(filePath);
9361
9625
  if (stat2.size >= MAX_FILE_SIZE_BYTES) {
9362
9626
  rotateLedgerFile(meshId, filePath);
9363
9627
  } else if (stat2.size >= COMPACT_THRESHOLD_BYTES) {
@@ -9382,7 +9646,7 @@ function appendLedgerEntry(meshId, partial) {
9382
9646
  }
9383
9647
  try {
9384
9648
  const line = JSON.stringify(entry) + "\n";
9385
- (0, import_fs6.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
9649
+ (0, import_fs7.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
9386
9650
  invalidateLedgerCache(meshId);
9387
9651
  meshLedgerEvents.emit("append", meshId, entry);
9388
9652
  if (entry.kind === OPERATING_NOTE_KIND || entry.kind === OPERATING_NOTE_TOMBSTONE_KIND) {
@@ -9474,7 +9738,7 @@ function pruneOperatingNotes(meshId, keepLatest = OPERATING_NOTE_KEEP_LATEST) {
9474
9738
  const remaining = readLedgerFile(meshId).filter((e) => !removeIds.includes(e.id));
9475
9739
  const filePath = getLedgerPath(meshId);
9476
9740
  const lines = remaining.length ? remaining.map((e) => JSON.stringify(e)).join("\n") + "\n" : "";
9477
- (0, import_fs6.writeFileSync)(filePath, lines, { encoding: "utf-8", mode: 384 });
9741
+ (0, import_fs7.writeFileSync)(filePath, lines, { encoding: "utf-8", mode: 384 });
9478
9742
  } catch {
9479
9743
  }
9480
9744
  invalidateLedgerCache(meshId);
@@ -9531,7 +9795,7 @@ function appendRemoteLedgerEntries(meshId, entries) {
9531
9795
  }
9532
9796
  try {
9533
9797
  const lines = validEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
9534
- (0, import_fs6.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
9798
+ (0, import_fs7.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
9535
9799
  invalidateLedgerCache(meshId);
9536
9800
  for (const entry of validEntries) {
9537
9801
  meshLedgerEvents.emit("append", meshId, entry);
@@ -9543,10 +9807,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
9543
9807
  }
9544
9808
  function readLedgerFile(meshId) {
9545
9809
  const filePath = getLedgerPath(meshId);
9546
- if (!(0, import_fs6.existsSync)(filePath)) return [];
9810
+ if (!(0, import_fs7.existsSync)(filePath)) return [];
9547
9811
  let content;
9548
9812
  try {
9549
- content = (0, import_fs6.readFileSync)(filePath, "utf-8");
9813
+ content = (0, import_fs7.readFileSync)(filePath, "utf-8");
9550
9814
  } catch {
9551
9815
  return [];
9552
9816
  }
@@ -9811,24 +10075,24 @@ function getSessionRecoveryContext(meshId, opts) {
9811
10075
  }
9812
10076
  function rotateLedgerFile(meshId, currentPath) {
9813
10077
  let index = 1;
9814
- while ((0, import_fs6.existsSync)(getRotatedPath(meshId, index))) {
10078
+ while ((0, import_fs7.existsSync)(getRotatedPath(meshId, index))) {
9815
10079
  index++;
9816
10080
  if (index > 10) break;
9817
10081
  }
9818
10082
  if (index > 10) index = 10;
9819
10083
  try {
9820
- (0, import_fs6.renameSync)(currentPath, getRotatedPath(meshId, index));
10084
+ (0, import_fs7.renameSync)(currentPath, getRotatedPath(meshId, index));
9821
10085
  } catch (e) {
9822
10086
  process.stderr.write(`[adhdev-mesh] Ledger rotation failed for mesh ${meshId}: ${e?.message || e}. File will continue to grow.
9823
10087
  `);
9824
10088
  }
9825
10089
  }
9826
- var import_fs6, import_path6, import_crypto8, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, COMPACT_THRESHOLD_BYTES, ARCHIVE_TERMINAL_OLDER_THAN_MS, RECENT_FAILURE_WINDOW_MS, ARCHIVABLE_KINDS, DEFAULT_LEDGER_SLICE_LIMIT, MAX_LEDGER_SLICE_LIMIT, OPERATING_NOTE_KIND, OPERATING_NOTE_TOMBSTONE_KIND, OPERATING_NOTE_DEDUPE_WINDOW, OPERATING_NOTE_KEEP_LATEST, OPERATING_NOTE_CATEGORY_TTL_DAYS, MS_PER_DAY, meshLedgerEvents, ledgerReadCache, LEDGER_CACHE_TTL_MS, ledgerImportStoreRef, ledgerImportDone;
10090
+ var import_fs7, import_path7, import_crypto8, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, COMPACT_THRESHOLD_BYTES, ARCHIVE_TERMINAL_OLDER_THAN_MS, RECENT_FAILURE_WINDOW_MS, ARCHIVABLE_KINDS, DEFAULT_LEDGER_SLICE_LIMIT, MAX_LEDGER_SLICE_LIMIT, OPERATING_NOTE_KIND, OPERATING_NOTE_TOMBSTONE_KIND, OPERATING_NOTE_DEDUPE_WINDOW, OPERATING_NOTE_KEEP_LATEST, OPERATING_NOTE_CATEGORY_TTL_DAYS, MS_PER_DAY, meshLedgerEvents, ledgerReadCache, LEDGER_CACHE_TTL_MS, ledgerImportStoreRef, ledgerImportDone;
9827
10091
  var init_mesh_ledger = __esm({
9828
10092
  "src/mesh/mesh-ledger.ts"() {
9829
10093
  "use strict";
9830
- import_fs6 = require("fs");
9831
- import_path6 = require("path");
10094
+ import_fs7 = require("fs");
10095
+ import_path7 = require("path");
9832
10096
  import_crypto8 = require("crypto");
9833
10097
  init_config();
9834
10098
  init_dist();
@@ -11213,13 +11477,13 @@ var init_mesh_coordinator = __esm({
11213
11477
 
11214
11478
  // src/mesh/coordinator-registry.ts
11215
11479
  function getRegistryPath() {
11216
- return (0, import_path7.join)(getDaemonDataDir(), "mesh-coordinators.json");
11480
+ return (0, import_path8.join)(getDaemonDataDir(), "mesh-coordinators.json");
11217
11481
  }
11218
11482
  function loadMeshCoordinatorRegistry() {
11219
11483
  const path46 = getRegistryPath();
11220
- if (!(0, import_fs7.existsSync)(path46)) return;
11484
+ if (!(0, import_fs8.existsSync)(path46)) return;
11221
11485
  try {
11222
- const raw = JSON.parse((0, import_fs7.readFileSync)(path46, "utf-8"));
11486
+ const raw = JSON.parse((0, import_fs8.readFileSync)(path46, "utf-8"));
11223
11487
  if (!Array.isArray(raw)) return;
11224
11488
  _registry.clear();
11225
11489
  for (const entry of raw) {
@@ -11232,7 +11496,7 @@ function loadMeshCoordinatorRegistry() {
11232
11496
  }
11233
11497
  function saveRegistry() {
11234
11498
  try {
11235
- (0, import_fs7.writeFileSync)(
11499
+ (0, import_fs8.writeFileSync)(
11236
11500
  getRegistryPath(),
11237
11501
  JSON.stringify([..._registry.values()], null, 2),
11238
11502
  { encoding: "utf-8", mode: 384 }
@@ -11265,12 +11529,12 @@ function getCoordinatorForSession(sessionId) {
11265
11529
  function listCoordinatorsForWorkspace(workspace) {
11266
11530
  return [..._registry.values()].filter((e) => e.workspace === workspace);
11267
11531
  }
11268
- var import_path7, import_fs7, _registry;
11532
+ var import_path8, import_fs8, _registry;
11269
11533
  var init_coordinator_registry = __esm({
11270
11534
  "src/mesh/coordinator-registry.ts"() {
11271
11535
  "use strict";
11272
- import_path7 = require("path");
11273
- import_fs7 = require("fs");
11536
+ import_path8 = require("path");
11537
+ import_fs8 = require("fs");
11274
11538
  init_config();
11275
11539
  _registry = /* @__PURE__ */ new Map();
11276
11540
  }
@@ -11360,14 +11624,14 @@ function validateMeshRefineConfig(config, source = "inline") {
11360
11624
  const rejectedCommands = [];
11361
11625
  const deprecationWarnings = [];
11362
11626
  let bootstrapMode = "inherit";
11363
- if (!isRecord2(config)) return { valid: false, errors: ["config must be an object"], bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
11627
+ if (!isRecord3(config)) return { valid: false, errors: ["config must be an object"], bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
11364
11628
  if (config.version !== 1) errors.push("version must be 1");
11365
11629
  if (config.allowAutoPublishSubmoduleMainCommits !== void 0 && typeof config.allowAutoPublishSubmoduleMainCommits !== "boolean") {
11366
11630
  errors.push("allowAutoPublishSubmoduleMainCommits must be a boolean when provided");
11367
11631
  }
11368
11632
  const validation = config.validation;
11369
- if (validation !== void 0 && !isRecord2(validation)) errors.push("validation must be an object");
11370
- const rawBootstrapMode = isRecord2(validation) ? validation.bootstrap : void 0;
11633
+ if (validation !== void 0 && !isRecord3(validation)) errors.push("validation must be an object");
11634
+ const rawBootstrapMode = isRecord3(validation) ? validation.bootstrap : void 0;
11371
11635
  if (rawBootstrapMode !== void 0) {
11372
11636
  if (rawBootstrapMode === "inherit" || rawBootstrapMode === "skip") {
11373
11637
  bootstrapMode = rawBootstrapMode;
@@ -11375,8 +11639,8 @@ function validateMeshRefineConfig(config, source = "inline") {
11375
11639
  errors.push("validation.bootstrap must be 'inherit' or 'skip' when provided");
11376
11640
  }
11377
11641
  }
11378
- const rawCommands = isRecord2(validation) ? validation.commands : void 0;
11379
- const rawBootstrapCommands = isRecord2(validation) ? validation.bootstrapCommands : void 0;
11642
+ const rawCommands = isRecord3(validation) ? validation.commands : void 0;
11643
+ const rawBootstrapCommands = isRecord3(validation) ? validation.bootstrapCommands : void 0;
11380
11644
  if (rawCommands !== void 0 && !Array.isArray(rawCommands)) errors.push("validation.commands must be an array");
11381
11645
  if (rawBootstrapCommands !== void 0 && !Array.isArray(rawBootstrapCommands)) errors.push("validation.bootstrapCommands must be an array");
11382
11646
  if (Array.isArray(rawBootstrapCommands) && rawBootstrapCommands.length > 0) {
@@ -11399,9 +11663,9 @@ function validateMeshRefineConfig(config, source = "inline") {
11399
11663
  if (rejectedCommands.length) errors.push("one or more validation commands are invalid");
11400
11664
  return { valid: errors.length === 0, errors, bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
11401
11665
  }
11402
- function parseConfigText2(path46, text) {
11666
+ function parseConfigText3(path46, text) {
11403
11667
  if (/\.json$/i.test(path46)) return JSON.parse(text);
11404
- return yaml2.load(text);
11668
+ return yaml3.load(text);
11405
11669
  }
11406
11670
  function loadMeshRefineConfig(mesh, workspace) {
11407
11671
  const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
@@ -11412,10 +11676,10 @@ function loadMeshRefineConfig(mesh, workspace) {
11412
11676
  return { config: inline, source: "mesh.policy.refineConfig", sourceType: "mesh_policy" };
11413
11677
  }
11414
11678
  for (const relative5 of MESH_REFINE_CONFIG_LOCATIONS) {
11415
- const configPath = (0, import_path8.join)(workspace, relative5);
11416
- if (!(0, import_fs8.existsSync)(configPath)) continue;
11679
+ const configPath = (0, import_path9.join)(workspace, relative5);
11680
+ if (!(0, import_fs9.existsSync)(configPath)) continue;
11417
11681
  try {
11418
- const parsed = parseConfigText2(configPath, (0, import_fs8.readFileSync)(configPath, "utf-8"));
11682
+ const parsed = parseConfigText3(configPath, (0, import_fs9.readFileSync)(configPath, "utf-8"));
11419
11683
  const validation = validateMeshRefineConfig(parsed, relative5);
11420
11684
  if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
11421
11685
  return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
@@ -11431,20 +11695,20 @@ function loadMeshRefineConfig(mesh, workspace) {
11431
11695
  }
11432
11696
  function readPackageScripts(workspace) {
11433
11697
  try {
11434
- const parsed = JSON.parse((0, import_fs8.readFileSync)((0, import_path8.join)(workspace, "package.json"), "utf-8"));
11435
- return isRecord2(parsed?.scripts) ? parsed.scripts : {};
11698
+ const parsed = JSON.parse((0, import_fs9.readFileSync)((0, import_path9.join)(workspace, "package.json"), "utf-8"));
11699
+ return isRecord3(parsed?.scripts) ? parsed.scripts : {};
11436
11700
  } catch {
11437
11701
  return {};
11438
11702
  }
11439
11703
  }
11440
11704
  function collectProjectContextSuggestions(mesh) {
11441
11705
  const commands = mesh?.projectContext?.commands;
11442
- if (!isRecord2(commands)) return [];
11706
+ if (!isRecord3(commands)) return [];
11443
11707
  const suggestions = [];
11444
11708
  for (const category of MESH_REFINE_VALIDATION_CATEGORIES) {
11445
11709
  const entries = Array.isArray(commands[category]) ? commands[category] : [];
11446
11710
  for (const entry of entries) {
11447
- if (isRecord2(entry) && typeof entry.command === "string") suggestions.push({ command: entry.command, category });
11711
+ if (isRecord3(entry) && typeof entry.command === "string") suggestions.push({ command: entry.command, category });
11448
11712
  }
11449
11713
  }
11450
11714
  return suggestions;
@@ -11506,13 +11770,13 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
11506
11770
  unavailableReason: validation.commands.length ? void 0 : "validation_unavailable: repo mesh/refine config has no validation.commands"
11507
11771
  };
11508
11772
  }
11509
- var import_fs8, import_path8, yaml2, MESH_REFINE_VALIDATION_CATEGORIES, MESH_REFINE_VALIDATION_SCOPES, MESH_REFINE_CONFIG_LOCATIONS, MESH_REFINE_CONFIG_SCHEMA, SHELL_METACHAR_RE, SAFE_TOKEN_RE, SAFE_WIN32_EXEC_TOKEN_RE, isRecord2;
11773
+ var import_fs9, import_path9, yaml3, MESH_REFINE_VALIDATION_CATEGORIES, MESH_REFINE_VALIDATION_SCOPES, MESH_REFINE_CONFIG_LOCATIONS, MESH_REFINE_CONFIG_SCHEMA, SHELL_METACHAR_RE, SAFE_TOKEN_RE, SAFE_WIN32_EXEC_TOKEN_RE, isRecord3;
11510
11774
  var init_refine_config = __esm({
11511
11775
  "src/mesh/refine-config.ts"() {
11512
11776
  "use strict";
11513
- import_fs8 = require("fs");
11514
- import_path8 = require("path");
11515
- yaml2 = __toESM(require("js-yaml"));
11777
+ import_fs9 = require("fs");
11778
+ import_path9 = require("path");
11779
+ yaml3 = __toESM(require("js-yaml"));
11516
11780
  MESH_REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
11517
11781
  MESH_REFINE_VALIDATION_SCOPES = ["none", "web", "daemon"];
11518
11782
  MESH_REFINE_CONFIG_LOCATIONS = [
@@ -11603,7 +11867,7 @@ var init_refine_config = __esm({
11603
11867
  SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
11604
11868
  SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
11605
11869
  SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
11606
- isRecord2 = isMeshConfigRecord;
11870
+ isRecord3 = isMeshConfigRecord;
11607
11871
  }
11608
11872
  });
11609
11873
 
@@ -11622,7 +11886,7 @@ function resolveWin32GlobalBin(trimmed) {
11622
11886
  if (!dir) continue;
11623
11887
  for (const ext of WIN_EXEC_EXT) {
11624
11888
  const full = path10.join(dir, trimmed + ext);
11625
- if ((0, import_fs9.existsSync)(full)) return full;
11889
+ if ((0, import_fs10.existsSync)(full)) return full;
11626
11890
  }
11627
11891
  }
11628
11892
  return null;
@@ -11639,7 +11903,7 @@ function resolveWin32Executable(command) {
11639
11903
  if (process.platform !== "win32") return command;
11640
11904
  const trimmed = (command || "").trim();
11641
11905
  if (!trimmed) return command;
11642
- if (path10.isAbsolute(trimmed) && (0, import_fs9.existsSync)(trimmed)) return trimmed;
11906
+ if (path10.isAbsolute(trimmed) && (0, import_fs10.existsSync)(trimmed)) return trimmed;
11643
11907
  try {
11644
11908
  const out = (0, import_child_process.execFileSync)("where", [trimmed], {
11645
11909
  encoding: "utf8",
@@ -11687,12 +11951,12 @@ function buildWin32ExecFileSpawn(resolvedCommand, args) {
11687
11951
  windowsVerbatimArguments: true
11688
11952
  };
11689
11953
  }
11690
- var import_child_process, import_fs9, path10, DIRECT_EXEC_EXT, SHIM_EXEC_EXT, WIN_EXEC_EXT;
11954
+ var import_child_process, import_fs10, path10, DIRECT_EXEC_EXT, SHIM_EXEC_EXT, WIN_EXEC_EXT;
11691
11955
  var init_resolve_executable = __esm({
11692
11956
  "src/cli-adapters/resolve-executable.ts"() {
11693
11957
  "use strict";
11694
11958
  import_child_process = require("child_process");
11695
- import_fs9 = require("fs");
11959
+ import_fs10 = require("fs");
11696
11960
  path10 = __toESM(require("path"));
11697
11961
  DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
11698
11962
  SHIM_EXEC_EXT = /* @__PURE__ */ new Set([".cmd", ".bat"]);
@@ -11832,7 +12096,7 @@ function isWorktreeBootstrapStaleRunning(node, nowMs = Date.now()) {
11832
12096
  if (!Number.isFinite(startedMs)) return false;
11833
12097
  if (nowMs - startedMs <= WORKTREE_BOOTSTRAP_STALE_RUNNING_MS) return false;
11834
12098
  const workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
11835
- if (!workspace || !(0, import_fs10.existsSync)(workspace)) return false;
12099
+ if (!workspace || !(0, import_fs11.existsSync)(workspace)) return false;
11836
12100
  try {
11837
12101
  const out = (0, import_node_child_process3.execFileSync)(resolveWin32Executable("git"), ["status", "--porcelain"], {
11838
12102
  cwd: workspace,
@@ -11853,9 +12117,9 @@ function shouldDeferDispatchForBootstrap(node, nowMs = Date.now()) {
11853
12117
  if (node?.worktreeBootstrap?.status !== "running") return false;
11854
12118
  return !isWorktreeBootstrapStaleRunning(node, nowMs);
11855
12119
  }
11856
- function parseConfigText3(path46, text) {
12120
+ function parseConfigText4(path46, text) {
11857
12121
  if (/\.json$/i.test(path46)) return JSON.parse(text);
11858
- return yaml3.load(text);
12122
+ return yaml4.load(text);
11859
12123
  }
11860
12124
  function truncateOutput(value) {
11861
12125
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
@@ -11895,10 +12159,10 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
11895
12159
  return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
11896
12160
  }
11897
12161
  for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
11898
- const configPath = (0, import_path9.join)(workspace, relative5);
11899
- if (!(0, import_fs10.existsSync)(configPath)) continue;
12162
+ const configPath = (0, import_path10.join)(workspace, relative5);
12163
+ if (!(0, import_fs11.existsSync)(configPath)) continue;
11900
12164
  try {
11901
- const parsed = parseConfigText3(configPath, (0, import_fs10.readFileSync)(configPath, "utf-8"));
12165
+ const parsed = parseConfigText4(configPath, (0, import_fs11.readFileSync)(configPath, "utf-8"));
11902
12166
  const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
11903
12167
  if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
11904
12168
  return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
@@ -11911,9 +12175,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
11911
12175
  function computeStaleInputsDigest(workspace, staleInputs) {
11912
12176
  const digest = {};
11913
12177
  for (const relative5 of staleInputs ?? []) {
11914
- const filePath = (0, import_path9.join)(workspace, relative5);
12178
+ const filePath = (0, import_path10.join)(workspace, relative5);
11915
12179
  try {
11916
- digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs10.readFileSync)(filePath)).digest("hex");
12180
+ digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs11.readFileSync)(filePath)).digest("hex");
11917
12181
  } catch {
11918
12182
  digest[relative5] = "absent";
11919
12183
  }
@@ -11984,10 +12248,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
11984
12248
  staleInputs: loaded.config.staleInputs
11985
12249
  };
11986
12250
  const staleInputPaths = loaded.config.staleInputs ?? [];
11987
- const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs10.existsSync)((0, import_path9.join)(workspace, p)));
12251
+ const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs11.existsSync)((0, import_path10.join)(workspace, p)));
11988
12252
  for (const command of validation.commands) {
11989
12253
  if (initiallyAbsent.length > 0) {
11990
- const appearedNow = initiallyAbsent.filter((p) => (0, import_fs10.existsSync)((0, import_path9.join)(workspace, p)));
12254
+ const appearedNow = initiallyAbsent.filter((p) => (0, import_fs11.existsSync)((0, import_path10.join)(workspace, p)));
11991
12255
  if (appearedNow.length > 0) {
11992
12256
  state.status = "stale";
11993
12257
  state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -11995,7 +12259,7 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
11995
12259
  return state;
11996
12260
  }
11997
12261
  }
11998
- const cwd = command.cwd ? (0, import_path9.resolve)(workspace, command.cwd) : workspace;
12262
+ const cwd = command.cwd ? (0, import_path10.resolve)(workspace, command.cwd) : workspace;
11999
12263
  const startedAt = Date.now();
12000
12264
  state.lastCommand = command.displayCommand;
12001
12265
  const resolvedCommand = resolveWin32Executable(command.command);
@@ -12055,16 +12319,16 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
12055
12319
  }
12056
12320
  return state;
12057
12321
  }
12058
- var import_fs10, import_path9, import_node_child_process3, import_node_crypto2, import_node_util3, yaml3, WORKTREE_BOOTSTRAP_STALE_RUNNING_MS, SUBMODULE_DEFAULT_BRANCH_FALLBACK, MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS, MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA, DEFAULT_TIMEOUT_MS2, DEFAULT_OUTPUT_LIMIT_BYTES, OUTPUT_SUMMARY_CHARS;
12322
+ var import_fs11, import_path10, import_node_child_process3, import_node_crypto2, import_node_util3, yaml4, WORKTREE_BOOTSTRAP_STALE_RUNNING_MS, SUBMODULE_DEFAULT_BRANCH_FALLBACK, MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS, MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA, DEFAULT_TIMEOUT_MS2, DEFAULT_OUTPUT_LIMIT_BYTES, OUTPUT_SUMMARY_CHARS;
12059
12323
  var init_worktree_bootstrap_config = __esm({
12060
12324
  "src/mesh/worktree-bootstrap-config.ts"() {
12061
12325
  "use strict";
12062
- import_fs10 = require("fs");
12063
- import_path9 = require("path");
12326
+ import_fs11 = require("fs");
12327
+ import_path10 = require("path");
12064
12328
  import_node_child_process3 = require("child_process");
12065
12329
  import_node_crypto2 = require("crypto");
12066
12330
  import_node_util3 = require("util");
12067
- yaml3 = __toESM(require("js-yaml"));
12331
+ yaml4 = __toESM(require("js-yaml"));
12068
12332
  init_resolve_executable();
12069
12333
  init_refine_config();
12070
12334
  WORKTREE_BOOTSTRAP_STALE_RUNNING_MS = 10 * 60 * 1e3;
@@ -12116,224 +12380,6 @@ var init_worktree_bootstrap_config = __esm({
12116
12380
  }
12117
12381
  });
12118
12382
 
12119
- // src/config/mesh-json-config.ts
12120
- var mesh_json_config_exports = {};
12121
- __export(mesh_json_config_exports, {
12122
- MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
12123
- MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
12124
- applyRepoMeshConfig: () => applyRepoMeshConfig,
12125
- buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
12126
- loadRepoMeshJsonConfig: () => loadRepoMeshJsonConfig,
12127
- mergeEffectiveCoordinatorConfig: () => mergeEffectiveCoordinatorConfig,
12128
- mergeEffectiveOperatingNotes: () => mergeEffectiveOperatingNotes,
12129
- normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
12130
- serializeMeshJsonConfigScaffold: () => serializeMeshJsonConfigScaffold
12131
- });
12132
- function isRecord3(value) {
12133
- return !!value && typeof value === "object" && !Array.isArray(value);
12134
- }
12135
- function parseConfigText4(path46, text) {
12136
- if (/\.json$/i.test(path46)) return JSON.parse(text);
12137
- return yaml4.load(text);
12138
- }
12139
- function normalizeOperatingNote(value) {
12140
- if (!isRecord3(value)) return null;
12141
- const text = typeof value.text === "string" ? value.text.trim() : "";
12142
- if (!text) return null;
12143
- const category = value.category === "provider_quirk" || value.category === "pattern_to_avoid" || value.category === "recovery_lesson" ? value.category : void 0;
12144
- return {
12145
- text,
12146
- ...category ? { category } : {},
12147
- ...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {},
12148
- ...typeof value.sourceCoordinator === "string" ? { sourceCoordinator: value.sourceCoordinator } : {},
12149
- // Operating-notes lifecycle: a repo-declared note may pin itself or set an
12150
- // explicit expiry, same as a runtime-recorded one. Phase 2 (b)/(c): it may
12151
- // also declare supersedes/subjectKey to retire an earlier note or group
12152
- // same-subject notes for folding.
12153
- ...value.pinned === true ? { pinned: true } : {},
12154
- ...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {},
12155
- ...typeof value.supersedes === "string" ? { supersedes: value.supersedes } : {},
12156
- ...typeof value.subjectKey === "string" ? { subjectKey: value.subjectKey } : {}
12157
- };
12158
- }
12159
- function normalizeRepoMeshDeclarativeConfig(parsed) {
12160
- const errors = [];
12161
- if (!isRecord3(parsed)) return { valid: false, errors: ["config must be an object"] };
12162
- if (parsed.version !== 1) {
12163
- return { valid: false, errors: [`version must be 1 (got ${JSON.stringify(parsed.version)})`] };
12164
- }
12165
- const config = { version: 1 };
12166
- if (parsed.coordinator !== void 0) {
12167
- if (isRecord3(parsed.coordinator)) {
12168
- const coord = {};
12169
- const c = parsed.coordinator;
12170
- if (typeof c.systemPromptOverride === "string") coord.systemPromptOverride = c.systemPromptOverride;
12171
- if (typeof c.systemPromptAppend === "string") coord.systemPromptAppend = c.systemPromptAppend;
12172
- if (Number.isFinite(Number(c.maxPromptChars))) coord.maxPromptChars = Number(c.maxPromptChars);
12173
- config.coordinator = coord;
12174
- } else {
12175
- errors.push("coordinator must be an object when provided");
12176
- }
12177
- }
12178
- if (parsed.operatingNotes !== void 0) {
12179
- if (Array.isArray(parsed.operatingNotes)) {
12180
- const notes = parsed.operatingNotes.map(normalizeOperatingNote).filter((n) => n !== null);
12181
- if (notes.length) config.operatingNotes = notes;
12182
- } else {
12183
- errors.push("operatingNotes must be an array when provided");
12184
- }
12185
- }
12186
- if (parsed.limits !== void 0) {
12187
- if (isRecord3(parsed.limits)) {
12188
- const limits = {};
12189
- if (Number.isFinite(Number(parsed.limits.maxNoteChars))) limits.maxNoteChars = Number(parsed.limits.maxNoteChars);
12190
- if (Number.isFinite(Number(parsed.limits.maxNotes))) limits.maxNotes = Number(parsed.limits.maxNotes);
12191
- if (Object.keys(limits).length) config.limits = limits;
12192
- } else {
12193
- errors.push("limits must be an object when provided");
12194
- }
12195
- }
12196
- return { valid: true, config, errors };
12197
- }
12198
- function loadRepoMeshJsonConfig(workspace) {
12199
- const bases = [];
12200
- const ws = typeof workspace === "string" ? workspace.trim() : "";
12201
- if (ws) bases.push(ws);
12202
- let cwd = "";
12203
- try {
12204
- cwd = process.cwd();
12205
- } catch {
12206
- }
12207
- if (cwd && cwd !== ws) bases.push(cwd);
12208
- for (const base of bases) {
12209
- for (const relative5 of MESH_JSON_CONFIG_LOCATIONS) {
12210
- const configPath = (0, import_path10.join)(base, relative5);
12211
- if (!(0, import_fs11.existsSync)(configPath)) continue;
12212
- try {
12213
- const parsed = parseConfigText4(configPath, (0, import_fs11.readFileSync)(configPath, "utf-8"));
12214
- const result = normalizeRepoMeshDeclarativeConfig(parsed);
12215
- if (!result.valid || !result.config) {
12216
- return { source: relative5, sourceType: "invalid", path: configPath, error: result.errors.join("; ") };
12217
- }
12218
- return { config: result.config, source: relative5, sourceType: "repo_file", path: configPath };
12219
- } catch (error) {
12220
- return { source: relative5, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
12221
- }
12222
- }
12223
- }
12224
- return {
12225
- source: "unavailable",
12226
- sourceType: "unavailable",
12227
- error: `No repo mesh config found. Checked: ${MESH_JSON_CONFIG_LOCATIONS.join(", ")}`
12228
- };
12229
- }
12230
- function mergeEffectiveCoordinatorConfig(repoCoord, localCoord) {
12231
- const out = { ...localCoord || {} };
12232
- const localOverride = localCoord?.systemPromptOverride?.trim();
12233
- const repoOverride = repoCoord?.systemPromptOverride?.trim();
12234
- if (localOverride) {
12235
- out.systemPromptOverride = localCoord.systemPromptOverride;
12236
- } else if (repoOverride) {
12237
- out.systemPromptOverride = repoCoord.systemPromptOverride;
12238
- } else {
12239
- delete out.systemPromptOverride;
12240
- }
12241
- const repoAppend = repoCoord?.systemPromptAppend?.trim() ? repoCoord.systemPromptAppend.trim() : "";
12242
- const localAppendRaw = localCoord?.systemPromptAppend ?? localCoord?.systemPromptSuffix;
12243
- const localAppend = localAppendRaw?.trim() ? localAppendRaw.trim() : "";
12244
- const stacked = [repoAppend, localAppend].filter(Boolean).join("\n\n");
12245
- if (stacked) {
12246
- out.systemPromptAppend = stacked;
12247
- delete out.systemPromptSuffix;
12248
- }
12249
- return out;
12250
- }
12251
- function mergeEffectiveOperatingNotes(repoNotes, ledgerNotes) {
12252
- const usable = (notes) => Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
12253
- const repo = usable(repoNotes);
12254
- const ledger = usable(ledgerNotes);
12255
- const ledgerTexts = new Set(ledger.map((n) => n.text.trim()));
12256
- const repoKept = repo.filter((n) => !ledgerTexts.has(n.text.trim()));
12257
- const merged = [...repoKept, ...ledger];
12258
- return merged.length ? merged : void 0;
12259
- }
12260
- function applyRepoMeshConfig(mesh, repoConfig) {
12261
- if (!repoConfig) return mesh;
12262
- return {
12263
- ...mesh,
12264
- coordinator: mergeEffectiveCoordinatorConfig(repoConfig.coordinator, mesh.coordinator)
12265
- };
12266
- }
12267
- function buildMeshJsonConfigScaffold(mesh) {
12268
- const scaffold = { version: 1 };
12269
- const coord = {};
12270
- const override = mesh.coordinator?.systemPromptOverride;
12271
- if (typeof override === "string" && override.trim()) coord.systemPromptOverride = override;
12272
- const append = mesh.coordinator?.systemPromptAppend ?? mesh.coordinator?.systemPromptSuffix;
12273
- if (typeof append === "string" && append.trim()) coord.systemPromptAppend = append;
12274
- if (Object.keys(coord).length) scaffold.coordinator = coord;
12275
- return scaffold;
12276
- }
12277
- function serializeMeshJsonConfigScaffold(config) {
12278
- return JSON.stringify(config, null, 2);
12279
- }
12280
- var import_fs11, import_path10, yaml4, MESH_JSON_CONFIG_LOCATIONS, MESH_JSON_CONFIG_SCHEMA;
12281
- var init_mesh_json_config = __esm({
12282
- "src/config/mesh-json-config.ts"() {
12283
- "use strict";
12284
- import_fs11 = require("fs");
12285
- import_path10 = require("path");
12286
- yaml4 = __toESM(require("js-yaml"));
12287
- MESH_JSON_CONFIG_LOCATIONS = [
12288
- ".adhdev/mesh.json",
12289
- ".adhdev/mesh.yaml",
12290
- ".adhdev/mesh.yml"
12291
- ];
12292
- MESH_JSON_CONFIG_SCHEMA = {
12293
- $schema: "https://json-schema.org/draft/2020-12/schema",
12294
- title: "ADHDev Repo Mesh Declarative Config",
12295
- type: "object",
12296
- additionalProperties: false,
12297
- required: ["version"],
12298
- properties: {
12299
- version: { const: 1 },
12300
- coordinator: {
12301
- type: "object",
12302
- additionalProperties: false,
12303
- properties: {
12304
- systemPromptOverride: { type: "string" },
12305
- systemPromptAppend: { type: "string" },
12306
- maxPromptChars: { type: "number", minimum: 1 }
12307
- }
12308
- },
12309
- operatingNotes: {
12310
- type: "array",
12311
- maxItems: 200,
12312
- items: {
12313
- type: "object",
12314
- additionalProperties: false,
12315
- required: ["text"],
12316
- properties: {
12317
- text: { type: "string", minLength: 1 },
12318
- category: { enum: ["provider_quirk", "pattern_to_avoid", "recovery_lesson"] },
12319
- createdAt: { type: "string" },
12320
- sourceCoordinator: { type: "string" }
12321
- }
12322
- }
12323
- },
12324
- limits: {
12325
- type: "object",
12326
- additionalProperties: false,
12327
- properties: {
12328
- maxNoteChars: { type: "number", minimum: 1 },
12329
- maxNotes: { type: "number", minimum: 1 }
12330
- }
12331
- }
12332
- }
12333
- };
12334
- }
12335
- });
12336
-
12337
12383
  // src/mesh/mesh-fast-forward.ts
12338
12384
  async function fastForwardMeshNode(args) {
12339
12385
  const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
@@ -16657,6 +16703,16 @@ function __resetIdleAutoFastForwardForTests() {
16657
16703
  continuousAutoFastForwardLastScan.clear();
16658
16704
  autoFastForwardWorkspaceLease.clear();
16659
16705
  }
16706
+ function loadRepoConfigForNode(node) {
16707
+ const workspace = typeof node?.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
16708
+ if (!workspace) return null;
16709
+ try {
16710
+ const result = loadRepoMeshJsonConfig(workspace);
16711
+ return result.sourceType === "repo_file" && result.config ? result.config : null;
16712
+ } catch {
16713
+ return null;
16714
+ }
16715
+ }
16660
16716
  function getMeshWithCache(components, meshId) {
16661
16717
  const localMesh = getMesh(meshId);
16662
16718
  const cachedMesh = components.router?.getCachedInlineMesh(meshId);
@@ -16919,7 +16975,9 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
16919
16975
  ...delegatedWorkerAutoApproveSettings(
16920
16976
  mesh?.policy,
16921
16977
  node?.policy,
16922
- components.providerLoader?.getMeta(providerType)
16978
+ components.providerLoader?.getMeta(providerType),
16979
+ loadRepoConfigForNode(node),
16980
+ providerType
16923
16981
  ),
16924
16982
  ...localDaemonId ? { meshCoordinatorDaemonId: localDaemonId } : {},
16925
16983
  // COMPLETION-PROPAGATION F5: (re)stamp the coordinator SESSION anchor from THIS
@@ -17358,10 +17416,10 @@ function liveSessionCountForNode(components, meshId, nodeId) {
17358
17416
  }
17359
17417
  return count;
17360
17418
  }
17361
- function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
17419
+ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node) {
17362
17420
  if (inWindowAutoLaunchSessionIdsForNode(meshId, nodeId).length > 0) return true;
17363
17421
  const busySessionIds = new Set(
17364
- getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId)).map((task) => readNonEmptyString(task.assignedSessionId)).filter(Boolean)
17422
+ getQueue(meshId, { status: ["assigned"] }).filter((task2) => daemonIdsEquivalent(task2.assignedNodeId, nodeId)).map((task2) => readNonEmptyString(task2.assignedSessionId)).filter(Boolean)
17365
17423
  );
17366
17424
  return components.instanceManager.getByCategory("cli").some((inst) => {
17367
17425
  const state = inst.getState();
@@ -17374,6 +17432,12 @@ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
17374
17432
  if (isTerminalSessionStatus(status)) return false;
17375
17433
  const sessionId = readNonEmptyString(state.instanceId);
17376
17434
  if (sessionId && busySessionIds.has(sessionId)) return false;
17435
+ if (task.requiredTags?.length) {
17436
+ const sessionProviderType = state.type || readNonEmptyString(settings.providerType);
17437
+ if (sessionProviderType && !nodeSatisfiesRequiredTags(task.requiredTags, buildMeshNodeCapabilityTags(node, sessionProviderType))) {
17438
+ return false;
17439
+ }
17440
+ }
17377
17441
  return true;
17378
17442
  });
17379
17443
  }
@@ -17654,7 +17718,7 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
17654
17718
  sweepExpiredCooldowns();
17655
17719
  continue;
17656
17720
  }
17657
- if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId)) {
17721
+ if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node)) {
17658
17722
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
17659
17723
  continue;
17660
17724
  }
@@ -17697,7 +17761,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
17697
17761
  ...delegatedWorkerAutoApproveSettings(
17698
17762
  mesh?.policy,
17699
17763
  node?.policy,
17700
- components.providerLoader?.getMeta(resolved.providerType)
17764
+ components.providerLoader?.getMeta(resolved.providerType),
17765
+ loadRepoConfigForNode(node),
17766
+ resolved.providerType
17701
17767
  ),
17702
17768
  launchedByCoordinator: true,
17703
17769
  autoLaunchedForQueueTaskId: task.id
@@ -18163,6 +18229,7 @@ var init_mesh_queue_assignment = __esm({
18163
18229
  init_mesh_event_trace();
18164
18230
  init_mesh_warmup_deadline();
18165
18231
  init_repo_mesh_types();
18232
+ init_mesh_json_config();
18166
18233
  init_dist();
18167
18234
  init_mesh_node_slots();
18168
18235
  init_mesh_events_stale();
@@ -21721,7 +21788,20 @@ function injectMeshSystemMessage(components, args) {
21721
21788
  ...delegatedWorkerAutoApproveSettings(
21722
21789
  mesh?.policy,
21723
21790
  node?.policy,
21724
- components.providerLoader?.getMeta(recoveryContext.failedProviderType)
21791
+ components.providerLoader?.getMeta(recoveryContext.failedProviderType),
21792
+ // Recovery relaunch: same repo-declared requested mode as the
21793
+ // primary path. node.workspace missing → null → provider default.
21794
+ (() => {
21795
+ const ws = typeof node?.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
21796
+ if (!ws) return null;
21797
+ try {
21798
+ const r = loadRepoMeshJsonConfig(ws);
21799
+ return r.sourceType === "repo_file" && r.config ? r.config : null;
21800
+ } catch {
21801
+ return null;
21802
+ }
21803
+ })(),
21804
+ recoveryContext.failedProviderType
21725
21805
  ),
21726
21806
  launchedByCoordinator: true
21727
21807
  }
@@ -22112,6 +22192,7 @@ var init_mesh_event_forwarding = __esm({
22112
22192
  init_mesh_event_trace();
22113
22193
  init_snapshot();
22114
22194
  init_repo_mesh_types();
22195
+ init_mesh_json_config();
22115
22196
  init_dist();
22116
22197
  init_mesh_events_stale();
22117
22198
  init_mesh_task_inflight();
@@ -30556,6 +30637,9 @@ __export(index_exports, {
30556
30637
  MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
30557
30638
  MESH_CONVERGE_FAST_FORWARD_TAG: () => MESH_CONVERGE_FAST_FORWARD_TAG,
30558
30639
  MESH_CONVERGE_REFINE_TAG: () => MESH_CONVERGE_REFINE_TAG,
30640
+ MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
30641
+ MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
30642
+ MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE: () => MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
30559
30643
  MESH_MAX_PARALLEL_TASKS_MAX: () => MESH_MAX_PARALLEL_TASKS_MAX,
30560
30644
  MESH_MAX_PARALLEL_TASKS_MIN: () => MESH_MAX_PARALLEL_TASKS_MIN,
30561
30645
  MESH_MISSION_LIST_HISTORY_ID_LIMIT: () => MESH_MISSION_LIST_HISTORY_ID_LIMIT,
@@ -30615,6 +30699,7 @@ __export(index_exports, {
30615
30699
  buildMeshActiveWorkSummary: () => buildMeshActiveWorkSummary,
30616
30700
  buildMeshAsyncRefineJobs: () => buildMeshAsyncRefineJobs,
30617
30701
  buildMeshHostRequiredFailure: () => buildMeshHostRequiredFailure,
30702
+ buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
30618
30703
  buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
30619
30704
  buildMeshLedgerReplicaEvidence: () => buildMeshLedgerReplicaEvidence,
30620
30705
  buildMeshMagiActivity: () => buildMeshMagiActivity,
@@ -30779,6 +30864,7 @@ __export(index_exports, {
30779
30864
  loadMeshCoordinatorRegistry: () => loadMeshCoordinatorRegistry,
30780
30865
  loadMeshRefineConfig: () => loadMeshRefineConfig,
30781
30866
  loadMeshWorktreeBootstrapConfig: () => loadMeshWorktreeBootstrapConfig,
30867
+ loadRepoMeshJsonConfig: () => loadRepoMeshJsonConfig,
30782
30868
  loadRepoSettings: () => loadRepoSettings,
30783
30869
  loadState: () => loadState,
30784
30870
  logCommand: () => logCommand,
@@ -30819,6 +30905,7 @@ __export(index_exports, {
30819
30905
  normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
30820
30906
  normalizeMessageParts: () => normalizeMessageParts,
30821
30907
  normalizeRepoIdentity: () => normalizeRepoIdentity,
30908
+ normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
30822
30909
  normalizeSessionModalFields: () => normalizeSessionModalFields,
30823
30910
  parsePorcelainV2Status: () => parsePorcelainV2Status,
30824
30911
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
@@ -30889,6 +30976,7 @@ __export(index_exports, {
30889
30976
  runMeshWorktreeBootstrap: () => runMeshWorktreeBootstrap,
30890
30977
  saveConfig: () => saveConfig,
30891
30978
  saveState: () => saveState,
30979
+ serializeMeshJsonConfigScaffold: () => serializeMeshJsonConfigScaffold,
30892
30980
  serializeV2EnvelopeToWire: () => serializeV2EnvelopeToWire,
30893
30981
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
30894
30982
  setLogLevel: () => setLogLevel,
@@ -31338,6 +31426,7 @@ function detectClaudeAskUserQuestionPromptFromJson(value, providerType = "claude
31338
31426
 
31339
31427
  // src/index.ts
31340
31428
  init_repo_mesh_types();
31429
+ init_mesh_json_config();
31341
31430
 
31342
31431
  // src/git/index.ts
31343
31432
  init_git_executor();
@@ -60653,6 +60742,139 @@ var meshCrudHandlers = {
60653
60742
  return { success: false, error: e.message };
60654
60743
  }
60655
60744
  },
60745
+ // READ path for `.adhdev/mesh.json` — returns the currently-committed repo
60746
+ // config (parsed + normalized) for a workspace so a UI can render/edit the
60747
+ // existing declarative zones (notably `providerDefaults.autoApproveModes`)
60748
+ // WITHOUT re-deriving them from the machine-local scaffold. Never writes.
60749
+ // `config` is undefined when no repo file exists (sourceType 'unavailable') or
60750
+ // it is unparseable (sourceType 'invalid', with the parse error surfaced).
60751
+ read_mesh_json_config: async (_ctx, args) => {
60752
+ const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
60753
+ try {
60754
+ const { loadRepoMeshJsonConfig: loadRepoMeshJsonConfig2 } = await Promise.resolve().then(() => (init_mesh_json_config(), mesh_json_config_exports));
60755
+ const loaded = loadRepoMeshJsonConfig2(workspace);
60756
+ return {
60757
+ success: true,
60758
+ workspace,
60759
+ sourceType: loaded.sourceType,
60760
+ source: loaded.source,
60761
+ ...loaded.path ? { path: loaded.path } : {},
60762
+ ...loaded.error ? { error: loaded.error } : {},
60763
+ config: loaded.config,
60764
+ // Convenience projection so the UI does not have to reach into config.
60765
+ providerDefaults: loaded.config?.providerDefaults
60766
+ };
60767
+ } catch (e) {
60768
+ return { success: false, error: e.message };
60769
+ }
60770
+ },
60771
+ // Partial-edit WRITE path for `.adhdev/mesh.json` `providerDefaults` — a
60772
+ // READ-MODIFY-WRITE that preserves operator hand-edits. Unlike
60773
+ // write_mesh_json_config (which rebuilds the WHOLE file from the machine-local
60774
+ // scaffold and can silently drop hand-edited zones), this parses the existing
60775
+ // repo file, merges ONLY the providerDefaults.autoApproveModes zone, and
60776
+ // re-serializes — coordinator prompt, operating notes and limits authored in
60777
+ // the repo are carried through untouched. Defaults to dry-run.
60778
+ //
60779
+ // args: { workspace?, autoApproveModes: Record<providerType,modeId>, write?, merge? }
60780
+ // merge=true (default): per-provider merge into the existing map; a modeId of
60781
+ // '' | null removes that provider's entry. merge=false: REPLACE the whole
60782
+ // autoApproveModes map with the supplied one.
60783
+ set_mesh_provider_defaults: async (_ctx, args) => {
60784
+ const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
60785
+ const write = args?.write === true;
60786
+ const merge = args?.merge !== false;
60787
+ const inputModes = args?.autoApproveModes;
60788
+ if (inputModes !== void 0 && (typeof inputModes !== "object" || inputModes === null || Array.isArray(inputModes))) {
60789
+ return { success: false, error: "autoApproveModes must be an object (providerType \u2192 modeId) when provided" };
60790
+ }
60791
+ try {
60792
+ const {
60793
+ loadRepoMeshJsonConfig: loadRepoMeshJsonConfig2,
60794
+ normalizeRepoMeshDeclarativeConfig: normalizeRepoMeshDeclarativeConfig2,
60795
+ MESH_JSON_CONFIG_LOCATIONS: MESH_JSON_CONFIG_LOCATIONS2
60796
+ } = await Promise.resolve().then(() => (init_mesh_json_config(), mesh_json_config_exports));
60797
+ const { existsSync: existsSync57, readFileSync: readFileSync44, mkdirSync: mkdirSync23, writeFileSync: writeFileSync25 } = await import("fs");
60798
+ const { dirname: dirname19, join: join54 } = await import("path");
60799
+ const yaml6 = await import("js-yaml");
60800
+ const relativePath = MESH_JSON_CONFIG_LOCATIONS2[0];
60801
+ let baseDoc = { version: 1 };
60802
+ let existingPath = join54(workspace, relativePath);
60803
+ let existedAsYaml = false;
60804
+ for (const relative5 of MESH_JSON_CONFIG_LOCATIONS2) {
60805
+ const candidate = join54(workspace, relative5);
60806
+ if (!existsSync57(candidate)) continue;
60807
+ try {
60808
+ const text = readFileSync44(candidate, "utf-8");
60809
+ const parsed = /\.json$/i.test(candidate) ? JSON.parse(text) : yaml6.load(text);
60810
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
60811
+ baseDoc = parsed;
60812
+ existingPath = candidate;
60813
+ existedAsYaml = !/\.json$/i.test(candidate);
60814
+ }
60815
+ } catch (e) {
60816
+ return { success: false, error: `existing ${relative5} is unparseable, refusing to overwrite: ${e?.message || e}` };
60817
+ }
60818
+ break;
60819
+ }
60820
+ const existingPd = baseDoc.providerDefaults && typeof baseDoc.providerDefaults === "object" && !Array.isArray(baseDoc.providerDefaults) ? baseDoc.providerDefaults : {};
60821
+ const existingModes = existingPd.autoApproveModes && typeof existingPd.autoApproveModes === "object" && !Array.isArray(existingPd.autoApproveModes) ? { ...existingPd.autoApproveModes } : {};
60822
+ const nextModes = merge ? existingModes : {};
60823
+ if (inputModes) {
60824
+ for (const [providerType, modeId] of Object.entries(inputModes)) {
60825
+ const type = typeof providerType === "string" ? providerType.trim() : "";
60826
+ if (!type) continue;
60827
+ const id = typeof modeId === "string" ? modeId.trim() : "";
60828
+ if (id) nextModes[type] = id;
60829
+ else delete nextModes[type];
60830
+ }
60831
+ }
60832
+ const nextDoc = { ...baseDoc, version: 1 };
60833
+ if (Object.keys(nextModes).length) {
60834
+ nextDoc.providerDefaults = { ...existingPd, autoApproveModes: nextModes };
60835
+ } else {
60836
+ if (nextDoc.providerDefaults) {
60837
+ const { autoApproveModes, ...restPd } = nextDoc.providerDefaults;
60838
+ if (Object.keys(restPd).length) nextDoc.providerDefaults = restPd;
60839
+ else delete nextDoc.providerDefaults;
60840
+ }
60841
+ }
60842
+ const validation = normalizeRepoMeshDeclarativeConfig2(nextDoc);
60843
+ if (!validation.valid) {
60844
+ return { success: false, error: `merged mesh.json is invalid: ${validation.errors.join("; ")}` };
60845
+ }
60846
+ const absolutePath = existingPath;
60847
+ const serialized = existedAsYaml ? yaml6.dump(nextDoc, { indent: 2 }) : `${JSON.stringify(nextDoc, null, 2)}
60848
+ `;
60849
+ if (!write) {
60850
+ return {
60851
+ success: true,
60852
+ written: false,
60853
+ dryRun: true,
60854
+ path: absolutePath,
60855
+ relativePath,
60856
+ merge,
60857
+ providerDefaults: nextDoc.providerDefaults,
60858
+ preview: serialized,
60859
+ note: "Dry-run: nothing written. Re-run with write=true to persist. Only the providerDefaults zone is merged; other repo zones are preserved."
60860
+ };
60861
+ }
60862
+ mkdirSync23(dirname19(absolutePath), { recursive: true });
60863
+ writeFileSync25(absolutePath, serialized, "utf-8");
60864
+ return {
60865
+ success: true,
60866
+ written: true,
60867
+ dryRun: false,
60868
+ path: absolutePath,
60869
+ relativePath,
60870
+ merge,
60871
+ providerDefaults: nextDoc.providerDefaults,
60872
+ note: "Wrote providerDefaults into .adhdev/mesh.json (read-modify-write; other zones preserved). Commit it to the repo."
60873
+ };
60874
+ } catch (e) {
60875
+ return { success: false, error: e.message };
60876
+ }
60877
+ },
60656
60878
  delete_mesh: async (_ctx, args) => {
60657
60879
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
60658
60880
  if (!meshId) return { success: false, error: "meshId required" };
@@ -76776,6 +76998,9 @@ var V1_CONTRACT_VERSION = "1.0.0";
76776
76998
  MAX_LEDGER_SLICE_LIMIT,
76777
76999
  MESH_CONVERGE_FAST_FORWARD_TAG,
76778
77000
  MESH_CONVERGE_REFINE_TAG,
77001
+ MESH_JSON_CONFIG_LOCATIONS,
77002
+ MESH_JSON_CONFIG_SCHEMA,
77003
+ MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
76779
77004
  MESH_MAX_PARALLEL_TASKS_MAX,
76780
77005
  MESH_MAX_PARALLEL_TASKS_MIN,
76781
77006
  MESH_MISSION_LIST_HISTORY_ID_LIMIT,
@@ -76835,6 +77060,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
76835
77060
  buildMeshActiveWorkSummary,
76836
77061
  buildMeshAsyncRefineJobs,
76837
77062
  buildMeshHostRequiredFailure,
77063
+ buildMeshJsonConfigScaffold,
76838
77064
  buildMeshLedgerReconciliationEvidence,
76839
77065
  buildMeshLedgerReplicaEvidence,
76840
77066
  buildMeshMagiActivity,
@@ -76999,6 +77225,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
76999
77225
  loadMeshCoordinatorRegistry,
77000
77226
  loadMeshRefineConfig,
77001
77227
  loadMeshWorktreeBootstrapConfig,
77228
+ loadRepoMeshJsonConfig,
77002
77229
  loadRepoSettings,
77003
77230
  loadState,
77004
77231
  logCommand,
@@ -77039,6 +77266,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
77039
77266
  normalizeMeshWorkerResult,
77040
77267
  normalizeMessageParts,
77041
77268
  normalizeRepoIdentity,
77269
+ normalizeRepoMeshDeclarativeConfig,
77042
77270
  normalizeSessionModalFields,
77043
77271
  parsePorcelainV2Status,
77044
77272
  parseProviderSourceConfigUpdate,
@@ -77109,6 +77337,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
77109
77337
  runMeshWorktreeBootstrap,
77110
77338
  saveConfig,
77111
77339
  saveState,
77340
+ serializeMeshJsonConfigScaffold,
77112
77341
  serializeV2EnvelopeToWire,
77113
77342
  setDebugRuntimeConfig,
77114
77343
  setLogLevel,