@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/config/mesh-json-config.d.ts +62 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +629 -400
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +592 -370
- package/dist/index.mjs.map +1 -1
- package/dist/repo-mesh-types.d.ts +25 -3
- package/package.json +3 -3
- package/src/commands/med-family/mesh-crud.ts +155 -0
- package/src/config/mesh-json-config.ts +103 -0
- package/src/index.ts +18 -0
- package/src/mesh/mesh-event-forwarding.ts +12 -0
- package/src/mesh/mesh-queue-assignment.ts +53 -3
- package/src/repo-mesh-types.ts +54 -7
package/dist/index.mjs
CHANGED
|
@@ -179,7 +179,7 @@ function mergeAndNormalizePolicy(base, patch) {
|
|
|
179
179
|
}
|
|
180
180
|
return policy;
|
|
181
181
|
}
|
|
182
|
-
function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
|
|
182
|
+
function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider, repoConfig, providerType) {
|
|
183
183
|
let enabled = true;
|
|
184
184
|
if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
|
|
185
185
|
enabled = nodePolicy.delegatedWorkerAutoApprove;
|
|
@@ -189,14 +189,17 @@ function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
|
|
|
189
189
|
if (!enabled) return false;
|
|
190
190
|
const modes = provider?.autoApproveModes;
|
|
191
191
|
if (!modes) return true;
|
|
192
|
-
const
|
|
193
|
-
|
|
192
|
+
const requestedModeRaw = typeof providerType === "string" ? repoConfig?.providerDefaults?.autoApproveModes?.[providerType.trim()] : void 0;
|
|
193
|
+
const requestedModeId = typeof requestedModeRaw === "string" && requestedModeRaw.trim() ? requestedModeRaw.trim() : "";
|
|
194
|
+
const requestedMode = requestedModeId ? modes.modes.find((mode) => mode.id === requestedModeId) : void 0;
|
|
195
|
+
const selectedMode = requestedMode ?? modes.modes.find((mode) => mode.id === modes.default);
|
|
196
|
+
if (!selectedMode || selectedMode.strategy === "post-boot-command") return false;
|
|
194
197
|
const dangerousAllowed = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
|
|
195
|
-
if (deriveAutoApproveModeRisk(
|
|
198
|
+
if (deriveAutoApproveModeRisk(selectedMode) === "dangerous" && !dangerousAllowed) {
|
|
196
199
|
const ptyFallback = modes.modes.find((mode) => mode.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(mode) !== "dangerous");
|
|
197
200
|
return ptyFallback?.id || false;
|
|
198
201
|
}
|
|
199
|
-
return
|
|
202
|
+
return selectedMode.id;
|
|
200
203
|
}
|
|
201
204
|
function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
|
|
202
205
|
if (typeof nodePolicy?.delegatedWorkerDangerousModeAllow === "boolean") {
|
|
@@ -204,8 +207,8 @@ function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
|
|
|
204
207
|
}
|
|
205
208
|
return meshPolicy?.delegatedWorkerDangerousModeAllow === true;
|
|
206
209
|
}
|
|
207
|
-
function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider) {
|
|
208
|
-
const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider);
|
|
210
|
+
function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider, repoConfig, providerType) {
|
|
211
|
+
const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider, repoConfig, providerType);
|
|
209
212
|
const delegatedWorkerDangerousModeAllow = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
|
|
210
213
|
return typeof resolved === "string" ? { autoApprove: void 0, autoApproveMode: resolved, delegatedWorkerDangerousModeAllow } : { autoApprove: resolved, autoApproveMode: void 0, delegatedWorkerDangerousModeAllow };
|
|
211
214
|
}
|
|
@@ -305,6 +308,267 @@ var init_repo_mesh_types = __esm({
|
|
|
305
308
|
}
|
|
306
309
|
});
|
|
307
310
|
|
|
311
|
+
// src/config/mesh-json-config.ts
|
|
312
|
+
var mesh_json_config_exports = {};
|
|
313
|
+
__export(mesh_json_config_exports, {
|
|
314
|
+
MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
|
|
315
|
+
MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
|
|
316
|
+
MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE: () => MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
|
|
317
|
+
applyRepoMeshConfig: () => applyRepoMeshConfig,
|
|
318
|
+
buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
|
|
319
|
+
loadRepoMeshJsonConfig: () => loadRepoMeshJsonConfig,
|
|
320
|
+
mergeEffectiveCoordinatorConfig: () => mergeEffectiveCoordinatorConfig,
|
|
321
|
+
mergeEffectiveOperatingNotes: () => mergeEffectiveOperatingNotes,
|
|
322
|
+
normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
|
|
323
|
+
serializeMeshJsonConfigScaffold: () => serializeMeshJsonConfigScaffold
|
|
324
|
+
});
|
|
325
|
+
import { existsSync, readFileSync } from "fs";
|
|
326
|
+
import { join } from "path";
|
|
327
|
+
import * as yaml from "js-yaml";
|
|
328
|
+
function isRecord(value) {
|
|
329
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
330
|
+
}
|
|
331
|
+
function parseConfigText(path46, text) {
|
|
332
|
+
if (/\.json$/i.test(path46)) return JSON.parse(text);
|
|
333
|
+
return yaml.load(text);
|
|
334
|
+
}
|
|
335
|
+
function normalizeOperatingNote(value) {
|
|
336
|
+
if (!isRecord(value)) return null;
|
|
337
|
+
const text = typeof value.text === "string" ? value.text.trim() : "";
|
|
338
|
+
if (!text) return null;
|
|
339
|
+
const category = value.category === "provider_quirk" || value.category === "pattern_to_avoid" || value.category === "recovery_lesson" ? value.category : void 0;
|
|
340
|
+
return {
|
|
341
|
+
text,
|
|
342
|
+
...category ? { category } : {},
|
|
343
|
+
...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {},
|
|
344
|
+
...typeof value.sourceCoordinator === "string" ? { sourceCoordinator: value.sourceCoordinator } : {},
|
|
345
|
+
// Operating-notes lifecycle: a repo-declared note may pin itself or set an
|
|
346
|
+
// explicit expiry, same as a runtime-recorded one. Phase 2 (b)/(c): it may
|
|
347
|
+
// also declare supersedes/subjectKey to retire an earlier note or group
|
|
348
|
+
// same-subject notes for folding.
|
|
349
|
+
...value.pinned === true ? { pinned: true } : {},
|
|
350
|
+
...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {},
|
|
351
|
+
...typeof value.supersedes === "string" ? { supersedes: value.supersedes } : {},
|
|
352
|
+
...typeof value.subjectKey === "string" ? { subjectKey: value.subjectKey } : {}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function normalizeRepoMeshDeclarativeConfig(parsed) {
|
|
356
|
+
const errors = [];
|
|
357
|
+
if (!isRecord(parsed)) return { valid: false, errors: ["config must be an object"] };
|
|
358
|
+
if (parsed.version !== 1) {
|
|
359
|
+
return { valid: false, errors: [`version must be 1 (got ${JSON.stringify(parsed.version)})`] };
|
|
360
|
+
}
|
|
361
|
+
const config = { version: 1 };
|
|
362
|
+
if (parsed.coordinator !== void 0) {
|
|
363
|
+
if (isRecord(parsed.coordinator)) {
|
|
364
|
+
const coord = {};
|
|
365
|
+
const c = parsed.coordinator;
|
|
366
|
+
if (typeof c.systemPromptOverride === "string") coord.systemPromptOverride = c.systemPromptOverride;
|
|
367
|
+
if (typeof c.systemPromptAppend === "string") coord.systemPromptAppend = c.systemPromptAppend;
|
|
368
|
+
if (Number.isFinite(Number(c.maxPromptChars))) coord.maxPromptChars = Number(c.maxPromptChars);
|
|
369
|
+
config.coordinator = coord;
|
|
370
|
+
} else {
|
|
371
|
+
errors.push("coordinator must be an object when provided");
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (parsed.operatingNotes !== void 0) {
|
|
375
|
+
if (Array.isArray(parsed.operatingNotes)) {
|
|
376
|
+
const notes = parsed.operatingNotes.map(normalizeOperatingNote).filter((n) => n !== null);
|
|
377
|
+
if (notes.length) config.operatingNotes = notes;
|
|
378
|
+
} else {
|
|
379
|
+
errors.push("operatingNotes must be an array when provided");
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (parsed.limits !== void 0) {
|
|
383
|
+
if (isRecord(parsed.limits)) {
|
|
384
|
+
const limits = {};
|
|
385
|
+
if (Number.isFinite(Number(parsed.limits.maxNoteChars))) limits.maxNoteChars = Number(parsed.limits.maxNoteChars);
|
|
386
|
+
if (Number.isFinite(Number(parsed.limits.maxNotes))) limits.maxNotes = Number(parsed.limits.maxNotes);
|
|
387
|
+
if (Object.keys(limits).length) config.limits = limits;
|
|
388
|
+
} else {
|
|
389
|
+
errors.push("limits must be an object when provided");
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (parsed.providerDefaults !== void 0) {
|
|
393
|
+
if (isRecord(parsed.providerDefaults)) {
|
|
394
|
+
const pd = {};
|
|
395
|
+
const rawModes = parsed.providerDefaults.autoApproveModes;
|
|
396
|
+
if (rawModes !== void 0) {
|
|
397
|
+
if (isRecord(rawModes)) {
|
|
398
|
+
const modes = {};
|
|
399
|
+
for (const [providerType, modeId] of Object.entries(rawModes)) {
|
|
400
|
+
const type = typeof providerType === "string" ? providerType.trim() : "";
|
|
401
|
+
const id = typeof modeId === "string" ? modeId.trim() : "";
|
|
402
|
+
if (type && id) modes[type] = id;
|
|
403
|
+
}
|
|
404
|
+
if (Object.keys(modes).length) pd.autoApproveModes = modes;
|
|
405
|
+
} else {
|
|
406
|
+
errors.push("providerDefaults.autoApproveModes must be an object when provided");
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (Object.keys(pd).length) config.providerDefaults = pd;
|
|
410
|
+
} else {
|
|
411
|
+
errors.push("providerDefaults must be an object when provided");
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return { valid: true, config, errors };
|
|
415
|
+
}
|
|
416
|
+
function loadRepoMeshJsonConfig(workspace) {
|
|
417
|
+
const bases = [];
|
|
418
|
+
const ws = typeof workspace === "string" ? workspace.trim() : "";
|
|
419
|
+
if (ws) bases.push(ws);
|
|
420
|
+
let cwd = "";
|
|
421
|
+
try {
|
|
422
|
+
cwd = process.cwd();
|
|
423
|
+
} catch {
|
|
424
|
+
}
|
|
425
|
+
if (cwd && cwd !== ws) bases.push(cwd);
|
|
426
|
+
for (const base of bases) {
|
|
427
|
+
for (const relative5 of MESH_JSON_CONFIG_LOCATIONS) {
|
|
428
|
+
const configPath = join(base, relative5);
|
|
429
|
+
if (!existsSync(configPath)) continue;
|
|
430
|
+
try {
|
|
431
|
+
const parsed = parseConfigText(configPath, readFileSync(configPath, "utf-8"));
|
|
432
|
+
const result = normalizeRepoMeshDeclarativeConfig(parsed);
|
|
433
|
+
if (!result.valid || !result.config) {
|
|
434
|
+
return { source: relative5, sourceType: "invalid", path: configPath, error: result.errors.join("; ") };
|
|
435
|
+
}
|
|
436
|
+
return { config: result.config, source: relative5, sourceType: "repo_file", path: configPath };
|
|
437
|
+
} catch (error) {
|
|
438
|
+
return { source: relative5, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
source: "unavailable",
|
|
444
|
+
sourceType: "unavailable",
|
|
445
|
+
error: `No repo mesh config found. Checked: ${MESH_JSON_CONFIG_LOCATIONS.join(", ")}`
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
function mergeEffectiveCoordinatorConfig(repoCoord, localCoord) {
|
|
449
|
+
const out = { ...localCoord || {} };
|
|
450
|
+
const localOverride = localCoord?.systemPromptOverride?.trim();
|
|
451
|
+
const repoOverride = repoCoord?.systemPromptOverride?.trim();
|
|
452
|
+
if (localOverride) {
|
|
453
|
+
out.systemPromptOverride = localCoord.systemPromptOverride;
|
|
454
|
+
} else if (repoOverride) {
|
|
455
|
+
out.systemPromptOverride = repoCoord.systemPromptOverride;
|
|
456
|
+
} else {
|
|
457
|
+
delete out.systemPromptOverride;
|
|
458
|
+
}
|
|
459
|
+
const repoAppend = repoCoord?.systemPromptAppend?.trim() ? repoCoord.systemPromptAppend.trim() : "";
|
|
460
|
+
const localAppendRaw = localCoord?.systemPromptAppend ?? localCoord?.systemPromptSuffix;
|
|
461
|
+
const localAppend = localAppendRaw?.trim() ? localAppendRaw.trim() : "";
|
|
462
|
+
const stacked = [repoAppend, localAppend].filter(Boolean).join("\n\n");
|
|
463
|
+
if (stacked) {
|
|
464
|
+
out.systemPromptAppend = stacked;
|
|
465
|
+
delete out.systemPromptSuffix;
|
|
466
|
+
}
|
|
467
|
+
return out;
|
|
468
|
+
}
|
|
469
|
+
function mergeEffectiveOperatingNotes(repoNotes, ledgerNotes) {
|
|
470
|
+
const usable = (notes) => Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
|
|
471
|
+
const repo = usable(repoNotes);
|
|
472
|
+
const ledger = usable(ledgerNotes);
|
|
473
|
+
const ledgerTexts = new Set(ledger.map((n) => n.text.trim()));
|
|
474
|
+
const repoKept = repo.filter((n) => !ledgerTexts.has(n.text.trim()));
|
|
475
|
+
const merged = [...repoKept, ...ledger];
|
|
476
|
+
return merged.length ? merged : void 0;
|
|
477
|
+
}
|
|
478
|
+
function applyRepoMeshConfig(mesh, repoConfig) {
|
|
479
|
+
if (!repoConfig) return mesh;
|
|
480
|
+
return {
|
|
481
|
+
...mesh,
|
|
482
|
+
coordinator: mergeEffectiveCoordinatorConfig(repoConfig.coordinator, mesh.coordinator)
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
function buildMeshJsonConfigScaffold(mesh) {
|
|
486
|
+
const scaffold = { version: 1 };
|
|
487
|
+
const coord = {};
|
|
488
|
+
const override = mesh.coordinator?.systemPromptOverride;
|
|
489
|
+
if (typeof override === "string" && override.trim()) coord.systemPromptOverride = override;
|
|
490
|
+
const append = mesh.coordinator?.systemPromptAppend ?? mesh.coordinator?.systemPromptSuffix;
|
|
491
|
+
if (typeof append === "string" && append.trim()) coord.systemPromptAppend = append;
|
|
492
|
+
if (Object.keys(coord).length) scaffold.coordinator = coord;
|
|
493
|
+
return scaffold;
|
|
494
|
+
}
|
|
495
|
+
function serializeMeshJsonConfigScaffold(config) {
|
|
496
|
+
return JSON.stringify(config, null, 2);
|
|
497
|
+
}
|
|
498
|
+
var MESH_JSON_CONFIG_LOCATIONS, MESH_JSON_CONFIG_SCHEMA, MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE;
|
|
499
|
+
var init_mesh_json_config = __esm({
|
|
500
|
+
"src/config/mesh-json-config.ts"() {
|
|
501
|
+
"use strict";
|
|
502
|
+
MESH_JSON_CONFIG_LOCATIONS = [
|
|
503
|
+
".adhdev/mesh.json",
|
|
504
|
+
".adhdev/mesh.yaml",
|
|
505
|
+
".adhdev/mesh.yml"
|
|
506
|
+
];
|
|
507
|
+
MESH_JSON_CONFIG_SCHEMA = {
|
|
508
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
509
|
+
title: "ADHDev Repo Mesh Declarative Config",
|
|
510
|
+
type: "object",
|
|
511
|
+
additionalProperties: false,
|
|
512
|
+
required: ["version"],
|
|
513
|
+
properties: {
|
|
514
|
+
version: { const: 1 },
|
|
515
|
+
coordinator: {
|
|
516
|
+
type: "object",
|
|
517
|
+
additionalProperties: false,
|
|
518
|
+
properties: {
|
|
519
|
+
systemPromptOverride: { type: "string" },
|
|
520
|
+
systemPromptAppend: { type: "string" },
|
|
521
|
+
maxPromptChars: { type: "number", minimum: 1 }
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
operatingNotes: {
|
|
525
|
+
type: "array",
|
|
526
|
+
maxItems: 200,
|
|
527
|
+
items: {
|
|
528
|
+
type: "object",
|
|
529
|
+
additionalProperties: false,
|
|
530
|
+
required: ["text"],
|
|
531
|
+
properties: {
|
|
532
|
+
text: { type: "string", minLength: 1 },
|
|
533
|
+
category: { enum: ["provider_quirk", "pattern_to_avoid", "recovery_lesson"] },
|
|
534
|
+
createdAt: { type: "string" },
|
|
535
|
+
sourceCoordinator: { type: "string" }
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
limits: {
|
|
540
|
+
type: "object",
|
|
541
|
+
additionalProperties: false,
|
|
542
|
+
properties: {
|
|
543
|
+
maxNoteChars: { type: "number", minimum: 1 },
|
|
544
|
+
maxNotes: { type: "number", minimum: 1 }
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
providerDefaults: {
|
|
548
|
+
type: "object",
|
|
549
|
+
additionalProperties: false,
|
|
550
|
+
properties: {
|
|
551
|
+
// providerType → requested auto-approve mode ID. Mode IDs are
|
|
552
|
+
// validated against the live provider spec at resolve time; an
|
|
553
|
+
// unknown ID is ignored (provider default is used), so the schema
|
|
554
|
+
// only constrains the shape (string→string), not the ID values.
|
|
555
|
+
autoApproveModes: {
|
|
556
|
+
type: "object",
|
|
557
|
+
additionalProperties: { type: "string" }
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE = {
|
|
564
|
+
autoApproveModes: {
|
|
565
|
+
"claude-cli": "accept-edits",
|
|
566
|
+
"codex-cli": "auto"
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
308
572
|
// src/git/git-executor.ts
|
|
309
573
|
var git_executor_exports = {};
|
|
310
574
|
__export(git_executor_exports, {
|
|
@@ -521,10 +785,10 @@ function readInjected(value) {
|
|
|
521
785
|
}
|
|
522
786
|
function getDaemonBuildInfo() {
|
|
523
787
|
if (cached) return cached;
|
|
524
|
-
const commit = readInjected(true ? "
|
|
525
|
-
const commitShort = readInjected(true ? "
|
|
526
|
-
const version = readInjected(true ? "1.0.18-rc.
|
|
527
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
788
|
+
const commit = readInjected(true ? "957753ce64d49cf4222cb2675d7d919871d3f009" : void 0) ?? "unknown";
|
|
789
|
+
const commitShort = readInjected(true ? "957753ce" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
790
|
+
const version = readInjected(true ? "1.0.18-rc.19" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
791
|
+
const builtAt = readInjected(true ? "2026-07-23T07:07:10.469Z" : void 0);
|
|
528
792
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
529
793
|
return cached;
|
|
530
794
|
}
|
|
@@ -536,17 +800,17 @@ var init_build_info = __esm({
|
|
|
536
800
|
});
|
|
537
801
|
|
|
538
802
|
// src/git/change-impact-config.ts
|
|
539
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
540
|
-
import { join } from "path";
|
|
541
|
-
import * as
|
|
542
|
-
function
|
|
803
|
+
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
804
|
+
import { join as join2 } from "path";
|
|
805
|
+
import * as yaml2 from "js-yaml";
|
|
806
|
+
function isRecord2(value) {
|
|
543
807
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
544
808
|
}
|
|
545
809
|
function isStringArray(value) {
|
|
546
810
|
return Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0);
|
|
547
811
|
}
|
|
548
812
|
function validateTarget(value, key2, errors) {
|
|
549
|
-
if (!
|
|
813
|
+
if (!isRecord2(value)) {
|
|
550
814
|
errors.push(`impactTargets.${key2} must be an object`);
|
|
551
815
|
return void 0;
|
|
552
816
|
}
|
|
@@ -562,7 +826,7 @@ function validateTarget(value, key2, errors) {
|
|
|
562
826
|
}
|
|
563
827
|
function validateChangeImpactConfig(raw, source = "inline") {
|
|
564
828
|
const errors = [];
|
|
565
|
-
if (!
|
|
829
|
+
if (!isRecord2(raw)) {
|
|
566
830
|
return { valid: false, errors: [`${source}: config must be an object`] };
|
|
567
831
|
}
|
|
568
832
|
const config = {};
|
|
@@ -579,7 +843,7 @@ function validateChangeImpactConfig(raw, source = "inline") {
|
|
|
579
843
|
else errors.push("nonRuntimeRootFilePatterns must be an array of non-empty strings");
|
|
580
844
|
}
|
|
581
845
|
if (raw.impactTargets !== void 0) {
|
|
582
|
-
if (!
|
|
846
|
+
if (!isRecord2(raw.impactTargets)) {
|
|
583
847
|
errors.push("impactTargets must be an object");
|
|
584
848
|
} else {
|
|
585
849
|
const targets = {};
|
|
@@ -601,23 +865,23 @@ function validateChangeImpactConfig(raw, source = "inline") {
|
|
|
601
865
|
}
|
|
602
866
|
return { valid: errors.length === 0, errors, config: errors.length === 0 ? config : void 0 };
|
|
603
867
|
}
|
|
604
|
-
function
|
|
868
|
+
function parseConfigText2(path46, text) {
|
|
605
869
|
if (/\.json$/i.test(path46)) return JSON.parse(text);
|
|
606
|
-
return
|
|
870
|
+
return yaml2.load(text);
|
|
607
871
|
}
|
|
608
872
|
function loadChangeImpactConfig(repoRoot) {
|
|
609
873
|
for (const relative5 of CHANGE_IMPACT_CONFIG_LOCATIONS) {
|
|
610
|
-
const configPath =
|
|
611
|
-
if (!
|
|
874
|
+
const configPath = join2(repoRoot, relative5);
|
|
875
|
+
if (!existsSync2(configPath)) continue;
|
|
612
876
|
try {
|
|
613
|
-
const text =
|
|
877
|
+
const text = readFileSync2(configPath, "utf-8");
|
|
614
878
|
let mtimeMs = 0;
|
|
615
879
|
try {
|
|
616
880
|
mtimeMs = statSync(configPath).mtimeMs;
|
|
617
881
|
} catch {
|
|
618
882
|
mtimeMs = text.length;
|
|
619
883
|
}
|
|
620
|
-
const parsed =
|
|
884
|
+
const parsed = parseConfigText2(configPath, text);
|
|
621
885
|
const validation = validateChangeImpactConfig(parsed, relative5);
|
|
622
886
|
if (!validation.valid) {
|
|
623
887
|
return {
|
|
@@ -686,10 +950,10 @@ function suggestChangeImpactConfig(repoRoot) {
|
|
|
686
950
|
const daemon = /* @__PURE__ */ new Set();
|
|
687
951
|
const web = /* @__PURE__ */ new Set();
|
|
688
952
|
const unclassified = [];
|
|
689
|
-
const roots = ["packages",
|
|
953
|
+
const roots = ["packages", join2("oss", "packages")];
|
|
690
954
|
for (const rel of roots) {
|
|
691
|
-
const packagesRoot =
|
|
692
|
-
if (!
|
|
955
|
+
const packagesRoot = join2(repoRoot, rel);
|
|
956
|
+
if (!existsSync2(packagesRoot)) continue;
|
|
693
957
|
for (const name of listPackageDirs(packagesRoot)) {
|
|
694
958
|
if (/(^web[-.]|[-.]web$)/i.test(name) || /dashboard|frontend|ui$/i.test(name)) {
|
|
695
959
|
web.add(name);
|
|
@@ -777,7 +1041,7 @@ var init_change_impact_config = __esm({
|
|
|
777
1041
|
});
|
|
778
1042
|
|
|
779
1043
|
// src/git/git-status.ts
|
|
780
|
-
import { join as
|
|
1044
|
+
import { join as join3 } from "path";
|
|
781
1045
|
function statusCacheKey(workspace, options) {
|
|
782
1046
|
const includeSubmodules = options.includeSubmodules !== false;
|
|
783
1047
|
const refreshUpstream = options.refreshUpstream === true;
|
|
@@ -960,7 +1224,7 @@ async function refineVerdictThroughSubmodules(repoPath, fromRef, toRef, options,
|
|
|
960
1224
|
}
|
|
961
1225
|
let subVerdict;
|
|
962
1226
|
try {
|
|
963
|
-
subVerdict = await classifyChangedPackages(
|
|
1227
|
+
subVerdict = await classifyChangedPackages(join3(repoPath, subPath), range.from, range.to, {
|
|
964
1228
|
...options,
|
|
965
1229
|
// Do not force the root's injected config onto the submodule — let it resolve
|
|
966
1230
|
// its own .adhdev/change-impact.* (or fall back to defaults).
|
|
@@ -1725,8 +1989,8 @@ __export(config_exports, {
|
|
|
1725
1989
|
updateConfig: () => updateConfig
|
|
1726
1990
|
});
|
|
1727
1991
|
import { homedir } from "os";
|
|
1728
|
-
import { join as
|
|
1729
|
-
import { existsSync as
|
|
1992
|
+
import { join as join4 } from "path";
|
|
1993
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync, chmodSync } from "fs";
|
|
1730
1994
|
import { randomUUID } from "crypto";
|
|
1731
1995
|
function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
|
|
1732
1996
|
if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
|
|
@@ -1823,25 +2087,25 @@ function ensureMachineId(config) {
|
|
|
1823
2087
|
}
|
|
1824
2088
|
function getConfigDir() {
|
|
1825
2089
|
const override = process.env.ADHDEV_CONFIG_DIR;
|
|
1826
|
-
const dir = override && override.trim() ? override.trim() :
|
|
1827
|
-
if (!
|
|
2090
|
+
const dir = override && override.trim() ? override.trim() : join4(homedir(), ".adhdev");
|
|
2091
|
+
if (!existsSync3(dir)) {
|
|
1828
2092
|
mkdirSync(dir, { recursive: true });
|
|
1829
2093
|
}
|
|
1830
2094
|
return dir;
|
|
1831
2095
|
}
|
|
1832
2096
|
function getDaemonDataDir() {
|
|
1833
|
-
const dir =
|
|
1834
|
-
if (!
|
|
2097
|
+
const dir = join4(getConfigDir(), "daemon");
|
|
2098
|
+
if (!existsSync3(dir)) {
|
|
1835
2099
|
mkdirSync(dir, { recursive: true });
|
|
1836
2100
|
}
|
|
1837
2101
|
return dir;
|
|
1838
2102
|
}
|
|
1839
2103
|
function getConfigPath() {
|
|
1840
|
-
return
|
|
2104
|
+
return join4(getConfigDir(), "config.json");
|
|
1841
2105
|
}
|
|
1842
2106
|
function migrateStateToStateFile(raw) {
|
|
1843
|
-
const statePath =
|
|
1844
|
-
if (
|
|
2107
|
+
const statePath = join4(getConfigDir(), "state.json");
|
|
2108
|
+
if (existsSync3(statePath)) return;
|
|
1845
2109
|
const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
|
|
1846
2110
|
const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
|
|
1847
2111
|
const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
|
|
@@ -1865,7 +2129,7 @@ function migrateStateToStateFile(raw) {
|
|
|
1865
2129
|
}
|
|
1866
2130
|
function loadConfig() {
|
|
1867
2131
|
const configPath = getConfigPath();
|
|
1868
|
-
if (!
|
|
2132
|
+
if (!existsSync3(configPath)) {
|
|
1869
2133
|
const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
|
|
1870
2134
|
try {
|
|
1871
2135
|
saveConfig(initialized.config);
|
|
@@ -1874,7 +2138,7 @@ function loadConfig() {
|
|
|
1874
2138
|
return initialized.config;
|
|
1875
2139
|
}
|
|
1876
2140
|
try {
|
|
1877
|
-
const raw =
|
|
2141
|
+
const raw = readFileSync3(configPath, "utf-8");
|
|
1878
2142
|
const parsed = JSON.parse(raw);
|
|
1879
2143
|
migrateStateToStateFile(parsed);
|
|
1880
2144
|
const normalizedInput = normalizeConfig(parsed);
|
|
@@ -1896,7 +2160,7 @@ function saveConfig(config) {
|
|
|
1896
2160
|
const configPath = getConfigPath();
|
|
1897
2161
|
const dir = getConfigDir();
|
|
1898
2162
|
const normalized = normalizeConfig(config);
|
|
1899
|
-
if (!
|
|
2163
|
+
if (!existsSync3(dir)) {
|
|
1900
2164
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1901
2165
|
}
|
|
1902
2166
|
writeFileSync(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
@@ -1972,7 +2236,7 @@ __export(git_worktree_exports, {
|
|
|
1972
2236
|
});
|
|
1973
2237
|
import * as path4 from "path";
|
|
1974
2238
|
import { mkdir } from "fs/promises";
|
|
1975
|
-
import { existsSync as
|
|
2239
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1976
2240
|
import { execFile as execFile2 } from "child_process";
|
|
1977
2241
|
import { promisify as promisify2 } from "util";
|
|
1978
2242
|
function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
@@ -2065,7 +2329,7 @@ async function createWorktree(opts) {
|
|
|
2065
2329
|
const { repoRoot, branch, baseBranch, meshName } = opts;
|
|
2066
2330
|
const remote = (opts.remote || "origin").trim() || "origin";
|
|
2067
2331
|
const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
|
|
2068
|
-
if (
|
|
2332
|
+
if (existsSync4(targetDir)) {
|
|
2069
2333
|
throw new Error(`Worktree target directory already exists: ${targetDir}`);
|
|
2070
2334
|
}
|
|
2071
2335
|
await mkdir(path4.dirname(targetDir), { recursive: true });
|
|
@@ -2090,7 +2354,7 @@ async function createWorktree(opts) {
|
|
|
2090
2354
|
} catch (error) {
|
|
2091
2355
|
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
2092
2356
|
if (/already exists/i.test(stderr)) {
|
|
2093
|
-
if (
|
|
2357
|
+
if (existsSync4(targetDir)) {
|
|
2094
2358
|
throw new Error(`Worktree target directory was created concurrently: ${targetDir}`);
|
|
2095
2359
|
}
|
|
2096
2360
|
throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
|
|
@@ -2105,7 +2369,7 @@ async function createWorktree(opts) {
|
|
|
2105
2369
|
};
|
|
2106
2370
|
}
|
|
2107
2371
|
async function removeWorktree(repoRoot, worktreePath, opts = {}) {
|
|
2108
|
-
if (!
|
|
2372
|
+
if (!existsSync4(worktreePath)) {
|
|
2109
2373
|
await pruneWorktrees(repoRoot);
|
|
2110
2374
|
return { success: true, removedPath: worktreePath };
|
|
2111
2375
|
}
|
|
@@ -3360,17 +3624,17 @@ __export(mesh_config_exports, {
|
|
|
3360
3624
|
updateMesh: () => updateMesh,
|
|
3361
3625
|
updateNode: () => updateNode
|
|
3362
3626
|
});
|
|
3363
|
-
import { existsSync as
|
|
3364
|
-
import { join as
|
|
3627
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
3628
|
+
import { join as join7 } from "path";
|
|
3365
3629
|
import { randomBytes, randomUUID as randomUUID3 } from "crypto";
|
|
3366
3630
|
function getMeshConfigPath() {
|
|
3367
|
-
return
|
|
3631
|
+
return join7(getConfigDir(), "meshes.json");
|
|
3368
3632
|
}
|
|
3369
3633
|
function loadMeshConfig() {
|
|
3370
3634
|
const path46 = getMeshConfigPath();
|
|
3371
|
-
if (!
|
|
3635
|
+
if (!existsSync6(path46)) return { meshes: [] };
|
|
3372
3636
|
try {
|
|
3373
|
-
const raw = JSON.parse(
|
|
3637
|
+
const raw = JSON.parse(readFileSync4(path46, "utf-8"));
|
|
3374
3638
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
3375
3639
|
const config = raw;
|
|
3376
3640
|
const migrated = migrateLoadedMeshConfig(config);
|
|
@@ -4974,8 +5238,8 @@ var init_contracts = __esm({
|
|
|
4974
5238
|
});
|
|
4975
5239
|
|
|
4976
5240
|
// src/mesh/mesh-events-pending.ts
|
|
4977
|
-
import { appendFileSync, existsSync as
|
|
4978
|
-
import { join as
|
|
5241
|
+
import { appendFileSync, existsSync as existsSync8, readFileSync as readFileSync5, renameSync as renameSync2, statSync as statSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
5242
|
+
import { join as join9 } from "path";
|
|
4979
5243
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
4980
5244
|
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
4981
5245
|
return expandDaemonIdForms(coordinatorDaemonId);
|
|
@@ -5198,9 +5462,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
|
|
|
5198
5462
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5199
5463
|
if (coordinatorDaemonId) {
|
|
5200
5464
|
const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5201
|
-
return
|
|
5465
|
+
return join9(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
|
|
5202
5466
|
}
|
|
5203
|
-
return
|
|
5467
|
+
return join9(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
5204
5468
|
}
|
|
5205
5469
|
function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
5206
5470
|
if (!meshId) return [];
|
|
@@ -5209,9 +5473,9 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
5209
5473
|
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
5210
5474
|
const events = [];
|
|
5211
5475
|
for (const path46 of paths) {
|
|
5212
|
-
if (!
|
|
5476
|
+
if (!existsSync8(path46)) continue;
|
|
5213
5477
|
try {
|
|
5214
|
-
const raw =
|
|
5478
|
+
const raw = readFileSync5(path46, "utf-8");
|
|
5215
5479
|
const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
5216
5480
|
try {
|
|
5217
5481
|
return [JSON.parse(line)];
|
|
@@ -5301,9 +5565,9 @@ function prunePendingMeshCoordinatorEventsRetention() {
|
|
|
5301
5565
|
}
|
|
5302
5566
|
function trimPendingEventsIfNeeded(path46) {
|
|
5303
5567
|
try {
|
|
5304
|
-
if (!
|
|
5568
|
+
if (!existsSync8(path46)) return;
|
|
5305
5569
|
if (statSync4(path46).size <= MAX_PENDING_EVENTS_BYTES) return;
|
|
5306
|
-
const lines =
|
|
5570
|
+
const lines = readFileSync5(path46, "utf-8").split("\n").filter(Boolean);
|
|
5307
5571
|
if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
|
|
5308
5572
|
const dropped = lines.slice(0, lines.length - MAX_PENDING_EVENTS_KEEP);
|
|
5309
5573
|
for (const line of dropped) {
|
|
@@ -5470,7 +5734,7 @@ function atomicDrainFile(path46) {
|
|
|
5470
5734
|
return null;
|
|
5471
5735
|
}
|
|
5472
5736
|
try {
|
|
5473
|
-
const content =
|
|
5737
|
+
const content = readFileSync5(tmpPath, "utf-8");
|
|
5474
5738
|
try {
|
|
5475
5739
|
unlinkSync2(tmpPath);
|
|
5476
5740
|
} catch {
|
|
@@ -5493,7 +5757,7 @@ function selectiveDrainFile(path46, predicate) {
|
|
|
5493
5757
|
}
|
|
5494
5758
|
let content;
|
|
5495
5759
|
try {
|
|
5496
|
-
content =
|
|
5760
|
+
content = readFileSync5(tmpPath, "utf-8");
|
|
5497
5761
|
} catch {
|
|
5498
5762
|
try {
|
|
5499
5763
|
unlinkSync2(tmpPath);
|
|
@@ -5524,7 +5788,7 @@ function selectiveDrainFile(path46, predicate) {
|
|
|
5524
5788
|
unlinkSync2(tmpPath);
|
|
5525
5789
|
} catch {
|
|
5526
5790
|
try {
|
|
5527
|
-
if (
|
|
5791
|
+
if (existsSync8(tmpPath) && !existsSync8(path46)) renameSync2(tmpPath, path46);
|
|
5528
5792
|
} catch {
|
|
5529
5793
|
}
|
|
5530
5794
|
return [];
|
|
@@ -5752,7 +6016,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
5752
6016
|
}
|
|
5753
6017
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
5754
6018
|
for (const path46 of paths) {
|
|
5755
|
-
if (
|
|
6019
|
+
if (existsSync8(path46)) try {
|
|
5756
6020
|
unlinkSync2(path46);
|
|
5757
6021
|
} catch {
|
|
5758
6022
|
}
|
|
@@ -7102,8 +7366,8 @@ var init_mesh_work_queue = __esm({
|
|
|
7102
7366
|
});
|
|
7103
7367
|
|
|
7104
7368
|
// src/mesh/mesh-runtime-store.ts
|
|
7105
|
-
import { existsSync as
|
|
7106
|
-
import { dirname as dirname2, join as
|
|
7369
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync3, statSync as statSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
7370
|
+
import { dirname as dirname2, join as join10 } from "path";
|
|
7107
7371
|
function loadDatabaseCtor() {
|
|
7108
7372
|
if (DatabaseCtor) return DatabaseCtor;
|
|
7109
7373
|
DatabaseCtor = loadBetterSqlite3();
|
|
@@ -7113,13 +7377,13 @@ function safeMeshId(meshId) {
|
|
|
7113
7377
|
return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7114
7378
|
}
|
|
7115
7379
|
function legacyQueuePath(meshId) {
|
|
7116
|
-
return
|
|
7380
|
+
return join10(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
|
|
7117
7381
|
}
|
|
7118
7382
|
function cleanupStrayRootRuntimeDb(canonicalPath) {
|
|
7119
7383
|
try {
|
|
7120
|
-
const strayPath =
|
|
7384
|
+
const strayPath = join10(getConfigDir(), "mesh-runtime.db");
|
|
7121
7385
|
if (strayPath === canonicalPath) return;
|
|
7122
|
-
if (!
|
|
7386
|
+
if (!existsSync9(strayPath)) return;
|
|
7123
7387
|
if (statSync5(strayPath).size !== 0) return;
|
|
7124
7388
|
unlinkSync3(strayPath);
|
|
7125
7389
|
if (!loggedStrayCleanup) {
|
|
@@ -7135,16 +7399,16 @@ function cleanupStrayRootRuntimeDb(canonicalPath) {
|
|
|
7135
7399
|
}
|
|
7136
7400
|
function meshRuntimeStorePath() {
|
|
7137
7401
|
const dir = getLedgerDir();
|
|
7138
|
-
const nextPath =
|
|
7402
|
+
const nextPath = join10(dir, "mesh-runtime.db");
|
|
7139
7403
|
cleanupStrayRootRuntimeDb(nextPath);
|
|
7140
|
-
if (
|
|
7141
|
-
const legacyPath =
|
|
7142
|
-
if (!
|
|
7404
|
+
if (existsSync9(nextPath)) return nextPath;
|
|
7405
|
+
const legacyPath = join10(dir, "beads.db");
|
|
7406
|
+
if (!existsSync9(legacyPath)) return nextPath;
|
|
7143
7407
|
try {
|
|
7144
7408
|
renameSync3(legacyPath, nextPath);
|
|
7145
7409
|
for (const suffix of ["-wal", "-shm"]) {
|
|
7146
7410
|
const legacyCompanion = `${legacyPath}${suffix}`;
|
|
7147
|
-
if (
|
|
7411
|
+
if (existsSync9(legacyCompanion)) {
|
|
7148
7412
|
renameSync3(legacyCompanion, `${nextPath}${suffix}`);
|
|
7149
7413
|
}
|
|
7150
7414
|
}
|
|
@@ -7156,7 +7420,7 @@ function meshRuntimeStorePath() {
|
|
|
7156
7420
|
`Legacy beads.db\u2192mesh-runtime.db migration failed; using existing DB in-place to avoid data loss: ${err?.message || err}`
|
|
7157
7421
|
);
|
|
7158
7422
|
}
|
|
7159
|
-
return
|
|
7423
|
+
return existsSync9(nextPath) ? nextPath : legacyPath;
|
|
7160
7424
|
}
|
|
7161
7425
|
return nextPath;
|
|
7162
7426
|
}
|
|
@@ -7210,7 +7474,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
7210
7474
|
// 50 MB
|
|
7211
7475
|
constructor(dbPath) {
|
|
7212
7476
|
const dir = dirname2(dbPath);
|
|
7213
|
-
if (!
|
|
7477
|
+
if (!existsSync9(dir)) mkdirSync4(dir, { recursive: true });
|
|
7214
7478
|
this.dbPath = dbPath;
|
|
7215
7479
|
this.db = new (loadDatabaseCtor())(dbPath);
|
|
7216
7480
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -7589,7 +7853,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
7589
7853
|
this.walWriteCounter = 0;
|
|
7590
7854
|
try {
|
|
7591
7855
|
const walPath = `${this.dbPath}-wal`;
|
|
7592
|
-
if (!
|
|
7856
|
+
if (!existsSync9(walPath)) return;
|
|
7593
7857
|
const size = statSync5(walPath).size;
|
|
7594
7858
|
if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
|
|
7595
7859
|
process.stderr.write(
|
|
@@ -7606,9 +7870,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
7606
7870
|
const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
|
|
7607
7871
|
if (count.count > 0) return;
|
|
7608
7872
|
const path46 = legacyQueuePath(meshId);
|
|
7609
|
-
if (!
|
|
7873
|
+
if (!existsSync9(path46)) return;
|
|
7610
7874
|
try {
|
|
7611
|
-
const entries = JSON.parse(
|
|
7875
|
+
const entries = JSON.parse(readFileSync6(path46, "utf-8"));
|
|
7612
7876
|
if (!Array.isArray(entries)) return;
|
|
7613
7877
|
const insert = this.db.prepare(`
|
|
7614
7878
|
INSERT OR REPLACE INTO mesh_queue (
|
|
@@ -9039,8 +9303,8 @@ __export(mesh_ledger_exports, {
|
|
|
9039
9303
|
readOperatingNotes: () => readOperatingNotes,
|
|
9040
9304
|
tombstoneOperatingNote: () => tombstoneOperatingNote
|
|
9041
9305
|
});
|
|
9042
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
9043
|
-
import { join as
|
|
9306
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync7, statSync as statSync6, renameSync as renameSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
9307
|
+
import { join as join11 } from "path";
|
|
9044
9308
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
9045
9309
|
import { EventEmitter } from "events";
|
|
9046
9310
|
function isIntentionalCleanupStopEntry(entry) {
|
|
@@ -9063,35 +9327,35 @@ function isNoteExpired(note, now) {
|
|
|
9063
9327
|
return now - created >= ttlDays * MS_PER_DAY;
|
|
9064
9328
|
}
|
|
9065
9329
|
function getLedgerDir() {
|
|
9066
|
-
const dir =
|
|
9067
|
-
if (!
|
|
9330
|
+
const dir = join11(getConfigDir(), LEDGER_DIR_NAME);
|
|
9331
|
+
if (!existsSync10(dir)) {
|
|
9068
9332
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
9069
9333
|
}
|
|
9070
9334
|
return dir;
|
|
9071
9335
|
}
|
|
9072
9336
|
function getLedgerPath(meshId) {
|
|
9073
9337
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9074
|
-
return
|
|
9338
|
+
return join11(getLedgerDir(), `${safe}.jsonl`);
|
|
9075
9339
|
}
|
|
9076
9340
|
function getRotatedPath(meshId, index) {
|
|
9077
9341
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9078
|
-
return
|
|
9342
|
+
return join11(getLedgerDir(), `${safe}.${index}.jsonl`);
|
|
9079
9343
|
}
|
|
9080
9344
|
function getArchivePath(meshId) {
|
|
9081
9345
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9082
|
-
return
|
|
9346
|
+
return join11(getLedgerDir(), `${safe}.archive.jsonl`);
|
|
9083
9347
|
}
|
|
9084
9348
|
function getRotatedArchivePath(meshId, index) {
|
|
9085
9349
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9086
|
-
return
|
|
9350
|
+
return join11(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
|
|
9087
9351
|
}
|
|
9088
9352
|
function getArchivedCountsPath(meshId) {
|
|
9089
9353
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9090
|
-
return
|
|
9354
|
+
return join11(getLedgerDir(), `${safe}.archived-counts.json`);
|
|
9091
9355
|
}
|
|
9092
9356
|
function rotateArchiveFile(meshId, archivePath) {
|
|
9093
9357
|
let index = 1;
|
|
9094
|
-
while (
|
|
9358
|
+
while (existsSync10(getRotatedArchivePath(meshId, index))) {
|
|
9095
9359
|
index++;
|
|
9096
9360
|
if (index > 5) break;
|
|
9097
9361
|
}
|
|
@@ -9105,9 +9369,9 @@ function rotateArchiveFile(meshId, archivePath) {
|
|
|
9105
9369
|
}
|
|
9106
9370
|
function readArchivedCounts(meshId) {
|
|
9107
9371
|
const path46 = getArchivedCountsPath(meshId);
|
|
9108
|
-
if (!
|
|
9372
|
+
if (!existsSync10(path46)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
|
|
9109
9373
|
try {
|
|
9110
|
-
return JSON.parse(
|
|
9374
|
+
return JSON.parse(readFileSync7(path46, "utf-8"));
|
|
9111
9375
|
} catch {
|
|
9112
9376
|
return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
|
|
9113
9377
|
}
|
|
@@ -9146,7 +9410,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
9146
9410
|
}
|
|
9147
9411
|
function compactLedger(meshId) {
|
|
9148
9412
|
const filePath = getLedgerPath(meshId);
|
|
9149
|
-
if (!
|
|
9413
|
+
if (!existsSync10(filePath)) return { archivedCount: 0, retainedCount: 0 };
|
|
9150
9414
|
const cutoff = Date.now() - ARCHIVE_TERMINAL_OLDER_THAN_MS;
|
|
9151
9415
|
const entries = readLedgerEntries(meshId);
|
|
9152
9416
|
const keep = [];
|
|
@@ -9161,7 +9425,7 @@ function compactLedger(meshId) {
|
|
|
9161
9425
|
if (archive.length === 0) return { archivedCount: 0, retainedCount: keep.length };
|
|
9162
9426
|
const archivePath = getArchivePath(meshId);
|
|
9163
9427
|
try {
|
|
9164
|
-
if (
|
|
9428
|
+
if (existsSync10(archivePath) && statSync6(archivePath).size > 50 * 1024 * 1024) {
|
|
9165
9429
|
rotateArchiveFile(meshId, archivePath);
|
|
9166
9430
|
}
|
|
9167
9431
|
const archiveLines = archive.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
@@ -9352,7 +9616,7 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
9352
9616
|
...partial
|
|
9353
9617
|
};
|
|
9354
9618
|
const filePath = getLedgerPath(meshId);
|
|
9355
|
-
if (
|
|
9619
|
+
if (existsSync10(filePath)) {
|
|
9356
9620
|
try {
|
|
9357
9621
|
const stat2 = statSync6(filePath);
|
|
9358
9622
|
if (stat2.size >= MAX_FILE_SIZE_BYTES) {
|
|
@@ -9540,10 +9804,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
|
|
|
9540
9804
|
}
|
|
9541
9805
|
function readLedgerFile(meshId) {
|
|
9542
9806
|
const filePath = getLedgerPath(meshId);
|
|
9543
|
-
if (!
|
|
9807
|
+
if (!existsSync10(filePath)) return [];
|
|
9544
9808
|
let content;
|
|
9545
9809
|
try {
|
|
9546
|
-
content =
|
|
9810
|
+
content = readFileSync7(filePath, "utf-8");
|
|
9547
9811
|
} catch {
|
|
9548
9812
|
return [];
|
|
9549
9813
|
}
|
|
@@ -9808,7 +10072,7 @@ function getSessionRecoveryContext(meshId, opts) {
|
|
|
9808
10072
|
}
|
|
9809
10073
|
function rotateLedgerFile(meshId, currentPath) {
|
|
9810
10074
|
let index = 1;
|
|
9811
|
-
while (
|
|
10075
|
+
while (existsSync10(getRotatedPath(meshId, index))) {
|
|
9812
10076
|
index++;
|
|
9813
10077
|
if (index > 10) break;
|
|
9814
10078
|
}
|
|
@@ -10813,10 +11077,10 @@ __export(mesh_coordinator_exports, {
|
|
|
10813
11077
|
resolveMeshCoordinatorSetup: () => resolveMeshCoordinatorSetup,
|
|
10814
11078
|
stripCoordinatorWrapperFile: () => stripCoordinatorWrapperFile
|
|
10815
11079
|
});
|
|
10816
|
-
import { existsSync as
|
|
11080
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
10817
11081
|
import * as os4 from "os";
|
|
10818
11082
|
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
|
|
10819
|
-
import { basename as basename2, isAbsolute as isAbsolute4, join as
|
|
11083
|
+
import { basename as basename2, isAbsolute as isAbsolute4, join as join13, resolve as resolve7 } from "path";
|
|
10820
11084
|
function isHermesProvider(provider, cliType) {
|
|
10821
11085
|
const type = cliType?.trim() || provider?.type?.trim() || "";
|
|
10822
11086
|
return type === HERMES_CLI_TYPE;
|
|
@@ -10836,7 +11100,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
10836
11100
|
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
10837
11101
|
};
|
|
10838
11102
|
}
|
|
10839
|
-
const configPath =
|
|
11103
|
+
const configPath = join13(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
|
|
10840
11104
|
if (!configPath.trim()) {
|
|
10841
11105
|
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
10842
11106
|
}
|
|
@@ -10983,14 +11247,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
|
|
|
10983
11247
|
const key2 = `${meshId || "mesh"}
|
|
10984
11248
|
${resolve7(workspace || os4.tmpdir())}`;
|
|
10985
11249
|
const hash = shortHash(key2);
|
|
10986
|
-
return
|
|
11250
|
+
return join13(os4.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
|
|
10987
11251
|
}
|
|
10988
11252
|
function resolveMcpConfigPath(configPath, workspace) {
|
|
10989
11253
|
const trimmed = configPath.trim();
|
|
10990
11254
|
if (trimmed === "~") return os4.homedir();
|
|
10991
|
-
if (trimmed.startsWith("~/")) return
|
|
11255
|
+
if (trimmed.startsWith("~/")) return join13(os4.homedir(), trimmed.slice(2));
|
|
10992
11256
|
if (isAbsolute4(trimmed)) return trimmed;
|
|
10993
|
-
return
|
|
11257
|
+
return join13(workspace, trimmed);
|
|
10994
11258
|
}
|
|
10995
11259
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
10996
11260
|
const directEntryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
@@ -11061,7 +11325,7 @@ function applyInjectionRule(systemPrompt, injection, ctx) {
|
|
|
11061
11325
|
}
|
|
11062
11326
|
case "context_file": {
|
|
11063
11327
|
if (!injection.path) return {};
|
|
11064
|
-
const target = isAbsolute4(injection.path) ? injection.path :
|
|
11328
|
+
const target = isAbsolute4(injection.path) ? injection.path : join13(ctx.workspace, injection.path);
|
|
11065
11329
|
const wrapper = injection.wrapper && injection.wrapper.includes("{prompt}") ? injection.wrapper : "{prompt}";
|
|
11066
11330
|
const managedNote = "> _Managed by adhdev mesh coordinator \u2014 do not hand-edit this block. Changes inside the sentinels are overwritten on next coordinator launch._";
|
|
11067
11331
|
const promptWithNote = `${managedNote}
|
|
@@ -11070,8 +11334,8 @@ ${systemPrompt}`;
|
|
|
11070
11334
|
const rendered = wrapper.replace(/\{prompt\}/g, promptWithNote);
|
|
11071
11335
|
const sentinel = wrapper.split("{prompt}")[0].trim();
|
|
11072
11336
|
try {
|
|
11073
|
-
if (
|
|
11074
|
-
const existing =
|
|
11337
|
+
if (existsSync11(target)) {
|
|
11338
|
+
const existing = readFileSync9(target, "utf-8");
|
|
11075
11339
|
if (sentinel && existing.includes(sentinel)) {
|
|
11076
11340
|
const closing = wrapper.split("{prompt}")[1]?.trim();
|
|
11077
11341
|
const safeOpen = sentinel.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
@@ -11101,8 +11365,8 @@ function stripCoordinatorWrapperFile(filePath) {
|
|
|
11101
11365
|
const OPEN = "<!-- adhdev-mesh-coordinator-prompt -->";
|
|
11102
11366
|
const CLOSE = "<!-- /adhdev-mesh-coordinator-prompt -->";
|
|
11103
11367
|
try {
|
|
11104
|
-
if (!
|
|
11105
|
-
const existing =
|
|
11368
|
+
if (!existsSync11(filePath)) return;
|
|
11369
|
+
const existing = readFileSync9(filePath, "utf-8");
|
|
11106
11370
|
const openIdx = existing.indexOf(OPEN);
|
|
11107
11371
|
if (openIdx < 0) return;
|
|
11108
11372
|
const closeIdx = existing.indexOf(CLOSE, openIdx);
|
|
@@ -11205,16 +11469,16 @@ var init_mesh_coordinator = __esm({
|
|
|
11205
11469
|
});
|
|
11206
11470
|
|
|
11207
11471
|
// src/mesh/coordinator-registry.ts
|
|
11208
|
-
import { join as
|
|
11209
|
-
import { existsSync as
|
|
11472
|
+
import { join as join14 } from "path";
|
|
11473
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
11210
11474
|
function getRegistryPath() {
|
|
11211
|
-
return
|
|
11475
|
+
return join14(getDaemonDataDir(), "mesh-coordinators.json");
|
|
11212
11476
|
}
|
|
11213
11477
|
function loadMeshCoordinatorRegistry() {
|
|
11214
11478
|
const path46 = getRegistryPath();
|
|
11215
|
-
if (!
|
|
11479
|
+
if (!existsSync12(path46)) return;
|
|
11216
11480
|
try {
|
|
11217
|
-
const raw = JSON.parse(
|
|
11481
|
+
const raw = JSON.parse(readFileSync10(path46, "utf-8"));
|
|
11218
11482
|
if (!Array.isArray(raw)) return;
|
|
11219
11483
|
_registry.clear();
|
|
11220
11484
|
for (const entry of raw) {
|
|
@@ -11270,9 +11534,9 @@ var init_coordinator_registry = __esm({
|
|
|
11270
11534
|
});
|
|
11271
11535
|
|
|
11272
11536
|
// src/mesh/refine-config.ts
|
|
11273
|
-
import { existsSync as
|
|
11274
|
-
import { join as
|
|
11275
|
-
import * as
|
|
11537
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
11538
|
+
import { join as join15 } from "path";
|
|
11539
|
+
import * as yaml3 from "js-yaml";
|
|
11276
11540
|
function isMeshConfigRecord(value) {
|
|
11277
11541
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
11278
11542
|
}
|
|
@@ -11356,14 +11620,14 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
11356
11620
|
const rejectedCommands = [];
|
|
11357
11621
|
const deprecationWarnings = [];
|
|
11358
11622
|
let bootstrapMode = "inherit";
|
|
11359
|
-
if (!
|
|
11623
|
+
if (!isRecord3(config)) return { valid: false, errors: ["config must be an object"], bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
|
|
11360
11624
|
if (config.version !== 1) errors.push("version must be 1");
|
|
11361
11625
|
if (config.allowAutoPublishSubmoduleMainCommits !== void 0 && typeof config.allowAutoPublishSubmoduleMainCommits !== "boolean") {
|
|
11362
11626
|
errors.push("allowAutoPublishSubmoduleMainCommits must be a boolean when provided");
|
|
11363
11627
|
}
|
|
11364
11628
|
const validation = config.validation;
|
|
11365
|
-
if (validation !== void 0 && !
|
|
11366
|
-
const rawBootstrapMode =
|
|
11629
|
+
if (validation !== void 0 && !isRecord3(validation)) errors.push("validation must be an object");
|
|
11630
|
+
const rawBootstrapMode = isRecord3(validation) ? validation.bootstrap : void 0;
|
|
11367
11631
|
if (rawBootstrapMode !== void 0) {
|
|
11368
11632
|
if (rawBootstrapMode === "inherit" || rawBootstrapMode === "skip") {
|
|
11369
11633
|
bootstrapMode = rawBootstrapMode;
|
|
@@ -11371,8 +11635,8 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
11371
11635
|
errors.push("validation.bootstrap must be 'inherit' or 'skip' when provided");
|
|
11372
11636
|
}
|
|
11373
11637
|
}
|
|
11374
|
-
const rawCommands =
|
|
11375
|
-
const rawBootstrapCommands =
|
|
11638
|
+
const rawCommands = isRecord3(validation) ? validation.commands : void 0;
|
|
11639
|
+
const rawBootstrapCommands = isRecord3(validation) ? validation.bootstrapCommands : void 0;
|
|
11376
11640
|
if (rawCommands !== void 0 && !Array.isArray(rawCommands)) errors.push("validation.commands must be an array");
|
|
11377
11641
|
if (rawBootstrapCommands !== void 0 && !Array.isArray(rawBootstrapCommands)) errors.push("validation.bootstrapCommands must be an array");
|
|
11378
11642
|
if (Array.isArray(rawBootstrapCommands) && rawBootstrapCommands.length > 0) {
|
|
@@ -11395,9 +11659,9 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
11395
11659
|
if (rejectedCommands.length) errors.push("one or more validation commands are invalid");
|
|
11396
11660
|
return { valid: errors.length === 0, errors, bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
|
|
11397
11661
|
}
|
|
11398
|
-
function
|
|
11662
|
+
function parseConfigText3(path46, text) {
|
|
11399
11663
|
if (/\.json$/i.test(path46)) return JSON.parse(text);
|
|
11400
|
-
return
|
|
11664
|
+
return yaml3.load(text);
|
|
11401
11665
|
}
|
|
11402
11666
|
function loadMeshRefineConfig(mesh, workspace) {
|
|
11403
11667
|
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
@@ -11408,10 +11672,10 @@ function loadMeshRefineConfig(mesh, workspace) {
|
|
|
11408
11672
|
return { config: inline, source: "mesh.policy.refineConfig", sourceType: "mesh_policy" };
|
|
11409
11673
|
}
|
|
11410
11674
|
for (const relative5 of MESH_REFINE_CONFIG_LOCATIONS) {
|
|
11411
|
-
const configPath =
|
|
11412
|
-
if (!
|
|
11675
|
+
const configPath = join15(workspace, relative5);
|
|
11676
|
+
if (!existsSync13(configPath)) continue;
|
|
11413
11677
|
try {
|
|
11414
|
-
const parsed =
|
|
11678
|
+
const parsed = parseConfigText3(configPath, readFileSync11(configPath, "utf-8"));
|
|
11415
11679
|
const validation = validateMeshRefineConfig(parsed, relative5);
|
|
11416
11680
|
if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
11417
11681
|
return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
|
|
@@ -11427,20 +11691,20 @@ function loadMeshRefineConfig(mesh, workspace) {
|
|
|
11427
11691
|
}
|
|
11428
11692
|
function readPackageScripts(workspace) {
|
|
11429
11693
|
try {
|
|
11430
|
-
const parsed = JSON.parse(
|
|
11431
|
-
return
|
|
11694
|
+
const parsed = JSON.parse(readFileSync11(join15(workspace, "package.json"), "utf-8"));
|
|
11695
|
+
return isRecord3(parsed?.scripts) ? parsed.scripts : {};
|
|
11432
11696
|
} catch {
|
|
11433
11697
|
return {};
|
|
11434
11698
|
}
|
|
11435
11699
|
}
|
|
11436
11700
|
function collectProjectContextSuggestions(mesh) {
|
|
11437
11701
|
const commands = mesh?.projectContext?.commands;
|
|
11438
|
-
if (!
|
|
11702
|
+
if (!isRecord3(commands)) return [];
|
|
11439
11703
|
const suggestions = [];
|
|
11440
11704
|
for (const category of MESH_REFINE_VALIDATION_CATEGORIES) {
|
|
11441
11705
|
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
11442
11706
|
for (const entry of entries) {
|
|
11443
|
-
if (
|
|
11707
|
+
if (isRecord3(entry) && typeof entry.command === "string") suggestions.push({ command: entry.command, category });
|
|
11444
11708
|
}
|
|
11445
11709
|
}
|
|
11446
11710
|
return suggestions;
|
|
@@ -11502,7 +11766,7 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
|
11502
11766
|
unavailableReason: validation.commands.length ? void 0 : "validation_unavailable: repo mesh/refine config has no validation.commands"
|
|
11503
11767
|
};
|
|
11504
11768
|
}
|
|
11505
|
-
var 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,
|
|
11769
|
+
var 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;
|
|
11506
11770
|
var init_refine_config = __esm({
|
|
11507
11771
|
"src/mesh/refine-config.ts"() {
|
|
11508
11772
|
"use strict";
|
|
@@ -11596,13 +11860,13 @@ var init_refine_config = __esm({
|
|
|
11596
11860
|
SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
|
|
11597
11861
|
SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
|
|
11598
11862
|
SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
|
|
11599
|
-
|
|
11863
|
+
isRecord3 = isMeshConfigRecord;
|
|
11600
11864
|
}
|
|
11601
11865
|
});
|
|
11602
11866
|
|
|
11603
11867
|
// src/cli-adapters/resolve-executable.ts
|
|
11604
11868
|
import { execFileSync } from "child_process";
|
|
11605
|
-
import { existsSync as
|
|
11869
|
+
import { existsSync as existsSync14 } from "fs";
|
|
11606
11870
|
import * as path10 from "path";
|
|
11607
11871
|
function resolveWin32GlobalBin(trimmed) {
|
|
11608
11872
|
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
@@ -11618,7 +11882,7 @@ function resolveWin32GlobalBin(trimmed) {
|
|
|
11618
11882
|
if (!dir) continue;
|
|
11619
11883
|
for (const ext of WIN_EXEC_EXT) {
|
|
11620
11884
|
const full = path10.join(dir, trimmed + ext);
|
|
11621
|
-
if (
|
|
11885
|
+
if (existsSync14(full)) return full;
|
|
11622
11886
|
}
|
|
11623
11887
|
}
|
|
11624
11888
|
return null;
|
|
@@ -11635,7 +11899,7 @@ function resolveWin32Executable(command) {
|
|
|
11635
11899
|
if (process.platform !== "win32") return command;
|
|
11636
11900
|
const trimmed = (command || "").trim();
|
|
11637
11901
|
if (!trimmed) return command;
|
|
11638
|
-
if (path10.isAbsolute(trimmed) &&
|
|
11902
|
+
if (path10.isAbsolute(trimmed) && existsSync14(trimmed)) return trimmed;
|
|
11639
11903
|
try {
|
|
11640
11904
|
const out = execFileSync("where", [trimmed], {
|
|
11641
11905
|
encoding: "utf8",
|
|
@@ -11711,12 +11975,12 @@ __export(worktree_bootstrap_config_exports, {
|
|
|
11711
11975
|
shouldDeferDispatchForBootstrap: () => shouldDeferDispatchForBootstrap,
|
|
11712
11976
|
validateMeshWorktreeBootstrapConfig: () => validateMeshWorktreeBootstrapConfig
|
|
11713
11977
|
});
|
|
11714
|
-
import { existsSync as
|
|
11715
|
-
import { join as
|
|
11978
|
+
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
11979
|
+
import { join as join17, resolve as pathResolve } from "path";
|
|
11716
11980
|
import { execFile as execFile3, execFileSync as execFileSync2 } from "child_process";
|
|
11717
11981
|
import { createHash as createHash2 } from "crypto";
|
|
11718
11982
|
import { promisify as promisify3 } from "util";
|
|
11719
|
-
import * as
|
|
11983
|
+
import * as yaml4 from "js-yaml";
|
|
11720
11984
|
function getRegisteredSubmodulePaths(workspace) {
|
|
11721
11985
|
const paths = /* @__PURE__ */ new Set();
|
|
11722
11986
|
try {
|
|
@@ -11831,7 +12095,7 @@ function isWorktreeBootstrapStaleRunning(node, nowMs = Date.now()) {
|
|
|
11831
12095
|
if (!Number.isFinite(startedMs)) return false;
|
|
11832
12096
|
if (nowMs - startedMs <= WORKTREE_BOOTSTRAP_STALE_RUNNING_MS) return false;
|
|
11833
12097
|
const workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
|
|
11834
|
-
if (!workspace || !
|
|
12098
|
+
if (!workspace || !existsSync15(workspace)) return false;
|
|
11835
12099
|
try {
|
|
11836
12100
|
const out = execFileSync2(resolveWin32Executable("git"), ["status", "--porcelain"], {
|
|
11837
12101
|
cwd: workspace,
|
|
@@ -11852,9 +12116,9 @@ function shouldDeferDispatchForBootstrap(node, nowMs = Date.now()) {
|
|
|
11852
12116
|
if (node?.worktreeBootstrap?.status !== "running") return false;
|
|
11853
12117
|
return !isWorktreeBootstrapStaleRunning(node, nowMs);
|
|
11854
12118
|
}
|
|
11855
|
-
function
|
|
12119
|
+
function parseConfigText4(path46, text) {
|
|
11856
12120
|
if (/\.json$/i.test(path46)) return JSON.parse(text);
|
|
11857
|
-
return
|
|
12121
|
+
return yaml4.load(text);
|
|
11858
12122
|
}
|
|
11859
12123
|
function truncateOutput(value) {
|
|
11860
12124
|
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
@@ -11894,10 +12158,10 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
11894
12158
|
return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
|
|
11895
12159
|
}
|
|
11896
12160
|
for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
11897
|
-
const configPath =
|
|
11898
|
-
if (!
|
|
12161
|
+
const configPath = join17(workspace, relative5);
|
|
12162
|
+
if (!existsSync15(configPath)) continue;
|
|
11899
12163
|
try {
|
|
11900
|
-
const parsed =
|
|
12164
|
+
const parsed = parseConfigText4(configPath, readFileSync12(configPath, "utf-8"));
|
|
11901
12165
|
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
|
|
11902
12166
|
if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
11903
12167
|
return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
|
|
@@ -11910,9 +12174,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
11910
12174
|
function computeStaleInputsDigest(workspace, staleInputs) {
|
|
11911
12175
|
const digest = {};
|
|
11912
12176
|
for (const relative5 of staleInputs ?? []) {
|
|
11913
|
-
const filePath =
|
|
12177
|
+
const filePath = join17(workspace, relative5);
|
|
11914
12178
|
try {
|
|
11915
|
-
digest[relative5] = createHash2("sha256").update(
|
|
12179
|
+
digest[relative5] = createHash2("sha256").update(readFileSync12(filePath)).digest("hex");
|
|
11916
12180
|
} catch {
|
|
11917
12181
|
digest[relative5] = "absent";
|
|
11918
12182
|
}
|
|
@@ -11983,10 +12247,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
11983
12247
|
staleInputs: loaded.config.staleInputs
|
|
11984
12248
|
};
|
|
11985
12249
|
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
11986
|
-
const initiallyAbsent = staleInputPaths.filter((p) => !
|
|
12250
|
+
const initiallyAbsent = staleInputPaths.filter((p) => !existsSync15(join17(workspace, p)));
|
|
11987
12251
|
for (const command of validation.commands) {
|
|
11988
12252
|
if (initiallyAbsent.length > 0) {
|
|
11989
|
-
const appearedNow = initiallyAbsent.filter((p) =>
|
|
12253
|
+
const appearedNow = initiallyAbsent.filter((p) => existsSync15(join17(workspace, p)));
|
|
11990
12254
|
if (appearedNow.length > 0) {
|
|
11991
12255
|
state.status = "stale";
|
|
11992
12256
|
state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -12109,224 +12373,6 @@ var init_worktree_bootstrap_config = __esm({
|
|
|
12109
12373
|
}
|
|
12110
12374
|
});
|
|
12111
12375
|
|
|
12112
|
-
// src/config/mesh-json-config.ts
|
|
12113
|
-
var mesh_json_config_exports = {};
|
|
12114
|
-
__export(mesh_json_config_exports, {
|
|
12115
|
-
MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
|
|
12116
|
-
MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
|
|
12117
|
-
applyRepoMeshConfig: () => applyRepoMeshConfig,
|
|
12118
|
-
buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
|
|
12119
|
-
loadRepoMeshJsonConfig: () => loadRepoMeshJsonConfig,
|
|
12120
|
-
mergeEffectiveCoordinatorConfig: () => mergeEffectiveCoordinatorConfig,
|
|
12121
|
-
mergeEffectiveOperatingNotes: () => mergeEffectiveOperatingNotes,
|
|
12122
|
-
normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
|
|
12123
|
-
serializeMeshJsonConfigScaffold: () => serializeMeshJsonConfigScaffold
|
|
12124
|
-
});
|
|
12125
|
-
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
12126
|
-
import { join as join17 } from "path";
|
|
12127
|
-
import * as yaml4 from "js-yaml";
|
|
12128
|
-
function isRecord3(value) {
|
|
12129
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
12130
|
-
}
|
|
12131
|
-
function parseConfigText4(path46, text) {
|
|
12132
|
-
if (/\.json$/i.test(path46)) return JSON.parse(text);
|
|
12133
|
-
return yaml4.load(text);
|
|
12134
|
-
}
|
|
12135
|
-
function normalizeOperatingNote(value) {
|
|
12136
|
-
if (!isRecord3(value)) return null;
|
|
12137
|
-
const text = typeof value.text === "string" ? value.text.trim() : "";
|
|
12138
|
-
if (!text) return null;
|
|
12139
|
-
const category = value.category === "provider_quirk" || value.category === "pattern_to_avoid" || value.category === "recovery_lesson" ? value.category : void 0;
|
|
12140
|
-
return {
|
|
12141
|
-
text,
|
|
12142
|
-
...category ? { category } : {},
|
|
12143
|
-
...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {},
|
|
12144
|
-
...typeof value.sourceCoordinator === "string" ? { sourceCoordinator: value.sourceCoordinator } : {},
|
|
12145
|
-
// Operating-notes lifecycle: a repo-declared note may pin itself or set an
|
|
12146
|
-
// explicit expiry, same as a runtime-recorded one. Phase 2 (b)/(c): it may
|
|
12147
|
-
// also declare supersedes/subjectKey to retire an earlier note or group
|
|
12148
|
-
// same-subject notes for folding.
|
|
12149
|
-
...value.pinned === true ? { pinned: true } : {},
|
|
12150
|
-
...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {},
|
|
12151
|
-
...typeof value.supersedes === "string" ? { supersedes: value.supersedes } : {},
|
|
12152
|
-
...typeof value.subjectKey === "string" ? { subjectKey: value.subjectKey } : {}
|
|
12153
|
-
};
|
|
12154
|
-
}
|
|
12155
|
-
function normalizeRepoMeshDeclarativeConfig(parsed) {
|
|
12156
|
-
const errors = [];
|
|
12157
|
-
if (!isRecord3(parsed)) return { valid: false, errors: ["config must be an object"] };
|
|
12158
|
-
if (parsed.version !== 1) {
|
|
12159
|
-
return { valid: false, errors: [`version must be 1 (got ${JSON.stringify(parsed.version)})`] };
|
|
12160
|
-
}
|
|
12161
|
-
const config = { version: 1 };
|
|
12162
|
-
if (parsed.coordinator !== void 0) {
|
|
12163
|
-
if (isRecord3(parsed.coordinator)) {
|
|
12164
|
-
const coord = {};
|
|
12165
|
-
const c = parsed.coordinator;
|
|
12166
|
-
if (typeof c.systemPromptOverride === "string") coord.systemPromptOverride = c.systemPromptOverride;
|
|
12167
|
-
if (typeof c.systemPromptAppend === "string") coord.systemPromptAppend = c.systemPromptAppend;
|
|
12168
|
-
if (Number.isFinite(Number(c.maxPromptChars))) coord.maxPromptChars = Number(c.maxPromptChars);
|
|
12169
|
-
config.coordinator = coord;
|
|
12170
|
-
} else {
|
|
12171
|
-
errors.push("coordinator must be an object when provided");
|
|
12172
|
-
}
|
|
12173
|
-
}
|
|
12174
|
-
if (parsed.operatingNotes !== void 0) {
|
|
12175
|
-
if (Array.isArray(parsed.operatingNotes)) {
|
|
12176
|
-
const notes = parsed.operatingNotes.map(normalizeOperatingNote).filter((n) => n !== null);
|
|
12177
|
-
if (notes.length) config.operatingNotes = notes;
|
|
12178
|
-
} else {
|
|
12179
|
-
errors.push("operatingNotes must be an array when provided");
|
|
12180
|
-
}
|
|
12181
|
-
}
|
|
12182
|
-
if (parsed.limits !== void 0) {
|
|
12183
|
-
if (isRecord3(parsed.limits)) {
|
|
12184
|
-
const limits = {};
|
|
12185
|
-
if (Number.isFinite(Number(parsed.limits.maxNoteChars))) limits.maxNoteChars = Number(parsed.limits.maxNoteChars);
|
|
12186
|
-
if (Number.isFinite(Number(parsed.limits.maxNotes))) limits.maxNotes = Number(parsed.limits.maxNotes);
|
|
12187
|
-
if (Object.keys(limits).length) config.limits = limits;
|
|
12188
|
-
} else {
|
|
12189
|
-
errors.push("limits must be an object when provided");
|
|
12190
|
-
}
|
|
12191
|
-
}
|
|
12192
|
-
return { valid: true, config, errors };
|
|
12193
|
-
}
|
|
12194
|
-
function loadRepoMeshJsonConfig(workspace) {
|
|
12195
|
-
const bases = [];
|
|
12196
|
-
const ws = typeof workspace === "string" ? workspace.trim() : "";
|
|
12197
|
-
if (ws) bases.push(ws);
|
|
12198
|
-
let cwd = "";
|
|
12199
|
-
try {
|
|
12200
|
-
cwd = process.cwd();
|
|
12201
|
-
} catch {
|
|
12202
|
-
}
|
|
12203
|
-
if (cwd && cwd !== ws) bases.push(cwd);
|
|
12204
|
-
for (const base of bases) {
|
|
12205
|
-
for (const relative5 of MESH_JSON_CONFIG_LOCATIONS) {
|
|
12206
|
-
const configPath = join17(base, relative5);
|
|
12207
|
-
if (!existsSync15(configPath)) continue;
|
|
12208
|
-
try {
|
|
12209
|
-
const parsed = parseConfigText4(configPath, readFileSync12(configPath, "utf-8"));
|
|
12210
|
-
const result = normalizeRepoMeshDeclarativeConfig(parsed);
|
|
12211
|
-
if (!result.valid || !result.config) {
|
|
12212
|
-
return { source: relative5, sourceType: "invalid", path: configPath, error: result.errors.join("; ") };
|
|
12213
|
-
}
|
|
12214
|
-
return { config: result.config, source: relative5, sourceType: "repo_file", path: configPath };
|
|
12215
|
-
} catch (error) {
|
|
12216
|
-
return { source: relative5, sourceType: "invalid", path: configPath, error: error?.message || String(error) };
|
|
12217
|
-
}
|
|
12218
|
-
}
|
|
12219
|
-
}
|
|
12220
|
-
return {
|
|
12221
|
-
source: "unavailable",
|
|
12222
|
-
sourceType: "unavailable",
|
|
12223
|
-
error: `No repo mesh config found. Checked: ${MESH_JSON_CONFIG_LOCATIONS.join(", ")}`
|
|
12224
|
-
};
|
|
12225
|
-
}
|
|
12226
|
-
function mergeEffectiveCoordinatorConfig(repoCoord, localCoord) {
|
|
12227
|
-
const out = { ...localCoord || {} };
|
|
12228
|
-
const localOverride = localCoord?.systemPromptOverride?.trim();
|
|
12229
|
-
const repoOverride = repoCoord?.systemPromptOverride?.trim();
|
|
12230
|
-
if (localOverride) {
|
|
12231
|
-
out.systemPromptOverride = localCoord.systemPromptOverride;
|
|
12232
|
-
} else if (repoOverride) {
|
|
12233
|
-
out.systemPromptOverride = repoCoord.systemPromptOverride;
|
|
12234
|
-
} else {
|
|
12235
|
-
delete out.systemPromptOverride;
|
|
12236
|
-
}
|
|
12237
|
-
const repoAppend = repoCoord?.systemPromptAppend?.trim() ? repoCoord.systemPromptAppend.trim() : "";
|
|
12238
|
-
const localAppendRaw = localCoord?.systemPromptAppend ?? localCoord?.systemPromptSuffix;
|
|
12239
|
-
const localAppend = localAppendRaw?.trim() ? localAppendRaw.trim() : "";
|
|
12240
|
-
const stacked = [repoAppend, localAppend].filter(Boolean).join("\n\n");
|
|
12241
|
-
if (stacked) {
|
|
12242
|
-
out.systemPromptAppend = stacked;
|
|
12243
|
-
delete out.systemPromptSuffix;
|
|
12244
|
-
}
|
|
12245
|
-
return out;
|
|
12246
|
-
}
|
|
12247
|
-
function mergeEffectiveOperatingNotes(repoNotes, ledgerNotes) {
|
|
12248
|
-
const usable = (notes) => Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
|
|
12249
|
-
const repo = usable(repoNotes);
|
|
12250
|
-
const ledger = usable(ledgerNotes);
|
|
12251
|
-
const ledgerTexts = new Set(ledger.map((n) => n.text.trim()));
|
|
12252
|
-
const repoKept = repo.filter((n) => !ledgerTexts.has(n.text.trim()));
|
|
12253
|
-
const merged = [...repoKept, ...ledger];
|
|
12254
|
-
return merged.length ? merged : void 0;
|
|
12255
|
-
}
|
|
12256
|
-
function applyRepoMeshConfig(mesh, repoConfig) {
|
|
12257
|
-
if (!repoConfig) return mesh;
|
|
12258
|
-
return {
|
|
12259
|
-
...mesh,
|
|
12260
|
-
coordinator: mergeEffectiveCoordinatorConfig(repoConfig.coordinator, mesh.coordinator)
|
|
12261
|
-
};
|
|
12262
|
-
}
|
|
12263
|
-
function buildMeshJsonConfigScaffold(mesh) {
|
|
12264
|
-
const scaffold = { version: 1 };
|
|
12265
|
-
const coord = {};
|
|
12266
|
-
const override = mesh.coordinator?.systemPromptOverride;
|
|
12267
|
-
if (typeof override === "string" && override.trim()) coord.systemPromptOverride = override;
|
|
12268
|
-
const append = mesh.coordinator?.systemPromptAppend ?? mesh.coordinator?.systemPromptSuffix;
|
|
12269
|
-
if (typeof append === "string" && append.trim()) coord.systemPromptAppend = append;
|
|
12270
|
-
if (Object.keys(coord).length) scaffold.coordinator = coord;
|
|
12271
|
-
return scaffold;
|
|
12272
|
-
}
|
|
12273
|
-
function serializeMeshJsonConfigScaffold(config) {
|
|
12274
|
-
return JSON.stringify(config, null, 2);
|
|
12275
|
-
}
|
|
12276
|
-
var MESH_JSON_CONFIG_LOCATIONS, MESH_JSON_CONFIG_SCHEMA;
|
|
12277
|
-
var init_mesh_json_config = __esm({
|
|
12278
|
-
"src/config/mesh-json-config.ts"() {
|
|
12279
|
-
"use strict";
|
|
12280
|
-
MESH_JSON_CONFIG_LOCATIONS = [
|
|
12281
|
-
".adhdev/mesh.json",
|
|
12282
|
-
".adhdev/mesh.yaml",
|
|
12283
|
-
".adhdev/mesh.yml"
|
|
12284
|
-
];
|
|
12285
|
-
MESH_JSON_CONFIG_SCHEMA = {
|
|
12286
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
12287
|
-
title: "ADHDev Repo Mesh Declarative Config",
|
|
12288
|
-
type: "object",
|
|
12289
|
-
additionalProperties: false,
|
|
12290
|
-
required: ["version"],
|
|
12291
|
-
properties: {
|
|
12292
|
-
version: { const: 1 },
|
|
12293
|
-
coordinator: {
|
|
12294
|
-
type: "object",
|
|
12295
|
-
additionalProperties: false,
|
|
12296
|
-
properties: {
|
|
12297
|
-
systemPromptOverride: { type: "string" },
|
|
12298
|
-
systemPromptAppend: { type: "string" },
|
|
12299
|
-
maxPromptChars: { type: "number", minimum: 1 }
|
|
12300
|
-
}
|
|
12301
|
-
},
|
|
12302
|
-
operatingNotes: {
|
|
12303
|
-
type: "array",
|
|
12304
|
-
maxItems: 200,
|
|
12305
|
-
items: {
|
|
12306
|
-
type: "object",
|
|
12307
|
-
additionalProperties: false,
|
|
12308
|
-
required: ["text"],
|
|
12309
|
-
properties: {
|
|
12310
|
-
text: { type: "string", minLength: 1 },
|
|
12311
|
-
category: { enum: ["provider_quirk", "pattern_to_avoid", "recovery_lesson"] },
|
|
12312
|
-
createdAt: { type: "string" },
|
|
12313
|
-
sourceCoordinator: { type: "string" }
|
|
12314
|
-
}
|
|
12315
|
-
}
|
|
12316
|
-
},
|
|
12317
|
-
limits: {
|
|
12318
|
-
type: "object",
|
|
12319
|
-
additionalProperties: false,
|
|
12320
|
-
properties: {
|
|
12321
|
-
maxNoteChars: { type: "number", minimum: 1 },
|
|
12322
|
-
maxNotes: { type: "number", minimum: 1 }
|
|
12323
|
-
}
|
|
12324
|
-
}
|
|
12325
|
-
}
|
|
12326
|
-
};
|
|
12327
|
-
}
|
|
12328
|
-
});
|
|
12329
|
-
|
|
12330
12376
|
// src/mesh/mesh-fast-forward.ts
|
|
12331
12377
|
async function fastForwardMeshNode(args) {
|
|
12332
12378
|
const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -16660,6 +16706,16 @@ function __resetIdleAutoFastForwardForTests() {
|
|
|
16660
16706
|
continuousAutoFastForwardLastScan.clear();
|
|
16661
16707
|
autoFastForwardWorkspaceLease.clear();
|
|
16662
16708
|
}
|
|
16709
|
+
function loadRepoConfigForNode(node) {
|
|
16710
|
+
const workspace = typeof node?.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
|
|
16711
|
+
if (!workspace) return null;
|
|
16712
|
+
try {
|
|
16713
|
+
const result = loadRepoMeshJsonConfig(workspace);
|
|
16714
|
+
return result.sourceType === "repo_file" && result.config ? result.config : null;
|
|
16715
|
+
} catch {
|
|
16716
|
+
return null;
|
|
16717
|
+
}
|
|
16718
|
+
}
|
|
16663
16719
|
function getMeshWithCache(components, meshId) {
|
|
16664
16720
|
const localMesh = getMesh(meshId);
|
|
16665
16721
|
const cachedMesh = components.router?.getCachedInlineMesh(meshId);
|
|
@@ -16922,7 +16978,9 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
16922
16978
|
...delegatedWorkerAutoApproveSettings(
|
|
16923
16979
|
mesh?.policy,
|
|
16924
16980
|
node?.policy,
|
|
16925
|
-
components.providerLoader?.getMeta(providerType)
|
|
16981
|
+
components.providerLoader?.getMeta(providerType),
|
|
16982
|
+
loadRepoConfigForNode(node),
|
|
16983
|
+
providerType
|
|
16926
16984
|
),
|
|
16927
16985
|
...localDaemonId ? { meshCoordinatorDaemonId: localDaemonId } : {},
|
|
16928
16986
|
// COMPLETION-PROPAGATION F5: (re)stamp the coordinator SESSION anchor from THIS
|
|
@@ -17361,10 +17419,10 @@ function liveSessionCountForNode(components, meshId, nodeId) {
|
|
|
17361
17419
|
}
|
|
17362
17420
|
return count;
|
|
17363
17421
|
}
|
|
17364
|
-
function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
|
|
17422
|
+
function nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node) {
|
|
17365
17423
|
if (inWindowAutoLaunchSessionIdsForNode(meshId, nodeId).length > 0) return true;
|
|
17366
17424
|
const busySessionIds = new Set(
|
|
17367
|
-
getQueue(meshId, { status: ["assigned"] }).filter((
|
|
17425
|
+
getQueue(meshId, { status: ["assigned"] }).filter((task2) => daemonIdsEquivalent(task2.assignedNodeId, nodeId)).map((task2) => readNonEmptyString(task2.assignedSessionId)).filter(Boolean)
|
|
17368
17426
|
);
|
|
17369
17427
|
return components.instanceManager.getByCategory("cli").some((inst) => {
|
|
17370
17428
|
const state = inst.getState();
|
|
@@ -17377,6 +17435,12 @@ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
|
|
|
17377
17435
|
if (isTerminalSessionStatus(status)) return false;
|
|
17378
17436
|
const sessionId = readNonEmptyString(state.instanceId);
|
|
17379
17437
|
if (sessionId && busySessionIds.has(sessionId)) return false;
|
|
17438
|
+
if (task.requiredTags?.length) {
|
|
17439
|
+
const sessionProviderType = state.type || readNonEmptyString(settings.providerType);
|
|
17440
|
+
if (sessionProviderType && !nodeSatisfiesRequiredTags(task.requiredTags, buildMeshNodeCapabilityTags(node, sessionProviderType))) {
|
|
17441
|
+
return false;
|
|
17442
|
+
}
|
|
17443
|
+
}
|
|
17380
17444
|
return true;
|
|
17381
17445
|
});
|
|
17382
17446
|
}
|
|
@@ -17657,7 +17721,7 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
17657
17721
|
sweepExpiredCooldowns();
|
|
17658
17722
|
continue;
|
|
17659
17723
|
}
|
|
17660
|
-
if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId)) {
|
|
17724
|
+
if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node)) {
|
|
17661
17725
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
|
|
17662
17726
|
continue;
|
|
17663
17727
|
}
|
|
@@ -17700,7 +17764,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
17700
17764
|
...delegatedWorkerAutoApproveSettings(
|
|
17701
17765
|
mesh?.policy,
|
|
17702
17766
|
node?.policy,
|
|
17703
|
-
components.providerLoader?.getMeta(resolved.providerType)
|
|
17767
|
+
components.providerLoader?.getMeta(resolved.providerType),
|
|
17768
|
+
loadRepoConfigForNode(node),
|
|
17769
|
+
resolved.providerType
|
|
17704
17770
|
),
|
|
17705
17771
|
launchedByCoordinator: true,
|
|
17706
17772
|
autoLaunchedForQueueTaskId: task.id
|
|
@@ -18165,6 +18231,7 @@ var init_mesh_queue_assignment = __esm({
|
|
|
18165
18231
|
init_mesh_event_trace();
|
|
18166
18232
|
init_mesh_warmup_deadline();
|
|
18167
18233
|
init_repo_mesh_types();
|
|
18234
|
+
init_mesh_json_config();
|
|
18168
18235
|
init_dist();
|
|
18169
18236
|
init_mesh_node_slots();
|
|
18170
18237
|
init_mesh_events_stale();
|
|
@@ -21723,7 +21790,20 @@ function injectMeshSystemMessage(components, args) {
|
|
|
21723
21790
|
...delegatedWorkerAutoApproveSettings(
|
|
21724
21791
|
mesh?.policy,
|
|
21725
21792
|
node?.policy,
|
|
21726
|
-
components.providerLoader?.getMeta(recoveryContext.failedProviderType)
|
|
21793
|
+
components.providerLoader?.getMeta(recoveryContext.failedProviderType),
|
|
21794
|
+
// Recovery relaunch: same repo-declared requested mode as the
|
|
21795
|
+
// primary path. node.workspace missing → null → provider default.
|
|
21796
|
+
(() => {
|
|
21797
|
+
const ws = typeof node?.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
|
|
21798
|
+
if (!ws) return null;
|
|
21799
|
+
try {
|
|
21800
|
+
const r = loadRepoMeshJsonConfig(ws);
|
|
21801
|
+
return r.sourceType === "repo_file" && r.config ? r.config : null;
|
|
21802
|
+
} catch {
|
|
21803
|
+
return null;
|
|
21804
|
+
}
|
|
21805
|
+
})(),
|
|
21806
|
+
recoveryContext.failedProviderType
|
|
21727
21807
|
),
|
|
21728
21808
|
launchedByCoordinator: true
|
|
21729
21809
|
}
|
|
@@ -22114,6 +22194,7 @@ var init_mesh_event_forwarding = __esm({
|
|
|
22114
22194
|
init_mesh_event_trace();
|
|
22115
22195
|
init_snapshot();
|
|
22116
22196
|
init_repo_mesh_types();
|
|
22197
|
+
init_mesh_json_config();
|
|
22117
22198
|
init_dist();
|
|
22118
22199
|
init_mesh_events_stale();
|
|
22119
22200
|
init_mesh_task_inflight();
|
|
@@ -30909,6 +30990,7 @@ function detectClaudeAskUserQuestionPromptFromJson(value, providerType = "claude
|
|
|
30909
30990
|
|
|
30910
30991
|
// src/index.ts
|
|
30911
30992
|
init_repo_mesh_types();
|
|
30993
|
+
init_mesh_json_config();
|
|
30912
30994
|
|
|
30913
30995
|
// src/git/index.ts
|
|
30914
30996
|
init_git_executor();
|
|
@@ -60229,6 +60311,139 @@ var meshCrudHandlers = {
|
|
|
60229
60311
|
return { success: false, error: e.message };
|
|
60230
60312
|
}
|
|
60231
60313
|
},
|
|
60314
|
+
// READ path for `.adhdev/mesh.json` — returns the currently-committed repo
|
|
60315
|
+
// config (parsed + normalized) for a workspace so a UI can render/edit the
|
|
60316
|
+
// existing declarative zones (notably `providerDefaults.autoApproveModes`)
|
|
60317
|
+
// WITHOUT re-deriving them from the machine-local scaffold. Never writes.
|
|
60318
|
+
// `config` is undefined when no repo file exists (sourceType 'unavailable') or
|
|
60319
|
+
// it is unparseable (sourceType 'invalid', with the parse error surfaced).
|
|
60320
|
+
read_mesh_json_config: async (_ctx, args) => {
|
|
60321
|
+
const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
|
|
60322
|
+
try {
|
|
60323
|
+
const { loadRepoMeshJsonConfig: loadRepoMeshJsonConfig2 } = await Promise.resolve().then(() => (init_mesh_json_config(), mesh_json_config_exports));
|
|
60324
|
+
const loaded = loadRepoMeshJsonConfig2(workspace);
|
|
60325
|
+
return {
|
|
60326
|
+
success: true,
|
|
60327
|
+
workspace,
|
|
60328
|
+
sourceType: loaded.sourceType,
|
|
60329
|
+
source: loaded.source,
|
|
60330
|
+
...loaded.path ? { path: loaded.path } : {},
|
|
60331
|
+
...loaded.error ? { error: loaded.error } : {},
|
|
60332
|
+
config: loaded.config,
|
|
60333
|
+
// Convenience projection so the UI does not have to reach into config.
|
|
60334
|
+
providerDefaults: loaded.config?.providerDefaults
|
|
60335
|
+
};
|
|
60336
|
+
} catch (e) {
|
|
60337
|
+
return { success: false, error: e.message };
|
|
60338
|
+
}
|
|
60339
|
+
},
|
|
60340
|
+
// Partial-edit WRITE path for `.adhdev/mesh.json` `providerDefaults` — a
|
|
60341
|
+
// READ-MODIFY-WRITE that preserves operator hand-edits. Unlike
|
|
60342
|
+
// write_mesh_json_config (which rebuilds the WHOLE file from the machine-local
|
|
60343
|
+
// scaffold and can silently drop hand-edited zones), this parses the existing
|
|
60344
|
+
// repo file, merges ONLY the providerDefaults.autoApproveModes zone, and
|
|
60345
|
+
// re-serializes — coordinator prompt, operating notes and limits authored in
|
|
60346
|
+
// the repo are carried through untouched. Defaults to dry-run.
|
|
60347
|
+
//
|
|
60348
|
+
// args: { workspace?, autoApproveModes: Record<providerType,modeId>, write?, merge? }
|
|
60349
|
+
// merge=true (default): per-provider merge into the existing map; a modeId of
|
|
60350
|
+
// '' | null removes that provider's entry. merge=false: REPLACE the whole
|
|
60351
|
+
// autoApproveModes map with the supplied one.
|
|
60352
|
+
set_mesh_provider_defaults: async (_ctx, args) => {
|
|
60353
|
+
const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
|
|
60354
|
+
const write = args?.write === true;
|
|
60355
|
+
const merge = args?.merge !== false;
|
|
60356
|
+
const inputModes = args?.autoApproveModes;
|
|
60357
|
+
if (inputModes !== void 0 && (typeof inputModes !== "object" || inputModes === null || Array.isArray(inputModes))) {
|
|
60358
|
+
return { success: false, error: "autoApproveModes must be an object (providerType \u2192 modeId) when provided" };
|
|
60359
|
+
}
|
|
60360
|
+
try {
|
|
60361
|
+
const {
|
|
60362
|
+
loadRepoMeshJsonConfig: loadRepoMeshJsonConfig2,
|
|
60363
|
+
normalizeRepoMeshDeclarativeConfig: normalizeRepoMeshDeclarativeConfig2,
|
|
60364
|
+
MESH_JSON_CONFIG_LOCATIONS: MESH_JSON_CONFIG_LOCATIONS2
|
|
60365
|
+
} = await Promise.resolve().then(() => (init_mesh_json_config(), mesh_json_config_exports));
|
|
60366
|
+
const { existsSync: existsSync57, readFileSync: readFileSync44, mkdirSync: mkdirSync23, writeFileSync: writeFileSync25 } = await import("fs");
|
|
60367
|
+
const { dirname: dirname19, join: join54 } = await import("path");
|
|
60368
|
+
const yaml6 = await import("js-yaml");
|
|
60369
|
+
const relativePath = MESH_JSON_CONFIG_LOCATIONS2[0];
|
|
60370
|
+
let baseDoc = { version: 1 };
|
|
60371
|
+
let existingPath = join54(workspace, relativePath);
|
|
60372
|
+
let existedAsYaml = false;
|
|
60373
|
+
for (const relative5 of MESH_JSON_CONFIG_LOCATIONS2) {
|
|
60374
|
+
const candidate = join54(workspace, relative5);
|
|
60375
|
+
if (!existsSync57(candidate)) continue;
|
|
60376
|
+
try {
|
|
60377
|
+
const text = readFileSync44(candidate, "utf-8");
|
|
60378
|
+
const parsed = /\.json$/i.test(candidate) ? JSON.parse(text) : yaml6.load(text);
|
|
60379
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
60380
|
+
baseDoc = parsed;
|
|
60381
|
+
existingPath = candidate;
|
|
60382
|
+
existedAsYaml = !/\.json$/i.test(candidate);
|
|
60383
|
+
}
|
|
60384
|
+
} catch (e) {
|
|
60385
|
+
return { success: false, error: `existing ${relative5} is unparseable, refusing to overwrite: ${e?.message || e}` };
|
|
60386
|
+
}
|
|
60387
|
+
break;
|
|
60388
|
+
}
|
|
60389
|
+
const existingPd = baseDoc.providerDefaults && typeof baseDoc.providerDefaults === "object" && !Array.isArray(baseDoc.providerDefaults) ? baseDoc.providerDefaults : {};
|
|
60390
|
+
const existingModes = existingPd.autoApproveModes && typeof existingPd.autoApproveModes === "object" && !Array.isArray(existingPd.autoApproveModes) ? { ...existingPd.autoApproveModes } : {};
|
|
60391
|
+
const nextModes = merge ? existingModes : {};
|
|
60392
|
+
if (inputModes) {
|
|
60393
|
+
for (const [providerType, modeId] of Object.entries(inputModes)) {
|
|
60394
|
+
const type = typeof providerType === "string" ? providerType.trim() : "";
|
|
60395
|
+
if (!type) continue;
|
|
60396
|
+
const id = typeof modeId === "string" ? modeId.trim() : "";
|
|
60397
|
+
if (id) nextModes[type] = id;
|
|
60398
|
+
else delete nextModes[type];
|
|
60399
|
+
}
|
|
60400
|
+
}
|
|
60401
|
+
const nextDoc = { ...baseDoc, version: 1 };
|
|
60402
|
+
if (Object.keys(nextModes).length) {
|
|
60403
|
+
nextDoc.providerDefaults = { ...existingPd, autoApproveModes: nextModes };
|
|
60404
|
+
} else {
|
|
60405
|
+
if (nextDoc.providerDefaults) {
|
|
60406
|
+
const { autoApproveModes, ...restPd } = nextDoc.providerDefaults;
|
|
60407
|
+
if (Object.keys(restPd).length) nextDoc.providerDefaults = restPd;
|
|
60408
|
+
else delete nextDoc.providerDefaults;
|
|
60409
|
+
}
|
|
60410
|
+
}
|
|
60411
|
+
const validation = normalizeRepoMeshDeclarativeConfig2(nextDoc);
|
|
60412
|
+
if (!validation.valid) {
|
|
60413
|
+
return { success: false, error: `merged mesh.json is invalid: ${validation.errors.join("; ")}` };
|
|
60414
|
+
}
|
|
60415
|
+
const absolutePath = existingPath;
|
|
60416
|
+
const serialized = existedAsYaml ? yaml6.dump(nextDoc, { indent: 2 }) : `${JSON.stringify(nextDoc, null, 2)}
|
|
60417
|
+
`;
|
|
60418
|
+
if (!write) {
|
|
60419
|
+
return {
|
|
60420
|
+
success: true,
|
|
60421
|
+
written: false,
|
|
60422
|
+
dryRun: true,
|
|
60423
|
+
path: absolutePath,
|
|
60424
|
+
relativePath,
|
|
60425
|
+
merge,
|
|
60426
|
+
providerDefaults: nextDoc.providerDefaults,
|
|
60427
|
+
preview: serialized,
|
|
60428
|
+
note: "Dry-run: nothing written. Re-run with write=true to persist. Only the providerDefaults zone is merged; other repo zones are preserved."
|
|
60429
|
+
};
|
|
60430
|
+
}
|
|
60431
|
+
mkdirSync23(dirname19(absolutePath), { recursive: true });
|
|
60432
|
+
writeFileSync25(absolutePath, serialized, "utf-8");
|
|
60433
|
+
return {
|
|
60434
|
+
success: true,
|
|
60435
|
+
written: true,
|
|
60436
|
+
dryRun: false,
|
|
60437
|
+
path: absolutePath,
|
|
60438
|
+
relativePath,
|
|
60439
|
+
merge,
|
|
60440
|
+
providerDefaults: nextDoc.providerDefaults,
|
|
60441
|
+
note: "Wrote providerDefaults into .adhdev/mesh.json (read-modify-write; other zones preserved). Commit it to the repo."
|
|
60442
|
+
};
|
|
60443
|
+
} catch (e) {
|
|
60444
|
+
return { success: false, error: e.message };
|
|
60445
|
+
}
|
|
60446
|
+
},
|
|
60232
60447
|
delete_mesh: async (_ctx, args) => {
|
|
60233
60448
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
60234
60449
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
@@ -76361,6 +76576,9 @@ export {
|
|
|
76361
76576
|
MAX_LEDGER_SLICE_LIMIT,
|
|
76362
76577
|
MESH_CONVERGE_FAST_FORWARD_TAG,
|
|
76363
76578
|
MESH_CONVERGE_REFINE_TAG,
|
|
76579
|
+
MESH_JSON_CONFIG_LOCATIONS,
|
|
76580
|
+
MESH_JSON_CONFIG_SCHEMA,
|
|
76581
|
+
MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
|
|
76364
76582
|
MESH_MAX_PARALLEL_TASKS_MAX,
|
|
76365
76583
|
MESH_MAX_PARALLEL_TASKS_MIN,
|
|
76366
76584
|
MESH_MISSION_LIST_HISTORY_ID_LIMIT,
|
|
@@ -76420,6 +76638,7 @@ export {
|
|
|
76420
76638
|
buildMeshActiveWorkSummary,
|
|
76421
76639
|
buildMeshAsyncRefineJobs,
|
|
76422
76640
|
buildMeshHostRequiredFailure,
|
|
76641
|
+
buildMeshJsonConfigScaffold,
|
|
76423
76642
|
buildMeshLedgerReconciliationEvidence,
|
|
76424
76643
|
buildMeshLedgerReplicaEvidence,
|
|
76425
76644
|
buildMeshMagiActivity,
|
|
@@ -76584,6 +76803,7 @@ export {
|
|
|
76584
76803
|
loadMeshCoordinatorRegistry,
|
|
76585
76804
|
loadMeshRefineConfig,
|
|
76586
76805
|
loadMeshWorktreeBootstrapConfig,
|
|
76806
|
+
loadRepoMeshJsonConfig,
|
|
76587
76807
|
loadRepoSettings,
|
|
76588
76808
|
loadState,
|
|
76589
76809
|
logCommand,
|
|
@@ -76624,6 +76844,7 @@ export {
|
|
|
76624
76844
|
normalizeMeshWorkerResult,
|
|
76625
76845
|
normalizeMessageParts,
|
|
76626
76846
|
normalizeRepoIdentity,
|
|
76847
|
+
normalizeRepoMeshDeclarativeConfig,
|
|
76627
76848
|
normalizeSessionModalFields,
|
|
76628
76849
|
parsePorcelainV2Status,
|
|
76629
76850
|
parseProviderSourceConfigUpdate,
|
|
@@ -76694,6 +76915,7 @@ export {
|
|
|
76694
76915
|
runMeshWorktreeBootstrap,
|
|
76695
76916
|
saveConfig,
|
|
76696
76917
|
saveState,
|
|
76918
|
+
serializeMeshJsonConfigScaffold,
|
|
76697
76919
|
serializeV2EnvelopeToWire,
|
|
76698
76920
|
setDebugRuntimeConfig,
|
|
76699
76921
|
setLogLevel,
|