@adhdev/daemon-core 0.9.82-rc.365 → 0.9.82-rc.366
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/commands/high-family/index.d.ts +3 -0
- package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
- package/dist/commands/high-family/mesh-events.d.ts +2 -0
- package/dist/commands/high-family/mesh-status.d.ts +2 -0
- package/dist/commands/high-family/types.d.ts +60 -0
- package/dist/commands/router.d.ts +208 -0
- package/dist/index.js +1937 -1755
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1922 -1740
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-coordinator.d.ts +8 -0
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +28 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +592 -0
- package/src/commands/high-family/mesh-events.ts +47 -0
- package/src/commands/high-family/mesh-status.ts +639 -0
- package/src/commands/high-family/types.ts +76 -0
- package/src/commands/router.ts +272 -1246
- package/src/mesh/mesh-events-coordinator.ts +35 -1
package/dist/index.js
CHANGED
|
@@ -316,10 +316,10 @@ function readInjected(value) {
|
|
|
316
316
|
}
|
|
317
317
|
function getDaemonBuildInfo() {
|
|
318
318
|
if (cached) return cached;
|
|
319
|
-
const commit = readInjected(true ? "
|
|
320
|
-
const commitShort = readInjected(true ? "
|
|
321
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
322
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "c2224ab0c9d05e85b4cbf88e4fc696f3733ec397" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "c2224ab0" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.366" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-24T02:22:36.214Z" : void 0);
|
|
323
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
324
324
|
return cached;
|
|
325
325
|
}
|
|
@@ -7231,8 +7231,8 @@ function stripCoordinatorWrapperFile(filePath) {
|
|
|
7231
7231
|
const remaining = (existing.slice(0, openIdx) + existing.slice(closeIdx + CLOSE.length)).replace(/^\s*\n+/, "").replace(/\n+\s*$/, "");
|
|
7232
7232
|
if (!remaining.trim()) {
|
|
7233
7233
|
try {
|
|
7234
|
-
const
|
|
7235
|
-
|
|
7234
|
+
const fs35 = require("fs");
|
|
7235
|
+
fs35.unlinkSync(filePath);
|
|
7236
7236
|
} catch {
|
|
7237
7237
|
}
|
|
7238
7238
|
} else {
|
|
@@ -9671,9 +9671,9 @@ function findBinary(name) {
|
|
|
9671
9671
|
for (const ext of exes) {
|
|
9672
9672
|
const fullPath = path11.join(p, trimmed + ext);
|
|
9673
9673
|
try {
|
|
9674
|
-
const
|
|
9675
|
-
if (
|
|
9676
|
-
const stat2 =
|
|
9674
|
+
const fs35 = require("fs");
|
|
9675
|
+
if (fs35.existsSync(fullPath)) {
|
|
9676
|
+
const stat2 = fs35.statSync(fullPath);
|
|
9677
9677
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
9678
9678
|
return fullPath;
|
|
9679
9679
|
}
|
|
@@ -9687,12 +9687,12 @@ function findBinary(name) {
|
|
|
9687
9687
|
function isScriptBinary(binaryPath) {
|
|
9688
9688
|
if (!path11.isAbsolute(binaryPath)) return false;
|
|
9689
9689
|
try {
|
|
9690
|
-
const
|
|
9691
|
-
const resolved =
|
|
9690
|
+
const fs35 = require("fs");
|
|
9691
|
+
const resolved = fs35.realpathSync(binaryPath);
|
|
9692
9692
|
const head = Buffer.alloc(8);
|
|
9693
|
-
const fd =
|
|
9694
|
-
|
|
9695
|
-
|
|
9693
|
+
const fd = fs35.openSync(resolved, "r");
|
|
9694
|
+
fs35.readSync(fd, head, 0, 8, 0);
|
|
9695
|
+
fs35.closeSync(fd);
|
|
9696
9696
|
let i = 0;
|
|
9697
9697
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
9698
9698
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -9703,12 +9703,12 @@ function isScriptBinary(binaryPath) {
|
|
|
9703
9703
|
function looksLikeMachOOrElf(filePath) {
|
|
9704
9704
|
if (!path11.isAbsolute(filePath)) return false;
|
|
9705
9705
|
try {
|
|
9706
|
-
const
|
|
9707
|
-
const resolved =
|
|
9706
|
+
const fs35 = require("fs");
|
|
9707
|
+
const resolved = fs35.realpathSync(filePath);
|
|
9708
9708
|
const buf = Buffer.alloc(8);
|
|
9709
|
-
const fd =
|
|
9710
|
-
|
|
9711
|
-
|
|
9709
|
+
const fd = fs35.openSync(resolved, "r");
|
|
9710
|
+
fs35.readSync(fd, buf, 0, 8, 0);
|
|
9711
|
+
fs35.closeSync(fd);
|
|
9712
9712
|
let i = 0;
|
|
9713
9713
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
9714
9714
|
const b = buf.subarray(i);
|
|
@@ -13496,6 +13496,13 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
13496
13496
|
nodeId: task.assignedNodeId,
|
|
13497
13497
|
sessionId: task.assignedSessionId
|
|
13498
13498
|
}));
|
|
13499
|
+
const autoLaunchPending = autoLaunchStarted || afterQueue.some((task) => {
|
|
13500
|
+
if (task.status !== "pending") return false;
|
|
13501
|
+
const al = task.autoLaunch;
|
|
13502
|
+
if (!al || al.status !== "started" && al.status !== "completed") return false;
|
|
13503
|
+
const launchedAtMs = Date.parse(al.updatedAt);
|
|
13504
|
+
return Number.isFinite(launchedAtMs) && Date.now() - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
|
|
13505
|
+
});
|
|
13499
13506
|
return {
|
|
13500
13507
|
success: true,
|
|
13501
13508
|
meshId,
|
|
@@ -13509,7 +13516,11 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
13509
13516
|
remoteIdleSessionsChecked,
|
|
13510
13517
|
skippedSessions,
|
|
13511
13518
|
autoLaunchStarted,
|
|
13512
|
-
...
|
|
13519
|
+
...autoLaunchPending ? { autoLaunchPending: true } : {},
|
|
13520
|
+
// Only report "no idle session, go launch one" when nothing is already on its way.
|
|
13521
|
+
// A pending auto-launch (this tick or a prior still-converging one) means a session
|
|
13522
|
+
// WILL claim shortly, so it is not a no-session-available situation.
|
|
13523
|
+
...pendingAfter > 0 && newlyAssignedTasks.length === 0 && localIdleSessionsChecked === 0 && remoteIdleSessionsChecked === 0 && !autoLaunchPending ? { noIdleMeshSessionAvailable: true } : {}
|
|
13513
13524
|
};
|
|
13514
13525
|
}
|
|
13515
13526
|
async function maybeAutoFastForwardIdleNode(components, args) {
|
|
@@ -16478,8 +16489,8 @@ var init_pty_transport = __esm({
|
|
|
16478
16489
|
let cwd = options.cwd;
|
|
16479
16490
|
if (cwd) {
|
|
16480
16491
|
try {
|
|
16481
|
-
const
|
|
16482
|
-
const stat2 =
|
|
16492
|
+
const fs35 = require("fs");
|
|
16493
|
+
const stat2 = fs35.statSync(cwd);
|
|
16483
16494
|
if (!stat2.isDirectory()) cwd = os14.homedir();
|
|
16484
16495
|
} catch {
|
|
16485
16496
|
cwd = os14.homedir();
|
|
@@ -32368,7 +32379,7 @@ var DaemonCommandHandler = class {
|
|
|
32368
32379
|
return { success: false, error: "invalid type" };
|
|
32369
32380
|
}
|
|
32370
32381
|
const https = require("https");
|
|
32371
|
-
const
|
|
32382
|
+
const fs35 = require("fs");
|
|
32372
32383
|
const path42 = require("path");
|
|
32373
32384
|
const crypto6 = require("crypto");
|
|
32374
32385
|
const REGISTRY = "https://api.adhf.dev/api/v1/registry";
|
|
@@ -32412,7 +32423,7 @@ var DaemonCommandHandler = class {
|
|
|
32412
32423
|
if (!targetDir.startsWith(installRootResolved + path42.sep)) {
|
|
32413
32424
|
return { success: false, error: "install path escaped upstream root" };
|
|
32414
32425
|
}
|
|
32415
|
-
|
|
32426
|
+
fs35.mkdirSync(targetDir, { recursive: true });
|
|
32416
32427
|
let manifestProbe = {};
|
|
32417
32428
|
try {
|
|
32418
32429
|
manifestProbe = JSON.parse(manifestBody);
|
|
@@ -32437,7 +32448,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32437
32448
|
}
|
|
32438
32449
|
const targetFile = isV1 ? "provider.v1.json" : "provider.json";
|
|
32439
32450
|
const targetPath = path42.join(targetDir, targetFile);
|
|
32440
|
-
|
|
32451
|
+
fs35.writeFileSync(targetPath, manifestBody, "utf-8");
|
|
32441
32452
|
const manifestJson = JSON.parse(manifestBody);
|
|
32442
32453
|
const scriptFetch = await this.fetchProviderSources(
|
|
32443
32454
|
manifestJson,
|
|
@@ -32507,7 +32518,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32507
32518
|
const repo = source.repo;
|
|
32508
32519
|
const ref = source.ref;
|
|
32509
32520
|
const https = require("https");
|
|
32510
|
-
const
|
|
32521
|
+
const fs35 = require("fs");
|
|
32511
32522
|
const path42 = require("path");
|
|
32512
32523
|
function fetchJson(url, timeoutMs) {
|
|
32513
32524
|
return new Promise((resolve24, reject) => {
|
|
@@ -32591,8 +32602,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32591
32602
|
const relInside = entry.path.startsWith(sharedDirRel + "/") ? entry.path.slice(sharedDirRel.length + 1) : entry.path;
|
|
32592
32603
|
const outPath = path42.resolve(path42.join(sharedTargetDir, relInside));
|
|
32593
32604
|
if (!outPath.startsWith(path42.resolve(sharedTargetDir) + path42.sep)) continue;
|
|
32594
|
-
|
|
32595
|
-
|
|
32605
|
+
fs35.mkdirSync(path42.dirname(outPath), { recursive: true });
|
|
32606
|
+
fs35.writeFileSync(outPath, body);
|
|
32596
32607
|
fetchedCount++;
|
|
32597
32608
|
} catch (e) {
|
|
32598
32609
|
errors.push(`fetch shared ${entry.path}: ${e?.message ?? e}`);
|
|
@@ -32630,8 +32641,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32630
32641
|
errors.push(`refusing to write outside targetDir: ${entry.path}`);
|
|
32631
32642
|
continue;
|
|
32632
32643
|
}
|
|
32633
|
-
|
|
32634
|
-
|
|
32644
|
+
fs35.mkdirSync(path42.dirname(outPath), { recursive: true });
|
|
32645
|
+
fs35.writeFileSync(outPath, body);
|
|
32635
32646
|
fetchedCount++;
|
|
32636
32647
|
} catch (e) {
|
|
32637
32648
|
errors.push(`fetch ${entry.path}: ${e?.message ?? e}`);
|
|
@@ -32659,7 +32670,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32659
32670
|
if (!["cli", "ide", "extension", "acp"].includes(category)) {
|
|
32660
32671
|
return { success: false, error: `unknown category: ${category}` };
|
|
32661
32672
|
}
|
|
32662
|
-
const
|
|
32673
|
+
const fs35 = require("fs");
|
|
32663
32674
|
const path42 = require("path");
|
|
32664
32675
|
try {
|
|
32665
32676
|
const installRoot = this.getUpstreamInstallRoot();
|
|
@@ -32668,10 +32679,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32668
32679
|
if (!targetDir.startsWith(installRootResolved + path42.sep)) {
|
|
32669
32680
|
return { success: false, error: "refusing to delete outside upstream root" };
|
|
32670
32681
|
}
|
|
32671
|
-
if (!
|
|
32682
|
+
if (!fs35.existsSync(targetDir)) {
|
|
32672
32683
|
return { success: false, error: "not installed" };
|
|
32673
32684
|
}
|
|
32674
|
-
|
|
32685
|
+
fs35.rmSync(targetDir, { recursive: true, force: true });
|
|
32675
32686
|
if (this._ctx.providerLoader) {
|
|
32676
32687
|
this._ctx.providerLoader.reload();
|
|
32677
32688
|
this._ctx.providerLoader.registerToDetector();
|
|
@@ -32687,28 +32698,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32687
32698
|
* the UI and by the update checker.
|
|
32688
32699
|
*/
|
|
32689
32700
|
handleListInstalledProviders(_args) {
|
|
32690
|
-
const
|
|
32701
|
+
const fs35 = require("fs");
|
|
32691
32702
|
const path42 = require("path");
|
|
32692
32703
|
const installRoot = this.getUpstreamInstallRoot();
|
|
32693
|
-
if (!
|
|
32704
|
+
if (!fs35.existsSync(installRoot)) return { success: true, providers: [] };
|
|
32694
32705
|
const CATEGORIES = ["cli", "ide", "extension", "acp"];
|
|
32695
32706
|
const items = [];
|
|
32696
32707
|
for (const category of CATEGORIES) {
|
|
32697
32708
|
const categoryDir = path42.join(installRoot, category);
|
|
32698
|
-
if (!
|
|
32709
|
+
if (!fs35.existsSync(categoryDir)) continue;
|
|
32699
32710
|
let entries;
|
|
32700
32711
|
try {
|
|
32701
|
-
entries =
|
|
32712
|
+
entries = fs35.readdirSync(categoryDir);
|
|
32702
32713
|
} catch {
|
|
32703
32714
|
continue;
|
|
32704
32715
|
}
|
|
32705
32716
|
for (const type of entries) {
|
|
32706
32717
|
const v1Path = path42.join(categoryDir, type, "provider.v1.json");
|
|
32707
32718
|
const v0Path = path42.join(categoryDir, type, "provider.json");
|
|
32708
|
-
const manifestPath =
|
|
32719
|
+
const manifestPath = fs35.existsSync(v1Path) ? v1Path : fs35.existsSync(v0Path) ? v0Path : null;
|
|
32709
32720
|
if (!manifestPath) continue;
|
|
32710
32721
|
try {
|
|
32711
|
-
const m = JSON.parse(
|
|
32722
|
+
const m = JSON.parse(fs35.readFileSync(manifestPath, "utf-8"));
|
|
32712
32723
|
items.push({
|
|
32713
32724
|
type,
|
|
32714
32725
|
category,
|
|
@@ -32819,7 +32830,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32819
32830
|
if (!/^@[a-z0-9_-]+$/i.test(requestedName)) {
|
|
32820
32831
|
return { success: false, error: "name must match @[a-z0-9_-]+" };
|
|
32821
32832
|
}
|
|
32822
|
-
const
|
|
32833
|
+
const fs35 = require("fs");
|
|
32823
32834
|
const path42 = require("path");
|
|
32824
32835
|
const { spawnSync: spawnSync2 } = require("child_process");
|
|
32825
32836
|
const file = ext.loadExternalSources();
|
|
@@ -32830,8 +32841,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32830
32841
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
32831
32842
|
}
|
|
32832
32843
|
const sourceDir = path42.join(ext.externalRoot(), requestedName);
|
|
32833
|
-
if (!
|
|
32834
|
-
if (
|
|
32844
|
+
if (!fs35.existsSync(ext.externalRoot())) fs35.mkdirSync(ext.externalRoot(), { recursive: true });
|
|
32845
|
+
if (fs35.existsSync(sourceDir)) {
|
|
32835
32846
|
return { success: false, error: `directory already exists: ${sourceDir} (rename or remove first)` };
|
|
32836
32847
|
}
|
|
32837
32848
|
const clone = spawnSync2("git", ["clone", "--depth=1", "--branch", ref, "--", url, sourceDir], {
|
|
@@ -32841,7 +32852,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32841
32852
|
});
|
|
32842
32853
|
if (clone.status !== 0) {
|
|
32843
32854
|
try {
|
|
32844
|
-
|
|
32855
|
+
fs35.rmSync(sourceDir, { recursive: true, force: true });
|
|
32845
32856
|
} catch {
|
|
32846
32857
|
}
|
|
32847
32858
|
return { success: false, error: `git clone failed: ${(clone.stderr || clone.stdout || "").trim() || "unknown error"}` };
|
|
@@ -32885,15 +32896,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32885
32896
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
32886
32897
|
if (!name) return { success: false, error: "name is required" };
|
|
32887
32898
|
const ext = (init_external_sources(), __toCommonJS(external_sources_exports));
|
|
32888
|
-
const
|
|
32899
|
+
const fs35 = require("fs");
|
|
32889
32900
|
const path42 = require("path");
|
|
32890
32901
|
const file = ext.loadExternalSources();
|
|
32891
32902
|
const match = file.sources.find((s2) => s2.name === name);
|
|
32892
32903
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
32893
32904
|
const sourceDir = path42.join(ext.externalRoot(), name);
|
|
32894
|
-
if (
|
|
32905
|
+
if (fs35.existsSync(sourceDir)) {
|
|
32895
32906
|
try {
|
|
32896
|
-
|
|
32907
|
+
fs35.rmSync(sourceDir, { recursive: true, force: true });
|
|
32897
32908
|
} catch (e) {
|
|
32898
32909
|
return { success: false, error: `failed to delete ${sourceDir}: ${e?.message || e}` };
|
|
32899
32910
|
}
|
|
@@ -33674,14 +33685,14 @@ var statusMetaHandlers = {
|
|
|
33674
33685
|
// src/commands/low-family/coordinator-prompt.ts
|
|
33675
33686
|
var coordinatorPromptHandlers = {
|
|
33676
33687
|
list_coordinator_prompts: async (_ctx, _args) => {
|
|
33677
|
-
const
|
|
33688
|
+
const fs35 = await import("fs");
|
|
33678
33689
|
const path42 = await import("path");
|
|
33679
33690
|
const os30 = await import("os");
|
|
33680
33691
|
const dir = path42.join(os30.homedir(), ".adhdev", "coordinator-prompts");
|
|
33681
33692
|
const entries = {};
|
|
33682
33693
|
try {
|
|
33683
|
-
if (
|
|
33684
|
-
for (const name of
|
|
33694
|
+
if (fs35.existsSync(dir)) {
|
|
33695
|
+
for (const name of fs35.readdirSync(dir)) {
|
|
33685
33696
|
const matchOverride = name.match(/^([a-zA-Z0-9_.-]+)\.md$/);
|
|
33686
33697
|
const matchAppend = name.match(/^([a-zA-Z0-9_.-]+)\.append\.md$/);
|
|
33687
33698
|
const m = matchAppend || matchOverride;
|
|
@@ -33691,7 +33702,7 @@ var coordinatorPromptHandlers = {
|
|
|
33691
33702
|
const full = path42.join(dir, name);
|
|
33692
33703
|
let content = "";
|
|
33693
33704
|
try {
|
|
33694
|
-
content =
|
|
33705
|
+
content = fs35.readFileSync(full, "utf8");
|
|
33695
33706
|
} catch {
|
|
33696
33707
|
}
|
|
33697
33708
|
if (!entries[key]) entries[key] = { override: "", append: "" };
|
|
@@ -33705,7 +33716,7 @@ var coordinatorPromptHandlers = {
|
|
|
33705
33716
|
return { success: true, dir, entries };
|
|
33706
33717
|
},
|
|
33707
33718
|
write_coordinator_prompt: async (_ctx, args) => {
|
|
33708
|
-
const
|
|
33719
|
+
const fs35 = await import("fs");
|
|
33709
33720
|
const path42 = await import("path");
|
|
33710
33721
|
const os30 = await import("os");
|
|
33711
33722
|
const key = typeof args?.key === "string" ? args.key.trim() : "";
|
|
@@ -33718,11 +33729,11 @@ var coordinatorPromptHandlers = {
|
|
|
33718
33729
|
const filename = kind === "append" ? `${key}.append.md` : `${key}.md`;
|
|
33719
33730
|
const full = path42.join(dir, filename);
|
|
33720
33731
|
try {
|
|
33721
|
-
|
|
33732
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
33722
33733
|
if (content.trim()) {
|
|
33723
|
-
|
|
33724
|
-
} else if (
|
|
33725
|
-
|
|
33734
|
+
fs35.writeFileSync(full, content, { encoding: "utf8", mode: 384 });
|
|
33735
|
+
} else if (fs35.existsSync(full)) {
|
|
33736
|
+
fs35.unlinkSync(full);
|
|
33726
33737
|
}
|
|
33727
33738
|
return { success: true, path: full, kind, key };
|
|
33728
33739
|
} catch (error) {
|
|
@@ -41742,7 +41753,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
41742
41753
|
continue;
|
|
41743
41754
|
}
|
|
41744
41755
|
const restoredSettings = { ...this.providerLoader.getSettings(normalizedType) };
|
|
41745
|
-
|
|
41756
|
+
let coordinatorEntry = getCoordinatorForSession(record.runtimeId);
|
|
41757
|
+
if (!coordinatorEntry?.meshId && record.workspace) {
|
|
41758
|
+
const workspaceCoordinators = listCoordinatorsForWorkspace(record.workspace).filter((e) => e.meshId && (!e.cliType || e.cliType === record.cliType));
|
|
41759
|
+
if (workspaceCoordinators.length === 1) {
|
|
41760
|
+
coordinatorEntry = workspaceCoordinators[0];
|
|
41761
|
+
LOG.info(
|
|
41762
|
+
"CLI",
|
|
41763
|
+
`\u21BB Rebound coordinator mark by workspace for ${record.runtimeKey || record.runtimeId} (mesh ${coordinatorEntry.meshId} @ ${record.workspace}); registry key did not match runtimeId`
|
|
41764
|
+
);
|
|
41765
|
+
}
|
|
41766
|
+
}
|
|
41746
41767
|
if (coordinatorEntry?.meshId) {
|
|
41747
41768
|
restoredSettings.meshCoordinatorFor = coordinatorEntry.meshId;
|
|
41748
41769
|
}
|
|
@@ -44653,7 +44674,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
44653
44674
|
}
|
|
44654
44675
|
if (providerDir) {
|
|
44655
44676
|
try {
|
|
44656
|
-
const
|
|
44677
|
+
const fs35 = require("fs");
|
|
44657
44678
|
const path42 = require("path");
|
|
44658
44679
|
const candidates = [];
|
|
44659
44680
|
if (Array.isArray(base.compatibility)) {
|
|
@@ -44665,13 +44686,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
44665
44686
|
}
|
|
44666
44687
|
candidates.push(path42.join(providerDir, "specs", "default.json"));
|
|
44667
44688
|
candidates.push(path42.join(providerDir, "spec.json"));
|
|
44668
|
-
const specPath = candidates.find((p) =>
|
|
44689
|
+
const specPath = candidates.find((p) => fs35.existsSync(p));
|
|
44669
44690
|
if (specPath) {
|
|
44670
44691
|
resolved._resolvedSpecPath = specPath;
|
|
44671
44692
|
let specControls;
|
|
44672
44693
|
let nh;
|
|
44673
44694
|
try {
|
|
44674
|
-
const rawSpec = JSON.parse(
|
|
44695
|
+
const rawSpec = JSON.parse(fs35.readFileSync(specPath, "utf8"));
|
|
44675
44696
|
specControls = rawSpec.control_bar;
|
|
44676
44697
|
nh = rawSpec.native_history;
|
|
44677
44698
|
} catch {
|
|
@@ -44703,7 +44724,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
44703
44724
|
reader = (input) => executeNativeHistory(nh, input);
|
|
44704
44725
|
} else if (nh.override_path) {
|
|
44705
44726
|
const overrideFile = path42.resolve(providerDir, nh.override_path);
|
|
44706
|
-
if (
|
|
44727
|
+
if (fs35.existsSync(overrideFile)) {
|
|
44707
44728
|
try {
|
|
44708
44729
|
registerProviderScriptRootSafely(path42.dirname(path42.dirname(providerDir)));
|
|
44709
44730
|
delete require.cache[require.resolve(overrideFile)];
|
|
@@ -45250,8 +45271,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
45250
45271
|
}
|
|
45251
45272
|
}
|
|
45252
45273
|
writeConfig(config) {
|
|
45253
|
-
const { saveConfig:
|
|
45254
|
-
|
|
45274
|
+
const { saveConfig: saveConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
45275
|
+
saveConfig2(config);
|
|
45255
45276
|
}
|
|
45256
45277
|
getPlatformVersionCommand(versionCommand) {
|
|
45257
45278
|
if (!versionCommand) return void 0;
|
|
@@ -45888,7 +45909,7 @@ async function detectCurrentWorkspace(ideId) {
|
|
|
45888
45909
|
}
|
|
45889
45910
|
} else if (plat === "win32") {
|
|
45890
45911
|
try {
|
|
45891
|
-
const
|
|
45912
|
+
const fs35 = require("fs");
|
|
45892
45913
|
const appNameMap = getMacAppIdentifiers();
|
|
45893
45914
|
const appName = appNameMap[ideId];
|
|
45894
45915
|
if (appName) {
|
|
@@ -45897,8 +45918,8 @@ async function detectCurrentWorkspace(ideId) {
|
|
|
45897
45918
|
appName,
|
|
45898
45919
|
"storage.json"
|
|
45899
45920
|
);
|
|
45900
|
-
if (
|
|
45901
|
-
const data = JSON.parse(
|
|
45921
|
+
if (fs35.existsSync(storagePath)) {
|
|
45922
|
+
const data = JSON.parse(fs35.readFileSync(storagePath, "utf-8"));
|
|
45902
45923
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
45903
45924
|
if (workspaces.length > 0) {
|
|
45904
45925
|
const recent = workspaces[0];
|
|
@@ -47409,15 +47430,1054 @@ var medFamilyRegistry = new Map(
|
|
|
47409
47430
|
})
|
|
47410
47431
|
);
|
|
47411
47432
|
|
|
47412
|
-
// src/commands/
|
|
47433
|
+
// src/commands/high-family/mesh-events.ts
|
|
47434
|
+
init_mesh_events();
|
|
47435
|
+
var meshEventsHandlers = {
|
|
47436
|
+
mesh_forward_event: async (ctx, args) => {
|
|
47437
|
+
return handleMeshForwardEvent({ instanceManager: ctx.deps.instanceManager }, args);
|
|
47438
|
+
},
|
|
47439
|
+
get_pending_mesh_events: async (_ctx, args) => {
|
|
47440
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47441
|
+
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
47442
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
|
|
47443
|
+
return { success: true, events };
|
|
47444
|
+
},
|
|
47445
|
+
interactive_prompt_response: async (ctx, args) => {
|
|
47446
|
+
const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
|
|
47447
|
+
if (!sessionId) return { success: false, error: "targetSessionId required" };
|
|
47448
|
+
const response = normalizeInteractivePromptResponse(args?.response ?? args);
|
|
47449
|
+
const instance = ctx.deps.instanceManager.getInstance(sessionId);
|
|
47450
|
+
if (!instance) return { success: false, error: `No running instance for session ${sessionId}` };
|
|
47451
|
+
ctx.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
|
|
47452
|
+
return { success: true };
|
|
47453
|
+
}
|
|
47454
|
+
};
|
|
47455
|
+
|
|
47456
|
+
// src/commands/high-family/mesh-coordinator-launch.ts
|
|
47457
|
+
var import_path12 = require("path");
|
|
47458
|
+
var fs26 = __toESM(require("fs"));
|
|
47459
|
+
init_logger();
|
|
47460
|
+
init_mesh_host_ownership();
|
|
47461
|
+
init_coordinator_registry();
|
|
47462
|
+
init_mesh_coordinator();
|
|
47463
|
+
init_dist();
|
|
47464
|
+
var meshCoordinatorLaunchHandlers = {
|
|
47465
|
+
launch_mesh_coordinator: async (ctx, args) => {
|
|
47466
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47467
|
+
let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
|
|
47468
|
+
const extraSystemPrompt = typeof args?.extraSystemPrompt === "string" ? args.extraSystemPrompt.trim() : "";
|
|
47469
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
47470
|
+
try {
|
|
47471
|
+
const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
47472
|
+
const { buildMissionPromptSection: buildMissionPromptSection2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
|
|
47473
|
+
const buildMissionSectionBestEffort = (id) => {
|
|
47474
|
+
try {
|
|
47475
|
+
return buildMissionPromptSection2(id);
|
|
47476
|
+
} catch {
|
|
47477
|
+
return "";
|
|
47478
|
+
}
|
|
47479
|
+
};
|
|
47480
|
+
let mesh;
|
|
47481
|
+
if (args?.inlineMesh && typeof args.inlineMesh === "object") {
|
|
47482
|
+
mesh = args.inlineMesh;
|
|
47483
|
+
ctx.inlineMeshCache.set(meshId, mesh);
|
|
47484
|
+
} else {
|
|
47485
|
+
const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
47486
|
+
mesh = getMesh2(meshId);
|
|
47487
|
+
}
|
|
47488
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
47489
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
47490
|
+
if (!meshHost.canOwnCoordinator) {
|
|
47491
|
+
return {
|
|
47492
|
+
success: false,
|
|
47493
|
+
...buildMeshHostRequiredFailure(mesh, "coordinator launch"),
|
|
47494
|
+
meshId,
|
|
47495
|
+
cliType
|
|
47496
|
+
};
|
|
47497
|
+
}
|
|
47498
|
+
if (!Array.isArray(mesh.nodes) || mesh.nodes.length === 0) return { success: false, error: "No nodes in mesh" };
|
|
47499
|
+
const requestedCoordinatorNodeId = typeof args?.coordinatorNodeId === "string" ? args.coordinatorNodeId.trim() : "";
|
|
47500
|
+
const preferredCoordinatorNodeId = requestedCoordinatorNodeId || (typeof mesh.coordinator?.preferredNodeId === "string" ? mesh.coordinator.preferredNodeId.trim() : "");
|
|
47501
|
+
const coordinatorNode = preferredCoordinatorNodeId ? mesh.nodes.find((node) => node?.id === preferredCoordinatorNodeId || node?.nodeId === preferredCoordinatorNodeId) : mesh.nodes[0];
|
|
47502
|
+
if (!coordinatorNode) {
|
|
47503
|
+
return {
|
|
47504
|
+
success: false,
|
|
47505
|
+
code: "mesh_coordinator_node_not_found",
|
|
47506
|
+
error: `Coordinator node ${preferredCoordinatorNodeId} was not found in mesh`,
|
|
47507
|
+
meshId,
|
|
47508
|
+
cliType
|
|
47509
|
+
};
|
|
47510
|
+
}
|
|
47511
|
+
const sessionHostRecords = ctx.deps.sessionHostControl?.listSessions ? await ctx.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
47512
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
47513
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
47514
|
+
meshId,
|
|
47515
|
+
nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || ""),
|
|
47516
|
+
liveSessionRecords: liveMeshSessions,
|
|
47517
|
+
allowCoordinatorSession: true
|
|
47518
|
+
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
47519
|
+
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
47520
|
+
if (!cliType) {
|
|
47521
|
+
const resolved = await resolveProviderTypeFromPriority({
|
|
47522
|
+
nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || "coordinator"),
|
|
47523
|
+
providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
|
|
47524
|
+
providerLoader: ctx.deps.providerLoader,
|
|
47525
|
+
onStatusChange: ctx.deps.onStatusChange
|
|
47526
|
+
});
|
|
47527
|
+
if (!resolved.providerType) {
|
|
47528
|
+
return {
|
|
47529
|
+
success: false,
|
|
47530
|
+
code: "mesh_coordinator_provider_priority_unusable",
|
|
47531
|
+
error: resolved.error || "No usable provider found from node providerPriority",
|
|
47532
|
+
meshId,
|
|
47533
|
+
cliType,
|
|
47534
|
+
workspace
|
|
47535
|
+
};
|
|
47536
|
+
}
|
|
47537
|
+
cliType = resolved.providerType;
|
|
47538
|
+
}
|
|
47539
|
+
const providerMeta = ctx.deps.providerLoader.resolve?.(cliType) || ctx.deps.providerLoader.getMeta(cliType);
|
|
47540
|
+
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
47541
|
+
provider: providerMeta,
|
|
47542
|
+
cliType,
|
|
47543
|
+
meshId,
|
|
47544
|
+
workspace
|
|
47545
|
+
});
|
|
47546
|
+
if (coordinatorSetup.kind === "unsupported") {
|
|
47547
|
+
return {
|
|
47548
|
+
success: false,
|
|
47549
|
+
code: "mesh_coordinator_unsupported",
|
|
47550
|
+
error: coordinatorSetup.reason,
|
|
47551
|
+
meshId,
|
|
47552
|
+
cliType,
|
|
47553
|
+
workspace
|
|
47554
|
+
};
|
|
47555
|
+
}
|
|
47556
|
+
if (coordinatorSetup.kind === "manual") {
|
|
47557
|
+
return {
|
|
47558
|
+
success: false,
|
|
47559
|
+
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
47560
|
+
error: coordinatorSetup.instructions,
|
|
47561
|
+
meshId,
|
|
47562
|
+
cliType,
|
|
47563
|
+
workspace,
|
|
47564
|
+
meshCoordinatorSetup: coordinatorSetup
|
|
47565
|
+
};
|
|
47566
|
+
}
|
|
47567
|
+
if (coordinatorSetup.kind === "cli_command") {
|
|
47568
|
+
let cliCmdSystemPrompt = "";
|
|
47569
|
+
try {
|
|
47570
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
47571
|
+
} catch (error) {
|
|
47572
|
+
const message = error?.message || String(error);
|
|
47573
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
47574
|
+
return {
|
|
47575
|
+
success: false,
|
|
47576
|
+
code: "mesh_coordinator_prompt_failed",
|
|
47577
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
47578
|
+
meshId,
|
|
47579
|
+
cliType,
|
|
47580
|
+
workspace
|
|
47581
|
+
};
|
|
47582
|
+
}
|
|
47583
|
+
let mcpRegistrationOk = false;
|
|
47584
|
+
let mcpRegistrationFailure = null;
|
|
47585
|
+
try {
|
|
47586
|
+
const { buildMeshCoordinatorRegistrationPlan: buildMeshCoordinatorRegistrationPlan2, execUnderPty: execUnderPty2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
47587
|
+
const registrationPlan = buildMeshCoordinatorRegistrationPlan2(
|
|
47588
|
+
cliType,
|
|
47589
|
+
coordinatorSetup.serverName,
|
|
47590
|
+
coordinatorSetup.command
|
|
47591
|
+
);
|
|
47592
|
+
for (const step of registrationPlan) {
|
|
47593
|
+
const renderedCommand = [step.command, ...step.args].join(" ");
|
|
47594
|
+
LOG.info("MeshCoordinator", `Running MCP ${step.label} (pty): ${renderedCommand}`);
|
|
47595
|
+
const ptyResult = await execUnderPty2(step.command, step.args, { cwd: workspace, timeoutMs: 2e4 });
|
|
47596
|
+
if (ptyResult.exitCode === 0 && !ptyResult.timedOut) {
|
|
47597
|
+
if (step.required) mcpRegistrationOk = true;
|
|
47598
|
+
continue;
|
|
47599
|
+
}
|
|
47600
|
+
LOG.warn("MeshCoordinator", `MCP ${step.label} failed exit=${ptyResult.exitCode} signal=${ptyResult.signal} timedOut=${ptyResult.timedOut} \u2014 output:
|
|
47601
|
+
${ptyResult.output.slice(-2e3)}`);
|
|
47602
|
+
if (step.required) {
|
|
47603
|
+
mcpRegistrationFailure = {
|
|
47604
|
+
command: renderedCommand,
|
|
47605
|
+
output: ptyResult.output.slice(-2e3),
|
|
47606
|
+
exitCode: ptyResult.exitCode,
|
|
47607
|
+
signal: ptyResult.signal,
|
|
47608
|
+
timedOut: ptyResult.timedOut
|
|
47609
|
+
};
|
|
47610
|
+
break;
|
|
47611
|
+
}
|
|
47612
|
+
}
|
|
47613
|
+
} catch (error) {
|
|
47614
|
+
LOG.warn("MeshCoordinator", `MCP registration command failed: ${error?.message || error}`);
|
|
47615
|
+
mcpRegistrationFailure = {
|
|
47616
|
+
command: coordinatorSetup.command,
|
|
47617
|
+
output: error?.message || String(error),
|
|
47618
|
+
exitCode: null,
|
|
47619
|
+
signal: null,
|
|
47620
|
+
timedOut: false
|
|
47621
|
+
};
|
|
47622
|
+
}
|
|
47623
|
+
if (!mcpRegistrationOk) {
|
|
47624
|
+
return {
|
|
47625
|
+
success: false,
|
|
47626
|
+
code: "mesh_coordinator_mcp_registration_failed",
|
|
47627
|
+
error: `Could not register ${coordinatorSetup.serverName}; coordinator session was not launched`,
|
|
47628
|
+
meshId,
|
|
47629
|
+
cliType,
|
|
47630
|
+
workspace,
|
|
47631
|
+
registration: mcpRegistrationFailure
|
|
47632
|
+
};
|
|
47633
|
+
}
|
|
47634
|
+
if (cliType === "codex-cli") {
|
|
47635
|
+
const repoMcpConfigPath = (0, import_path12.join)(workspace, ".mcp.json");
|
|
47636
|
+
if (fs26.existsSync(repoMcpConfigPath)) {
|
|
47637
|
+
try {
|
|
47638
|
+
const repoMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
47639
|
+
fs26.readFileSync(repoMcpConfigPath, "utf-8"),
|
|
47640
|
+
"claude_mcp_json"
|
|
47641
|
+
);
|
|
47642
|
+
const existingServers2 = repoMcpConfig.mcpServers;
|
|
47643
|
+
if (existingServers2 && typeof existingServers2 === "object" && !Array.isArray(existingServers2) && existingServers2[coordinatorSetup.serverName]) {
|
|
47644
|
+
fs26.writeFileSync(repoMcpConfigPath, serializeMeshCoordinatorMcpConfig({
|
|
47645
|
+
...repoMcpConfig,
|
|
47646
|
+
mcpServers: {
|
|
47647
|
+
...existingServers2,
|
|
47648
|
+
[coordinatorSetup.serverName]: coordinatorSetup.mcpServer
|
|
47649
|
+
}
|
|
47650
|
+
}, "claude_mcp_json"), "utf-8");
|
|
47651
|
+
LOG.info("MeshCoordinator", `Refreshed repo-local ${repoMcpConfigPath} entry for ${coordinatorSetup.serverName}`);
|
|
47652
|
+
}
|
|
47653
|
+
} catch (error) {
|
|
47654
|
+
return {
|
|
47655
|
+
success: false,
|
|
47656
|
+
code: "mesh_coordinator_config_write_failed",
|
|
47657
|
+
error: `Could not refresh repo-local MCP config: ${error?.message || error}`,
|
|
47658
|
+
meshId,
|
|
47659
|
+
cliType,
|
|
47660
|
+
workspace
|
|
47661
|
+
};
|
|
47662
|
+
}
|
|
47663
|
+
}
|
|
47664
|
+
}
|
|
47665
|
+
const cliCmdArgs = [];
|
|
47666
|
+
const cliCmdEnv = {};
|
|
47667
|
+
let cliCmdContextFilePath;
|
|
47668
|
+
if (cliCmdSystemPrompt) {
|
|
47669
|
+
const { applyMeshCoordinatorSystemPromptInjection: applyMeshCoordinatorSystemPromptInjection2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
47670
|
+
const effect = applyMeshCoordinatorSystemPromptInjection2(
|
|
47671
|
+
cliCmdSystemPrompt,
|
|
47672
|
+
providerMeta?.meshCoordinator?.systemPromptInjection,
|
|
47673
|
+
{ cliArgs: cliCmdArgs, launchEnv: cliCmdEnv, workspace, cliType }
|
|
47674
|
+
);
|
|
47675
|
+
cliCmdContextFilePath = effect.contextFilePath;
|
|
47676
|
+
}
|
|
47677
|
+
const cliCmdLaunch = await ctx.deps.cliManager.handleCliCommand("launch_cli", {
|
|
47678
|
+
cliType,
|
|
47679
|
+
dir: workspace,
|
|
47680
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
47681
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
47682
|
+
settings: { meshCoordinatorFor: meshId }
|
|
47683
|
+
});
|
|
47684
|
+
if (cliCmdLaunch?.success && cliCmdContextFilePath) {
|
|
47685
|
+
const stripPath = cliCmdContextFilePath;
|
|
47686
|
+
setTimeout(() => {
|
|
47687
|
+
void Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports)).then(({ stripCoordinatorWrapperFile: stripCoordinatorWrapperFile2 }) => {
|
|
47688
|
+
stripCoordinatorWrapperFile2(stripPath);
|
|
47689
|
+
LOG.info("MeshCoordinator", `Stripped wrapper from ${stripPath} after launch settle (cli_command)`);
|
|
47690
|
+
}).catch(() => {
|
|
47691
|
+
});
|
|
47692
|
+
}, 5e3);
|
|
47693
|
+
}
|
|
47694
|
+
if (!cliCmdLaunch?.success) {
|
|
47695
|
+
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
47696
|
+
}
|
|
47697
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
47698
|
+
const cliCmdSessionId = cliCmdLaunch.sessionId || cliCmdLaunch.id;
|
|
47699
|
+
if (cliCmdSessionId) {
|
|
47700
|
+
const cliCmdInjectionDecl = providerMeta?.meshCoordinator?.systemPromptInjection;
|
|
47701
|
+
registerMeshCoordinator({
|
|
47702
|
+
meshId,
|
|
47703
|
+
sessionId: cliCmdSessionId,
|
|
47704
|
+
workspace,
|
|
47705
|
+
startedAt: Date.now(),
|
|
47706
|
+
cliType,
|
|
47707
|
+
systemPrompt: cliCmdSystemPrompt || void 0,
|
|
47708
|
+
extraSystemPrompt: extraSystemPrompt || void 0,
|
|
47709
|
+
injection: cliCmdInjectionDecl ? {
|
|
47710
|
+
mode: cliCmdInjectionDecl.mode,
|
|
47711
|
+
target: "flag" in cliCmdInjectionDecl ? cliCmdInjectionDecl.flag : "name" in cliCmdInjectionDecl ? cliCmdInjectionDecl.name : "path" in cliCmdInjectionDecl ? cliCmdInjectionDecl.path : void 0
|
|
47712
|
+
} : void 0
|
|
47713
|
+
});
|
|
47714
|
+
}
|
|
47715
|
+
try {
|
|
47716
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
47717
|
+
appendLedgerEntry2(meshId, {
|
|
47718
|
+
kind: "coordinator_started",
|
|
47719
|
+
sessionId: cliCmdSessionId,
|
|
47720
|
+
providerType: cliType,
|
|
47721
|
+
payload: { workspace }
|
|
47722
|
+
});
|
|
47723
|
+
} catch {
|
|
47724
|
+
}
|
|
47725
|
+
return {
|
|
47726
|
+
success: true,
|
|
47727
|
+
meshId,
|
|
47728
|
+
cliType,
|
|
47729
|
+
workspace,
|
|
47730
|
+
sessionId: cliCmdSessionId,
|
|
47731
|
+
mcpRegistered: mcpRegistrationOk
|
|
47732
|
+
};
|
|
47733
|
+
}
|
|
47734
|
+
const configFormat = coordinatorSetup.configFormat;
|
|
47735
|
+
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
47736
|
+
return {
|
|
47737
|
+
success: false,
|
|
47738
|
+
code: "mesh_coordinator_unsupported",
|
|
47739
|
+
error: `Unsupported auto-import MCP config format: ${String(coordinatorSetup.configFormat)}`,
|
|
47740
|
+
meshId,
|
|
47741
|
+
cliType,
|
|
47742
|
+
workspace
|
|
47743
|
+
};
|
|
47744
|
+
}
|
|
47745
|
+
let systemPrompt = "";
|
|
47746
|
+
try {
|
|
47747
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
47748
|
+
} catch (error) {
|
|
47749
|
+
const message = error?.message || String(error);
|
|
47750
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
47751
|
+
return {
|
|
47752
|
+
success: false,
|
|
47753
|
+
code: "mesh_coordinator_prompt_failed",
|
|
47754
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
47755
|
+
meshId,
|
|
47756
|
+
cliType,
|
|
47757
|
+
workspace
|
|
47758
|
+
};
|
|
47759
|
+
}
|
|
47760
|
+
const { existsSync: existsSync49, readFileSync: readFileSync39, writeFileSync: writeFileSync24, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
|
|
47761
|
+
const { dirname: dirname17 } = await import("path");
|
|
47762
|
+
const mcpConfigPath = coordinatorSetup.configPath;
|
|
47763
|
+
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
47764
|
+
let hermesBaseConfig = null;
|
|
47765
|
+
if (hermesManualFallback) {
|
|
47766
|
+
try {
|
|
47767
|
+
hermesBaseConfig = loadHermesCoordinatorBaseConfig(mcpConfigPath);
|
|
47768
|
+
} catch (error) {
|
|
47769
|
+
const message = `Failed to parse Hermes base config for automatic coordinator setup: ${error?.message || error}`;
|
|
47770
|
+
LOG.error("MeshCoordinator", message);
|
|
47771
|
+
return { success: false, code: "mesh_coordinator_config_parse_failed", error: message, meshId, cliType, workspace };
|
|
47772
|
+
}
|
|
47773
|
+
}
|
|
47774
|
+
const returnManualFallback = (message) => ({
|
|
47775
|
+
success: false,
|
|
47776
|
+
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
47777
|
+
error: message,
|
|
47778
|
+
meshId,
|
|
47779
|
+
cliType,
|
|
47780
|
+
workspace,
|
|
47781
|
+
meshCoordinatorSetup: hermesManualFallback
|
|
47782
|
+
});
|
|
47783
|
+
const mcpServerEntry = {
|
|
47784
|
+
command: coordinatorSetup.mcpServer.command,
|
|
47785
|
+
args: coordinatorSetup.mcpServer.args
|
|
47786
|
+
};
|
|
47787
|
+
if (args?.inlineMesh) {
|
|
47788
|
+
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
47789
|
+
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
47790
|
+
mcpServerEntry.env = {
|
|
47791
|
+
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
47792
|
+
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
47793
|
+
};
|
|
47794
|
+
}
|
|
47795
|
+
try {
|
|
47796
|
+
mkdirSync21(dirname17(mcpConfigPath), { recursive: true });
|
|
47797
|
+
} catch (error) {
|
|
47798
|
+
const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
|
|
47799
|
+
LOG.error("MeshCoordinator", message);
|
|
47800
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
47801
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
47802
|
+
}
|
|
47803
|
+
const hadExistingMcpConfig = existsSync49(mcpConfigPath);
|
|
47804
|
+
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
47805
|
+
if (hermesBaseConfig) {
|
|
47806
|
+
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname17(mcpConfigPath));
|
|
47807
|
+
}
|
|
47808
|
+
if (hadExistingMcpConfig) {
|
|
47809
|
+
try {
|
|
47810
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync39(mcpConfigPath, "utf-8"), configFormat);
|
|
47811
|
+
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
47812
|
+
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
47813
|
+
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
47814
|
+
} catch (error) {
|
|
47815
|
+
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
47816
|
+
return {
|
|
47817
|
+
success: false,
|
|
47818
|
+
code: "mesh_coordinator_config_parse_failed",
|
|
47819
|
+
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
47820
|
+
};
|
|
47821
|
+
}
|
|
47822
|
+
}
|
|
47823
|
+
const mcpServersKey = getMcpServersKey(configFormat);
|
|
47824
|
+
const existingServers = existingMcpConfig[mcpServersKey];
|
|
47825
|
+
const mcpConfig = {
|
|
47826
|
+
...existingMcpConfig,
|
|
47827
|
+
[mcpServersKey]: {
|
|
47828
|
+
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
47829
|
+
[coordinatorSetup.serverName]: mcpServerEntry
|
|
47830
|
+
}
|
|
47831
|
+
};
|
|
47832
|
+
try {
|
|
47833
|
+
writeFileSync24(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
47834
|
+
} catch (error) {
|
|
47835
|
+
const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
|
|
47836
|
+
LOG.error("MeshCoordinator", message);
|
|
47837
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
47838
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
47839
|
+
}
|
|
47840
|
+
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
47841
|
+
const cliArgs = [];
|
|
47842
|
+
const launchEnv = {};
|
|
47843
|
+
if (configFormat === "hermes_config_yaml") {
|
|
47844
|
+
launchEnv.HERMES_HOME = dirname17(mcpConfigPath);
|
|
47845
|
+
launchEnv.HERMES_IGNORE_USER_CONFIG = "";
|
|
47846
|
+
}
|
|
47847
|
+
let autoImportContextFilePath;
|
|
47848
|
+
if (systemPrompt) {
|
|
47849
|
+
const { applyMeshCoordinatorSystemPromptInjection: applyMeshCoordinatorSystemPromptInjection2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
47850
|
+
const effect = applyMeshCoordinatorSystemPromptInjection2(
|
|
47851
|
+
systemPrompt,
|
|
47852
|
+
providerMeta?.meshCoordinator?.systemPromptInjection,
|
|
47853
|
+
{ cliArgs, launchEnv, workspace, cliType }
|
|
47854
|
+
);
|
|
47855
|
+
autoImportContextFilePath = effect.contextFilePath;
|
|
47856
|
+
}
|
|
47857
|
+
if (cliType === "claude-cli") {
|
|
47858
|
+
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
47859
|
+
}
|
|
47860
|
+
const launchResult = await ctx.deps.cliManager.handleCliCommand("launch_cli", {
|
|
47861
|
+
cliType,
|
|
47862
|
+
dir: workspace,
|
|
47863
|
+
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
47864
|
+
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
47865
|
+
settings: {
|
|
47866
|
+
meshCoordinatorFor: meshId
|
|
47867
|
+
}
|
|
47868
|
+
});
|
|
47869
|
+
if (launchResult?.success && autoImportContextFilePath) {
|
|
47870
|
+
const stripPath = autoImportContextFilePath;
|
|
47871
|
+
setTimeout(() => {
|
|
47872
|
+
void Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports)).then(({ stripCoordinatorWrapperFile: stripCoordinatorWrapperFile2 }) => {
|
|
47873
|
+
stripCoordinatorWrapperFile2(stripPath);
|
|
47874
|
+
LOG.info("MeshCoordinator", `Stripped wrapper from ${stripPath} after launch settle (auto_import)`);
|
|
47875
|
+
}).catch(() => {
|
|
47876
|
+
});
|
|
47877
|
+
}, 5e3);
|
|
47878
|
+
}
|
|
47879
|
+
if (!launchResult?.success) {
|
|
47880
|
+
return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
|
|
47881
|
+
}
|
|
47882
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
|
|
47883
|
+
const launchSessionId = launchResult.sessionId || launchResult.id;
|
|
47884
|
+
if (launchSessionId) {
|
|
47885
|
+
const autoImportInjectionDecl = providerMeta?.meshCoordinator?.systemPromptInjection;
|
|
47886
|
+
registerMeshCoordinator({
|
|
47887
|
+
meshId,
|
|
47888
|
+
sessionId: launchSessionId,
|
|
47889
|
+
workspace,
|
|
47890
|
+
startedAt: Date.now(),
|
|
47891
|
+
cliType,
|
|
47892
|
+
systemPrompt: systemPrompt || void 0,
|
|
47893
|
+
extraSystemPrompt: extraSystemPrompt || void 0,
|
|
47894
|
+
mcpConfigPath,
|
|
47895
|
+
injection: autoImportInjectionDecl ? {
|
|
47896
|
+
mode: autoImportInjectionDecl.mode,
|
|
47897
|
+
target: "flag" in autoImportInjectionDecl ? autoImportInjectionDecl.flag : "name" in autoImportInjectionDecl ? autoImportInjectionDecl.name : "path" in autoImportInjectionDecl ? autoImportInjectionDecl.path : void 0
|
|
47898
|
+
} : void 0
|
|
47899
|
+
});
|
|
47900
|
+
}
|
|
47901
|
+
try {
|
|
47902
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
47903
|
+
appendLedgerEntry2(meshId, {
|
|
47904
|
+
kind: "coordinator_started",
|
|
47905
|
+
sessionId: launchSessionId,
|
|
47906
|
+
providerType: cliType,
|
|
47907
|
+
payload: { workspace }
|
|
47908
|
+
});
|
|
47909
|
+
} catch {
|
|
47910
|
+
}
|
|
47911
|
+
return {
|
|
47912
|
+
success: true,
|
|
47913
|
+
meshId,
|
|
47914
|
+
cliType,
|
|
47915
|
+
workspace,
|
|
47916
|
+
sessionId: launchSessionId,
|
|
47917
|
+
mcpConfigWritten: true
|
|
47918
|
+
};
|
|
47919
|
+
} catch (e) {
|
|
47920
|
+
LOG.error("MeshCoordinator", `Failed: ${e.message}`);
|
|
47921
|
+
return { success: false, error: e.message };
|
|
47922
|
+
}
|
|
47923
|
+
}
|
|
47924
|
+
};
|
|
47925
|
+
|
|
47926
|
+
// src/commands/high-family/mesh-status.ts
|
|
47927
|
+
var fs27 = __toESM(require("fs"));
|
|
47928
|
+
var import_os3 = require("os");
|
|
47413
47929
|
init_config();
|
|
47930
|
+
init_git_status();
|
|
47931
|
+
init_dist();
|
|
47932
|
+
init_mesh_events();
|
|
47933
|
+
init_mesh_routing();
|
|
47934
|
+
init_mesh_host_ownership();
|
|
47935
|
+
|
|
47936
|
+
// src/mesh/preview-freshness.ts
|
|
47937
|
+
var import_node_child_process4 = require("child_process");
|
|
47938
|
+
var import_node_fs4 = require("fs");
|
|
47939
|
+
var import_node_path2 = require("path");
|
|
47940
|
+
var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
|
|
47941
|
+
function runGit2(repoRoot, args) {
|
|
47942
|
+
try {
|
|
47943
|
+
return (0, import_node_child_process4.execFileSync)("git", args, {
|
|
47944
|
+
cwd: repoRoot,
|
|
47945
|
+
encoding: "utf8",
|
|
47946
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
47947
|
+
timeout: 5e3
|
|
47948
|
+
}).trim();
|
|
47949
|
+
} catch {
|
|
47950
|
+
return "";
|
|
47951
|
+
}
|
|
47952
|
+
}
|
|
47953
|
+
function readRecord5(repoRoot) {
|
|
47954
|
+
const path42 = (0, import_node_path2.resolve)(repoRoot, PREVIEW_DEPLOY_RECORD);
|
|
47955
|
+
if (!(0, import_node_fs4.existsSync)(path42)) return null;
|
|
47956
|
+
try {
|
|
47957
|
+
const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path42, "utf8"));
|
|
47958
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
47959
|
+
} catch {
|
|
47960
|
+
return null;
|
|
47961
|
+
}
|
|
47962
|
+
}
|
|
47963
|
+
function normalizeCommit(value) {
|
|
47964
|
+
return typeof value === "string" && /^[0-9a-f]{7,40}$/i.test(value.trim()) ? value.trim() : null;
|
|
47965
|
+
}
|
|
47966
|
+
function readTargetFreshness(record, currentCommit) {
|
|
47967
|
+
const targets = record?.targets && typeof record.targets === "object" && !Array.isArray(record.targets) ? record.targets : {};
|
|
47968
|
+
const result = {};
|
|
47969
|
+
for (const targetName of ["npm", "server", "web"]) {
|
|
47970
|
+
const targetRecord = targets[targetName] && typeof targets[targetName] === "object" && !Array.isArray(targets[targetName]) ? targets[targetName] : {};
|
|
47971
|
+
const commit = normalizeCommit(targetRecord.commit);
|
|
47972
|
+
result[targetName] = {
|
|
47973
|
+
commit,
|
|
47974
|
+
deployedAt: typeof targetRecord.deployedAt === "string" ? targetRecord.deployedAt : void 0,
|
|
47975
|
+
status: commit && currentCommit ? commit === currentCommit ? "fresh" : "stale" : "unknown"
|
|
47976
|
+
};
|
|
47977
|
+
}
|
|
47978
|
+
return result;
|
|
47979
|
+
}
|
|
47980
|
+
function readCurrentMainCommit(repoRoot) {
|
|
47981
|
+
const originMain = runGit2(repoRoot, ["rev-parse", "--verify", "origin/main^{commit}"]);
|
|
47982
|
+
if (originMain) {
|
|
47983
|
+
return { currentMainCommit: originMain, currentMainCommitSource: "origin/main" };
|
|
47984
|
+
}
|
|
47985
|
+
const head = runGit2(repoRoot, ["rev-parse", "--verify", "HEAD"]);
|
|
47986
|
+
if (head) {
|
|
47987
|
+
return { currentMainCommit: head, currentMainCommitSource: "HEAD" };
|
|
47988
|
+
}
|
|
47989
|
+
return { currentMainCommit: null, currentMainCommitSource: "unknown" };
|
|
47990
|
+
}
|
|
47991
|
+
function buildPreviewFreshness(repoRoot) {
|
|
47992
|
+
const current = readCurrentMainCommit(repoRoot);
|
|
47993
|
+
const record = readRecord5(repoRoot);
|
|
47994
|
+
const lastPreviewCommit = normalizeCommit(record?.lastPreviewCommit);
|
|
47995
|
+
const targets = readTargetFreshness(record, current.currentMainCommit);
|
|
47996
|
+
let status = "unknown";
|
|
47997
|
+
let nextAction = "Run npm run deploy:preview from the current main commit, then smoke preview.";
|
|
47998
|
+
if (lastPreviewCommit && current.currentMainCommit) {
|
|
47999
|
+
status = lastPreviewCommit === current.currentMainCommit ? "fresh" : "stale";
|
|
48000
|
+
nextAction = status === "fresh" ? "No preview deploy action needed." : "Run npm run deploy:preview from origin/main, then smoke preview.";
|
|
48001
|
+
} else if (!current.currentMainCommit) {
|
|
48002
|
+
nextAction = "Resolve the current main commit before judging preview freshness.";
|
|
48003
|
+
}
|
|
48004
|
+
return {
|
|
48005
|
+
status,
|
|
48006
|
+
lastPreviewCommit,
|
|
48007
|
+
currentMainCommit: current.currentMainCommit,
|
|
48008
|
+
currentMainCommitSource: current.currentMainCommitSource,
|
|
48009
|
+
recordPath: PREVIEW_DEPLOY_RECORD,
|
|
48010
|
+
lastDeployedAt: typeof record?.updatedAt === "string" ? record.updatedAt : void 0,
|
|
48011
|
+
lastTarget: typeof record?.target === "string" ? record.target : void 0,
|
|
48012
|
+
previewVersion: typeof record?.previewVersion === "string" ? record.previewVersion : void 0,
|
|
48013
|
+
targets,
|
|
48014
|
+
nextAction
|
|
48015
|
+
};
|
|
48016
|
+
}
|
|
48017
|
+
|
|
48018
|
+
// src/commands/high-family/mesh-status.ts
|
|
48019
|
+
init_mesh_refine_status();
|
|
48020
|
+
var meshStatusHandlers = {
|
|
48021
|
+
mesh_status: async (ctx, args) => {
|
|
48022
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48023
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
48024
|
+
try {
|
|
48025
|
+
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48026
|
+
const mesh = meshRecord?.mesh;
|
|
48027
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
48028
|
+
const meshHost = resolveMeshHostStatus(mesh);
|
|
48029
|
+
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
48030
|
+
const verboseMissions = args?.verbose === true || args?.compact === false;
|
|
48031
|
+
const peekScope = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
48032
|
+
const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
|
|
48033
|
+
const hadAggregateCache = ctx.aggregateMeshStatusCache.has(meshId);
|
|
48034
|
+
if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
|
|
48035
|
+
const cachedStatus = ctx.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
|
|
48036
|
+
if (cachedStatus) {
|
|
48037
|
+
logRepoMeshStatusDebug("return_cached", {
|
|
48038
|
+
meshId,
|
|
48039
|
+
command: "mesh_status",
|
|
48040
|
+
refreshRequested,
|
|
48041
|
+
summary: summarizeRepoMeshStatusDebug(cachedStatus)
|
|
48042
|
+
});
|
|
48043
|
+
return cachedStatus;
|
|
48044
|
+
}
|
|
48045
|
+
}
|
|
48046
|
+
const refreshReason = refreshRequested ? "explicit_refresh" : pendingCoordinatorEventCount > 0 ? "pending_coordinator_events" : hadAggregateCache ? "stale_pending_cache_refresh" : "cold_cache_miss";
|
|
48047
|
+
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
48048
|
+
const queue = getQueue2(meshId);
|
|
48049
|
+
const queueSummary = getMeshQueueStats2(meshId);
|
|
48050
|
+
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48051
|
+
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48052
|
+
const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
|
|
48053
|
+
const ledgerSummary = getLedgerSummary2(meshId);
|
|
48054
|
+
const sessionHostRecords = ctx.deps.sessionHostControl?.listSessions ? await ctx.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
48055
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
48056
|
+
const localMachineId = loadConfig().machineId || "";
|
|
48057
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
48058
|
+
const meshGitProbeCache = ctx.meshGitProbeCache;
|
|
48059
|
+
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
48060
|
+
mesh,
|
|
48061
|
+
meshSource: meshRecord.source,
|
|
48062
|
+
dispatchMeshCommand: ctx.deps.dispatchMeshCommand,
|
|
48063
|
+
getMeshPeerConnectionStatus: ctx.deps.getMeshPeerConnectionStatus,
|
|
48064
|
+
statusInstanceId: ctx.deps.statusInstanceId,
|
|
48065
|
+
localMachineId,
|
|
48066
|
+
// Standing-state model: only an explicit refresh fans
|
|
48067
|
+
// out a blocking peer git probe. Default loads return
|
|
48068
|
+
// held truth so one slow peer can't block the graph.
|
|
48069
|
+
probeRemotePeers: refreshRequested,
|
|
48070
|
+
probeCache: meshGitProbeCache
|
|
48071
|
+
}) : {
|
|
48072
|
+
directEvidenceCount: 0,
|
|
48073
|
+
localConfirmedCount: 0,
|
|
48074
|
+
peerAttemptedCount: 0,
|
|
48075
|
+
peerConfirmedCount: 0,
|
|
48076
|
+
standingEvidenceCount: 0,
|
|
48077
|
+
unavailableNodeIds: [],
|
|
48078
|
+
deadNodeIds: []
|
|
48079
|
+
};
|
|
48080
|
+
const passivePeerTruthNotAttempted = requireDirectPeerTruth && !refreshRequested && directTruth.directEvidenceCount > 0 && directTruth.peerAttemptedCount === 0;
|
|
48081
|
+
const effectiveDirectTruth = passivePeerTruthNotAttempted ? { ...directTruth, unavailableNodeIds: [] } : directTruth;
|
|
48082
|
+
const unavailableDirectTruthNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
48083
|
+
const unavailableNodesAreOnlyRemovedWorktrees = unavailableDirectTruthNodeIds.size > 0 && Array.isArray(mesh.nodes) && mesh.nodes.filter((node) => unavailableDirectTruthNodeIds.has(normalizeMeshNodeId(node) ?? "")).every((node) => node?.isLocalWorktree === true);
|
|
48084
|
+
const directTruthSatisfied = !requireDirectPeerTruth || !refreshRequested || effectiveDirectTruth.directEvidenceCount > 0 && (effectiveDirectTruth.unavailableNodeIds.length === 0 || unavailableNodesAreOnlyRemovedWorktrees);
|
|
48085
|
+
if (requireDirectPeerTruth && refreshRequested && !directTruthSatisfied) {
|
|
48086
|
+
const failureResult = {
|
|
48087
|
+
success: false,
|
|
48088
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
48089
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
|
|
48090
|
+
sourceOfTruth: {
|
|
48091
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
48092
|
+
coordinatorOwnsLiveTruth: false,
|
|
48093
|
+
currentStatus: "direct_peer_truth_unavailable",
|
|
48094
|
+
directPeerTruth: {
|
|
48095
|
+
required: true,
|
|
48096
|
+
satisfied: false,
|
|
48097
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
48098
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
48099
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
48100
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
48101
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
48102
|
+
}
|
|
48103
|
+
}
|
|
48104
|
+
};
|
|
48105
|
+
logRepoMeshStatusDebug("direct_truth_unavailable", {
|
|
48106
|
+
meshId,
|
|
48107
|
+
command: "mesh_status",
|
|
48108
|
+
refreshRequested,
|
|
48109
|
+
meshSource: meshRecord.source,
|
|
48110
|
+
directTruth
|
|
48111
|
+
});
|
|
48112
|
+
return failureResult;
|
|
48113
|
+
}
|
|
48114
|
+
const directTruthUnavailableNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
48115
|
+
const coordinatorHostname = (0, import_os3.hostname)();
|
|
48116
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
48117
|
+
mesh.coordinator?.preferredNodeId,
|
|
48118
|
+
normalizeMeshNodeId(mesh.nodes?.[0])
|
|
48119
|
+
);
|
|
48120
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
48121
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
48122
|
+
const nodeStatuses = [];
|
|
48123
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
48124
|
+
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
48125
|
+
const daemonId = readStringValue(node.daemonId);
|
|
48126
|
+
const nodeMachineId = readMeshNodeMachineId(node);
|
|
48127
|
+
const nodeHostname = readMeshNodeHostname(node);
|
|
48128
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
48129
|
+
const configuredCoordinatorNode = Boolean(
|
|
48130
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
48131
|
+
);
|
|
48132
|
+
const sparseConfiguredCoordinatorNode = configuredCoordinatorNode && !daemonId && !nodeMachineId && !nodeHostname;
|
|
48133
|
+
const isSelfNode = Boolean(
|
|
48134
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
48135
|
+
) || Boolean(
|
|
48136
|
+
daemonId && (daemonIdsEquivalent(daemonId, localMachineId) || daemonIdsEquivalent(daemonId, ctx.deps.statusInstanceId))
|
|
48137
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0) || sparseConfiguredCoordinatorNode;
|
|
48138
|
+
const machineIdentity = buildMeshNodeMachineIdentity(node, {
|
|
48139
|
+
localMachineId,
|
|
48140
|
+
localDaemonId: ctx.deps.statusInstanceId,
|
|
48141
|
+
coordinatorHostname,
|
|
48142
|
+
isSelfNode
|
|
48143
|
+
});
|
|
48144
|
+
const status = {
|
|
48145
|
+
nodeId,
|
|
48146
|
+
machineLabel: buildMeshNodeDisplayLabel(node, nodeId, providerPriority),
|
|
48147
|
+
labelSource: readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias) ? "explicit_metadata" : "workspace_host_provider_context",
|
|
48148
|
+
workspace: node.workspace,
|
|
48149
|
+
repoRoot: node.repoRoot,
|
|
48150
|
+
isLocalWorktree: node.isLocalWorktree,
|
|
48151
|
+
worktreeBranch: node.worktreeBranch,
|
|
48152
|
+
role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? "host" : void 0),
|
|
48153
|
+
daemonId,
|
|
48154
|
+
machineId: nodeMachineId || node.machineId,
|
|
48155
|
+
machine: machineIdentity,
|
|
48156
|
+
machineStatus: node.machineStatus,
|
|
48157
|
+
health: "unknown",
|
|
48158
|
+
providers: node.providers || [],
|
|
48159
|
+
providerPriority,
|
|
48160
|
+
activeSessions: [],
|
|
48161
|
+
activeSessionDetails: [],
|
|
48162
|
+
launchReady: false
|
|
48163
|
+
};
|
|
48164
|
+
if (isSelfNode) {
|
|
48165
|
+
status.connection = {
|
|
48166
|
+
perspective: "selected_coordinator",
|
|
48167
|
+
source: "mesh_peer_status",
|
|
48168
|
+
state: "self",
|
|
48169
|
+
transport: "local",
|
|
48170
|
+
reported: true,
|
|
48171
|
+
reason: "Selected coordinator daemon",
|
|
48172
|
+
lastStateChangeAt: refreshedAt
|
|
48173
|
+
};
|
|
48174
|
+
} else if (daemonId) {
|
|
48175
|
+
const connection = ctx.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
48176
|
+
status.connection = connection ?? {
|
|
48177
|
+
perspective: "selected_coordinator",
|
|
48178
|
+
source: "not_reported",
|
|
48179
|
+
state: "unknown",
|
|
48180
|
+
transport: "unknown",
|
|
48181
|
+
reported: false,
|
|
48182
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
48183
|
+
};
|
|
48184
|
+
} else {
|
|
48185
|
+
status.connection = {
|
|
48186
|
+
perspective: "selected_coordinator",
|
|
48187
|
+
source: "not_reported",
|
|
48188
|
+
state: "unknown",
|
|
48189
|
+
transport: "unknown",
|
|
48190
|
+
reported: false,
|
|
48191
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
48192
|
+
};
|
|
48193
|
+
}
|
|
48194
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
48195
|
+
meshId,
|
|
48196
|
+
node,
|
|
48197
|
+
nodeId,
|
|
48198
|
+
liveSessionRecords: liveMeshSessions,
|
|
48199
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
48200
|
+
});
|
|
48201
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
48202
|
+
meshId,
|
|
48203
|
+
nodeId,
|
|
48204
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
48205
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
48206
|
+
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
48207
|
+
status.workspace = workspace || node.workspace;
|
|
48208
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
48209
|
+
const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
|
|
48210
|
+
const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
|
|
48211
|
+
status.activeSessions = sessionIds;
|
|
48212
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
48213
|
+
if (providerTypes.length > 0) {
|
|
48214
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
48215
|
+
}
|
|
48216
|
+
}
|
|
48217
|
+
if (workspace) {
|
|
48218
|
+
if (!fs27.existsSync(workspace)) {
|
|
48219
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
48220
|
+
let remoteProbeApplied = false;
|
|
48221
|
+
if (inlineTransitGit) {
|
|
48222
|
+
status.git = inlineTransitGit;
|
|
48223
|
+
status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
|
|
48224
|
+
const connection = readObjectRecord(status.connection);
|
|
48225
|
+
const connectionState = readStringValue(connection.state);
|
|
48226
|
+
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
48227
|
+
if (!connectionReported || connectionState === "unknown") {
|
|
48228
|
+
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
48229
|
+
}
|
|
48230
|
+
remoteProbeApplied = true;
|
|
48231
|
+
} else if (refreshRequested && !isSelfNode && daemonId && ctx.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
48232
|
+
const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
48233
|
+
dispatchMeshCommand: ctx.deps.dispatchMeshCommand,
|
|
48234
|
+
daemonId,
|
|
48235
|
+
workspace,
|
|
48236
|
+
timeoutMs: MESH_DIRECT_PROBE_TIMEOUT_MS,
|
|
48237
|
+
retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
48238
|
+
getConnection: ctx.deps.getMeshPeerConnectionStatus,
|
|
48239
|
+
onConnection: (connection) => {
|
|
48240
|
+
status.connection = connection;
|
|
48241
|
+
}
|
|
48242
|
+
});
|
|
48243
|
+
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
48244
|
+
if (remoteGit) {
|
|
48245
|
+
status.git = remoteGit;
|
|
48246
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
48247
|
+
const connection = readObjectRecord(status.connection);
|
|
48248
|
+
const connectionState = readStringValue(connection.state);
|
|
48249
|
+
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
48250
|
+
if (!connectionReported || connectionState === "unknown") {
|
|
48251
|
+
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
48252
|
+
}
|
|
48253
|
+
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
48254
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
48255
|
+
remoteProbeApplied = true;
|
|
48256
|
+
}
|
|
48257
|
+
}
|
|
48258
|
+
if (!remoteProbeApplied) {
|
|
48259
|
+
const connectionState = readStringValue(status.connection?.state);
|
|
48260
|
+
const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
|
|
48261
|
+
if (pendingPeerGitProbe) {
|
|
48262
|
+
status.gitProbePending = true;
|
|
48263
|
+
status.health = "unknown";
|
|
48264
|
+
}
|
|
48265
|
+
if (applyCachedInlineMeshNodeStatus(
|
|
48266
|
+
status,
|
|
48267
|
+
node,
|
|
48268
|
+
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
48269
|
+
)) {
|
|
48270
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48271
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48272
|
+
nodeStatuses.push(status);
|
|
48273
|
+
continue;
|
|
48274
|
+
}
|
|
48275
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
48276
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48277
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48278
|
+
nodeStatuses.push(status);
|
|
48279
|
+
continue;
|
|
48280
|
+
}
|
|
48281
|
+
}
|
|
48282
|
+
} else {
|
|
48283
|
+
try {
|
|
48284
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
48285
|
+
status.git = gitStatus;
|
|
48286
|
+
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
48287
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
48288
|
+
if (gitStatus.isGitRepo) {
|
|
48289
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
48290
|
+
} else {
|
|
48291
|
+
status.health = "degraded";
|
|
48292
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
48293
|
+
}
|
|
48294
|
+
} catch {
|
|
48295
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
48296
|
+
status.health = "degraded";
|
|
48297
|
+
}
|
|
48298
|
+
}
|
|
48299
|
+
}
|
|
48300
|
+
} else {
|
|
48301
|
+
applyCachedInlineMeshNodeStatus(status, node);
|
|
48302
|
+
}
|
|
48303
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
48304
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48305
|
+
nodeStatuses.push(status);
|
|
48306
|
+
}
|
|
48307
|
+
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
|
|
48308
|
+
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
48309
|
+
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
48310
|
+
const previewFreshness = (() => {
|
|
48311
|
+
const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs27.existsSync(candidate));
|
|
48312
|
+
return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
|
|
48313
|
+
})();
|
|
48314
|
+
const asyncRefineJobs = buildMeshAsyncRefineJobs({
|
|
48315
|
+
meshId,
|
|
48316
|
+
ledgerEntries: asyncRefineLedgerEntries,
|
|
48317
|
+
pendingEvents: [...pendingCoordinatorEvents]
|
|
48318
|
+
});
|
|
48319
|
+
const historicalSessions = buildHistoricalMeshSessions({
|
|
48320
|
+
meshId,
|
|
48321
|
+
nodes: mesh.nodes || [],
|
|
48322
|
+
liveSessionRecords: liveMeshSessions
|
|
48323
|
+
});
|
|
48324
|
+
const { getMeshStatusMissionSummaries: getMeshStatusMissionSummaries2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
|
|
48325
|
+
const missions = getMeshStatusMissionSummaries2(meshId, { verbose: verboseMissions, withStats: true });
|
|
48326
|
+
const statusResult = {
|
|
48327
|
+
success: true,
|
|
48328
|
+
meshId: mesh.id,
|
|
48329
|
+
meshName: mesh.name,
|
|
48330
|
+
repoIdentity: mesh.repoIdentity,
|
|
48331
|
+
defaultBranch: mesh.defaultBranch,
|
|
48332
|
+
refreshedAt,
|
|
48333
|
+
meshHost,
|
|
48334
|
+
sourceOfTruth: {
|
|
48335
|
+
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
48336
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
48337
|
+
meshHost: {
|
|
48338
|
+
owner: "mesh_host_daemon",
|
|
48339
|
+
localRole: meshHost.role,
|
|
48340
|
+
hostDaemonId: meshHost.hostDaemonId,
|
|
48341
|
+
hostNodeId: meshHost.hostNodeId,
|
|
48342
|
+
hostAddress: meshHost.hostAddress
|
|
48343
|
+
},
|
|
48344
|
+
...requireDirectPeerTruth ? {
|
|
48345
|
+
currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
|
|
48346
|
+
directPeerTruth: {
|
|
48347
|
+
required: true,
|
|
48348
|
+
satisfied: directTruthSatisfied,
|
|
48349
|
+
directEvidenceCount: effectiveDirectTruth.directEvidenceCount,
|
|
48350
|
+
localConfirmedCount: effectiveDirectTruth.localConfirmedCount,
|
|
48351
|
+
peerAttemptedCount: effectiveDirectTruth.peerAttemptedCount,
|
|
48352
|
+
peerConfirmedCount: effectiveDirectTruth.peerConfirmedCount,
|
|
48353
|
+
unavailableNodeIds: effectiveDirectTruth.unavailableNodeIds,
|
|
48354
|
+
partialNodeFailures: effectiveDirectTruth.unavailableNodeIds
|
|
48355
|
+
}
|
|
48356
|
+
} : {},
|
|
48357
|
+
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary", "historicalSessions"]
|
|
48358
|
+
},
|
|
48359
|
+
branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
|
|
48360
|
+
...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
|
|
48361
|
+
nodes: nodeStatuses,
|
|
48362
|
+
queue: { tasks: queue, summary: queueSummary },
|
|
48363
|
+
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
|
48364
|
+
...missions.length > 0 ? { missions } : {},
|
|
48365
|
+
...asyncRefineJobs.length > 0 ? { asyncRefineJobs } : {},
|
|
48366
|
+
...historicalSessions ? { historicalSessions } : {},
|
|
48367
|
+
...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
|
|
48368
|
+
...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
|
|
48369
|
+
activeRefineJobs: Array.from(ctx.runningRefineJobs.values()).filter((job) => job.meshId === meshId).map((job) => ({
|
|
48370
|
+
jobId: job.jobId,
|
|
48371
|
+
nodeId: job.targetNodeId,
|
|
48372
|
+
workspace: job.workspace,
|
|
48373
|
+
startedAt: job.startedAt,
|
|
48374
|
+
status: job.status,
|
|
48375
|
+
targetCoordinatorDaemonId: job.targetCoordinatorDaemonId
|
|
48376
|
+
}))
|
|
48377
|
+
};
|
|
48378
|
+
const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
|
|
48379
|
+
const rememberedStatus = verboseMissions ? cacheableStatusResult : ctx.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
|
|
48380
|
+
const returnedStatus = {
|
|
48381
|
+
...rememberedStatus,
|
|
48382
|
+
...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
|
|
48383
|
+
...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}
|
|
48384
|
+
};
|
|
48385
|
+
logRepoMeshStatusDebug("return_live", {
|
|
48386
|
+
meshId,
|
|
48387
|
+
command: "mesh_status",
|
|
48388
|
+
refreshRequested,
|
|
48389
|
+
refreshReason,
|
|
48390
|
+
meshSource: meshRecord.source,
|
|
48391
|
+
directTruth,
|
|
48392
|
+
summary: summarizeRepoMeshStatusDebug(returnedStatus)
|
|
48393
|
+
});
|
|
48394
|
+
return returnedStatus;
|
|
48395
|
+
} catch (e) {
|
|
48396
|
+
return { success: false, error: e.message };
|
|
48397
|
+
}
|
|
48398
|
+
},
|
|
48399
|
+
get_mesh_review_inbox: async (ctx, args) => {
|
|
48400
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48401
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
48402
|
+
try {
|
|
48403
|
+
const { deriveMeshReviewInboxItems: deriveMeshReviewInboxItems2 } = await Promise.resolve().then(() => (init_mesh_review_inbox(), mesh_review_inbox_exports));
|
|
48404
|
+
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48405
|
+
const { getGitDiffSummary: getGitDiffSummary2 } = await Promise.resolve().then(() => (init_git_diff(), git_diff_exports));
|
|
48406
|
+
const { existsSync: existsSync49 } = await import("fs");
|
|
48407
|
+
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48408
|
+
const mesh = meshRecord?.mesh;
|
|
48409
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
48410
|
+
const inlineNodes = args?.inlineMesh && Array.isArray(args.inlineMesh?.nodes) ? args.inlineMesh.nodes : null;
|
|
48411
|
+
let cachedStatus = !inlineNodes ? ctx.getCachedAggregateMeshStatus(meshId, mesh, {}) : null;
|
|
48412
|
+
if (!cachedStatus && !inlineNodes) {
|
|
48413
|
+
const freshStatus = await ctx.execute("mesh_status", {
|
|
48414
|
+
meshId,
|
|
48415
|
+
inlineMesh: args?.inlineMesh,
|
|
48416
|
+
refresh: true
|
|
48417
|
+
}, "get_mesh_review_inbox");
|
|
48418
|
+
cachedStatus = freshStatus?.success !== false ? freshStatus : null;
|
|
48419
|
+
}
|
|
48420
|
+
const nodeStatuses = inlineNodes ? inlineNodes : Array.isArray(cachedStatus?.nodes) ? cachedStatus.nodes : Array.isArray(mesh.nodes) ? mesh.nodes : [];
|
|
48421
|
+
const ledgerEntries = readLedgerEntries2(meshId, { tail: 300 });
|
|
48422
|
+
const derivation = deriveMeshReviewInboxItems2({ nodes: nodeStatuses, ledgerEntries });
|
|
48423
|
+
for (const item of derivation.items) {
|
|
48424
|
+
const workspace = item.workspace;
|
|
48425
|
+
if (!workspace || !existsSync49(workspace)) continue;
|
|
48426
|
+
const baseRef = item.defaultBranch ? `origin/${item.defaultBranch}` : "origin/main";
|
|
48427
|
+
try {
|
|
48428
|
+
const diffResult = await getGitDiffSummary2(workspace, { baseRef, maxFiles: 100 });
|
|
48429
|
+
if (diffResult.isGitRepo) {
|
|
48430
|
+
item.diffSummary = {
|
|
48431
|
+
baseRef,
|
|
48432
|
+
files: diffResult.files.map((f) => ({
|
|
48433
|
+
path: f.path,
|
|
48434
|
+
status: f.status,
|
|
48435
|
+
insertions: f.insertions,
|
|
48436
|
+
deletions: f.deletions,
|
|
48437
|
+
binary: f.binary,
|
|
48438
|
+
oldPath: f.oldPath
|
|
48439
|
+
})),
|
|
48440
|
+
totalFiles: diffResult.files.length,
|
|
48441
|
+
totalInsertions: diffResult.totalInsertions,
|
|
48442
|
+
totalDeletions: diffResult.totalDeletions,
|
|
48443
|
+
truncated: diffResult.truncated,
|
|
48444
|
+
...diffResult.error ? { error: diffResult.error } : {}
|
|
48445
|
+
};
|
|
48446
|
+
}
|
|
48447
|
+
} catch {
|
|
48448
|
+
item.diffSummary = null;
|
|
48449
|
+
}
|
|
48450
|
+
}
|
|
48451
|
+
return {
|
|
48452
|
+
success: true,
|
|
48453
|
+
meshId,
|
|
48454
|
+
inbox: derivation.items,
|
|
48455
|
+
remoteNodesExcluded: derivation.remoteNodesExcluded,
|
|
48456
|
+
excludedRemoteNodeIds: derivation.excludedRemoteNodeIds
|
|
48457
|
+
};
|
|
48458
|
+
} catch (e) {
|
|
48459
|
+
return { success: false, error: e.message };
|
|
48460
|
+
}
|
|
48461
|
+
}
|
|
48462
|
+
};
|
|
48463
|
+
|
|
48464
|
+
// src/commands/high-family/index.ts
|
|
48465
|
+
var highFamilyRegistry = new Map(
|
|
48466
|
+
Object.entries({
|
|
48467
|
+
...meshEventsHandlers,
|
|
48468
|
+
...meshCoordinatorLaunchHandlers,
|
|
48469
|
+
...meshStatusHandlers
|
|
48470
|
+
})
|
|
48471
|
+
);
|
|
48472
|
+
|
|
48473
|
+
// src/commands/router.ts
|
|
47414
48474
|
init_cli_detector();
|
|
47415
48475
|
init_git_status();
|
|
47416
48476
|
init_dist();
|
|
47417
48477
|
init_logger();
|
|
47418
48478
|
|
|
47419
48479
|
// src/logging/command-log.ts
|
|
47420
|
-
var
|
|
48480
|
+
var fs28 = __toESM(require("fs"));
|
|
47421
48481
|
var path36 = __toESM(require("path"));
|
|
47422
48482
|
var os27 = __toESM(require("os"));
|
|
47423
48483
|
var ADHDEV_HOME2 = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path36.join(os27.homedir(), ".adhdev");
|
|
@@ -47425,7 +48485,7 @@ var LOG_DIR2 = path36.join(ADHDEV_HOME2, "logs");
|
|
|
47425
48485
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
47426
48486
|
var MAX_DAYS = 7;
|
|
47427
48487
|
try {
|
|
47428
|
-
|
|
48488
|
+
fs28.mkdirSync(LOG_DIR2, { recursive: true });
|
|
47429
48489
|
} catch {
|
|
47430
48490
|
}
|
|
47431
48491
|
var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -47471,7 +48531,7 @@ function checkRotation() {
|
|
|
47471
48531
|
}
|
|
47472
48532
|
function cleanOldFiles() {
|
|
47473
48533
|
try {
|
|
47474
|
-
const files =
|
|
48534
|
+
const files = fs28.readdirSync(LOG_DIR2).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
|
|
47475
48535
|
const cutoff = /* @__PURE__ */ new Date();
|
|
47476
48536
|
cutoff.setDate(cutoff.getDate() - MAX_DAYS);
|
|
47477
48537
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -47479,7 +48539,7 @@ function cleanOldFiles() {
|
|
|
47479
48539
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
47480
48540
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
47481
48541
|
try {
|
|
47482
|
-
|
|
48542
|
+
fs28.unlinkSync(path36.join(LOG_DIR2, file));
|
|
47483
48543
|
} catch {
|
|
47484
48544
|
}
|
|
47485
48545
|
}
|
|
@@ -47489,14 +48549,14 @@ function cleanOldFiles() {
|
|
|
47489
48549
|
}
|
|
47490
48550
|
function checkSize() {
|
|
47491
48551
|
try {
|
|
47492
|
-
const stat2 =
|
|
48552
|
+
const stat2 = fs28.statSync(currentFile);
|
|
47493
48553
|
if (stat2.size > MAX_FILE_SIZE) {
|
|
47494
48554
|
const backup = currentFile.replace(".jsonl", ".1.jsonl");
|
|
47495
48555
|
try {
|
|
47496
|
-
|
|
48556
|
+
fs28.unlinkSync(backup);
|
|
47497
48557
|
} catch {
|
|
47498
48558
|
}
|
|
47499
|
-
|
|
48559
|
+
fs28.renameSync(currentFile, backup);
|
|
47500
48560
|
}
|
|
47501
48561
|
} catch {
|
|
47502
48562
|
}
|
|
@@ -47529,14 +48589,14 @@ function logCommand(entry) {
|
|
|
47529
48589
|
...entry.error ? { err: entry.error } : {},
|
|
47530
48590
|
...entry.durationMs !== void 0 ? { ms: entry.durationMs } : {}
|
|
47531
48591
|
});
|
|
47532
|
-
|
|
48592
|
+
fs28.appendFileSync(currentFile, line + "\n");
|
|
47533
48593
|
} catch {
|
|
47534
48594
|
}
|
|
47535
48595
|
}
|
|
47536
48596
|
function getRecentCommands(count = 50) {
|
|
47537
48597
|
try {
|
|
47538
|
-
if (!
|
|
47539
|
-
const content =
|
|
48598
|
+
if (!fs28.existsSync(currentFile)) return [];
|
|
48599
|
+
const content = fs28.readFileSync(currentFile, "utf-8");
|
|
47540
48600
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
47541
48601
|
return lines.slice(-count).map((line) => {
|
|
47542
48602
|
try {
|
|
@@ -47563,16 +48623,13 @@ cleanOldFiles();
|
|
|
47563
48623
|
|
|
47564
48624
|
// src/commands/router.ts
|
|
47565
48625
|
var yaml4 = __toESM(require("js-yaml"));
|
|
47566
|
-
init_mesh_coordinator();
|
|
47567
|
-
init_coordinator_registry();
|
|
47568
48626
|
init_mesh_events();
|
|
47569
|
-
init_mesh_routing();
|
|
47570
48627
|
init_mesh_host_ownership();
|
|
47571
48628
|
|
|
47572
48629
|
// src/mesh/mesh-refine-batch.ts
|
|
47573
|
-
var
|
|
48630
|
+
var import_node_child_process5 = require("child_process");
|
|
47574
48631
|
var import_node_util4 = require("util");
|
|
47575
|
-
var execFileAsync3 = (0, import_node_util4.promisify)(
|
|
48632
|
+
var execFileAsync3 = (0, import_node_util4.promisify)(import_node_child_process5.execFile);
|
|
47576
48633
|
var MAX_CHANGED_FILES2 = 500;
|
|
47577
48634
|
function topLevel(path42) {
|
|
47578
48635
|
const slash = path42.indexOf("/");
|
|
@@ -47656,95 +48713,12 @@ function orderMeshRefineBatchNodes(changeAreas) {
|
|
|
47656
48713
|
return { order: ranked.map((a) => a.nodeId), changeAreas: areaById, rationale };
|
|
47657
48714
|
}
|
|
47658
48715
|
|
|
47659
|
-
// src/mesh/preview-freshness.ts
|
|
47660
|
-
var import_node_child_process5 = require("child_process");
|
|
47661
|
-
var import_node_fs4 = require("fs");
|
|
47662
|
-
var import_node_path2 = require("path");
|
|
47663
|
-
var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
|
|
47664
|
-
function runGit2(repoRoot, args) {
|
|
47665
|
-
try {
|
|
47666
|
-
return (0, import_node_child_process5.execFileSync)("git", args, {
|
|
47667
|
-
cwd: repoRoot,
|
|
47668
|
-
encoding: "utf8",
|
|
47669
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
47670
|
-
timeout: 5e3
|
|
47671
|
-
}).trim();
|
|
47672
|
-
} catch {
|
|
47673
|
-
return "";
|
|
47674
|
-
}
|
|
47675
|
-
}
|
|
47676
|
-
function readRecord5(repoRoot) {
|
|
47677
|
-
const path42 = (0, import_node_path2.resolve)(repoRoot, PREVIEW_DEPLOY_RECORD);
|
|
47678
|
-
if (!(0, import_node_fs4.existsSync)(path42)) return null;
|
|
47679
|
-
try {
|
|
47680
|
-
const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path42, "utf8"));
|
|
47681
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
47682
|
-
} catch {
|
|
47683
|
-
return null;
|
|
47684
|
-
}
|
|
47685
|
-
}
|
|
47686
|
-
function normalizeCommit(value) {
|
|
47687
|
-
return typeof value === "string" && /^[0-9a-f]{7,40}$/i.test(value.trim()) ? value.trim() : null;
|
|
47688
|
-
}
|
|
47689
|
-
function readTargetFreshness(record, currentCommit) {
|
|
47690
|
-
const targets = record?.targets && typeof record.targets === "object" && !Array.isArray(record.targets) ? record.targets : {};
|
|
47691
|
-
const result = {};
|
|
47692
|
-
for (const targetName of ["npm", "server", "web"]) {
|
|
47693
|
-
const targetRecord = targets[targetName] && typeof targets[targetName] === "object" && !Array.isArray(targets[targetName]) ? targets[targetName] : {};
|
|
47694
|
-
const commit = normalizeCommit(targetRecord.commit);
|
|
47695
|
-
result[targetName] = {
|
|
47696
|
-
commit,
|
|
47697
|
-
deployedAt: typeof targetRecord.deployedAt === "string" ? targetRecord.deployedAt : void 0,
|
|
47698
|
-
status: commit && currentCommit ? commit === currentCommit ? "fresh" : "stale" : "unknown"
|
|
47699
|
-
};
|
|
47700
|
-
}
|
|
47701
|
-
return result;
|
|
47702
|
-
}
|
|
47703
|
-
function readCurrentMainCommit(repoRoot) {
|
|
47704
|
-
const originMain = runGit2(repoRoot, ["rev-parse", "--verify", "origin/main^{commit}"]);
|
|
47705
|
-
if (originMain) {
|
|
47706
|
-
return { currentMainCommit: originMain, currentMainCommitSource: "origin/main" };
|
|
47707
|
-
}
|
|
47708
|
-
const head = runGit2(repoRoot, ["rev-parse", "--verify", "HEAD"]);
|
|
47709
|
-
if (head) {
|
|
47710
|
-
return { currentMainCommit: head, currentMainCommitSource: "HEAD" };
|
|
47711
|
-
}
|
|
47712
|
-
return { currentMainCommit: null, currentMainCommitSource: "unknown" };
|
|
47713
|
-
}
|
|
47714
|
-
function buildPreviewFreshness(repoRoot) {
|
|
47715
|
-
const current = readCurrentMainCommit(repoRoot);
|
|
47716
|
-
const record = readRecord5(repoRoot);
|
|
47717
|
-
const lastPreviewCommit = normalizeCommit(record?.lastPreviewCommit);
|
|
47718
|
-
const targets = readTargetFreshness(record, current.currentMainCommit);
|
|
47719
|
-
let status = "unknown";
|
|
47720
|
-
let nextAction = "Run npm run deploy:preview from the current main commit, then smoke preview.";
|
|
47721
|
-
if (lastPreviewCommit && current.currentMainCommit) {
|
|
47722
|
-
status = lastPreviewCommit === current.currentMainCommit ? "fresh" : "stale";
|
|
47723
|
-
nextAction = status === "fresh" ? "No preview deploy action needed." : "Run npm run deploy:preview from origin/main, then smoke preview.";
|
|
47724
|
-
} else if (!current.currentMainCommit) {
|
|
47725
|
-
nextAction = "Resolve the current main commit before judging preview freshness.";
|
|
47726
|
-
}
|
|
47727
|
-
return {
|
|
47728
|
-
status,
|
|
47729
|
-
lastPreviewCommit,
|
|
47730
|
-
currentMainCommit: current.currentMainCommit,
|
|
47731
|
-
currentMainCommitSource: current.currentMainCommitSource,
|
|
47732
|
-
recordPath: PREVIEW_DEPLOY_RECORD,
|
|
47733
|
-
lastDeployedAt: typeof record?.updatedAt === "string" ? record.updatedAt : void 0,
|
|
47734
|
-
lastTarget: typeof record?.target === "string" ? record.target : void 0,
|
|
47735
|
-
previewVersion: typeof record?.previewVersion === "string" ? record.previewVersion : void 0,
|
|
47736
|
-
targets,
|
|
47737
|
-
nextAction
|
|
47738
|
-
};
|
|
47739
|
-
}
|
|
47740
|
-
|
|
47741
48716
|
// src/commands/router.ts
|
|
47742
|
-
init_mesh_refine_status();
|
|
47743
48717
|
init_mesh_work_queue();
|
|
47744
48718
|
init_repo_mesh_types();
|
|
47745
|
-
var
|
|
47746
|
-
var
|
|
47747
|
-
var
|
|
48719
|
+
var import_os4 = require("os");
|
|
48720
|
+
var import_path13 = require("path");
|
|
48721
|
+
var fs29 = __toESM(require("fs"));
|
|
47748
48722
|
var import_node_child_process6 = require("child_process");
|
|
47749
48723
|
init_resolve_executable();
|
|
47750
48724
|
function readProviderPriorityFromPolicy(policy) {
|
|
@@ -48092,7 +49066,7 @@ function isDeadLocalWorktreeNode(node) {
|
|
|
48092
49066
|
if (node?.isLocalWorktree !== true) return false;
|
|
48093
49067
|
const workspace = readStringValue(node?.workspace);
|
|
48094
49068
|
if (!workspace) return false;
|
|
48095
|
-
return !
|
|
49069
|
+
return !fs29.existsSync(workspace);
|
|
48096
49070
|
}
|
|
48097
49071
|
function foldMeshNodeIdentityToCanonical(node) {
|
|
48098
49072
|
if (!node || typeof node !== "object" || Array.isArray(node)) return node;
|
|
@@ -48340,7 +49314,7 @@ function summarizeInlineMeshBranchConvergence(nodes) {
|
|
|
48340
49314
|
const followUps = nodes.filter((node) => {
|
|
48341
49315
|
if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
|
|
48342
49316
|
const workspace = typeof node.workspace === "string" ? node.workspace : "";
|
|
48343
|
-
if (workspace && !
|
|
49317
|
+
if (workspace && !fs29.existsSync(workspace)) return false;
|
|
48344
49318
|
return true;
|
|
48345
49319
|
}).map((node) => {
|
|
48346
49320
|
const convergence = readObjectRecord(node.branchConvergence);
|
|
@@ -48648,7 +49622,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
48648
49622
|
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
48649
49623
|
continue;
|
|
48650
49624
|
}
|
|
48651
|
-
if (
|
|
49625
|
+
if (fs29.existsSync(workspace)) {
|
|
48652
49626
|
try {
|
|
48653
49627
|
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
48654
49628
|
if (localGit?.isGitRepo) {
|
|
@@ -48756,7 +49730,7 @@ function readLiveMeshNodeWorkspace(args) {
|
|
|
48756
49730
|
}
|
|
48757
49731
|
function collectLiveMeshSessionRecords(args) {
|
|
48758
49732
|
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
48759
|
-
const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !
|
|
49733
|
+
const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !fs29.existsSync(nodeWorkspace);
|
|
48760
49734
|
const matches = args.liveSessionRecords.filter((record) => {
|
|
48761
49735
|
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
48762
49736
|
if (recordNodeId && recordNodeId !== args.nodeId) return false;
|
|
@@ -48783,7 +49757,7 @@ function buildHistoricalMeshSessions(args) {
|
|
|
48783
49757
|
const workspace = readStringValue(node?.workspace);
|
|
48784
49758
|
if (nodeId) liveNodeIds.add(nodeId);
|
|
48785
49759
|
if (workspace) liveWorkspaces.add(workspace);
|
|
48786
|
-
if (nodeId && node?.isLocalWorktree === true && workspace && !
|
|
49760
|
+
if (nodeId && node?.isLocalWorktree === true && workspace && !fs29.existsSync(workspace)) {
|
|
48787
49761
|
missingLocalWorktreeNodeIds.add(nodeId);
|
|
48788
49762
|
}
|
|
48789
49763
|
}
|
|
@@ -49219,7 +50193,7 @@ function isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit) {
|
|
|
49219
50193
|
if (!baseCommit || !branchCommit) return false;
|
|
49220
50194
|
if (baseCommit === branchCommit) return true;
|
|
49221
50195
|
try {
|
|
49222
|
-
if (!
|
|
50196
|
+
if (!fs29.existsSync(submoduleRepoPath)) return false;
|
|
49223
50197
|
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
49224
50198
|
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
49225
50199
|
(0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
@@ -49258,14 +50232,14 @@ function collectFastForwardGitlinkPaths(repoRoot, baseHead, branchHead) {
|
|
|
49258
50232
|
const baseCommit = readTreeObject(repoRoot, baseHead, path42);
|
|
49259
50233
|
const branchCommit = readTreeObject(repoRoot, branchHead, path42);
|
|
49260
50234
|
if (!baseCommit || !branchCommit) return false;
|
|
49261
|
-
return isSubmoduleFastForward((0,
|
|
50235
|
+
return isSubmoduleFastForward((0, import_path13.resolve)(repoRoot, path42), baseCommit, branchCommit);
|
|
49262
50236
|
});
|
|
49263
50237
|
}
|
|
49264
50238
|
function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
49265
50239
|
const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path42) => {
|
|
49266
50240
|
const baseCommit = readTreeObject(repoRoot, baseHead, path42);
|
|
49267
50241
|
const branchCommit = readTreeObject(repoRoot, branchHead, path42);
|
|
49268
|
-
const submoduleRepoPath = (0,
|
|
50242
|
+
const submoduleRepoPath = (0, import_path13.resolve)(repoRoot, path42);
|
|
49269
50243
|
const fastForward = !!baseCommit && !!branchCommit && isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit);
|
|
49270
50244
|
return { path: path42, baseCommit, branchCommit, fastForward };
|
|
49271
50245
|
});
|
|
@@ -49320,7 +50294,7 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
49320
50294
|
if (!tree) return void 0;
|
|
49321
50295
|
const updates = paths.map((path42) => `160000 commit ${placeholderCommit} ${path42}`).join("\n");
|
|
49322
50296
|
if (!updates) return tree;
|
|
49323
|
-
const tmpIndex = (0,
|
|
50297
|
+
const tmpIndex = (0, import_path13.join)(resolveGitDir(repoRoot), `adhdev-refine-eq-${commitish.slice(0, 12)}.index`);
|
|
49324
50298
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
49325
50299
|
try {
|
|
49326
50300
|
(0, import_node_child_process6.execFileSync)("git", ["read-tree", tree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
@@ -49336,7 +50310,7 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
49336
50310
|
return newTree || void 0;
|
|
49337
50311
|
} finally {
|
|
49338
50312
|
try {
|
|
49339
|
-
|
|
50313
|
+
fs29.rmSync(tmpIndex, { force: true });
|
|
49340
50314
|
} catch {
|
|
49341
50315
|
}
|
|
49342
50316
|
}
|
|
@@ -49395,7 +50369,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
49395
50369
|
if (!contentTree) return void 0;
|
|
49396
50370
|
const updates = branchGitlinks.map((entry) => `160000 commit ${entry.branchCommit} ${entry.path}`).join("\n");
|
|
49397
50371
|
if (!updates) return contentTree;
|
|
49398
|
-
const tmpIndex = (0,
|
|
50372
|
+
const tmpIndex = (0, import_path13.join)(resolveGitDir(repoRoot), `adhdev-refine-ff-${baseHead.slice(0, 12)}-${branchHead.slice(0, 12)}.index`);
|
|
49399
50373
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
49400
50374
|
try {
|
|
49401
50375
|
(0, import_node_child_process6.execFileSync)("git", ["read-tree", contentTree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
@@ -49411,7 +50385,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
49411
50385
|
return newTree || void 0;
|
|
49412
50386
|
} finally {
|
|
49413
50387
|
try {
|
|
49414
|
-
|
|
50388
|
+
fs29.rmSync(tmpIndex, { force: true });
|
|
49415
50389
|
} catch {
|
|
49416
50390
|
}
|
|
49417
50391
|
}
|
|
@@ -49517,7 +50491,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
49517
50491
|
return { stdout: String(stdout || ""), stderr: String(stderr || ""), refspec };
|
|
49518
50492
|
};
|
|
49519
50493
|
const importCommitFromWorktreeSubmodule = async (submodulePath, worktreeSubmodulePath, commit) => {
|
|
49520
|
-
if (!
|
|
50494
|
+
if (!fs29.existsSync(worktreeSubmodulePath)) return false;
|
|
49521
50495
|
try {
|
|
49522
50496
|
await runGit3(worktreeSubmodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
|
|
49523
50497
|
} catch {
|
|
@@ -49533,14 +50507,14 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
49533
50507
|
return match ? { commit: match[1], path: match[2] } : null;
|
|
49534
50508
|
}).filter((entry) => !!entry);
|
|
49535
50509
|
for (const gitlink of gitlinks) {
|
|
49536
|
-
const submodulePath = (0,
|
|
50510
|
+
const submodulePath = (0, import_path13.resolve)(repoRoot, gitlink.path);
|
|
49537
50511
|
const entry = {
|
|
49538
50512
|
path: gitlink.path,
|
|
49539
50513
|
commit: gitlink.commit,
|
|
49540
50514
|
reachable: false
|
|
49541
50515
|
};
|
|
49542
50516
|
try {
|
|
49543
|
-
if (!
|
|
50517
|
+
if (!fs29.existsSync(submodulePath)) {
|
|
49544
50518
|
entry.error = `Submodule checkout missing at ${gitlink.path}`;
|
|
49545
50519
|
entry.publishRequired = true;
|
|
49546
50520
|
if (options.allowAutoPublishSubmoduleMainCommits === true) {
|
|
@@ -49561,7 +50535,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
49561
50535
|
try {
|
|
49562
50536
|
const imported = await importCommitFromWorktreeSubmodule(
|
|
49563
50537
|
submodulePath,
|
|
49564
|
-
(0,
|
|
50538
|
+
(0, import_path13.resolve)(options.worktreeRoot, gitlink.path),
|
|
49565
50539
|
gitlink.commit
|
|
49566
50540
|
);
|
|
49567
50541
|
if (imported) {
|
|
@@ -49773,19 +50747,19 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
49773
50747
|
...extras
|
|
49774
50748
|
});
|
|
49775
50749
|
const isPackageManagerValidation = (candidate) => {
|
|
49776
|
-
const command = (0,
|
|
50750
|
+
const command = (0, import_path13.basename)(candidate.command).replace(/\.(?:cmd|exe)$/i, "");
|
|
49777
50751
|
return ["npm", "pnpm", "yarn", "bun"].includes(command) && candidate.args.some((arg) => arg === "run" || arg === "test" || arg === "exec");
|
|
49778
50752
|
};
|
|
49779
50753
|
const dependenciesLikelyMissing = (cwd) => {
|
|
49780
|
-
if (!
|
|
49781
|
-
if (
|
|
49782
|
-
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) =>
|
|
50754
|
+
if (!fs29.existsSync((0, import_path13.join)(cwd, "package.json"))) return false;
|
|
50755
|
+
if (fs29.existsSync((0, import_path13.join)(cwd, "node_modules"))) return false;
|
|
50756
|
+
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs29.existsSync((0, import_path13.join)(cwd, lock)));
|
|
49783
50757
|
};
|
|
49784
50758
|
if (runLegacyBootstrapCommands) {
|
|
49785
50759
|
summary.bootstrap = { stage: "legacy" };
|
|
49786
50760
|
for (const candidate of selection.bootstrapCommands) {
|
|
49787
50761
|
const startedAt = Date.now();
|
|
49788
|
-
const cwd = candidate.cwd ? (0,
|
|
50762
|
+
const cwd = candidate.cwd ? (0, import_path13.resolve)(workspace, candidate.cwd) : workspace;
|
|
49789
50763
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
49790
50764
|
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
49791
50765
|
try {
|
|
@@ -49815,7 +50789,7 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
49815
50789
|
}
|
|
49816
50790
|
for (const candidate of selection.commands) {
|
|
49817
50791
|
const startedAt = Date.now();
|
|
49818
|
-
const cwd = candidate.cwd ? (0,
|
|
50792
|
+
const cwd = candidate.cwd ? (0, import_path13.resolve)(workspace, candidate.cwd) : workspace;
|
|
49819
50793
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
49820
50794
|
const bootstrapProvidedDependencies = summary.bootstrap?.stage === "cached" || summary.bootstrap?.stage === "ran" || summary.bootstrap?.stage === "legacy";
|
|
49821
50795
|
if (!bootstrapProvidedDependencies && isPackageManagerValidation(candidate) && dependenciesLikelyMissing(cwd)) {
|
|
@@ -49884,14 +50858,14 @@ function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
|
49884
50858
|
}
|
|
49885
50859
|
function resolveHermesUserHome() {
|
|
49886
50860
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
49887
|
-
return explicitHome || (0,
|
|
50861
|
+
return explicitHome || (0, import_path13.join)((0, import_os4.homedir)(), ".hermes");
|
|
49888
50862
|
}
|
|
49889
50863
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
49890
50864
|
const sourceHome = resolveHermesUserHome();
|
|
49891
|
-
const sourceConfigPath = (0,
|
|
49892
|
-
if (!
|
|
49893
|
-
if ((0,
|
|
49894
|
-
const parsed = parseMeshCoordinatorMcpConfig(
|
|
50865
|
+
const sourceConfigPath = (0, import_path13.join)(sourceHome, "config.yaml");
|
|
50866
|
+
if (!fs29.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
50867
|
+
if ((0, import_path13.resolve)(sourceConfigPath) === (0, import_path13.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
50868
|
+
const parsed = parseMeshCoordinatorMcpConfig(fs29.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
49895
50869
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
49896
50870
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
49897
50871
|
}
|
|
@@ -49924,13 +50898,13 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
|
49924
50898
|
return sanitized;
|
|
49925
50899
|
}
|
|
49926
50900
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
49927
|
-
if ((0,
|
|
50901
|
+
if ((0, import_path13.resolve)(sourceHome) === (0, import_path13.resolve)(targetHome)) return;
|
|
49928
50902
|
for (const fileName of [".env", "auth.json"]) {
|
|
49929
|
-
const sourcePath = (0,
|
|
49930
|
-
const targetPath = (0,
|
|
49931
|
-
if (!
|
|
50903
|
+
const sourcePath = (0, import_path13.join)(sourceHome, fileName);
|
|
50904
|
+
const targetPath = (0, import_path13.join)(targetHome, fileName);
|
|
50905
|
+
if (!fs29.existsSync(sourcePath)) continue;
|
|
49932
50906
|
try {
|
|
49933
|
-
|
|
50907
|
+
fs29.copyFileSync(sourcePath, targetPath);
|
|
49934
50908
|
} catch (error) {
|
|
49935
50909
|
LOG.warn("MeshCoordinator", `Could not copy Hermes ${fileName} into isolated coordinator home: ${error?.message || error}`);
|
|
49936
50910
|
}
|
|
@@ -50322,6 +51296,29 @@ var DaemonCommandRouter = class {
|
|
|
50322
51296
|
};
|
|
50323
51297
|
return ctx;
|
|
50324
51298
|
}
|
|
51299
|
+
/**
|
|
51300
|
+
* Build the HighFamilyContext handed to RF-ROUTER HIGH family handlers. Binds
|
|
51301
|
+
* the router-private collaborators those handlers need (mesh resolution, the
|
|
51302
|
+
* aggregate-status memory cache + its bound read/write helpers, the
|
|
51303
|
+
* running-refine-job table, inline-mesh + git-probe caches, and the router's
|
|
51304
|
+
* own `execute` for the get_mesh_review_inbox mesh_status re-entry). HIGH
|
|
51305
|
+
* handlers reach more router-owned state than MED, but the binding shape is
|
|
51306
|
+
* the same: bound methods + direct field references, none reachable from
|
|
51307
|
+
* `deps`.
|
|
51308
|
+
*/
|
|
51309
|
+
buildHighFamilyContext() {
|
|
51310
|
+
return {
|
|
51311
|
+
deps: this.deps,
|
|
51312
|
+
getMeshForCommand: this.getMeshForCommand.bind(this),
|
|
51313
|
+
getCachedAggregateMeshStatus: this.getCachedAggregateMeshStatus.bind(this),
|
|
51314
|
+
rememberAggregateMeshStatus: this.rememberAggregateMeshStatus.bind(this),
|
|
51315
|
+
execute: this.execute.bind(this),
|
|
51316
|
+
aggregateMeshStatusCache: this.aggregateMeshStatusCache,
|
|
51317
|
+
runningRefineJobs: this.runningRefineJobs,
|
|
51318
|
+
inlineMeshCache: this.inlineMeshCache,
|
|
51319
|
+
meshGitProbeCache: this.meshGitProbeCache
|
|
51320
|
+
};
|
|
51321
|
+
}
|
|
50325
51322
|
async requireMeshHostMutationOwner(meshId, inlineMesh, operation) {
|
|
50326
51323
|
const meshRecord = await this.getMeshForCommand(meshId, inlineMesh, { preferInline: true });
|
|
50327
51324
|
const mesh = meshRecord?.mesh;
|
|
@@ -50379,7 +51376,7 @@ var DaemonCommandRouter = class {
|
|
|
50379
51376
|
const nodeId = readInlineMeshNodeId(node);
|
|
50380
51377
|
if (!nodeId || !tombstones.has(nodeId)) return true;
|
|
50381
51378
|
const workspace = readStringValue(node?.workspace);
|
|
50382
|
-
if (workspace &&
|
|
51379
|
+
if (workspace && fs29.existsSync(workspace)) {
|
|
50383
51380
|
tombstones.delete(nodeId);
|
|
50384
51381
|
return true;
|
|
50385
51382
|
}
|
|
@@ -50414,14 +51411,14 @@ var DaemonCommandRouter = class {
|
|
|
50414
51411
|
* to give handles time to release, and reports whether residue remains.
|
|
50415
51412
|
*/
|
|
50416
51413
|
async bestEffortRemoveWorktreeDir(dir) {
|
|
50417
|
-
if (!dir || !
|
|
51414
|
+
if (!dir || !fs29.existsSync(dir)) return { removed: true, residue: false };
|
|
50418
51415
|
const sleep3 = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
50419
51416
|
const ABSORB = /* @__PURE__ */ new Set(["EINVAL", "EPERM", "EBUSY", "ENOTEMPTY", "EACCES", "EMFILE", "ENFILE"]);
|
|
50420
51417
|
let lastErr;
|
|
50421
51418
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
50422
51419
|
try {
|
|
50423
|
-
|
|
50424
|
-
if (!
|
|
51420
|
+
fs29.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
51421
|
+
if (!fs29.existsSync(dir)) return { removed: true, residue: false };
|
|
50425
51422
|
lastErr = new Error("directory still present after rmSync");
|
|
50426
51423
|
} catch (e) {
|
|
50427
51424
|
lastErr = e;
|
|
@@ -50432,7 +51429,7 @@ var DaemonCommandRouter = class {
|
|
|
50432
51429
|
}
|
|
50433
51430
|
await sleep3(150 * (attempt + 1));
|
|
50434
51431
|
}
|
|
50435
|
-
return
|
|
51432
|
+
return fs29.existsSync(dir) ? { removed: false, residue: true, error: String(lastErr?.message || lastErr || "unknown rm error") } : { removed: true, residue: false };
|
|
50436
51433
|
}
|
|
50437
51434
|
async cleanupLocalWorktreeNode(args) {
|
|
50438
51435
|
const workspace = typeof args.node?.workspace === "string" ? args.node.workspace.trim() : "";
|
|
@@ -50444,13 +51441,13 @@ var DaemonCommandRouter = class {
|
|
|
50444
51441
|
recoveryHint: "Inspect the mesh node record before removing it, or remove stale metadata manually only after confirming no managed worktree remains."
|
|
50445
51442
|
};
|
|
50446
51443
|
}
|
|
50447
|
-
const worktreeExists =
|
|
51444
|
+
const worktreeExists = fs29.existsSync(workspace);
|
|
50448
51445
|
const sourceNode = args.node?.clonedFromNodeId ? args.mesh?.nodes?.find((n) => meshNodeIdMatches(n, args.node.clonedFromNodeId)) : args.mesh?.nodes?.find((n) => !n.isLocalWorktree);
|
|
50449
51446
|
const repoRoot = typeof sourceNode?.repoRoot === "string" && sourceNode.repoRoot.trim() ? sourceNode.repoRoot.trim() : typeof sourceNode?.workspace === "string" && sourceNode.workspace.trim() ? sourceNode.workspace.trim() : "";
|
|
50450
51447
|
if (!worktreeExists) {
|
|
50451
51448
|
return { success: true, skipped: true, removedPath: workspace, repoRoot: repoRoot || void 0, reason: "worktree_path_missing" };
|
|
50452
51449
|
}
|
|
50453
|
-
if (!repoRoot || !
|
|
51450
|
+
if (!repoRoot || !fs29.existsSync(repoRoot)) {
|
|
50454
51451
|
return {
|
|
50455
51452
|
success: false,
|
|
50456
51453
|
code: "mesh_worktree_cleanup_missing_source_repo",
|
|
@@ -50468,9 +51465,9 @@ var DaemonCommandRouter = class {
|
|
|
50468
51465
|
}
|
|
50469
51466
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
50470
51467
|
const normalizePath = (value) => {
|
|
50471
|
-
const resolved = (0,
|
|
51468
|
+
const resolved = (0, import_path13.resolve)(value);
|
|
50472
51469
|
try {
|
|
50473
|
-
return
|
|
51470
|
+
return fs29.realpathSync(resolved);
|
|
50474
51471
|
} catch {
|
|
50475
51472
|
return resolved;
|
|
50476
51473
|
}
|
|
@@ -51065,196 +52062,242 @@ var DaemonCommandRouter = class {
|
|
|
51065
52062
|
LOG.warn("Mesh", `[Refinery] resumePendingRefineJobsOnStartup failed: ${e?.message || e}`);
|
|
51066
52063
|
}
|
|
51067
52064
|
}
|
|
52065
|
+
/**
|
|
52066
|
+
* Synchronous refinery for a single worktree node — the gate pipeline that
|
|
52067
|
+
* validates, preflights (patch-equivalence / submodule-reachability /
|
|
52068
|
+
* no-op), merges, aligns submodules, cleans up the worktree node and
|
|
52069
|
+
* (optionally) pushes. The body is a flat sequence of stage methods; each
|
|
52070
|
+
* stage either returns a terminal CommandRouterResult (gate failure or a
|
|
52071
|
+
* successful already-merged short-circuit) or `continue` with the extended
|
|
52072
|
+
* context. Behavior — stage order, every early-exit, and every result shape —
|
|
52073
|
+
* is identical to the previous single inlined body.
|
|
52074
|
+
*/
|
|
51068
52075
|
async executeMeshRefineNodeSynchronously(meshId, nodeId, args) {
|
|
51069
52076
|
const refineStages = [];
|
|
51070
52077
|
try {
|
|
51071
|
-
const
|
|
51072
|
-
|
|
51073
|
-
const
|
|
51074
|
-
|
|
51075
|
-
if (
|
|
51076
|
-
|
|
51077
|
-
|
|
51078
|
-
const
|
|
51079
|
-
|
|
51080
|
-
|
|
51081
|
-
|
|
51082
|
-
const
|
|
51083
|
-
|
|
51084
|
-
|
|
51085
|
-
|
|
51086
|
-
|
|
51087
|
-
|
|
51088
|
-
|
|
51089
|
-
|
|
51090
|
-
|
|
51091
|
-
|
|
51092
|
-
|
|
51093
|
-
|
|
51094
|
-
|
|
51095
|
-
|
|
51096
|
-
|
|
51097
|
-
|
|
51098
|
-
|
|
51099
|
-
|
|
51100
|
-
|
|
51101
|
-
|
|
51102
|
-
|
|
51103
|
-
|
|
51104
|
-
|
|
51105
|
-
|
|
51106
|
-
|
|
51107
|
-
|
|
51108
|
-
|
|
51109
|
-
|
|
51110
|
-
|
|
51111
|
-
|
|
51112
|
-
|
|
51113
|
-
|
|
51114
|
-
|
|
51115
|
-
|
|
51116
|
-
|
|
51117
|
-
})
|
|
51118
|
-
|
|
52078
|
+
const resolved = await this.refineResolveRefsStage(meshId, nodeId, args, refineStages);
|
|
52079
|
+
if (resolved.kind === "terminal") return resolved.result;
|
|
52080
|
+
const ctx = resolved.ctx;
|
|
52081
|
+
const validation = await this.refineValidationStage(ctx);
|
|
52082
|
+
if (validation.kind === "terminal") return validation.result;
|
|
52083
|
+
const patchEquivalence = await this.refinePatchEquivalenceStage(ctx);
|
|
52084
|
+
if (patchEquivalence.kind === "terminal") return patchEquivalence.result;
|
|
52085
|
+
const submoduleReachability = await this.refineSubmoduleReachabilityStage(ctx);
|
|
52086
|
+
if (submoduleReachability.kind === "terminal") return submoduleReachability.result;
|
|
52087
|
+
const effectiveDiff = await this.refineEffectiveDiffStage(ctx);
|
|
52088
|
+
if (effectiveDiff.kind === "terminal") return effectiveDiff.result;
|
|
52089
|
+
const merge = await this.refineMergeAndFinalizeStage(ctx);
|
|
52090
|
+
return merge.result;
|
|
52091
|
+
} catch (e) {
|
|
52092
|
+
return { success: false, error: e.message, refineStages };
|
|
52093
|
+
}
|
|
52094
|
+
}
|
|
52095
|
+
/**
|
|
52096
|
+
* resolve_refs stage: resolve the mesh / worktree node / source node /
|
|
52097
|
+
* repoRoot, then the worktree branch, base branch, fetched base head and
|
|
52098
|
+
* branch head. Seeds the RefineContext consumed by every later stage.
|
|
52099
|
+
*/
|
|
52100
|
+
async refineResolveRefsStage(meshId, nodeId, args, refineStages) {
|
|
52101
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
52102
|
+
const mesh = meshRecord?.mesh;
|
|
52103
|
+
const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
52104
|
+
if (!node) return { kind: "terminal", result: { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages } };
|
|
52105
|
+
if (!node.isLocalWorktree || !node.workspace) {
|
|
52106
|
+
return { kind: "terminal", result: { success: false, error: `Refinery requires a local worktree node`, refineStages } };
|
|
52107
|
+
}
|
|
52108
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => meshNodeIdMatches(n, node.clonedFromNodeId)) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
52109
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
52110
|
+
if (!repoRoot) return { kind: "terminal", result: { success: false, error: "Source node repoRoot not found", refineStages } };
|
|
52111
|
+
const { execFile: execFile5 } = await import("child_process");
|
|
52112
|
+
const { promisify: promisify8 } = await import("util");
|
|
52113
|
+
const execFileAsync4 = promisify8(execFile5);
|
|
52114
|
+
const resolveStarted = Date.now();
|
|
52115
|
+
const { stdout: branchStdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
|
|
52116
|
+
const branch = branchStdout.trim();
|
|
52117
|
+
if (!branch) return { kind: "terminal", result: { success: false, error: "Could not determine branch of the worktree node", refineStages } };
|
|
52118
|
+
const { stdout: baseBranchStdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
52119
|
+
const baseBranch = baseBranchStdout.trim();
|
|
52120
|
+
let fetchWarning;
|
|
52121
|
+
try {
|
|
52122
|
+
await execFileAsync4("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
|
|
52123
|
+
} catch (e) {
|
|
52124
|
+
fetchWarning = `git fetch origin ${baseBranch} failed (proceeding with local HEAD): ${e?.message}`;
|
|
52125
|
+
}
|
|
52126
|
+
let baseHeadRaw;
|
|
52127
|
+
try {
|
|
52128
|
+
const { stdout } = await execFileAsync4("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
|
|
52129
|
+
baseHeadRaw = stdout.trim();
|
|
52130
|
+
} catch {
|
|
52131
|
+
const { stdout: localHead } = await execFileAsync4("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
|
|
52132
|
+
baseHeadRaw = localHead.trim();
|
|
52133
|
+
}
|
|
52134
|
+
const { stdout: branchHeadStdout } = await execFileAsync4("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
|
|
52135
|
+
const baseHead = baseHeadRaw;
|
|
52136
|
+
const branchHead = branchHeadStdout.trim();
|
|
52137
|
+
recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead, ...fetchWarning ? { fetchWarning } : {} });
|
|
52138
|
+
return {
|
|
52139
|
+
kind: "continue",
|
|
52140
|
+
ctx: {
|
|
52141
|
+
meshId,
|
|
52142
|
+
nodeId,
|
|
52143
|
+
args,
|
|
51119
52144
|
refineStages,
|
|
51120
|
-
|
|
51121
|
-
|
|
51122
|
-
|
|
51123
|
-
|
|
51124
|
-
|
|
51125
|
-
|
|
51126
|
-
|
|
51127
|
-
|
|
51128
|
-
|
|
51129
|
-
|
|
51130
|
-
|
|
51131
|
-
|
|
51132
|
-
|
|
51133
|
-
|
|
51134
|
-
|
|
51135
|
-
|
|
51136
|
-
|
|
52145
|
+
execFileAsync: execFileAsync4,
|
|
52146
|
+
mesh,
|
|
52147
|
+
node,
|
|
52148
|
+
sourceNode,
|
|
52149
|
+
repoRoot,
|
|
52150
|
+
branch,
|
|
52151
|
+
baseBranch,
|
|
52152
|
+
baseHead,
|
|
52153
|
+
branchHead,
|
|
52154
|
+
validationSummary: void 0,
|
|
52155
|
+
patchEquivalence: void 0,
|
|
52156
|
+
submoduleReachability: void 0
|
|
52157
|
+
}
|
|
52158
|
+
};
|
|
52159
|
+
}
|
|
52160
|
+
/**
|
|
52161
|
+
* validation stage: run the refinery validation gate (typecheck / test /
|
|
52162
|
+
* lint / build per node config) and block on failure or when no allowlisted
|
|
52163
|
+
* command was available. On pass, stores the summary on the context.
|
|
52164
|
+
*/
|
|
52165
|
+
async refineValidationStage(ctx) {
|
|
52166
|
+
const { mesh, node, branch, baseBranch, refineStages } = ctx;
|
|
52167
|
+
const validationStarted = Date.now();
|
|
52168
|
+
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace, {
|
|
52169
|
+
// M2-2: consume the node's persisted bootstrap state; persist re-runs.
|
|
52170
|
+
persistedBootstrapState: node.worktreeBootstrap,
|
|
52171
|
+
onBootstrapStateChange: (state) => {
|
|
52172
|
+
node.worktreeBootstrap = state;
|
|
52173
|
+
void Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)).then(({ updateNode: updateNode2 }) => updateNode2(mesh.id, node.id, { worktreeBootstrap: state })).catch(() => {
|
|
52174
|
+
});
|
|
52175
|
+
}
|
|
52176
|
+
});
|
|
52177
|
+
ctx.validationSummary = validationSummary;
|
|
52178
|
+
recordMeshRefineStage(
|
|
52179
|
+
refineStages,
|
|
52180
|
+
"validation",
|
|
52181
|
+
validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
|
|
52182
|
+
validationStarted,
|
|
52183
|
+
{ validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
|
|
52184
|
+
);
|
|
52185
|
+
if (validationSummary.status === "failed") {
|
|
52186
|
+
const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
|
|
52187
|
+
const buildValidationFailedError = () => {
|
|
52188
|
+
const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : validationSummary.failureCode === "spawn_resolution_failed" ? validationSummary.spawnResolutionError || "Refinery validation command could not be spawned (executable not found); merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
|
|
52189
|
+
if (!firstFailedCmd) return base;
|
|
52190
|
+
const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
|
|
52191
|
+
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
|
|
52192
|
+
const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
|
|
52193
|
+
return [
|
|
52194
|
+
base,
|
|
52195
|
+
cmdName ? `First failing command: ${cmdName}` : "",
|
|
52196
|
+
tail ? `Output (tail):
|
|
51137
52197
|
${tail}` : ""
|
|
51138
|
-
|
|
51139
|
-
|
|
51140
|
-
|
|
51141
|
-
|
|
51142
|
-
|
|
51143
|
-
|
|
51144
|
-
|
|
52198
|
+
].filter(Boolean).join("\n");
|
|
52199
|
+
};
|
|
52200
|
+
return { kind: "terminal", result: {
|
|
52201
|
+
success: false,
|
|
52202
|
+
code: validationSummary.failureCode || "validation_failed",
|
|
52203
|
+
convergenceStatus: "blocked_review",
|
|
52204
|
+
error: buildValidationFailedError(),
|
|
52205
|
+
branch,
|
|
52206
|
+
into: baseBranch,
|
|
52207
|
+
validationSummary,
|
|
52208
|
+
refineStages,
|
|
52209
|
+
finalBranchConvergenceState: {
|
|
51145
52210
|
branch,
|
|
51146
|
-
|
|
51147
|
-
|
|
51148
|
-
|
|
51149
|
-
|
|
51150
|
-
|
|
51151
|
-
|
|
51152
|
-
|
|
51153
|
-
|
|
51154
|
-
|
|
51155
|
-
|
|
51156
|
-
|
|
51157
|
-
|
|
51158
|
-
|
|
51159
|
-
|
|
51160
|
-
|
|
51161
|
-
|
|
51162
|
-
|
|
51163
|
-
|
|
51164
|
-
|
|
52211
|
+
baseBranch,
|
|
52212
|
+
merged: false,
|
|
52213
|
+
removed: false,
|
|
52214
|
+
validation: "failed",
|
|
52215
|
+
status: "blocked_review"
|
|
52216
|
+
}
|
|
52217
|
+
} };
|
|
52218
|
+
}
|
|
52219
|
+
if (validationSummary.status === "skipped") {
|
|
52220
|
+
return { kind: "terminal", result: {
|
|
52221
|
+
success: false,
|
|
52222
|
+
code: "validation_unavailable",
|
|
52223
|
+
convergenceStatus: "blocked_review",
|
|
52224
|
+
error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
|
|
52225
|
+
branch,
|
|
52226
|
+
into: baseBranch,
|
|
52227
|
+
validationSummary,
|
|
52228
|
+
refineStages,
|
|
52229
|
+
finalBranchConvergenceState: {
|
|
51165
52230
|
branch,
|
|
51166
|
-
|
|
51167
|
-
|
|
51168
|
-
|
|
51169
|
-
|
|
51170
|
-
|
|
51171
|
-
|
|
51172
|
-
|
|
51173
|
-
|
|
51174
|
-
|
|
51175
|
-
|
|
51176
|
-
|
|
51177
|
-
|
|
52231
|
+
baseBranch,
|
|
52232
|
+
merged: false,
|
|
52233
|
+
removed: false,
|
|
52234
|
+
validation: "unavailable",
|
|
52235
|
+
status: "blocked_review"
|
|
52236
|
+
}
|
|
52237
|
+
} };
|
|
52238
|
+
}
|
|
52239
|
+
return { kind: "continue", ctx };
|
|
52240
|
+
}
|
|
52241
|
+
/**
|
|
52242
|
+
* patch_equivalence stage: preflight that the worktree branch's cumulative
|
|
52243
|
+
* patch is equivalent to base+branch. On a "behind base" branch, auto-rebase
|
|
52244
|
+
* once and re-check; on an empty merge-tree with real branch changes, treat as
|
|
52245
|
+
* already-merged-via-another-path and short-circuit to cleanup. Mutates the
|
|
52246
|
+
* context's branchHead (after rebase) and patchEquivalence (rebased gate).
|
|
52247
|
+
*/
|
|
52248
|
+
async refinePatchEquivalenceStage(ctx) {
|
|
52249
|
+
const { meshId, nodeId, args, repoRoot, baseHead, node, branch, baseBranch, validationSummary, refineStages, execFileAsync: execFileAsync4 } = ctx;
|
|
52250
|
+
let branchHead = ctx.branchHead;
|
|
52251
|
+
const patchEquivalenceStarted = Date.now();
|
|
52252
|
+
let patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
|
|
52253
|
+
recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
|
|
52254
|
+
equivalent: patchEquivalence.equivalent,
|
|
52255
|
+
expectedPatchId: patchEquivalence.expectedPatchId,
|
|
52256
|
+
actualPatchId: patchEquivalence.actualPatchId,
|
|
52257
|
+
error: patchEquivalence.error,
|
|
52258
|
+
actionableHint: patchEquivalence.actionableHint
|
|
52259
|
+
});
|
|
52260
|
+
if (!patchEquivalence.equivalent) {
|
|
52261
|
+
let didAutoRebase = false;
|
|
52262
|
+
let isBehindBase = false;
|
|
52263
|
+
try {
|
|
52264
|
+
(0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", branchHead, baseHead], {
|
|
52265
|
+
cwd: node.workspace,
|
|
52266
|
+
stdio: "ignore"
|
|
52267
|
+
});
|
|
52268
|
+
isBehindBase = true;
|
|
52269
|
+
} catch {
|
|
51178
52270
|
}
|
|
51179
|
-
|
|
51180
|
-
|
|
51181
|
-
recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
|
|
51182
|
-
equivalent: patchEquivalence.equivalent,
|
|
51183
|
-
expectedPatchId: patchEquivalence.expectedPatchId,
|
|
51184
|
-
actualPatchId: patchEquivalence.actualPatchId,
|
|
51185
|
-
error: patchEquivalence.error,
|
|
51186
|
-
actionableHint: patchEquivalence.actionableHint
|
|
51187
|
-
});
|
|
51188
|
-
if (!patchEquivalence.equivalent) {
|
|
51189
|
-
let didAutoRebase = false;
|
|
51190
|
-
let isBehindBase = false;
|
|
52271
|
+
if (isBehindBase) {
|
|
52272
|
+
const autoRebaseStarted = Date.now();
|
|
51191
52273
|
try {
|
|
51192
|
-
(0, import_node_child_process6.execFileSync)("git", ["
|
|
52274
|
+
(0, import_node_child_process6.execFileSync)("git", ["rebase", baseHead], {
|
|
51193
52275
|
cwd: node.workspace,
|
|
51194
|
-
stdio: "ignore"
|
|
52276
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
51195
52277
|
});
|
|
51196
|
-
|
|
51197
|
-
|
|
51198
|
-
|
|
51199
|
-
|
|
51200
|
-
|
|
51201
|
-
|
|
51202
|
-
|
|
51203
|
-
|
|
51204
|
-
|
|
51205
|
-
|
|
51206
|
-
|
|
51207
|
-
|
|
51208
|
-
|
|
51209
|
-
|
|
51210
|
-
|
|
51211
|
-
expectedPatchId: rebasedPatchEquivalence.expectedPatchId,
|
|
51212
|
-
actualPatchId: rebasedPatchEquivalence.actualPatchId,
|
|
51213
|
-
error: rebasedPatchEquivalence.error,
|
|
51214
|
-
rebasedBranchHead: branchHead
|
|
51215
|
-
});
|
|
51216
|
-
if (rebasedPatchEquivalence.equivalent) {
|
|
51217
|
-
patchEquivalence = rebasedPatchEquivalence;
|
|
51218
|
-
didAutoRebase = true;
|
|
51219
|
-
} else {
|
|
51220
|
-
return {
|
|
51221
|
-
success: false,
|
|
51222
|
-
code: "needs_rebase",
|
|
51223
|
-
convergenceStatus: "blocked_review",
|
|
51224
|
-
error: "Branch was rebased onto base but patch equivalence still failed; manual intervention required.",
|
|
51225
|
-
branch,
|
|
51226
|
-
into: baseBranch,
|
|
51227
|
-
validationSummary,
|
|
51228
|
-
patchEquivalence: rebasedPatchEquivalence,
|
|
51229
|
-
refineStages,
|
|
51230
|
-
finalBranchConvergenceState: {
|
|
51231
|
-
branch,
|
|
51232
|
-
baseBranch,
|
|
51233
|
-
merged: false,
|
|
51234
|
-
removed: false,
|
|
51235
|
-
validation: "passed",
|
|
51236
|
-
patchEquivalence: "failed",
|
|
51237
|
-
status: "blocked_review"
|
|
51238
|
-
}
|
|
51239
|
-
};
|
|
51240
|
-
}
|
|
51241
|
-
} catch (rebaseErr) {
|
|
51242
|
-
try {
|
|
51243
|
-
(0, import_node_child_process6.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
|
|
51244
|
-
} catch {
|
|
51245
|
-
}
|
|
51246
|
-
recordMeshRefineStage(refineStages, "patch_equivalence_after_auto_rebase", "failed", autoRebaseStarted, {
|
|
51247
|
-
error: rebaseErr?.message || String(rebaseErr)
|
|
51248
|
-
});
|
|
51249
|
-
return {
|
|
52278
|
+
const { stdout: rebasedHeadStdout } = await execFileAsync4("git", ["rev-parse", "HEAD"], { cwd: node.workspace, encoding: "utf8" });
|
|
52279
|
+
branchHead = rebasedHeadStdout.trim();
|
|
52280
|
+
const rebasedPatchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
|
|
52281
|
+
recordMeshRefineStage(refineStages, "patch_equivalence_after_auto_rebase", rebasedPatchEquivalence.status, autoRebaseStarted, {
|
|
52282
|
+
equivalent: rebasedPatchEquivalence.equivalent,
|
|
52283
|
+
expectedPatchId: rebasedPatchEquivalence.expectedPatchId,
|
|
52284
|
+
actualPatchId: rebasedPatchEquivalence.actualPatchId,
|
|
52285
|
+
error: rebasedPatchEquivalence.error,
|
|
52286
|
+
rebasedBranchHead: branchHead
|
|
52287
|
+
});
|
|
52288
|
+
if (rebasedPatchEquivalence.equivalent) {
|
|
52289
|
+
patchEquivalence = rebasedPatchEquivalence;
|
|
52290
|
+
didAutoRebase = true;
|
|
52291
|
+
} else {
|
|
52292
|
+
return { kind: "terminal", result: {
|
|
51250
52293
|
success: false,
|
|
51251
|
-
code: "
|
|
52294
|
+
code: "needs_rebase",
|
|
51252
52295
|
convergenceStatus: "blocked_review",
|
|
51253
|
-
error: "Branch
|
|
52296
|
+
error: "Branch was rebased onto base but patch equivalence still failed; manual intervention required.",
|
|
51254
52297
|
branch,
|
|
51255
52298
|
into: baseBranch,
|
|
51256
52299
|
validationSummary,
|
|
51257
|
-
patchEquivalence,
|
|
52300
|
+
patchEquivalence: rebasedPatchEquivalence,
|
|
51258
52301
|
refineStages,
|
|
51259
52302
|
finalBranchConvergenceState: {
|
|
51260
52303
|
branch,
|
|
@@ -51265,16 +52308,21 @@ ${tail}` : ""
|
|
|
51265
52308
|
patchEquivalence: "failed",
|
|
51266
52309
|
status: "blocked_review"
|
|
51267
52310
|
}
|
|
51268
|
-
};
|
|
52311
|
+
} };
|
|
51269
52312
|
}
|
|
51270
|
-
}
|
|
51271
|
-
|
|
51272
|
-
|
|
51273
|
-
|
|
52313
|
+
} catch (rebaseErr) {
|
|
52314
|
+
try {
|
|
52315
|
+
(0, import_node_child_process6.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
|
|
52316
|
+
} catch {
|
|
52317
|
+
}
|
|
52318
|
+
recordMeshRefineStage(refineStages, "patch_equivalence_after_auto_rebase", "failed", autoRebaseStarted, {
|
|
52319
|
+
error: rebaseErr?.message || String(rebaseErr)
|
|
52320
|
+
});
|
|
52321
|
+
return { kind: "terminal", result: {
|
|
51274
52322
|
success: false,
|
|
51275
|
-
code: "
|
|
52323
|
+
code: "needs_rebase_with_conflicts",
|
|
51276
52324
|
convergenceStatus: "blocked_review",
|
|
51277
|
-
error: "
|
|
52325
|
+
error: "Branch is behind base and auto-rebase failed due to conflicts; resolve conflicts manually and retry.",
|
|
51278
52326
|
branch,
|
|
51279
52327
|
into: baseBranch,
|
|
51280
52328
|
validationSummary,
|
|
@@ -51289,188 +52337,20 @@ ${tail}` : ""
|
|
|
51289
52337
|
patchEquivalence: "failed",
|
|
51290
52338
|
status: "blocked_review"
|
|
51291
52339
|
}
|
|
51292
|
-
};
|
|
51293
|
-
}
|
|
51294
|
-
if (!didAutoRebase && alreadyMergedViaOtherPath) {
|
|
51295
|
-
recordMeshRefineStage(refineStages, "merge", "skipped", Date.now(), {
|
|
51296
|
-
reason: "already_merged_via_other_path",
|
|
51297
|
-
note: "actualPatchId is empty; branch content is already present in base via a different commit path"
|
|
51298
|
-
});
|
|
51299
|
-
const cleanupStarted2 = Date.now();
|
|
51300
|
-
const removeResult2 = await this.execute("remove_mesh_node", {
|
|
51301
|
-
meshId,
|
|
51302
|
-
nodeId,
|
|
51303
|
-
sessionCleanupMode: "preserve",
|
|
51304
|
-
inlineMesh: args?.inlineMesh
|
|
51305
|
-
});
|
|
51306
|
-
recordMeshRefineStage(refineStages, "cleanup", removeResult2?.success === false ? "failed" : "passed", cleanupStarted2, {
|
|
51307
|
-
removed: removeResult2?.removed,
|
|
51308
|
-
code: removeResult2?.code,
|
|
51309
|
-
error: removeResult2?.error
|
|
51310
|
-
});
|
|
51311
|
-
try {
|
|
51312
|
-
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
51313
|
-
appendLedgerEntry2(meshId, {
|
|
51314
|
-
kind: "node_removed",
|
|
51315
|
-
nodeId,
|
|
51316
|
-
payload: { alreadyMergedViaOtherPath: true, branch, into: baseBranch, validationSummary, patchEquivalence }
|
|
51317
|
-
});
|
|
51318
|
-
} catch {
|
|
51319
|
-
}
|
|
51320
|
-
return {
|
|
51321
|
-
success: removeResult2?.success !== false,
|
|
51322
|
-
code: "already_merged",
|
|
51323
|
-
merged: false,
|
|
51324
|
-
alreadyMergedViaOtherPath: true,
|
|
51325
|
-
branch,
|
|
51326
|
-
into: baseBranch,
|
|
51327
|
-
removeResult: removeResult2,
|
|
51328
|
-
validationSummary,
|
|
51329
|
-
patchEquivalence,
|
|
51330
|
-
refineStages,
|
|
51331
|
-
finalBranchConvergenceState: {
|
|
51332
|
-
branch: baseBranch,
|
|
51333
|
-
mergedBranch: branch,
|
|
51334
|
-
baseBranch,
|
|
51335
|
-
merged: false,
|
|
51336
|
-
alreadyMergedViaOtherPath: true,
|
|
51337
|
-
removed: removeResult2?.success !== false,
|
|
51338
|
-
validation: "passed",
|
|
51339
|
-
patchEquivalence: "already_merged",
|
|
51340
|
-
status: removeResult2?.success === false ? "merged_cleanup_failed" : "merged_to_main"
|
|
51341
|
-
}
|
|
51342
|
-
};
|
|
52340
|
+
} };
|
|
51343
52341
|
}
|
|
51344
52342
|
}
|
|
51345
|
-
const
|
|
51346
|
-
|
|
51347
|
-
|
|
51348
|
-
allowAutoPublishSubmoduleMainCommits: autoPublishSubmoduleMainCommits.enabled,
|
|
51349
|
-
autoPublishPolicySource: autoPublishSubmoduleMainCommits.source,
|
|
51350
|
-
worktreeRoot: node.workspace
|
|
51351
|
-
});
|
|
51352
|
-
recordMeshRefineStage(refineStages, "submodule_reachability", submoduleReachability.status, submoduleReachabilityStarted, {
|
|
51353
|
-
checked: submoduleReachability.checked,
|
|
51354
|
-
autoPublishAllowed: submoduleReachability.autoPublishAllowed,
|
|
51355
|
-
autoPublishPolicySource: submoduleReachability.autoPublishPolicySource,
|
|
51356
|
-
autoPublished: submoduleReachability.entries.filter((entry) => entry.autoPublishAttempted).map((entry) => ({
|
|
51357
|
-
path: entry.path,
|
|
51358
|
-
commit: entry.commit,
|
|
51359
|
-
remote: entry.remote,
|
|
51360
|
-
remoteUrl: entry.remoteUrl,
|
|
51361
|
-
remoteMainBranch: entry.remoteMainBranch,
|
|
51362
|
-
refspec: entry.autoPublishRefspec,
|
|
51363
|
-
succeeded: entry.autoPublishSucceeded,
|
|
51364
|
-
verified: entry.autoPublishVerified,
|
|
51365
|
-
remoteMainReachable: entry.remoteMainReachable,
|
|
51366
|
-
error: entry.error
|
|
51367
|
-
})),
|
|
51368
|
-
autoPublishSkipped: submoduleReachability.entries.filter((entry) => entry.autoPublishAllowed === true && entry.autoPublishAttempted !== true).map((entry) => ({
|
|
51369
|
-
path: entry.path,
|
|
51370
|
-
commit: entry.commit,
|
|
51371
|
-
remote: entry.remote,
|
|
51372
|
-
remoteUrl: entry.remoteUrl,
|
|
51373
|
-
remoteMainBranch: entry.remoteMainBranch,
|
|
51374
|
-
reason: entry.autoPublishSkippedReason || entry.error || "auto-publish was allowed but no publish attempt was possible"
|
|
51375
|
-
})),
|
|
51376
|
-
unreachable: submoduleReachability.unreachable.map((entry) => ({
|
|
51377
|
-
path: entry.path,
|
|
51378
|
-
commit: entry.commit,
|
|
51379
|
-
publishRequired: entry.publishRequired === true,
|
|
51380
|
-
autoPublishAllowed: entry.autoPublishAllowed,
|
|
51381
|
-
autoPublishAttempted: entry.autoPublishAttempted,
|
|
51382
|
-
autoPublishSucceeded: entry.autoPublishSucceeded,
|
|
51383
|
-
autoPublishVerified: entry.autoPublishVerified,
|
|
51384
|
-
autoPublishRefspec: entry.autoPublishRefspec,
|
|
51385
|
-
autoPublishSkippedReason: entry.autoPublishSkippedReason,
|
|
51386
|
-
remote: entry.remote,
|
|
51387
|
-
remoteUrl: entry.remoteUrl,
|
|
51388
|
-
remoteReachable: entry.remoteReachable,
|
|
51389
|
-
remoteMainBranch: entry.remoteMainBranch,
|
|
51390
|
-
remoteMainReachable: entry.remoteMainReachable,
|
|
51391
|
-
error: entry.error
|
|
51392
|
-
})),
|
|
51393
|
-
error: submoduleReachability.error
|
|
51394
|
-
});
|
|
51395
|
-
if (submoduleReachability.status === "failed") {
|
|
51396
|
-
const nextStep = buildSubmodulePublishRequiredNextStep(submoduleReachability.unreachable);
|
|
51397
|
-
return {
|
|
51398
|
-
success: false,
|
|
51399
|
-
code: "submodule_reachability_failed",
|
|
51400
|
-
convergenceStatus: "blocked_review",
|
|
51401
|
-
publishRequired: true,
|
|
51402
|
-
blockedReason: "submodule_publish_required",
|
|
51403
|
-
error: "Refinery submodule reachability preflight failed because one or more submodule gitlink commits are not reachable from their configured remote main branch; merge/refine cleanup was not attempted.",
|
|
51404
|
-
nextStep,
|
|
51405
|
-
nextSteps: [
|
|
51406
|
-
"Ask the user for explicit approval before pushing or publishing any submodule commit.",
|
|
51407
|
-
"Push/publish each unreachable submodule commit to the configured submodule remote main branch shown in the evidence.",
|
|
51408
|
-
"Rerun mesh_refine_node after remote reachability is confirmed.",
|
|
51409
|
-
"Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main."
|
|
51410
|
-
],
|
|
51411
|
-
unreachableSubmoduleCommits: submoduleReachability.unreachable.map((entry) => ({
|
|
51412
|
-
path: entry.path,
|
|
51413
|
-
commit: entry.commit,
|
|
51414
|
-
remote: entry.remote,
|
|
51415
|
-
remoteUrl: entry.remoteUrl,
|
|
51416
|
-
remoteReachable: entry.remoteReachable,
|
|
51417
|
-
remoteMainBranch: entry.remoteMainBranch,
|
|
51418
|
-
remoteMainReachable: entry.remoteMainReachable,
|
|
51419
|
-
autoPublishAllowed: entry.autoPublishAllowed,
|
|
51420
|
-
autoPublishAttempted: entry.autoPublishAttempted,
|
|
51421
|
-
autoPublishSucceeded: entry.autoPublishSucceeded,
|
|
51422
|
-
autoPublishVerified: entry.autoPublishVerified,
|
|
51423
|
-
autoPublishRefspec: entry.autoPublishRefspec,
|
|
51424
|
-
autoPublishSkippedReason: entry.autoPublishSkippedReason,
|
|
51425
|
-
error: entry.error
|
|
51426
|
-
})),
|
|
51427
|
-
branch,
|
|
51428
|
-
into: baseBranch,
|
|
51429
|
-
validationSummary,
|
|
51430
|
-
patchEquivalence,
|
|
51431
|
-
submoduleReachability,
|
|
51432
|
-
refineStages,
|
|
51433
|
-
finalBranchConvergenceState: {
|
|
51434
|
-
branch,
|
|
51435
|
-
baseBranch,
|
|
51436
|
-
merged: false,
|
|
51437
|
-
removed: false,
|
|
51438
|
-
validation: "passed",
|
|
51439
|
-
patchEquivalence: "passed",
|
|
51440
|
-
submoduleReachability: "failed",
|
|
51441
|
-
status: "blocked_review",
|
|
51442
|
-
reason: "submodule_publish_required",
|
|
51443
|
-
nextStep
|
|
51444
|
-
}
|
|
51445
|
-
};
|
|
51446
|
-
}
|
|
51447
|
-
const effectiveDiffStarted = Date.now();
|
|
51448
|
-
const effectiveDiff = await runMeshRefineEffectiveDiffGate(repoRoot, baseHead, branchHead);
|
|
51449
|
-
recordMeshRefineStage(refineStages, "effective_diff", effectiveDiff.status, effectiveDiffStarted, {
|
|
51450
|
-
hasEffectiveDiff: effectiveDiff.hasEffectiveDiff,
|
|
51451
|
-
changedPaths: effectiveDiff.changedPaths,
|
|
51452
|
-
submoduleHints: effectiveDiff.submoduleHints,
|
|
51453
|
-
...effectiveDiff.error ? { error: effectiveDiff.error } : {}
|
|
51454
|
-
});
|
|
51455
|
-
if (effectiveDiff.status === "failed" && !effectiveDiff.hasEffectiveDiff) {
|
|
51456
|
-
const hintLines = (effectiveDiff.submoduleHints || []).map((h) => ` - ${h.path}: ${h.reason}`);
|
|
51457
|
-
const message = [
|
|
51458
|
-
`Refinery no-op guard: branch '${branch}' has no effective root-tree diff against '${baseBranch}' (${baseHead.slice(0, 12)}); nothing would merge.`,
|
|
51459
|
-
"This usually means a submodule (e.g. oss) has commits but the root branch never committed the gitlink (pointer) bump, so the merge would be a silent no-op while the real change never reaches main.",
|
|
51460
|
-
hintLines.length ? `Submodules with uncommitted pointer bumps:
|
|
51461
|
-
${hintLines.join("\n")}` : "",
|
|
51462
|
-
`Fix: commit the submodule pointer bump on '${branch}' (git add <submodule-path> && git commit), then re-run refine.`
|
|
51463
|
-
].filter(Boolean).join("\n");
|
|
51464
|
-
return {
|
|
52343
|
+
const alreadyMergedViaOtherPath = !patchEquivalence.actualPatchId && !!patchEquivalence.expectedPatchId;
|
|
52344
|
+
if (!didAutoRebase && !alreadyMergedViaOtherPath) {
|
|
52345
|
+
return { kind: "terminal", result: {
|
|
51465
52346
|
success: false,
|
|
51466
|
-
code: "
|
|
52347
|
+
code: "patch_equivalence_failed",
|
|
51467
52348
|
convergenceStatus: "blocked_review",
|
|
51468
|
-
error:
|
|
52349
|
+
error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
|
|
51469
52350
|
branch,
|
|
51470
52351
|
into: baseBranch,
|
|
51471
52352
|
validationSummary,
|
|
51472
52353
|
patchEquivalence,
|
|
51473
|
-
effectiveDiff,
|
|
51474
52354
|
refineStages,
|
|
51475
52355
|
finalBranchConvergenceState: {
|
|
51476
52356
|
branch,
|
|
@@ -51478,190 +52358,378 @@ ${hintLines.join("\n")}` : "",
|
|
|
51478
52358
|
merged: false,
|
|
51479
52359
|
removed: false,
|
|
51480
52360
|
validation: "passed",
|
|
51481
|
-
patchEquivalence: "
|
|
51482
|
-
|
|
51483
|
-
status: "blocked_review",
|
|
51484
|
-
reason: "no_effective_diff",
|
|
51485
|
-
...effectiveDiff.submoduleHints?.length ? { submoduleHints: effectiveDiff.submoduleHints } : {}
|
|
52361
|
+
patchEquivalence: "failed",
|
|
52362
|
+
status: "blocked_review"
|
|
51486
52363
|
}
|
|
51487
|
-
};
|
|
52364
|
+
} };
|
|
51488
52365
|
}
|
|
51489
|
-
|
|
51490
|
-
|
|
51491
|
-
|
|
51492
|
-
|
|
51493
|
-
mergeResult = {
|
|
51494
|
-
stdout: truncateValidationOutput(result.stdout),
|
|
51495
|
-
stderr: truncateValidationOutput(result.stderr),
|
|
51496
|
-
durationMs: Date.now() - mergeStarted
|
|
51497
|
-
};
|
|
51498
|
-
recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
|
|
51499
|
-
} catch (e) {
|
|
51500
|
-
recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
|
|
51501
|
-
error: e?.message || String(e),
|
|
51502
|
-
stdout: truncateValidationOutput(e?.stdout),
|
|
51503
|
-
stderr: truncateValidationOutput(e?.stderr)
|
|
52366
|
+
if (!didAutoRebase && alreadyMergedViaOtherPath) {
|
|
52367
|
+
recordMeshRefineStage(refineStages, "merge", "skipped", Date.now(), {
|
|
52368
|
+
reason: "already_merged_via_other_path",
|
|
52369
|
+
note: "actualPatchId is empty; branch content is already present in base via a different commit path"
|
|
51504
52370
|
});
|
|
51505
|
-
|
|
51506
|
-
|
|
51507
|
-
|
|
51508
|
-
|
|
51509
|
-
|
|
51510
|
-
|
|
51511
|
-
finalBranchConvergenceState: {
|
|
51512
|
-
branch,
|
|
51513
|
-
baseBranch,
|
|
51514
|
-
merged: false,
|
|
51515
|
-
removed: false,
|
|
51516
|
-
validation: "passed",
|
|
51517
|
-
patchEquivalence: "passed",
|
|
51518
|
-
status: "not_mergeable"
|
|
51519
|
-
}
|
|
51520
|
-
};
|
|
51521
|
-
}
|
|
51522
|
-
const submoduleAlignmentStarted = Date.now();
|
|
51523
|
-
const submoduleAlignment = await alignRefinerySubmodulesAfterMerge(repoRoot, baseHead, "HEAD", {
|
|
51524
|
-
submoduleIgnorePaths: Array.isArray(sourceNode?.policy?.submoduleIgnorePaths) ? sourceNode.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0
|
|
51525
|
-
});
|
|
51526
|
-
if (submoduleAlignment.status !== "skipped") {
|
|
51527
|
-
recordMeshRefineStage(refineStages, "submodule_alignment", submoduleAlignment.status, submoduleAlignmentStarted, {
|
|
51528
|
-
changedGitlinkPaths: submoduleAlignment.changedGitlinkPaths,
|
|
51529
|
-
outOfSyncPaths: submoduleAlignment.outOfSyncPaths,
|
|
51530
|
-
updatedPaths: submoduleAlignment.updatedPaths,
|
|
51531
|
-
verifiedPaths: submoduleAlignment.verifiedPaths,
|
|
51532
|
-
command: submoduleAlignment.command,
|
|
51533
|
-
error: submoduleAlignment.error
|
|
52371
|
+
const cleanupStarted = Date.now();
|
|
52372
|
+
const removeResult = await this.execute("remove_mesh_node", {
|
|
52373
|
+
meshId,
|
|
52374
|
+
nodeId,
|
|
52375
|
+
sessionCleanupMode: "preserve",
|
|
52376
|
+
inlineMesh: args?.inlineMesh
|
|
51534
52377
|
});
|
|
51535
|
-
|
|
51536
|
-
|
|
51537
|
-
|
|
51538
|
-
|
|
51539
|
-
|
|
51540
|
-
|
|
51541
|
-
|
|
52378
|
+
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
52379
|
+
removed: removeResult?.removed,
|
|
52380
|
+
code: removeResult?.code,
|
|
52381
|
+
error: removeResult?.error
|
|
52382
|
+
});
|
|
52383
|
+
try {
|
|
52384
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
52385
|
+
appendLedgerEntry2(meshId, {
|
|
52386
|
+
kind: "node_removed",
|
|
52387
|
+
nodeId,
|
|
52388
|
+
payload: { alreadyMergedViaOtherPath: true, branch, into: baseBranch, validationSummary, patchEquivalence }
|
|
52389
|
+
});
|
|
52390
|
+
} catch {
|
|
52391
|
+
}
|
|
52392
|
+
return { kind: "terminal", result: {
|
|
52393
|
+
success: removeResult?.success !== false,
|
|
52394
|
+
code: "already_merged",
|
|
52395
|
+
merged: false,
|
|
52396
|
+
alreadyMergedViaOtherPath: true,
|
|
51542
52397
|
branch,
|
|
51543
52398
|
into: baseBranch,
|
|
52399
|
+
removeResult,
|
|
51544
52400
|
validationSummary,
|
|
51545
52401
|
patchEquivalence,
|
|
51546
|
-
submoduleReachability,
|
|
51547
|
-
submoduleAlignment,
|
|
51548
|
-
mergeResult,
|
|
51549
52402
|
refineStages,
|
|
51550
52403
|
finalBranchConvergenceState: {
|
|
51551
52404
|
branch: baseBranch,
|
|
51552
52405
|
mergedBranch: branch,
|
|
51553
52406
|
baseBranch,
|
|
51554
|
-
merged:
|
|
51555
|
-
|
|
52407
|
+
merged: false,
|
|
52408
|
+
alreadyMergedViaOtherPath: true,
|
|
52409
|
+
removed: removeResult?.success !== false,
|
|
51556
52410
|
validation: "passed",
|
|
51557
|
-
patchEquivalence: "
|
|
51558
|
-
|
|
51559
|
-
submoduleAlignment: "failed",
|
|
51560
|
-
status: "post_merge_alignment_failed",
|
|
51561
|
-
nextStep: submoduleAlignment.command || "Run git submodule update --init --recursive for the reported path(s), then re-check base workspace status."
|
|
52411
|
+
patchEquivalence: "already_merged",
|
|
52412
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged_to_main"
|
|
51562
52413
|
}
|
|
51563
|
-
};
|
|
52414
|
+
} };
|
|
51564
52415
|
}
|
|
51565
|
-
|
|
51566
|
-
|
|
51567
|
-
|
|
51568
|
-
|
|
51569
|
-
|
|
51570
|
-
|
|
51571
|
-
|
|
51572
|
-
|
|
51573
|
-
|
|
51574
|
-
|
|
51575
|
-
|
|
51576
|
-
|
|
51577
|
-
|
|
51578
|
-
|
|
51579
|
-
|
|
51580
|
-
|
|
51581
|
-
|
|
51582
|
-
|
|
51583
|
-
|
|
52416
|
+
}
|
|
52417
|
+
ctx.branchHead = branchHead;
|
|
52418
|
+
ctx.patchEquivalence = patchEquivalence;
|
|
52419
|
+
return { kind: "continue", ctx };
|
|
52420
|
+
}
|
|
52421
|
+
/**
|
|
52422
|
+
* submodule_reachability stage: verify every submodule gitlink commit that
|
|
52423
|
+
* would land via the merge is reachable from its configured remote main
|
|
52424
|
+
* branch (optionally auto-publishing when policy allows). Blocks the merge
|
|
52425
|
+
* when any commit is unreachable. Stores the result on the context.
|
|
52426
|
+
*/
|
|
52427
|
+
async refineSubmoduleReachabilityStage(ctx) {
|
|
52428
|
+
const { mesh, node, repoRoot, branch, baseBranch, branchHead, validationSummary, patchEquivalence, refineStages } = ctx;
|
|
52429
|
+
const submoduleReachabilityStarted = Date.now();
|
|
52430
|
+
const autoPublishSubmoduleMainCommits = resolveRefineryAutoPublishSubmoduleMainCommits(mesh, node.workspace);
|
|
52431
|
+
const submoduleReachability = await runMeshRefineSubmoduleReachabilityGate(repoRoot, patchEquivalence.mergedTree || branchHead, {
|
|
52432
|
+
allowAutoPublishSubmoduleMainCommits: autoPublishSubmoduleMainCommits.enabled,
|
|
52433
|
+
autoPublishPolicySource: autoPublishSubmoduleMainCommits.source,
|
|
52434
|
+
worktreeRoot: node.workspace
|
|
52435
|
+
});
|
|
52436
|
+
recordMeshRefineStage(refineStages, "submodule_reachability", submoduleReachability.status, submoduleReachabilityStarted, {
|
|
52437
|
+
checked: submoduleReachability.checked,
|
|
52438
|
+
autoPublishAllowed: submoduleReachability.autoPublishAllowed,
|
|
52439
|
+
autoPublishPolicySource: submoduleReachability.autoPublishPolicySource,
|
|
52440
|
+
autoPublished: submoduleReachability.entries.filter((entry) => entry.autoPublishAttempted).map((entry) => ({
|
|
52441
|
+
path: entry.path,
|
|
52442
|
+
commit: entry.commit,
|
|
52443
|
+
remote: entry.remote,
|
|
52444
|
+
remoteUrl: entry.remoteUrl,
|
|
52445
|
+
remoteMainBranch: entry.remoteMainBranch,
|
|
52446
|
+
refspec: entry.autoPublishRefspec,
|
|
52447
|
+
succeeded: entry.autoPublishSucceeded,
|
|
52448
|
+
verified: entry.autoPublishVerified,
|
|
52449
|
+
remoteMainReachable: entry.remoteMainReachable,
|
|
52450
|
+
error: entry.error
|
|
52451
|
+
})),
|
|
52452
|
+
autoPublishSkipped: submoduleReachability.entries.filter((entry) => entry.autoPublishAllowed === true && entry.autoPublishAttempted !== true).map((entry) => ({
|
|
52453
|
+
path: entry.path,
|
|
52454
|
+
commit: entry.commit,
|
|
52455
|
+
remote: entry.remote,
|
|
52456
|
+
remoteUrl: entry.remoteUrl,
|
|
52457
|
+
remoteMainBranch: entry.remoteMainBranch,
|
|
52458
|
+
reason: entry.autoPublishSkippedReason || entry.error || "auto-publish was allowed but no publish attempt was possible"
|
|
52459
|
+
})),
|
|
52460
|
+
unreachable: submoduleReachability.unreachable.map((entry) => ({
|
|
52461
|
+
path: entry.path,
|
|
52462
|
+
commit: entry.commit,
|
|
52463
|
+
publishRequired: entry.publishRequired === true,
|
|
52464
|
+
autoPublishAllowed: entry.autoPublishAllowed,
|
|
52465
|
+
autoPublishAttempted: entry.autoPublishAttempted,
|
|
52466
|
+
autoPublishSucceeded: entry.autoPublishSucceeded,
|
|
52467
|
+
autoPublishVerified: entry.autoPublishVerified,
|
|
52468
|
+
autoPublishRefspec: entry.autoPublishRefspec,
|
|
52469
|
+
autoPublishSkippedReason: entry.autoPublishSkippedReason,
|
|
52470
|
+
remote: entry.remote,
|
|
52471
|
+
remoteUrl: entry.remoteUrl,
|
|
52472
|
+
remoteReachable: entry.remoteReachable,
|
|
52473
|
+
remoteMainBranch: entry.remoteMainBranch,
|
|
52474
|
+
remoteMainReachable: entry.remoteMainReachable,
|
|
52475
|
+
error: entry.error
|
|
52476
|
+
})),
|
|
52477
|
+
error: submoduleReachability.error
|
|
52478
|
+
});
|
|
52479
|
+
if (submoduleReachability.status === "failed") {
|
|
52480
|
+
const nextStep = buildSubmodulePublishRequiredNextStep(submoduleReachability.unreachable);
|
|
52481
|
+
return { kind: "terminal", result: {
|
|
52482
|
+
success: false,
|
|
52483
|
+
code: "submodule_reachability_failed",
|
|
52484
|
+
convergenceStatus: "blocked_review",
|
|
52485
|
+
publishRequired: true,
|
|
52486
|
+
blockedReason: "submodule_publish_required",
|
|
52487
|
+
error: "Refinery submodule reachability preflight failed because one or more submodule gitlink commits are not reachable from their configured remote main branch; merge/refine cleanup was not attempted.",
|
|
52488
|
+
nextStep,
|
|
52489
|
+
nextSteps: [
|
|
52490
|
+
"Ask the user for explicit approval before pushing or publishing any submodule commit.",
|
|
52491
|
+
"Push/publish each unreachable submodule commit to the configured submodule remote main branch shown in the evidence.",
|
|
52492
|
+
"Rerun mesh_refine_node after remote reachability is confirmed.",
|
|
52493
|
+
"Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main."
|
|
52494
|
+
],
|
|
52495
|
+
unreachableSubmoduleCommits: submoduleReachability.unreachable.map((entry) => ({
|
|
52496
|
+
path: entry.path,
|
|
52497
|
+
commit: entry.commit,
|
|
52498
|
+
remote: entry.remote,
|
|
52499
|
+
remoteUrl: entry.remoteUrl,
|
|
52500
|
+
remoteReachable: entry.remoteReachable,
|
|
52501
|
+
remoteMainBranch: entry.remoteMainBranch,
|
|
52502
|
+
remoteMainReachable: entry.remoteMainReachable,
|
|
52503
|
+
autoPublishAllowed: entry.autoPublishAllowed,
|
|
52504
|
+
autoPublishAttempted: entry.autoPublishAttempted,
|
|
52505
|
+
autoPublishSucceeded: entry.autoPublishSucceeded,
|
|
52506
|
+
autoPublishVerified: entry.autoPublishVerified,
|
|
52507
|
+
autoPublishRefspec: entry.autoPublishRefspec,
|
|
52508
|
+
autoPublishSkippedReason: entry.autoPublishSkippedReason,
|
|
52509
|
+
error: entry.error
|
|
52510
|
+
})),
|
|
52511
|
+
branch,
|
|
52512
|
+
into: baseBranch,
|
|
52513
|
+
validationSummary,
|
|
52514
|
+
patchEquivalence,
|
|
52515
|
+
submoduleReachability,
|
|
52516
|
+
refineStages,
|
|
52517
|
+
finalBranchConvergenceState: {
|
|
52518
|
+
branch,
|
|
52519
|
+
baseBranch,
|
|
52520
|
+
merged: false,
|
|
52521
|
+
removed: false,
|
|
52522
|
+
validation: "passed",
|
|
52523
|
+
patchEquivalence: "passed",
|
|
52524
|
+
submoduleReachability: "failed",
|
|
52525
|
+
status: "blocked_review",
|
|
52526
|
+
reason: "submodule_publish_required",
|
|
52527
|
+
nextStep
|
|
51584
52528
|
}
|
|
51585
|
-
}
|
|
51586
|
-
|
|
51587
|
-
|
|
51588
|
-
|
|
51589
|
-
|
|
51590
|
-
|
|
51591
|
-
|
|
52529
|
+
} };
|
|
52530
|
+
}
|
|
52531
|
+
ctx.submoduleReachability = submoduleReachability;
|
|
52532
|
+
return { kind: "continue", ctx };
|
|
52533
|
+
}
|
|
52534
|
+
/**
|
|
52535
|
+
* effective_diff stage (no-op guard): block a silent no-op merge where the
|
|
52536
|
+
* branch produces no effective root-tree diff against base — typically a
|
|
52537
|
+
* submodule that has commits but whose root-level gitlink (pointer) bump was
|
|
52538
|
+
* never committed, so the merge would land nothing real on main.
|
|
52539
|
+
*/
|
|
52540
|
+
async refineEffectiveDiffStage(ctx) {
|
|
52541
|
+
const { repoRoot, baseHead, branchHead, branch, baseBranch, validationSummary, patchEquivalence, refineStages } = ctx;
|
|
52542
|
+
const effectiveDiffStarted = Date.now();
|
|
52543
|
+
const effectiveDiff = await runMeshRefineEffectiveDiffGate(repoRoot, baseHead, branchHead);
|
|
52544
|
+
recordMeshRefineStage(refineStages, "effective_diff", effectiveDiff.status, effectiveDiffStarted, {
|
|
52545
|
+
hasEffectiveDiff: effectiveDiff.hasEffectiveDiff,
|
|
52546
|
+
changedPaths: effectiveDiff.changedPaths,
|
|
52547
|
+
submoduleHints: effectiveDiff.submoduleHints,
|
|
52548
|
+
...effectiveDiff.error ? { error: effectiveDiff.error } : {}
|
|
52549
|
+
});
|
|
52550
|
+
if (effectiveDiff.status === "failed" && !effectiveDiff.hasEffectiveDiff) {
|
|
52551
|
+
const hintLines = (effectiveDiff.submoduleHints || []).map((h) => ` - ${h.path}: ${h.reason}`);
|
|
52552
|
+
const message = [
|
|
52553
|
+
`Refinery no-op guard: branch '${branch}' has no effective root-tree diff against '${baseBranch}' (${baseHead.slice(0, 12)}); nothing would merge.`,
|
|
52554
|
+
"This usually means a submodule (e.g. oss) has commits but the root branch never committed the gitlink (pointer) bump, so the merge would be a silent no-op while the real change never reaches main.",
|
|
52555
|
+
hintLines.length ? `Submodules with uncommitted pointer bumps:
|
|
52556
|
+
${hintLines.join("\n")}` : "",
|
|
52557
|
+
`Fix: commit the submodule pointer bump on '${branch}' (git add <submodule-path> && git commit), then re-run refine.`
|
|
52558
|
+
].filter(Boolean).join("\n");
|
|
52559
|
+
return { kind: "terminal", result: {
|
|
52560
|
+
success: false,
|
|
52561
|
+
code: "no_effective_diff",
|
|
52562
|
+
convergenceStatus: "blocked_review",
|
|
52563
|
+
error: message,
|
|
52564
|
+
branch,
|
|
52565
|
+
into: baseBranch,
|
|
52566
|
+
validationSummary,
|
|
52567
|
+
patchEquivalence,
|
|
52568
|
+
effectiveDiff,
|
|
52569
|
+
refineStages,
|
|
52570
|
+
finalBranchConvergenceState: {
|
|
52571
|
+
branch,
|
|
52572
|
+
baseBranch,
|
|
52573
|
+
merged: false,
|
|
52574
|
+
removed: false,
|
|
52575
|
+
validation: "passed",
|
|
52576
|
+
patchEquivalence: "passed",
|
|
52577
|
+
effectiveDiff: "no_effective_diff",
|
|
52578
|
+
status: "blocked_review",
|
|
52579
|
+
reason: "no_effective_diff",
|
|
52580
|
+
...effectiveDiff.submoduleHints?.length ? { submoduleHints: effectiveDiff.submoduleHints } : {}
|
|
52581
|
+
}
|
|
52582
|
+
} };
|
|
52583
|
+
}
|
|
52584
|
+
return { kind: "continue", ctx };
|
|
52585
|
+
}
|
|
52586
|
+
/**
|
|
52587
|
+
* merge + finalize stage: perform the --no-ff merge, align submodule
|
|
52588
|
+
* checkouts after merge, clean up (remove) the worktree node per policy,
|
|
52589
|
+
* append the refinery ledger entry, and (unless approval is required) push the
|
|
52590
|
+
* base branch. Always terminal — produces the final CommandRouterResult.
|
|
52591
|
+
*/
|
|
52592
|
+
async refineMergeAndFinalizeStage(ctx) {
|
|
52593
|
+
const { meshId, nodeId, args, repoRoot, baseHead, node, branch, baseBranch, sourceNode, validationSummary, patchEquivalence, submoduleReachability, mesh, refineStages, execFileAsync: execFileAsync4 } = ctx;
|
|
52594
|
+
let mergeResult;
|
|
52595
|
+
const mergeStarted = Date.now();
|
|
52596
|
+
try {
|
|
52597
|
+
const result = await execFileAsync4("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
52598
|
+
mergeResult = {
|
|
52599
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
52600
|
+
stderr: truncateValidationOutput(result.stderr),
|
|
52601
|
+
durationMs: Date.now() - mergeStarted
|
|
52602
|
+
};
|
|
52603
|
+
recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
|
|
52604
|
+
} catch (e) {
|
|
52605
|
+
recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
|
|
52606
|
+
error: e?.message || String(e),
|
|
52607
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
52608
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
51592
52609
|
});
|
|
51593
|
-
|
|
51594
|
-
|
|
51595
|
-
|
|
51596
|
-
|
|
52610
|
+
return { kind: "terminal", result: {
|
|
52611
|
+
success: false,
|
|
52612
|
+
error: `Merge failed (conflicts?): ${e.message}`,
|
|
52613
|
+
validationSummary,
|
|
52614
|
+
patchEquivalence,
|
|
52615
|
+
refineStages,
|
|
52616
|
+
finalBranchConvergenceState: {
|
|
52617
|
+
branch,
|
|
52618
|
+
baseBranch,
|
|
52619
|
+
merged: false,
|
|
52620
|
+
removed: false,
|
|
52621
|
+
validation: "passed",
|
|
52622
|
+
patchEquivalence: "passed",
|
|
52623
|
+
status: "not_mergeable"
|
|
52624
|
+
}
|
|
52625
|
+
} };
|
|
52626
|
+
}
|
|
52627
|
+
const submoduleAlignmentStarted = Date.now();
|
|
52628
|
+
const submoduleAlignment = await alignRefinerySubmodulesAfterMerge(repoRoot, baseHead, "HEAD", {
|
|
52629
|
+
submoduleIgnorePaths: Array.isArray(sourceNode?.policy?.submoduleIgnorePaths) ? sourceNode.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0
|
|
52630
|
+
});
|
|
52631
|
+
if (submoduleAlignment.status !== "skipped") {
|
|
52632
|
+
recordMeshRefineStage(refineStages, "submodule_alignment", submoduleAlignment.status, submoduleAlignmentStarted, {
|
|
52633
|
+
changedGitlinkPaths: submoduleAlignment.changedGitlinkPaths,
|
|
52634
|
+
outOfSyncPaths: submoduleAlignment.outOfSyncPaths,
|
|
52635
|
+
updatedPaths: submoduleAlignment.updatedPaths,
|
|
52636
|
+
verifiedPaths: submoduleAlignment.verifiedPaths,
|
|
52637
|
+
command: submoduleAlignment.command,
|
|
52638
|
+
error: submoduleAlignment.error
|
|
51597
52639
|
});
|
|
51598
|
-
|
|
51599
|
-
|
|
51600
|
-
|
|
51601
|
-
|
|
51602
|
-
|
|
51603
|
-
|
|
51604
|
-
nodeId,
|
|
51605
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence, submoduleReachability, submoduleAlignment }
|
|
51606
|
-
});
|
|
51607
|
-
recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
|
|
51608
|
-
} catch (e) {
|
|
51609
|
-
ledgerError = e?.message || String(e);
|
|
51610
|
-
recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
|
|
51611
|
-
}
|
|
51612
|
-
const finalBranchConvergenceState = {
|
|
51613
|
-
branch: baseBranch,
|
|
51614
|
-
mergedBranch: branch,
|
|
51615
|
-
baseBranch,
|
|
52640
|
+
}
|
|
52641
|
+
if (submoduleAlignment.status === "failed") {
|
|
52642
|
+
return { kind: "terminal", result: {
|
|
52643
|
+
success: false,
|
|
52644
|
+
code: "post_merge_submodule_alignment_failed",
|
|
52645
|
+
error: "Refinery merge completed but post-merge submodule checkout alignment failed; run the reported git submodule update command and re-check base workspace status.",
|
|
51616
52646
|
merged: true,
|
|
51617
|
-
|
|
51618
|
-
|
|
51619
|
-
|
|
51620
|
-
|
|
51621
|
-
|
|
51622
|
-
|
|
51623
|
-
|
|
51624
|
-
|
|
51625
|
-
|
|
51626
|
-
|
|
51627
|
-
|
|
52647
|
+
branch,
|
|
52648
|
+
into: baseBranch,
|
|
52649
|
+
validationSummary,
|
|
52650
|
+
patchEquivalence,
|
|
52651
|
+
submoduleReachability,
|
|
52652
|
+
submoduleAlignment,
|
|
52653
|
+
mergeResult,
|
|
52654
|
+
refineStages,
|
|
52655
|
+
finalBranchConvergenceState: {
|
|
52656
|
+
branch: baseBranch,
|
|
52657
|
+
mergedBranch: branch,
|
|
52658
|
+
baseBranch,
|
|
51628
52659
|
merged: true,
|
|
51629
|
-
|
|
51630
|
-
|
|
51631
|
-
|
|
51632
|
-
|
|
51633
|
-
|
|
51634
|
-
|
|
51635
|
-
submoduleAlignment,
|
|
51636
|
-
|
|
51637
|
-
|
|
51638
|
-
|
|
51639
|
-
|
|
51640
|
-
|
|
51641
|
-
|
|
51642
|
-
|
|
51643
|
-
|
|
51644
|
-
|
|
51645
|
-
|
|
51646
|
-
|
|
51647
|
-
|
|
51648
|
-
|
|
51649
|
-
|
|
51650
|
-
|
|
51651
|
-
|
|
51652
|
-
|
|
51653
|
-
|
|
51654
|
-
|
|
51655
|
-
|
|
51656
|
-
|
|
51657
|
-
|
|
51658
|
-
durationMs: Date.now() - pushStarted
|
|
51659
|
-
};
|
|
51660
|
-
recordMeshRefineStage(refineStages, "push", "failed", pushStarted, pushResult);
|
|
51661
|
-
}
|
|
52660
|
+
removed: false,
|
|
52661
|
+
validation: "passed",
|
|
52662
|
+
patchEquivalence: "passed",
|
|
52663
|
+
submoduleReachability: "passed",
|
|
52664
|
+
submoduleAlignment: "failed",
|
|
52665
|
+
status: "post_merge_alignment_failed",
|
|
52666
|
+
nextStep: submoduleAlignment.command || "Run git submodule update --init --recursive for the reported path(s), then re-check base workspace status."
|
|
52667
|
+
}
|
|
52668
|
+
} };
|
|
52669
|
+
}
|
|
52670
|
+
const cleanupStarted = Date.now();
|
|
52671
|
+
const refineSessionCleanupMode = this.normalizeMeshSessionCleanupMode(
|
|
52672
|
+
mesh?.policy?.sessionCleanupOnNodeRemove
|
|
52673
|
+
);
|
|
52674
|
+
let refineSessionIds;
|
|
52675
|
+
if (refineSessionCleanupMode !== "preserve" && this.deps.sessionHostControl) {
|
|
52676
|
+
try {
|
|
52677
|
+
const liveSessions = await this.deps.sessionHostControl.listSessions();
|
|
52678
|
+
const workspace = typeof node.workspace === "string" ? node.workspace : "";
|
|
52679
|
+
refineSessionIds = liveSessions.filter((record) => {
|
|
52680
|
+
const sid = typeof record?.sessionId === "string" ? record.sessionId : "";
|
|
52681
|
+
if (!sid) return false;
|
|
52682
|
+
if (readStringValue(record?.meta?.meshCoordinatorFor) === meshId) return false;
|
|
52683
|
+
const boundToNode = readStringValue(record?.meta?.meshNodeId) === nodeId;
|
|
52684
|
+
const matchedByWorkspace = !!workspace && record?.workspace === workspace;
|
|
52685
|
+
return boundToNode || matchedByWorkspace;
|
|
52686
|
+
}).map((record) => String(record.sessionId));
|
|
52687
|
+
} catch {
|
|
52688
|
+
refineSessionIds = void 0;
|
|
51662
52689
|
}
|
|
51663
|
-
|
|
51664
|
-
|
|
52690
|
+
}
|
|
52691
|
+
const removeResult = await this.execute("remove_mesh_node", {
|
|
52692
|
+
meshId,
|
|
52693
|
+
nodeId,
|
|
52694
|
+
sessionCleanupMode: refineSessionCleanupMode,
|
|
52695
|
+
...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
|
|
52696
|
+
inlineMesh: args?.inlineMesh
|
|
52697
|
+
});
|
|
52698
|
+
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
52699
|
+
removed: removeResult?.removed,
|
|
52700
|
+
code: removeResult?.code,
|
|
52701
|
+
error: removeResult?.error
|
|
52702
|
+
});
|
|
52703
|
+
let ledgerError;
|
|
52704
|
+
const ledgerStarted = Date.now();
|
|
52705
|
+
try {
|
|
52706
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
52707
|
+
appendLedgerEntry2(meshId, {
|
|
52708
|
+
kind: "node_removed",
|
|
52709
|
+
nodeId,
|
|
52710
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence, submoduleReachability, submoduleAlignment }
|
|
52711
|
+
});
|
|
52712
|
+
recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
|
|
52713
|
+
} catch (e) {
|
|
52714
|
+
ledgerError = e?.message || String(e);
|
|
52715
|
+
recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
|
|
52716
|
+
}
|
|
52717
|
+
const finalBranchConvergenceState = {
|
|
52718
|
+
branch: baseBranch,
|
|
52719
|
+
mergedBranch: branch,
|
|
52720
|
+
baseBranch,
|
|
52721
|
+
merged: true,
|
|
52722
|
+
removed: removeResult?.success !== false,
|
|
52723
|
+
validation: "passed",
|
|
52724
|
+
patchEquivalence: "passed",
|
|
52725
|
+
submoduleAlignment: submoduleAlignment.status,
|
|
52726
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
52727
|
+
};
|
|
52728
|
+
if (removeResult?.success === false) {
|
|
52729
|
+
return { kind: "terminal", result: {
|
|
52730
|
+
success: false,
|
|
52731
|
+
code: "cleanup_failed",
|
|
52732
|
+
error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
|
|
51665
52733
|
merged: true,
|
|
51666
52734
|
branch,
|
|
51667
52735
|
into: baseBranch,
|
|
@@ -51673,17 +52741,51 @@ ${hintLines.join("\n")}` : "",
|
|
|
51673
52741
|
mergeResult,
|
|
51674
52742
|
refineStages,
|
|
51675
52743
|
...ledgerError ? { ledgerError } : {},
|
|
51676
|
-
finalBranchConvergenceState
|
|
51677
|
-
|
|
51678
|
-
...pushResult ? { pushResult } : {
|
|
51679
|
-
pushReady: true,
|
|
51680
|
-
pushCommand: `git push origin ${baseBranch}`,
|
|
51681
|
-
pushNote: "requireApprovalForPush is enabled \u2014 run the push command or obtain user approval before pushing."
|
|
51682
|
-
}
|
|
51683
|
-
};
|
|
51684
|
-
} catch (e) {
|
|
51685
|
-
return { success: false, error: e.message, refineStages };
|
|
52744
|
+
finalBranchConvergenceState
|
|
52745
|
+
} };
|
|
51686
52746
|
}
|
|
52747
|
+
const requireApprovalForPush = mesh?.policy?.requireApprovalForPush ?? DEFAULT_MESH_POLICY.requireApprovalForPush;
|
|
52748
|
+
let pushResult;
|
|
52749
|
+
if (!requireApprovalForPush) {
|
|
52750
|
+
const pushStarted = Date.now();
|
|
52751
|
+
try {
|
|
52752
|
+
await execFileAsync4("git", ["push", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
|
|
52753
|
+
pushResult = { pushed: true, remote: "origin", branch: baseBranch, durationMs: Date.now() - pushStarted };
|
|
52754
|
+
recordMeshRefineStage(refineStages, "push", "passed", pushStarted, pushResult);
|
|
52755
|
+
finalBranchConvergenceState.status = "merged_pushed";
|
|
52756
|
+
} catch (e) {
|
|
52757
|
+
pushResult = {
|
|
52758
|
+
pushed: false,
|
|
52759
|
+
remote: "origin",
|
|
52760
|
+
branch: baseBranch,
|
|
52761
|
+
error: e?.message || String(e),
|
|
52762
|
+
stderr: e?.stderr,
|
|
52763
|
+
durationMs: Date.now() - pushStarted
|
|
52764
|
+
};
|
|
52765
|
+
recordMeshRefineStage(refineStages, "push", "failed", pushStarted, pushResult);
|
|
52766
|
+
}
|
|
52767
|
+
}
|
|
52768
|
+
return { kind: "terminal", result: {
|
|
52769
|
+
success: true,
|
|
52770
|
+
merged: true,
|
|
52771
|
+
branch,
|
|
52772
|
+
into: baseBranch,
|
|
52773
|
+
removeResult,
|
|
52774
|
+
validationSummary,
|
|
52775
|
+
patchEquivalence,
|
|
52776
|
+
submoduleReachability,
|
|
52777
|
+
submoduleAlignment,
|
|
52778
|
+
mergeResult,
|
|
52779
|
+
refineStages,
|
|
52780
|
+
...ledgerError ? { ledgerError } : {},
|
|
52781
|
+
finalBranchConvergenceState,
|
|
52782
|
+
// Push outcome or readiness info for coordinator.
|
|
52783
|
+
...pushResult ? { pushResult } : {
|
|
52784
|
+
pushReady: true,
|
|
52785
|
+
pushCommand: `git push origin ${baseBranch}`,
|
|
52786
|
+
pushNote: "requireApprovalForPush is enabled \u2014 run the push command or obtain user approval before pushing."
|
|
52787
|
+
}
|
|
52788
|
+
} };
|
|
51687
52789
|
}
|
|
51688
52790
|
/**
|
|
51689
52791
|
* Batch refinery: converge multiple sibling worktree nodes onto the base branch
|
|
@@ -52241,929 +53343,9 @@ ${hintLines.join("\n")}` : "",
|
|
|
52241
53343
|
if (medFamilyHandler) {
|
|
52242
53344
|
return await medFamilyHandler(this.buildMedFamilyContext(), args);
|
|
52243
53345
|
}
|
|
52244
|
-
|
|
52245
|
-
|
|
52246
|
-
|
|
52247
|
-
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
52248
|
-
}
|
|
52249
|
-
case "get_pending_mesh_events": {
|
|
52250
|
-
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
52251
|
-
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
52252
|
-
const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
|
|
52253
|
-
return { success: true, events };
|
|
52254
|
-
}
|
|
52255
|
-
case "interactive_prompt_response": {
|
|
52256
|
-
const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
|
|
52257
|
-
if (!sessionId) return { success: false, error: "targetSessionId required" };
|
|
52258
|
-
const response = normalizeInteractivePromptResponse(args?.response ?? args);
|
|
52259
|
-
const instance = this.deps.instanceManager.getInstance(sessionId);
|
|
52260
|
-
if (!instance) return { success: false, error: `No running instance for session ${sessionId}` };
|
|
52261
|
-
this.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
|
|
52262
|
-
return { success: true };
|
|
52263
|
-
}
|
|
52264
|
-
// ─── Mesh Coordinator Launch ───
|
|
52265
|
-
case "launch_mesh_coordinator": {
|
|
52266
|
-
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
52267
|
-
let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
|
|
52268
|
-
const extraSystemPrompt = typeof args?.extraSystemPrompt === "string" ? args.extraSystemPrompt.trim() : "";
|
|
52269
|
-
if (!meshId) return { success: false, error: "meshId required" };
|
|
52270
|
-
try {
|
|
52271
|
-
const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
52272
|
-
const { buildMissionPromptSection: buildMissionPromptSection2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
|
|
52273
|
-
const buildMissionSectionBestEffort = (id) => {
|
|
52274
|
-
try {
|
|
52275
|
-
return buildMissionPromptSection2(id);
|
|
52276
|
-
} catch {
|
|
52277
|
-
return "";
|
|
52278
|
-
}
|
|
52279
|
-
};
|
|
52280
|
-
let mesh;
|
|
52281
|
-
if (args?.inlineMesh && typeof args.inlineMesh === "object") {
|
|
52282
|
-
mesh = args.inlineMesh;
|
|
52283
|
-
this.inlineMeshCache.set(meshId, mesh);
|
|
52284
|
-
} else {
|
|
52285
|
-
const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
52286
|
-
mesh = getMesh2(meshId);
|
|
52287
|
-
}
|
|
52288
|
-
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
52289
|
-
const meshHost = resolveMeshHostStatus(mesh);
|
|
52290
|
-
if (!meshHost.canOwnCoordinator) {
|
|
52291
|
-
return {
|
|
52292
|
-
success: false,
|
|
52293
|
-
...buildMeshHostRequiredFailure(mesh, "coordinator launch"),
|
|
52294
|
-
meshId,
|
|
52295
|
-
cliType
|
|
52296
|
-
};
|
|
52297
|
-
}
|
|
52298
|
-
if (!Array.isArray(mesh.nodes) || mesh.nodes.length === 0) return { success: false, error: "No nodes in mesh" };
|
|
52299
|
-
const requestedCoordinatorNodeId = typeof args?.coordinatorNodeId === "string" ? args.coordinatorNodeId.trim() : "";
|
|
52300
|
-
const preferredCoordinatorNodeId = requestedCoordinatorNodeId || (typeof mesh.coordinator?.preferredNodeId === "string" ? mesh.coordinator.preferredNodeId.trim() : "");
|
|
52301
|
-
const coordinatorNode = preferredCoordinatorNodeId ? mesh.nodes.find((node) => node?.id === preferredCoordinatorNodeId || node?.nodeId === preferredCoordinatorNodeId) : mesh.nodes[0];
|
|
52302
|
-
if (!coordinatorNode) {
|
|
52303
|
-
return {
|
|
52304
|
-
success: false,
|
|
52305
|
-
code: "mesh_coordinator_node_not_found",
|
|
52306
|
-
error: `Coordinator node ${preferredCoordinatorNodeId} was not found in mesh`,
|
|
52307
|
-
meshId,
|
|
52308
|
-
cliType
|
|
52309
|
-
};
|
|
52310
|
-
}
|
|
52311
|
-
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
52312
|
-
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
52313
|
-
const workspace = readLiveMeshNodeWorkspace({
|
|
52314
|
-
meshId,
|
|
52315
|
-
nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || ""),
|
|
52316
|
-
liveSessionRecords: liveMeshSessions,
|
|
52317
|
-
allowCoordinatorSession: true
|
|
52318
|
-
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
52319
|
-
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
52320
|
-
if (!cliType) {
|
|
52321
|
-
const resolved = await resolveProviderTypeFromPriority({
|
|
52322
|
-
nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || "coordinator"),
|
|
52323
|
-
providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
|
|
52324
|
-
providerLoader: this.deps.providerLoader,
|
|
52325
|
-
onStatusChange: this.deps.onStatusChange
|
|
52326
|
-
});
|
|
52327
|
-
if (!resolved.providerType) {
|
|
52328
|
-
return {
|
|
52329
|
-
success: false,
|
|
52330
|
-
code: "mesh_coordinator_provider_priority_unusable",
|
|
52331
|
-
error: resolved.error || "No usable provider found from node providerPriority",
|
|
52332
|
-
meshId,
|
|
52333
|
-
cliType,
|
|
52334
|
-
workspace
|
|
52335
|
-
};
|
|
52336
|
-
}
|
|
52337
|
-
cliType = resolved.providerType;
|
|
52338
|
-
}
|
|
52339
|
-
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
52340
|
-
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
52341
|
-
provider: providerMeta,
|
|
52342
|
-
cliType,
|
|
52343
|
-
meshId,
|
|
52344
|
-
workspace
|
|
52345
|
-
});
|
|
52346
|
-
if (coordinatorSetup.kind === "unsupported") {
|
|
52347
|
-
return {
|
|
52348
|
-
success: false,
|
|
52349
|
-
code: "mesh_coordinator_unsupported",
|
|
52350
|
-
error: coordinatorSetup.reason,
|
|
52351
|
-
meshId,
|
|
52352
|
-
cliType,
|
|
52353
|
-
workspace
|
|
52354
|
-
};
|
|
52355
|
-
}
|
|
52356
|
-
if (coordinatorSetup.kind === "manual") {
|
|
52357
|
-
return {
|
|
52358
|
-
success: false,
|
|
52359
|
-
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
52360
|
-
error: coordinatorSetup.instructions,
|
|
52361
|
-
meshId,
|
|
52362
|
-
cliType,
|
|
52363
|
-
workspace,
|
|
52364
|
-
meshCoordinatorSetup: coordinatorSetup
|
|
52365
|
-
};
|
|
52366
|
-
}
|
|
52367
|
-
if (coordinatorSetup.kind === "cli_command") {
|
|
52368
|
-
let cliCmdSystemPrompt = "";
|
|
52369
|
-
try {
|
|
52370
|
-
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
52371
|
-
} catch (error) {
|
|
52372
|
-
const message = error?.message || String(error);
|
|
52373
|
-
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
52374
|
-
return {
|
|
52375
|
-
success: false,
|
|
52376
|
-
code: "mesh_coordinator_prompt_failed",
|
|
52377
|
-
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
52378
|
-
meshId,
|
|
52379
|
-
cliType,
|
|
52380
|
-
workspace
|
|
52381
|
-
};
|
|
52382
|
-
}
|
|
52383
|
-
let mcpRegistrationOk = false;
|
|
52384
|
-
let mcpRegistrationFailure = null;
|
|
52385
|
-
try {
|
|
52386
|
-
const { buildMeshCoordinatorRegistrationPlan: buildMeshCoordinatorRegistrationPlan2, execUnderPty: execUnderPty2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
52387
|
-
const registrationPlan = buildMeshCoordinatorRegistrationPlan2(
|
|
52388
|
-
cliType,
|
|
52389
|
-
coordinatorSetup.serverName,
|
|
52390
|
-
coordinatorSetup.command
|
|
52391
|
-
);
|
|
52392
|
-
for (const step of registrationPlan) {
|
|
52393
|
-
const renderedCommand = [step.command, ...step.args].join(" ");
|
|
52394
|
-
LOG.info("MeshCoordinator", `Running MCP ${step.label} (pty): ${renderedCommand}`);
|
|
52395
|
-
const ptyResult = await execUnderPty2(step.command, step.args, { cwd: workspace, timeoutMs: 2e4 });
|
|
52396
|
-
if (ptyResult.exitCode === 0 && !ptyResult.timedOut) {
|
|
52397
|
-
if (step.required) mcpRegistrationOk = true;
|
|
52398
|
-
continue;
|
|
52399
|
-
}
|
|
52400
|
-
LOG.warn("MeshCoordinator", `MCP ${step.label} failed exit=${ptyResult.exitCode} signal=${ptyResult.signal} timedOut=${ptyResult.timedOut} \u2014 output:
|
|
52401
|
-
${ptyResult.output.slice(-2e3)}`);
|
|
52402
|
-
if (step.required) {
|
|
52403
|
-
mcpRegistrationFailure = {
|
|
52404
|
-
command: renderedCommand,
|
|
52405
|
-
output: ptyResult.output.slice(-2e3),
|
|
52406
|
-
exitCode: ptyResult.exitCode,
|
|
52407
|
-
signal: ptyResult.signal,
|
|
52408
|
-
timedOut: ptyResult.timedOut
|
|
52409
|
-
};
|
|
52410
|
-
break;
|
|
52411
|
-
}
|
|
52412
|
-
}
|
|
52413
|
-
} catch (error) {
|
|
52414
|
-
LOG.warn("MeshCoordinator", `MCP registration command failed: ${error?.message || error}`);
|
|
52415
|
-
mcpRegistrationFailure = {
|
|
52416
|
-
command: coordinatorSetup.command,
|
|
52417
|
-
output: error?.message || String(error),
|
|
52418
|
-
exitCode: null,
|
|
52419
|
-
signal: null,
|
|
52420
|
-
timedOut: false
|
|
52421
|
-
};
|
|
52422
|
-
}
|
|
52423
|
-
if (!mcpRegistrationOk) {
|
|
52424
|
-
return {
|
|
52425
|
-
success: false,
|
|
52426
|
-
code: "mesh_coordinator_mcp_registration_failed",
|
|
52427
|
-
error: `Could not register ${coordinatorSetup.serverName}; coordinator session was not launched`,
|
|
52428
|
-
meshId,
|
|
52429
|
-
cliType,
|
|
52430
|
-
workspace,
|
|
52431
|
-
registration: mcpRegistrationFailure
|
|
52432
|
-
};
|
|
52433
|
-
}
|
|
52434
|
-
if (cliType === "codex-cli") {
|
|
52435
|
-
const repoMcpConfigPath = (0, import_path12.join)(workspace, ".mcp.json");
|
|
52436
|
-
if (fs27.existsSync(repoMcpConfigPath)) {
|
|
52437
|
-
try {
|
|
52438
|
-
const repoMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
52439
|
-
fs27.readFileSync(repoMcpConfigPath, "utf-8"),
|
|
52440
|
-
"claude_mcp_json"
|
|
52441
|
-
);
|
|
52442
|
-
const existingServers2 = repoMcpConfig.mcpServers;
|
|
52443
|
-
if (existingServers2 && typeof existingServers2 === "object" && !Array.isArray(existingServers2) && existingServers2[coordinatorSetup.serverName]) {
|
|
52444
|
-
fs27.writeFileSync(repoMcpConfigPath, serializeMeshCoordinatorMcpConfig({
|
|
52445
|
-
...repoMcpConfig,
|
|
52446
|
-
mcpServers: {
|
|
52447
|
-
...existingServers2,
|
|
52448
|
-
[coordinatorSetup.serverName]: coordinatorSetup.mcpServer
|
|
52449
|
-
}
|
|
52450
|
-
}, "claude_mcp_json"), "utf-8");
|
|
52451
|
-
LOG.info("MeshCoordinator", `Refreshed repo-local ${repoMcpConfigPath} entry for ${coordinatorSetup.serverName}`);
|
|
52452
|
-
}
|
|
52453
|
-
} catch (error) {
|
|
52454
|
-
return {
|
|
52455
|
-
success: false,
|
|
52456
|
-
code: "mesh_coordinator_config_write_failed",
|
|
52457
|
-
error: `Could not refresh repo-local MCP config: ${error?.message || error}`,
|
|
52458
|
-
meshId,
|
|
52459
|
-
cliType,
|
|
52460
|
-
workspace
|
|
52461
|
-
};
|
|
52462
|
-
}
|
|
52463
|
-
}
|
|
52464
|
-
}
|
|
52465
|
-
const cliCmdArgs = [];
|
|
52466
|
-
const cliCmdEnv = {};
|
|
52467
|
-
let cliCmdContextFilePath;
|
|
52468
|
-
if (cliCmdSystemPrompt) {
|
|
52469
|
-
const { applyMeshCoordinatorSystemPromptInjection: applyMeshCoordinatorSystemPromptInjection2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
52470
|
-
const effect = applyMeshCoordinatorSystemPromptInjection2(
|
|
52471
|
-
cliCmdSystemPrompt,
|
|
52472
|
-
providerMeta?.meshCoordinator?.systemPromptInjection,
|
|
52473
|
-
{ cliArgs: cliCmdArgs, launchEnv: cliCmdEnv, workspace, cliType }
|
|
52474
|
-
);
|
|
52475
|
-
cliCmdContextFilePath = effect.contextFilePath;
|
|
52476
|
-
}
|
|
52477
|
-
const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
52478
|
-
cliType,
|
|
52479
|
-
dir: workspace,
|
|
52480
|
-
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
52481
|
-
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
52482
|
-
settings: { meshCoordinatorFor: meshId }
|
|
52483
|
-
});
|
|
52484
|
-
if (cliCmdLaunch?.success && cliCmdContextFilePath) {
|
|
52485
|
-
const stripPath = cliCmdContextFilePath;
|
|
52486
|
-
setTimeout(() => {
|
|
52487
|
-
void Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports)).then(({ stripCoordinatorWrapperFile: stripCoordinatorWrapperFile2 }) => {
|
|
52488
|
-
stripCoordinatorWrapperFile2(stripPath);
|
|
52489
|
-
LOG.info("MeshCoordinator", `Stripped wrapper from ${stripPath} after launch settle (cli_command)`);
|
|
52490
|
-
}).catch(() => {
|
|
52491
|
-
});
|
|
52492
|
-
}, 5e3);
|
|
52493
|
-
}
|
|
52494
|
-
if (!cliCmdLaunch?.success) {
|
|
52495
|
-
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
52496
|
-
}
|
|
52497
|
-
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
52498
|
-
const cliCmdSessionId = cliCmdLaunch.sessionId || cliCmdLaunch.id;
|
|
52499
|
-
if (cliCmdSessionId) {
|
|
52500
|
-
const cliCmdInjectionDecl = providerMeta?.meshCoordinator?.systemPromptInjection;
|
|
52501
|
-
registerMeshCoordinator({
|
|
52502
|
-
meshId,
|
|
52503
|
-
sessionId: cliCmdSessionId,
|
|
52504
|
-
workspace,
|
|
52505
|
-
startedAt: Date.now(),
|
|
52506
|
-
cliType,
|
|
52507
|
-
systemPrompt: cliCmdSystemPrompt || void 0,
|
|
52508
|
-
extraSystemPrompt: extraSystemPrompt || void 0,
|
|
52509
|
-
injection: cliCmdInjectionDecl ? {
|
|
52510
|
-
mode: cliCmdInjectionDecl.mode,
|
|
52511
|
-
target: "flag" in cliCmdInjectionDecl ? cliCmdInjectionDecl.flag : "name" in cliCmdInjectionDecl ? cliCmdInjectionDecl.name : "path" in cliCmdInjectionDecl ? cliCmdInjectionDecl.path : void 0
|
|
52512
|
-
} : void 0
|
|
52513
|
-
});
|
|
52514
|
-
}
|
|
52515
|
-
try {
|
|
52516
|
-
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
52517
|
-
appendLedgerEntry2(meshId, {
|
|
52518
|
-
kind: "coordinator_started",
|
|
52519
|
-
sessionId: cliCmdSessionId,
|
|
52520
|
-
providerType: cliType,
|
|
52521
|
-
payload: { workspace }
|
|
52522
|
-
});
|
|
52523
|
-
} catch {
|
|
52524
|
-
}
|
|
52525
|
-
return {
|
|
52526
|
-
success: true,
|
|
52527
|
-
meshId,
|
|
52528
|
-
cliType,
|
|
52529
|
-
workspace,
|
|
52530
|
-
sessionId: cliCmdSessionId,
|
|
52531
|
-
mcpRegistered: mcpRegistrationOk
|
|
52532
|
-
};
|
|
52533
|
-
}
|
|
52534
|
-
const configFormat = coordinatorSetup.configFormat;
|
|
52535
|
-
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
52536
|
-
return {
|
|
52537
|
-
success: false,
|
|
52538
|
-
code: "mesh_coordinator_unsupported",
|
|
52539
|
-
error: `Unsupported auto-import MCP config format: ${String(coordinatorSetup.configFormat)}`,
|
|
52540
|
-
meshId,
|
|
52541
|
-
cliType,
|
|
52542
|
-
workspace
|
|
52543
|
-
};
|
|
52544
|
-
}
|
|
52545
|
-
let systemPrompt = "";
|
|
52546
|
-
try {
|
|
52547
|
-
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
|
|
52548
|
-
} catch (error) {
|
|
52549
|
-
const message = error?.message || String(error);
|
|
52550
|
-
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
52551
|
-
return {
|
|
52552
|
-
success: false,
|
|
52553
|
-
code: "mesh_coordinator_prompt_failed",
|
|
52554
|
-
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
52555
|
-
meshId,
|
|
52556
|
-
cliType,
|
|
52557
|
-
workspace
|
|
52558
|
-
};
|
|
52559
|
-
}
|
|
52560
|
-
const { existsSync: existsSync47, readFileSync: readFileSync38, writeFileSync: writeFileSync24, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
|
|
52561
|
-
const { dirname: dirname17 } = await import("path");
|
|
52562
|
-
const mcpConfigPath = coordinatorSetup.configPath;
|
|
52563
|
-
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
52564
|
-
let hermesBaseConfig = null;
|
|
52565
|
-
if (hermesManualFallback) {
|
|
52566
|
-
try {
|
|
52567
|
-
hermesBaseConfig = loadHermesCoordinatorBaseConfig(mcpConfigPath);
|
|
52568
|
-
} catch (error) {
|
|
52569
|
-
const message = `Failed to parse Hermes base config for automatic coordinator setup: ${error?.message || error}`;
|
|
52570
|
-
LOG.error("MeshCoordinator", message);
|
|
52571
|
-
return { success: false, code: "mesh_coordinator_config_parse_failed", error: message, meshId, cliType, workspace };
|
|
52572
|
-
}
|
|
52573
|
-
}
|
|
52574
|
-
const returnManualFallback = (message) => ({
|
|
52575
|
-
success: false,
|
|
52576
|
-
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
52577
|
-
error: message,
|
|
52578
|
-
meshId,
|
|
52579
|
-
cliType,
|
|
52580
|
-
workspace,
|
|
52581
|
-
meshCoordinatorSetup: hermesManualFallback
|
|
52582
|
-
});
|
|
52583
|
-
const mcpServerEntry = {
|
|
52584
|
-
command: coordinatorSetup.mcpServer.command,
|
|
52585
|
-
args: coordinatorSetup.mcpServer.args
|
|
52586
|
-
};
|
|
52587
|
-
if (args?.inlineMesh) {
|
|
52588
|
-
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
52589
|
-
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
52590
|
-
mcpServerEntry.env = {
|
|
52591
|
-
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
52592
|
-
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
52593
|
-
};
|
|
52594
|
-
}
|
|
52595
|
-
try {
|
|
52596
|
-
mkdirSync21(dirname17(mcpConfigPath), { recursive: true });
|
|
52597
|
-
} catch (error) {
|
|
52598
|
-
const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
|
|
52599
|
-
LOG.error("MeshCoordinator", message);
|
|
52600
|
-
if (hermesManualFallback) return returnManualFallback(message);
|
|
52601
|
-
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
52602
|
-
}
|
|
52603
|
-
const hadExistingMcpConfig = existsSync47(mcpConfigPath);
|
|
52604
|
-
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
52605
|
-
if (hermesBaseConfig) {
|
|
52606
|
-
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname17(mcpConfigPath));
|
|
52607
|
-
}
|
|
52608
|
-
if (hadExistingMcpConfig) {
|
|
52609
|
-
try {
|
|
52610
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync38(mcpConfigPath, "utf-8"), configFormat);
|
|
52611
|
-
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
52612
|
-
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
52613
|
-
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
52614
|
-
} catch (error) {
|
|
52615
|
-
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
52616
|
-
return {
|
|
52617
|
-
success: false,
|
|
52618
|
-
code: "mesh_coordinator_config_parse_failed",
|
|
52619
|
-
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
52620
|
-
};
|
|
52621
|
-
}
|
|
52622
|
-
}
|
|
52623
|
-
const mcpServersKey = getMcpServersKey(configFormat);
|
|
52624
|
-
const existingServers = existingMcpConfig[mcpServersKey];
|
|
52625
|
-
const mcpConfig = {
|
|
52626
|
-
...existingMcpConfig,
|
|
52627
|
-
[mcpServersKey]: {
|
|
52628
|
-
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
52629
|
-
[coordinatorSetup.serverName]: mcpServerEntry
|
|
52630
|
-
}
|
|
52631
|
-
};
|
|
52632
|
-
try {
|
|
52633
|
-
writeFileSync24(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
52634
|
-
} catch (error) {
|
|
52635
|
-
const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
|
|
52636
|
-
LOG.error("MeshCoordinator", message);
|
|
52637
|
-
if (hermesManualFallback) return returnManualFallback(message);
|
|
52638
|
-
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
52639
|
-
}
|
|
52640
|
-
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
52641
|
-
const cliArgs = [];
|
|
52642
|
-
const launchEnv = {};
|
|
52643
|
-
if (configFormat === "hermes_config_yaml") {
|
|
52644
|
-
launchEnv.HERMES_HOME = dirname17(mcpConfigPath);
|
|
52645
|
-
launchEnv.HERMES_IGNORE_USER_CONFIG = "";
|
|
52646
|
-
}
|
|
52647
|
-
let autoImportContextFilePath;
|
|
52648
|
-
if (systemPrompt) {
|
|
52649
|
-
const { applyMeshCoordinatorSystemPromptInjection: applyMeshCoordinatorSystemPromptInjection2 } = await Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports));
|
|
52650
|
-
const effect = applyMeshCoordinatorSystemPromptInjection2(
|
|
52651
|
-
systemPrompt,
|
|
52652
|
-
providerMeta?.meshCoordinator?.systemPromptInjection,
|
|
52653
|
-
{ cliArgs, launchEnv, workspace, cliType }
|
|
52654
|
-
);
|
|
52655
|
-
autoImportContextFilePath = effect.contextFilePath;
|
|
52656
|
-
}
|
|
52657
|
-
if (cliType === "claude-cli") {
|
|
52658
|
-
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
52659
|
-
}
|
|
52660
|
-
const launchResult = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
52661
|
-
cliType,
|
|
52662
|
-
dir: workspace,
|
|
52663
|
-
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
52664
|
-
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
52665
|
-
settings: {
|
|
52666
|
-
meshCoordinatorFor: meshId
|
|
52667
|
-
}
|
|
52668
|
-
});
|
|
52669
|
-
if (launchResult?.success && autoImportContextFilePath) {
|
|
52670
|
-
const stripPath = autoImportContextFilePath;
|
|
52671
|
-
setTimeout(() => {
|
|
52672
|
-
void Promise.resolve().then(() => (init_mesh_coordinator(), mesh_coordinator_exports)).then(({ stripCoordinatorWrapperFile: stripCoordinatorWrapperFile2 }) => {
|
|
52673
|
-
stripCoordinatorWrapperFile2(stripPath);
|
|
52674
|
-
LOG.info("MeshCoordinator", `Stripped wrapper from ${stripPath} after launch settle (auto_import)`);
|
|
52675
|
-
}).catch(() => {
|
|
52676
|
-
});
|
|
52677
|
-
}, 5e3);
|
|
52678
|
-
}
|
|
52679
|
-
if (!launchResult?.success) {
|
|
52680
|
-
return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
|
|
52681
|
-
}
|
|
52682
|
-
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
|
|
52683
|
-
const launchSessionId = launchResult.sessionId || launchResult.id;
|
|
52684
|
-
if (launchSessionId) {
|
|
52685
|
-
const autoImportInjectionDecl = providerMeta?.meshCoordinator?.systemPromptInjection;
|
|
52686
|
-
registerMeshCoordinator({
|
|
52687
|
-
meshId,
|
|
52688
|
-
sessionId: launchSessionId,
|
|
52689
|
-
workspace,
|
|
52690
|
-
startedAt: Date.now(),
|
|
52691
|
-
cliType,
|
|
52692
|
-
systemPrompt: systemPrompt || void 0,
|
|
52693
|
-
extraSystemPrompt: extraSystemPrompt || void 0,
|
|
52694
|
-
mcpConfigPath,
|
|
52695
|
-
injection: autoImportInjectionDecl ? {
|
|
52696
|
-
mode: autoImportInjectionDecl.mode,
|
|
52697
|
-
target: "flag" in autoImportInjectionDecl ? autoImportInjectionDecl.flag : "name" in autoImportInjectionDecl ? autoImportInjectionDecl.name : "path" in autoImportInjectionDecl ? autoImportInjectionDecl.path : void 0
|
|
52698
|
-
} : void 0
|
|
52699
|
-
});
|
|
52700
|
-
}
|
|
52701
|
-
try {
|
|
52702
|
-
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
52703
|
-
appendLedgerEntry2(meshId, {
|
|
52704
|
-
kind: "coordinator_started",
|
|
52705
|
-
sessionId: launchSessionId,
|
|
52706
|
-
providerType: cliType,
|
|
52707
|
-
payload: { workspace }
|
|
52708
|
-
});
|
|
52709
|
-
} catch {
|
|
52710
|
-
}
|
|
52711
|
-
return {
|
|
52712
|
-
success: true,
|
|
52713
|
-
meshId,
|
|
52714
|
-
cliType,
|
|
52715
|
-
workspace,
|
|
52716
|
-
sessionId: launchSessionId,
|
|
52717
|
-
mcpConfigWritten: true
|
|
52718
|
-
};
|
|
52719
|
-
} catch (e) {
|
|
52720
|
-
LOG.error("MeshCoordinator", `Failed: ${e.message}`);
|
|
52721
|
-
return { success: false, error: e.message };
|
|
52722
|
-
}
|
|
52723
|
-
}
|
|
52724
|
-
case "mesh_status": {
|
|
52725
|
-
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
52726
|
-
if (!meshId) return { success: false, error: "meshId required" };
|
|
52727
|
-
try {
|
|
52728
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
52729
|
-
const mesh = meshRecord?.mesh;
|
|
52730
|
-
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
52731
|
-
const meshHost = resolveMeshHostStatus(mesh);
|
|
52732
|
-
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
52733
|
-
const verboseMissions = args?.verbose === true || args?.compact === false;
|
|
52734
|
-
const peekScope = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
|
|
52735
|
-
const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
|
|
52736
|
-
const hadAggregateCache = this.aggregateMeshStatusCache.has(meshId);
|
|
52737
|
-
if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
|
|
52738
|
-
const cachedStatus = this.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
|
|
52739
|
-
if (cachedStatus) {
|
|
52740
|
-
logRepoMeshStatusDebug("return_cached", {
|
|
52741
|
-
meshId,
|
|
52742
|
-
command: "mesh_status",
|
|
52743
|
-
refreshRequested,
|
|
52744
|
-
summary: summarizeRepoMeshStatusDebug(cachedStatus)
|
|
52745
|
-
});
|
|
52746
|
-
return cachedStatus;
|
|
52747
|
-
}
|
|
52748
|
-
}
|
|
52749
|
-
const refreshReason = refreshRequested ? "explicit_refresh" : pendingCoordinatorEventCount > 0 ? "pending_coordinator_events" : hadAggregateCache ? "stale_pending_cache_refresh" : "cold_cache_miss";
|
|
52750
|
-
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
52751
|
-
const queue = getQueue2(meshId);
|
|
52752
|
-
const queueSummary = getMeshQueueStats2(meshId);
|
|
52753
|
-
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
52754
|
-
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
52755
|
-
const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
|
|
52756
|
-
const ledgerSummary = getLedgerSummary2(meshId);
|
|
52757
|
-
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
52758
|
-
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
52759
|
-
const localMachineId = loadConfig().machineId || "";
|
|
52760
|
-
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
52761
|
-
const meshGitProbeCache = this.meshGitProbeCache;
|
|
52762
|
-
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
52763
|
-
mesh,
|
|
52764
|
-
meshSource: meshRecord.source,
|
|
52765
|
-
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
52766
|
-
getMeshPeerConnectionStatus: this.deps.getMeshPeerConnectionStatus,
|
|
52767
|
-
statusInstanceId: this.deps.statusInstanceId,
|
|
52768
|
-
localMachineId,
|
|
52769
|
-
// Standing-state model: only an explicit refresh fans
|
|
52770
|
-
// out a blocking peer git probe. Default loads return
|
|
52771
|
-
// held truth so one slow peer can't block the graph.
|
|
52772
|
-
probeRemotePeers: refreshRequested,
|
|
52773
|
-
probeCache: meshGitProbeCache
|
|
52774
|
-
}) : {
|
|
52775
|
-
directEvidenceCount: 0,
|
|
52776
|
-
localConfirmedCount: 0,
|
|
52777
|
-
peerAttemptedCount: 0,
|
|
52778
|
-
peerConfirmedCount: 0,
|
|
52779
|
-
standingEvidenceCount: 0,
|
|
52780
|
-
unavailableNodeIds: [],
|
|
52781
|
-
deadNodeIds: []
|
|
52782
|
-
};
|
|
52783
|
-
const passivePeerTruthNotAttempted = requireDirectPeerTruth && !refreshRequested && directTruth.directEvidenceCount > 0 && directTruth.peerAttemptedCount === 0;
|
|
52784
|
-
const effectiveDirectTruth = passivePeerTruthNotAttempted ? { ...directTruth, unavailableNodeIds: [] } : directTruth;
|
|
52785
|
-
const unavailableDirectTruthNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
52786
|
-
const unavailableNodesAreOnlyRemovedWorktrees = unavailableDirectTruthNodeIds.size > 0 && Array.isArray(mesh.nodes) && mesh.nodes.filter((node) => unavailableDirectTruthNodeIds.has(normalizeMeshNodeId(node) ?? "")).every((node) => node?.isLocalWorktree === true);
|
|
52787
|
-
const directTruthSatisfied = !requireDirectPeerTruth || !refreshRequested || effectiveDirectTruth.directEvidenceCount > 0 && (effectiveDirectTruth.unavailableNodeIds.length === 0 || unavailableNodesAreOnlyRemovedWorktrees);
|
|
52788
|
-
if (requireDirectPeerTruth && refreshRequested && !directTruthSatisfied) {
|
|
52789
|
-
const failureResult = {
|
|
52790
|
-
success: false,
|
|
52791
|
-
code: "mesh_direct_peer_truth_unavailable",
|
|
52792
|
-
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
|
|
52793
|
-
sourceOfTruth: {
|
|
52794
|
-
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
52795
|
-
coordinatorOwnsLiveTruth: false,
|
|
52796
|
-
currentStatus: "direct_peer_truth_unavailable",
|
|
52797
|
-
directPeerTruth: {
|
|
52798
|
-
required: true,
|
|
52799
|
-
satisfied: false,
|
|
52800
|
-
directEvidenceCount: directTruth.directEvidenceCount,
|
|
52801
|
-
localConfirmedCount: directTruth.localConfirmedCount,
|
|
52802
|
-
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
52803
|
-
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
52804
|
-
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
52805
|
-
}
|
|
52806
|
-
}
|
|
52807
|
-
};
|
|
52808
|
-
logRepoMeshStatusDebug("direct_truth_unavailable", {
|
|
52809
|
-
meshId,
|
|
52810
|
-
command: "mesh_status",
|
|
52811
|
-
refreshRequested,
|
|
52812
|
-
meshSource: meshRecord.source,
|
|
52813
|
-
directTruth
|
|
52814
|
-
});
|
|
52815
|
-
return failureResult;
|
|
52816
|
-
}
|
|
52817
|
-
const directTruthUnavailableNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
52818
|
-
const coordinatorHostname = (0, import_os3.hostname)();
|
|
52819
|
-
const selectedCoordinatorNodeId = readStringValue(
|
|
52820
|
-
mesh.coordinator?.preferredNodeId,
|
|
52821
|
-
normalizeMeshNodeId(mesh.nodes?.[0])
|
|
52822
|
-
);
|
|
52823
|
-
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
52824
|
-
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
52825
|
-
const nodeStatuses = [];
|
|
52826
|
-
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
52827
|
-
const nodeId = normalizeMeshNodeId(node) ?? "";
|
|
52828
|
-
const daemonId = readStringValue(node.daemonId);
|
|
52829
|
-
const nodeMachineId = readMeshNodeMachineId(node);
|
|
52830
|
-
const nodeHostname = readMeshNodeHostname(node);
|
|
52831
|
-
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
52832
|
-
const configuredCoordinatorNode = Boolean(
|
|
52833
|
-
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
52834
|
-
);
|
|
52835
|
-
const sparseConfiguredCoordinatorNode = configuredCoordinatorNode && !daemonId && !nodeMachineId && !nodeHostname;
|
|
52836
|
-
const isSelfNode = Boolean(
|
|
52837
|
-
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
52838
|
-
) || Boolean(
|
|
52839
|
-
daemonId && (daemonIdsEquivalent(daemonId, localMachineId) || daemonIdsEquivalent(daemonId, this.deps.statusInstanceId))
|
|
52840
|
-
) || Boolean(meshRecord?.inline && nodeIndex === 0) || sparseConfiguredCoordinatorNode;
|
|
52841
|
-
const machineIdentity = buildMeshNodeMachineIdentity(node, {
|
|
52842
|
-
localMachineId,
|
|
52843
|
-
localDaemonId: this.deps.statusInstanceId,
|
|
52844
|
-
coordinatorHostname,
|
|
52845
|
-
isSelfNode
|
|
52846
|
-
});
|
|
52847
|
-
const status = {
|
|
52848
|
-
nodeId,
|
|
52849
|
-
machineLabel: buildMeshNodeDisplayLabel(node, nodeId, providerPriority),
|
|
52850
|
-
labelSource: readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias) ? "explicit_metadata" : "workspace_host_provider_context",
|
|
52851
|
-
workspace: node.workspace,
|
|
52852
|
-
repoRoot: node.repoRoot,
|
|
52853
|
-
isLocalWorktree: node.isLocalWorktree,
|
|
52854
|
-
worktreeBranch: node.worktreeBranch,
|
|
52855
|
-
role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? "host" : void 0),
|
|
52856
|
-
daemonId,
|
|
52857
|
-
machineId: nodeMachineId || node.machineId,
|
|
52858
|
-
machine: machineIdentity,
|
|
52859
|
-
machineStatus: node.machineStatus,
|
|
52860
|
-
health: "unknown",
|
|
52861
|
-
providers: node.providers || [],
|
|
52862
|
-
providerPriority,
|
|
52863
|
-
activeSessions: [],
|
|
52864
|
-
activeSessionDetails: [],
|
|
52865
|
-
launchReady: false
|
|
52866
|
-
};
|
|
52867
|
-
if (isSelfNode) {
|
|
52868
|
-
status.connection = {
|
|
52869
|
-
perspective: "selected_coordinator",
|
|
52870
|
-
source: "mesh_peer_status",
|
|
52871
|
-
state: "self",
|
|
52872
|
-
transport: "local",
|
|
52873
|
-
reported: true,
|
|
52874
|
-
reason: "Selected coordinator daemon",
|
|
52875
|
-
lastStateChangeAt: refreshedAt
|
|
52876
|
-
};
|
|
52877
|
-
} else if (daemonId) {
|
|
52878
|
-
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
52879
|
-
status.connection = connection ?? {
|
|
52880
|
-
perspective: "selected_coordinator",
|
|
52881
|
-
source: "not_reported",
|
|
52882
|
-
state: "unknown",
|
|
52883
|
-
transport: "unknown",
|
|
52884
|
-
reported: false,
|
|
52885
|
-
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
52886
|
-
};
|
|
52887
|
-
} else {
|
|
52888
|
-
status.connection = {
|
|
52889
|
-
perspective: "selected_coordinator",
|
|
52890
|
-
source: "not_reported",
|
|
52891
|
-
state: "unknown",
|
|
52892
|
-
transport: "unknown",
|
|
52893
|
-
reported: false,
|
|
52894
|
-
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
52895
|
-
};
|
|
52896
|
-
}
|
|
52897
|
-
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
52898
|
-
meshId,
|
|
52899
|
-
node,
|
|
52900
|
-
nodeId,
|
|
52901
|
-
liveSessionRecords: liveMeshSessions,
|
|
52902
|
-
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
52903
|
-
});
|
|
52904
|
-
const workspace = readLiveMeshNodeWorkspace({
|
|
52905
|
-
meshId,
|
|
52906
|
-
nodeId,
|
|
52907
|
-
liveSessionRecords: matchedLiveSessionRecords,
|
|
52908
|
-
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
52909
|
-
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
52910
|
-
status.workspace = workspace || node.workspace;
|
|
52911
|
-
if (matchedLiveSessionRecords.length > 0) {
|
|
52912
|
-
const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
|
|
52913
|
-
const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
|
|
52914
|
-
status.activeSessions = sessionIds;
|
|
52915
|
-
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
52916
|
-
if (providerTypes.length > 0) {
|
|
52917
|
-
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
52918
|
-
}
|
|
52919
|
-
}
|
|
52920
|
-
if (workspace) {
|
|
52921
|
-
if (!fs27.existsSync(workspace)) {
|
|
52922
|
-
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
52923
|
-
let remoteProbeApplied = false;
|
|
52924
|
-
if (inlineTransitGit) {
|
|
52925
|
-
status.git = inlineTransitGit;
|
|
52926
|
-
status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
|
|
52927
|
-
const connection = readObjectRecord(status.connection);
|
|
52928
|
-
const connectionState = readStringValue(connection.state);
|
|
52929
|
-
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
52930
|
-
if (!connectionReported || connectionState === "unknown") {
|
|
52931
|
-
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
52932
|
-
}
|
|
52933
|
-
remoteProbeApplied = true;
|
|
52934
|
-
} else if (refreshRequested && !isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
52935
|
-
const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
52936
|
-
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
52937
|
-
daemonId,
|
|
52938
|
-
workspace,
|
|
52939
|
-
timeoutMs: MESH_DIRECT_PROBE_TIMEOUT_MS,
|
|
52940
|
-
retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
52941
|
-
getConnection: this.deps.getMeshPeerConnectionStatus,
|
|
52942
|
-
onConnection: (connection) => {
|
|
52943
|
-
status.connection = connection;
|
|
52944
|
-
}
|
|
52945
|
-
});
|
|
52946
|
-
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
52947
|
-
if (remoteGit) {
|
|
52948
|
-
status.git = remoteGit;
|
|
52949
|
-
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
52950
|
-
const connection = readObjectRecord(status.connection);
|
|
52951
|
-
const connectionState = readStringValue(connection.state);
|
|
52952
|
-
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
52953
|
-
if (!connectionReported || connectionState === "unknown") {
|
|
52954
|
-
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
52955
|
-
}
|
|
52956
|
-
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
52957
|
-
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
52958
|
-
remoteProbeApplied = true;
|
|
52959
|
-
}
|
|
52960
|
-
}
|
|
52961
|
-
if (!remoteProbeApplied) {
|
|
52962
|
-
const connectionState = readStringValue(status.connection?.state);
|
|
52963
|
-
const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
|
|
52964
|
-
if (pendingPeerGitProbe) {
|
|
52965
|
-
status.gitProbePending = true;
|
|
52966
|
-
status.health = "unknown";
|
|
52967
|
-
}
|
|
52968
|
-
if (applyCachedInlineMeshNodeStatus(
|
|
52969
|
-
status,
|
|
52970
|
-
node,
|
|
52971
|
-
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
52972
|
-
)) {
|
|
52973
|
-
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
52974
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
52975
|
-
nodeStatuses.push(status);
|
|
52976
|
-
continue;
|
|
52977
|
-
}
|
|
52978
|
-
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
52979
|
-
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
52980
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
52981
|
-
nodeStatuses.push(status);
|
|
52982
|
-
continue;
|
|
52983
|
-
}
|
|
52984
|
-
}
|
|
52985
|
-
} else {
|
|
52986
|
-
try {
|
|
52987
|
-
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
52988
|
-
status.git = gitStatus;
|
|
52989
|
-
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
52990
|
-
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
52991
|
-
if (gitStatus.isGitRepo) {
|
|
52992
|
-
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
52993
|
-
} else {
|
|
52994
|
-
status.health = "degraded";
|
|
52995
|
-
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
52996
|
-
}
|
|
52997
|
-
} catch {
|
|
52998
|
-
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
52999
|
-
status.health = "degraded";
|
|
53000
|
-
}
|
|
53001
|
-
}
|
|
53002
|
-
}
|
|
53003
|
-
} else {
|
|
53004
|
-
applyCachedInlineMeshNodeStatus(status, node);
|
|
53005
|
-
}
|
|
53006
|
-
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
53007
|
-
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
53008
|
-
nodeStatuses.push(status);
|
|
53009
|
-
}
|
|
53010
|
-
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
|
|
53011
|
-
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
53012
|
-
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
53013
|
-
const previewFreshness = (() => {
|
|
53014
|
-
const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs27.existsSync(candidate));
|
|
53015
|
-
return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
|
|
53016
|
-
})();
|
|
53017
|
-
const asyncRefineJobs = buildMeshAsyncRefineJobs({
|
|
53018
|
-
meshId,
|
|
53019
|
-
ledgerEntries: asyncRefineLedgerEntries,
|
|
53020
|
-
pendingEvents: [...pendingCoordinatorEvents]
|
|
53021
|
-
});
|
|
53022
|
-
const historicalSessions = buildHistoricalMeshSessions({
|
|
53023
|
-
meshId,
|
|
53024
|
-
nodes: mesh.nodes || [],
|
|
53025
|
-
liveSessionRecords: liveMeshSessions
|
|
53026
|
-
});
|
|
53027
|
-
const { getMeshStatusMissionSummaries: getMeshStatusMissionSummaries2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
|
|
53028
|
-
const missions = getMeshStatusMissionSummaries2(meshId, { verbose: verboseMissions, withStats: true });
|
|
53029
|
-
const statusResult = {
|
|
53030
|
-
success: true,
|
|
53031
|
-
meshId: mesh.id,
|
|
53032
|
-
meshName: mesh.name,
|
|
53033
|
-
repoIdentity: mesh.repoIdentity,
|
|
53034
|
-
defaultBranch: mesh.defaultBranch,
|
|
53035
|
-
refreshedAt,
|
|
53036
|
-
meshHost,
|
|
53037
|
-
sourceOfTruth: {
|
|
53038
|
-
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
53039
|
-
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
53040
|
-
meshHost: {
|
|
53041
|
-
owner: "mesh_host_daemon",
|
|
53042
|
-
localRole: meshHost.role,
|
|
53043
|
-
hostDaemonId: meshHost.hostDaemonId,
|
|
53044
|
-
hostNodeId: meshHost.hostNodeId,
|
|
53045
|
-
hostAddress: meshHost.hostAddress
|
|
53046
|
-
},
|
|
53047
|
-
...requireDirectPeerTruth ? {
|
|
53048
|
-
currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
|
|
53049
|
-
directPeerTruth: {
|
|
53050
|
-
required: true,
|
|
53051
|
-
satisfied: directTruthSatisfied,
|
|
53052
|
-
directEvidenceCount: effectiveDirectTruth.directEvidenceCount,
|
|
53053
|
-
localConfirmedCount: effectiveDirectTruth.localConfirmedCount,
|
|
53054
|
-
peerAttemptedCount: effectiveDirectTruth.peerAttemptedCount,
|
|
53055
|
-
peerConfirmedCount: effectiveDirectTruth.peerConfirmedCount,
|
|
53056
|
-
unavailableNodeIds: effectiveDirectTruth.unavailableNodeIds,
|
|
53057
|
-
partialNodeFailures: effectiveDirectTruth.unavailableNodeIds
|
|
53058
|
-
}
|
|
53059
|
-
} : {},
|
|
53060
|
-
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary", "historicalSessions"]
|
|
53061
|
-
},
|
|
53062
|
-
branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
|
|
53063
|
-
...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
|
|
53064
|
-
nodes: nodeStatuses,
|
|
53065
|
-
queue: { tasks: queue, summary: queueSummary },
|
|
53066
|
-
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
|
53067
|
-
...missions.length > 0 ? { missions } : {},
|
|
53068
|
-
...asyncRefineJobs.length > 0 ? { asyncRefineJobs } : {},
|
|
53069
|
-
...historicalSessions ? { historicalSessions } : {},
|
|
53070
|
-
...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
|
|
53071
|
-
...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
|
|
53072
|
-
activeRefineJobs: Array.from(this.runningRefineJobs.values()).filter((job) => job.meshId === meshId).map((job) => ({
|
|
53073
|
-
jobId: job.jobId,
|
|
53074
|
-
nodeId: job.targetNodeId,
|
|
53075
|
-
workspace: job.workspace,
|
|
53076
|
-
startedAt: job.startedAt,
|
|
53077
|
-
status: job.status,
|
|
53078
|
-
targetCoordinatorDaemonId: job.targetCoordinatorDaemonId
|
|
53079
|
-
}))
|
|
53080
|
-
};
|
|
53081
|
-
const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
|
|
53082
|
-
const rememberedStatus = verboseMissions ? cacheableStatusResult : this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
|
|
53083
|
-
const returnedStatus = {
|
|
53084
|
-
...rememberedStatus,
|
|
53085
|
-
...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
|
|
53086
|
-
...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}
|
|
53087
|
-
};
|
|
53088
|
-
logRepoMeshStatusDebug("return_live", {
|
|
53089
|
-
meshId,
|
|
53090
|
-
command: "mesh_status",
|
|
53091
|
-
refreshRequested,
|
|
53092
|
-
refreshReason,
|
|
53093
|
-
meshSource: meshRecord.source,
|
|
53094
|
-
directTruth,
|
|
53095
|
-
summary: summarizeRepoMeshStatusDebug(returnedStatus)
|
|
53096
|
-
});
|
|
53097
|
-
return returnedStatus;
|
|
53098
|
-
} catch (e) {
|
|
53099
|
-
return { success: false, error: e.message };
|
|
53100
|
-
}
|
|
53101
|
-
}
|
|
53102
|
-
case "get_mesh_review_inbox": {
|
|
53103
|
-
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53104
|
-
if (!meshId) return { success: false, error: "meshId required" };
|
|
53105
|
-
try {
|
|
53106
|
-
const { deriveMeshReviewInboxItems: deriveMeshReviewInboxItems2 } = await Promise.resolve().then(() => (init_mesh_review_inbox(), mesh_review_inbox_exports));
|
|
53107
|
-
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53108
|
-
const { getGitDiffSummary: getGitDiffSummary2 } = await Promise.resolve().then(() => (init_git_diff(), git_diff_exports));
|
|
53109
|
-
const { existsSync: existsSync47 } = await import("fs");
|
|
53110
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
53111
|
-
const mesh = meshRecord?.mesh;
|
|
53112
|
-
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
53113
|
-
const inlineNodes = args?.inlineMesh && Array.isArray(args.inlineMesh?.nodes) ? args.inlineMesh.nodes : null;
|
|
53114
|
-
let cachedStatus = !inlineNodes ? this.getCachedAggregateMeshStatus(meshId, mesh, {}) : null;
|
|
53115
|
-
if (!cachedStatus && !inlineNodes) {
|
|
53116
|
-
const freshStatus = await this.execute("mesh_status", {
|
|
53117
|
-
meshId,
|
|
53118
|
-
inlineMesh: args?.inlineMesh,
|
|
53119
|
-
refresh: true
|
|
53120
|
-
}, "get_mesh_review_inbox");
|
|
53121
|
-
cachedStatus = freshStatus?.success !== false ? freshStatus : null;
|
|
53122
|
-
}
|
|
53123
|
-
const nodeStatuses = inlineNodes ? inlineNodes : Array.isArray(cachedStatus?.nodes) ? cachedStatus.nodes : Array.isArray(mesh.nodes) ? mesh.nodes : [];
|
|
53124
|
-
const ledgerEntries = readLedgerEntries2(meshId, { tail: 300 });
|
|
53125
|
-
const derivation = deriveMeshReviewInboxItems2({ nodes: nodeStatuses, ledgerEntries });
|
|
53126
|
-
for (const item of derivation.items) {
|
|
53127
|
-
const workspace = item.workspace;
|
|
53128
|
-
if (!workspace || !existsSync47(workspace)) continue;
|
|
53129
|
-
const baseRef = item.defaultBranch ? `origin/${item.defaultBranch}` : "origin/main";
|
|
53130
|
-
try {
|
|
53131
|
-
const diffResult = await getGitDiffSummary2(workspace, { baseRef, maxFiles: 100 });
|
|
53132
|
-
if (diffResult.isGitRepo) {
|
|
53133
|
-
item.diffSummary = {
|
|
53134
|
-
baseRef,
|
|
53135
|
-
files: diffResult.files.map((f) => ({
|
|
53136
|
-
path: f.path,
|
|
53137
|
-
status: f.status,
|
|
53138
|
-
insertions: f.insertions,
|
|
53139
|
-
deletions: f.deletions,
|
|
53140
|
-
binary: f.binary,
|
|
53141
|
-
oldPath: f.oldPath
|
|
53142
|
-
})),
|
|
53143
|
-
totalFiles: diffResult.files.length,
|
|
53144
|
-
totalInsertions: diffResult.totalInsertions,
|
|
53145
|
-
totalDeletions: diffResult.totalDeletions,
|
|
53146
|
-
truncated: diffResult.truncated,
|
|
53147
|
-
...diffResult.error ? { error: diffResult.error } : {}
|
|
53148
|
-
};
|
|
53149
|
-
}
|
|
53150
|
-
} catch {
|
|
53151
|
-
item.diffSummary = null;
|
|
53152
|
-
}
|
|
53153
|
-
}
|
|
53154
|
-
return {
|
|
53155
|
-
success: true,
|
|
53156
|
-
meshId,
|
|
53157
|
-
inbox: derivation.items,
|
|
53158
|
-
remoteNodesExcluded: derivation.remoteNodesExcluded,
|
|
53159
|
-
excludedRemoteNodeIds: derivation.excludedRemoteNodeIds
|
|
53160
|
-
};
|
|
53161
|
-
} catch (e) {
|
|
53162
|
-
return { success: false, error: e.message };
|
|
53163
|
-
}
|
|
53164
|
-
}
|
|
53165
|
-
default:
|
|
53166
|
-
break;
|
|
53346
|
+
const highFamilyHandler = highFamilyRegistry.get(cmd);
|
|
53347
|
+
if (highFamilyHandler) {
|
|
53348
|
+
return await highFamilyHandler(this.buildHighFamilyContext(), args);
|
|
53167
53349
|
}
|
|
53168
53350
|
return null;
|
|
53169
53351
|
}
|
|
@@ -54889,10 +55071,10 @@ init_io_contracts();
|
|
|
54889
55071
|
init_chat_message_normalization();
|
|
54890
55072
|
|
|
54891
55073
|
// src/providers/version-archive.ts
|
|
54892
|
-
var
|
|
55074
|
+
var fs30 = __toESM(require("fs"));
|
|
54893
55075
|
var path37 = __toESM(require("path"));
|
|
54894
55076
|
var os28 = __toESM(require("os"));
|
|
54895
|
-
var
|
|
55077
|
+
var import_os5 = require("os");
|
|
54896
55078
|
var import_child_process10 = require("child_process");
|
|
54897
55079
|
var ARCHIVE_PATH = path37.join(os28.homedir(), ".adhdev", "version-history.json");
|
|
54898
55080
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
@@ -54903,8 +55085,8 @@ var VersionArchive = class {
|
|
|
54903
55085
|
}
|
|
54904
55086
|
load() {
|
|
54905
55087
|
try {
|
|
54906
|
-
if (
|
|
54907
|
-
this.history = JSON.parse(
|
|
55088
|
+
if (fs30.existsSync(ARCHIVE_PATH)) {
|
|
55089
|
+
this.history = JSON.parse(fs30.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
54908
55090
|
}
|
|
54909
55091
|
} catch {
|
|
54910
55092
|
this.history = {};
|
|
@@ -54919,7 +55101,7 @@ var VersionArchive = class {
|
|
|
54919
55101
|
entries.push({
|
|
54920
55102
|
version,
|
|
54921
55103
|
detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
54922
|
-
os: (0,
|
|
55104
|
+
os: (0, import_os5.platform)()
|
|
54923
55105
|
});
|
|
54924
55106
|
if (entries.length > MAX_ENTRIES_PER_PROVIDER) {
|
|
54925
55107
|
this.history[type] = entries.slice(-MAX_ENTRIES_PER_PROVIDER);
|
|
@@ -54941,8 +55123,8 @@ var VersionArchive = class {
|
|
|
54941
55123
|
}
|
|
54942
55124
|
save() {
|
|
54943
55125
|
try {
|
|
54944
|
-
|
|
54945
|
-
|
|
55126
|
+
fs30.mkdirSync(path37.dirname(ARCHIVE_PATH), { recursive: true });
|
|
55127
|
+
fs30.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
54946
55128
|
} catch {
|
|
54947
55129
|
}
|
|
54948
55130
|
}
|
|
@@ -54959,7 +55141,7 @@ async function runCommand(cmd, timeout = 1e4) {
|
|
|
54959
55141
|
});
|
|
54960
55142
|
}
|
|
54961
55143
|
function findBinary2(name) {
|
|
54962
|
-
const isWin = (0,
|
|
55144
|
+
const isWin = (0, import_os5.platform)() === "win32";
|
|
54963
55145
|
const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
|
|
54964
55146
|
const exes = isWin ? [".exe", ".cmd", ".bat", ""] : [""];
|
|
54965
55147
|
for (const p of paths) {
|
|
@@ -54967,8 +55149,8 @@ function findBinary2(name) {
|
|
|
54967
55149
|
for (const ext of exes) {
|
|
54968
55150
|
const fullPath = path37.join(p, name + ext);
|
|
54969
55151
|
try {
|
|
54970
|
-
if (
|
|
54971
|
-
const stat2 =
|
|
55152
|
+
if (fs30.existsSync(fullPath)) {
|
|
55153
|
+
const stat2 = fs30.statSync(fullPath);
|
|
54972
55154
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
54973
55155
|
return fullPath;
|
|
54974
55156
|
}
|
|
@@ -55015,23 +55197,23 @@ function checkPathExists2(paths) {
|
|
|
55015
55197
|
if (p.includes("*")) {
|
|
55016
55198
|
const home = os28.homedir();
|
|
55017
55199
|
const resolved = p.replace(/\*/g, home.split(path37.sep).pop() || "");
|
|
55018
|
-
if (
|
|
55200
|
+
if (fs30.existsSync(resolved)) return resolved;
|
|
55019
55201
|
} else {
|
|
55020
|
-
if (
|
|
55202
|
+
if (fs30.existsSync(p)) return p;
|
|
55021
55203
|
}
|
|
55022
55204
|
}
|
|
55023
55205
|
return null;
|
|
55024
55206
|
}
|
|
55025
55207
|
async function getMacAppVersion(appPath) {
|
|
55026
|
-
if ((0,
|
|
55208
|
+
if ((0, import_os5.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
55027
55209
|
const plistPath = path37.join(appPath, "Contents", "Info.plist");
|
|
55028
|
-
if (!
|
|
55210
|
+
if (!fs30.existsSync(plistPath)) return null;
|
|
55029
55211
|
const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
55030
55212
|
return raw || null;
|
|
55031
55213
|
}
|
|
55032
55214
|
async function detectAllVersions(loader, archive) {
|
|
55033
55215
|
const results = [];
|
|
55034
|
-
const currentOs = (0,
|
|
55216
|
+
const currentOs = (0, import_os5.platform)();
|
|
55035
55217
|
const win32ProcessNames = typeof loader.getWinProcessNames === "function" ? loader.getWinProcessNames() : {};
|
|
55036
55218
|
for (const provider of loader.getAll()) {
|
|
55037
55219
|
const info = {
|
|
@@ -55052,7 +55234,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
55052
55234
|
let resolvedBin = cliBin;
|
|
55053
55235
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
55054
55236
|
const bundled = path37.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
55055
|
-
if (provider.cli &&
|
|
55237
|
+
if (provider.cli && fs30.existsSync(bundled)) resolvedBin = bundled;
|
|
55056
55238
|
}
|
|
55057
55239
|
info.installed = !!(appPath || resolvedBin);
|
|
55058
55240
|
info.path = appPath || null;
|
|
@@ -55100,7 +55282,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
55100
55282
|
|
|
55101
55283
|
// src/daemon/dev-server.ts
|
|
55102
55284
|
var http2 = __toESM(require("http"));
|
|
55103
|
-
var
|
|
55285
|
+
var fs34 = __toESM(require("fs"));
|
|
55104
55286
|
var path41 = __toESM(require("path"));
|
|
55105
55287
|
init_config();
|
|
55106
55288
|
|
|
@@ -55452,7 +55634,7 @@ init_logger();
|
|
|
55452
55634
|
init_builders();
|
|
55453
55635
|
|
|
55454
55636
|
// src/daemon/dev-cdp-handlers.ts
|
|
55455
|
-
var
|
|
55637
|
+
var fs31 = __toESM(require("fs"));
|
|
55456
55638
|
var path38 = __toESM(require("path"));
|
|
55457
55639
|
init_logger();
|
|
55458
55640
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
@@ -55633,17 +55815,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
55633
55815
|
}
|
|
55634
55816
|
let scriptsPath = "";
|
|
55635
55817
|
const directScripts = path38.join(dir, "scripts.js");
|
|
55636
|
-
if (
|
|
55818
|
+
if (fs31.existsSync(directScripts)) {
|
|
55637
55819
|
scriptsPath = directScripts;
|
|
55638
55820
|
} else {
|
|
55639
55821
|
const scriptsDir = path38.join(dir, "scripts");
|
|
55640
|
-
if (
|
|
55641
|
-
const versions =
|
|
55642
|
-
return
|
|
55822
|
+
if (fs31.existsSync(scriptsDir)) {
|
|
55823
|
+
const versions = fs31.readdirSync(scriptsDir).filter((d) => {
|
|
55824
|
+
return fs31.statSync(path38.join(scriptsDir, d)).isDirectory();
|
|
55643
55825
|
}).sort().reverse();
|
|
55644
55826
|
for (const ver of versions) {
|
|
55645
55827
|
const p = path38.join(scriptsDir, ver, "scripts.js");
|
|
55646
|
-
if (
|
|
55828
|
+
if (fs31.existsSync(p)) {
|
|
55647
55829
|
scriptsPath = p;
|
|
55648
55830
|
break;
|
|
55649
55831
|
}
|
|
@@ -55655,7 +55837,7 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
55655
55837
|
return;
|
|
55656
55838
|
}
|
|
55657
55839
|
try {
|
|
55658
|
-
const source =
|
|
55840
|
+
const source = fs31.readFileSync(scriptsPath, "utf-8");
|
|
55659
55841
|
const hints = {};
|
|
55660
55842
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
55661
55843
|
let match;
|
|
@@ -56470,7 +56652,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
56470
56652
|
}
|
|
56471
56653
|
|
|
56472
56654
|
// src/daemon/dev-cli-debug.ts
|
|
56473
|
-
var
|
|
56655
|
+
var fs32 = __toESM(require("fs"));
|
|
56474
56656
|
var path39 = __toESM(require("path"));
|
|
56475
56657
|
function slugifyFixtureName(value) {
|
|
56476
56658
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -56486,10 +56668,10 @@ function getCliFixtureDir(ctx, type) {
|
|
|
56486
56668
|
function readCliFixture(ctx, type, name) {
|
|
56487
56669
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
56488
56670
|
const filePath = path39.join(fixtureDir, `${name}.json`);
|
|
56489
|
-
if (!
|
|
56671
|
+
if (!fs32.existsSync(filePath)) {
|
|
56490
56672
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
56491
56673
|
}
|
|
56492
|
-
return JSON.parse(
|
|
56674
|
+
return JSON.parse(fs32.readFileSync(filePath, "utf-8"));
|
|
56493
56675
|
}
|
|
56494
56676
|
function getExerciseTranscriptText(result) {
|
|
56495
56677
|
const parts = [];
|
|
@@ -57234,7 +57416,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
57234
57416
|
return;
|
|
57235
57417
|
}
|
|
57236
57418
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
57237
|
-
|
|
57419
|
+
fs32.mkdirSync(fixtureDir, { recursive: true });
|
|
57238
57420
|
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
57239
57421
|
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
57240
57422
|
const fixture = {
|
|
@@ -57262,7 +57444,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
57262
57444
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
57263
57445
|
};
|
|
57264
57446
|
const filePath = path39.join(fixtureDir, `${name}.json`);
|
|
57265
|
-
|
|
57447
|
+
fs32.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
57266
57448
|
ctx.json(res, 200, {
|
|
57267
57449
|
saved: true,
|
|
57268
57450
|
name,
|
|
@@ -57280,14 +57462,14 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
57280
57462
|
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
57281
57463
|
try {
|
|
57282
57464
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
57283
|
-
if (!
|
|
57465
|
+
if (!fs32.existsSync(fixtureDir)) {
|
|
57284
57466
|
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
57285
57467
|
return;
|
|
57286
57468
|
}
|
|
57287
|
-
const fixtures =
|
|
57469
|
+
const fixtures = fs32.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
57288
57470
|
const fullPath = path39.join(fixtureDir, file);
|
|
57289
57471
|
try {
|
|
57290
|
-
const raw = JSON.parse(
|
|
57472
|
+
const raw = JSON.parse(fs32.readFileSync(fullPath, "utf-8"));
|
|
57291
57473
|
return {
|
|
57292
57474
|
name: raw.name || file.replace(/\.json$/i, ""),
|
|
57293
57475
|
path: fullPath,
|
|
@@ -57420,7 +57602,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
57420
57602
|
}
|
|
57421
57603
|
|
|
57422
57604
|
// src/daemon/dev-auto-implement.ts
|
|
57423
|
-
var
|
|
57605
|
+
var fs33 = __toESM(require("fs"));
|
|
57424
57606
|
var path40 = __toESM(require("path"));
|
|
57425
57607
|
var os29 = __toESM(require("os"));
|
|
57426
57608
|
var import_session_host_core8 = require("@adhdev/session-host-core");
|
|
@@ -57469,10 +57651,10 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
57469
57651
|
return fallback?.type || null;
|
|
57470
57652
|
}
|
|
57471
57653
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
57472
|
-
if (!
|
|
57473
|
-
const versions =
|
|
57654
|
+
if (!fs33.existsSync(scriptsDir)) return null;
|
|
57655
|
+
const versions = fs33.readdirSync(scriptsDir).filter((d) => {
|
|
57474
57656
|
try {
|
|
57475
|
-
return
|
|
57657
|
+
return fs33.statSync(path40.join(scriptsDir, d)).isDirectory();
|
|
57476
57658
|
} catch {
|
|
57477
57659
|
return false;
|
|
57478
57660
|
}
|
|
@@ -57494,13 +57676,13 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
57494
57676
|
if (!sourceDir) {
|
|
57495
57677
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
57496
57678
|
}
|
|
57497
|
-
if (!
|
|
57498
|
-
|
|
57499
|
-
|
|
57679
|
+
if (!fs33.existsSync(desiredDir)) {
|
|
57680
|
+
fs33.mkdirSync(path40.dirname(desiredDir), { recursive: true });
|
|
57681
|
+
fs33.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
57500
57682
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
57501
57683
|
}
|
|
57502
57684
|
const providerJson = path40.join(desiredDir, "provider.json");
|
|
57503
|
-
if (!
|
|
57685
|
+
if (!fs33.existsSync(providerJson)) {
|
|
57504
57686
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
57505
57687
|
}
|
|
57506
57688
|
return { dir: desiredDir };
|
|
@@ -57508,15 +57690,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
57508
57690
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
57509
57691
|
if (!referenceType) return {};
|
|
57510
57692
|
const refDir = ctx.findProviderDir(referenceType);
|
|
57511
|
-
if (!refDir || !
|
|
57693
|
+
if (!refDir || !fs33.existsSync(refDir)) return {};
|
|
57512
57694
|
const referenceScripts = {};
|
|
57513
57695
|
const scriptsDir = path40.join(refDir, "scripts");
|
|
57514
57696
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
57515
57697
|
if (!latestDir) return referenceScripts;
|
|
57516
|
-
for (const file of
|
|
57698
|
+
for (const file of fs33.readdirSync(latestDir)) {
|
|
57517
57699
|
if (!file.endsWith(".js")) continue;
|
|
57518
57700
|
try {
|
|
57519
|
-
referenceScripts[file] =
|
|
57701
|
+
referenceScripts[file] = fs33.readFileSync(path40.join(latestDir, file), "utf-8");
|
|
57520
57702
|
} catch {
|
|
57521
57703
|
}
|
|
57522
57704
|
}
|
|
@@ -57625,15 +57807,15 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57625
57807
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
57626
57808
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
57627
57809
|
const tmpDir = path40.join(os29.tmpdir(), "adhdev-autoimpl");
|
|
57628
|
-
if (!
|
|
57810
|
+
if (!fs33.existsSync(tmpDir)) fs33.mkdirSync(tmpDir, { recursive: true });
|
|
57629
57811
|
const promptFile = path40.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
57630
|
-
|
|
57812
|
+
fs33.writeFileSync(promptFile, prompt, "utf-8");
|
|
57631
57813
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
57632
57814
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
57633
57815
|
const spawn4 = agentProvider?.spawn;
|
|
57634
57816
|
if (!spawn4?.command) {
|
|
57635
57817
|
try {
|
|
57636
|
-
|
|
57818
|
+
fs33.unlinkSync(promptFile);
|
|
57637
57819
|
} catch {
|
|
57638
57820
|
}
|
|
57639
57821
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -57735,7 +57917,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57735
57917
|
} catch {
|
|
57736
57918
|
}
|
|
57737
57919
|
try {
|
|
57738
|
-
|
|
57920
|
+
fs33.unlinkSync(promptFile);
|
|
57739
57921
|
} catch {
|
|
57740
57922
|
}
|
|
57741
57923
|
ctx.log(`Auto-implement (ACP) ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -57961,7 +58143,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57961
58143
|
}
|
|
57962
58144
|
});
|
|
57963
58145
|
try {
|
|
57964
|
-
|
|
58146
|
+
fs33.unlinkSync(promptFile);
|
|
57965
58147
|
} catch {
|
|
57966
58148
|
}
|
|
57967
58149
|
ctx.log(`Auto-implement ${success ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
@@ -58066,10 +58248,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
58066
58248
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
58067
58249
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
58068
58250
|
lines.push("");
|
|
58069
|
-
for (const file of
|
|
58251
|
+
for (const file of fs33.readdirSync(latestScriptsDir)) {
|
|
58070
58252
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
58071
58253
|
try {
|
|
58072
|
-
const content =
|
|
58254
|
+
const content = fs33.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
58073
58255
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
58074
58256
|
lines.push("```javascript");
|
|
58075
58257
|
lines.push(content);
|
|
@@ -58079,14 +58261,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
58079
58261
|
}
|
|
58080
58262
|
}
|
|
58081
58263
|
}
|
|
58082
|
-
const refFiles =
|
|
58264
|
+
const refFiles = fs33.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
58083
58265
|
if (refFiles.length > 0) {
|
|
58084
58266
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
58085
58267
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
58086
58268
|
lines.push("");
|
|
58087
58269
|
for (const file of refFiles) {
|
|
58088
58270
|
try {
|
|
58089
|
-
const content =
|
|
58271
|
+
const content = fs33.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
58090
58272
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
58091
58273
|
lines.push("```javascript");
|
|
58092
58274
|
lines.push(content);
|
|
@@ -58131,7 +58313,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
58131
58313
|
const loadGuide = (name) => {
|
|
58132
58314
|
try {
|
|
58133
58315
|
const p = path40.join(docsDir, name);
|
|
58134
|
-
if (
|
|
58316
|
+
if (fs33.existsSync(p)) return fs33.readFileSync(p, "utf-8");
|
|
58135
58317
|
} catch {
|
|
58136
58318
|
}
|
|
58137
58319
|
return null;
|
|
@@ -58375,11 +58557,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
58375
58557
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
58376
58558
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
58377
58559
|
lines.push("");
|
|
58378
|
-
for (const file of
|
|
58560
|
+
for (const file of fs33.readdirSync(latestScriptsDir)) {
|
|
58379
58561
|
if (!file.endsWith(".js")) continue;
|
|
58380
58562
|
if (!targetFileNames.has(file)) continue;
|
|
58381
58563
|
try {
|
|
58382
|
-
const content =
|
|
58564
|
+
const content = fs33.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
58383
58565
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
58384
58566
|
lines.push("```javascript");
|
|
58385
58567
|
lines.push(content);
|
|
@@ -58388,14 +58570,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
58388
58570
|
} catch {
|
|
58389
58571
|
}
|
|
58390
58572
|
}
|
|
58391
|
-
const refFiles =
|
|
58573
|
+
const refFiles = fs33.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
58392
58574
|
if (refFiles.length > 0) {
|
|
58393
58575
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
58394
58576
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
58395
58577
|
lines.push("");
|
|
58396
58578
|
for (const file of refFiles) {
|
|
58397
58579
|
try {
|
|
58398
|
-
const content =
|
|
58580
|
+
const content = fs33.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
58399
58581
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
58400
58582
|
lines.push("```javascript");
|
|
58401
58583
|
lines.push(content);
|
|
@@ -58432,7 +58614,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
58432
58614
|
const loadGuide = (name) => {
|
|
58433
58615
|
try {
|
|
58434
58616
|
const p = path40.join(docsDir, name);
|
|
58435
|
-
if (
|
|
58617
|
+
if (fs33.existsSync(p)) return fs33.readFileSync(p, "utf-8");
|
|
58436
58618
|
} catch {
|
|
58437
58619
|
}
|
|
58438
58620
|
return null;
|
|
@@ -59172,7 +59354,7 @@ var DevServer = class _DevServer {
|
|
|
59172
59354
|
path41.join(process.cwd(), "packages/web-devconsole/dist")
|
|
59173
59355
|
];
|
|
59174
59356
|
for (const dir of candidates) {
|
|
59175
|
-
if (
|
|
59357
|
+
if (fs34.existsSync(path41.join(dir, "index.html"))) return dir;
|
|
59176
59358
|
}
|
|
59177
59359
|
return null;
|
|
59178
59360
|
}
|
|
@@ -59184,7 +59366,7 @@ var DevServer = class _DevServer {
|
|
|
59184
59366
|
}
|
|
59185
59367
|
const htmlPath = path41.join(distDir, "index.html");
|
|
59186
59368
|
try {
|
|
59187
|
-
const html =
|
|
59369
|
+
const html = fs34.readFileSync(htmlPath, "utf-8");
|
|
59188
59370
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
59189
59371
|
res.end(html);
|
|
59190
59372
|
} catch (e) {
|
|
@@ -59214,7 +59396,7 @@ var DevServer = class _DevServer {
|
|
|
59214
59396
|
return;
|
|
59215
59397
|
}
|
|
59216
59398
|
try {
|
|
59217
|
-
const content =
|
|
59399
|
+
const content = fs34.readFileSync(filePath);
|
|
59218
59400
|
const ext = path41.extname(filePath);
|
|
59219
59401
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
59220
59402
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
@@ -59323,14 +59505,14 @@ var DevServer = class _DevServer {
|
|
|
59323
59505
|
const files = [];
|
|
59324
59506
|
const scan = (d, prefix) => {
|
|
59325
59507
|
try {
|
|
59326
|
-
for (const entry of
|
|
59508
|
+
for (const entry of fs34.readdirSync(d, { withFileTypes: true })) {
|
|
59327
59509
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
59328
59510
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
59329
59511
|
if (entry.isDirectory()) {
|
|
59330
59512
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
59331
59513
|
scan(path41.join(d, entry.name), rel);
|
|
59332
59514
|
} else {
|
|
59333
|
-
const stat2 =
|
|
59515
|
+
const stat2 = fs34.statSync(path41.join(d, entry.name));
|
|
59334
59516
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
59335
59517
|
}
|
|
59336
59518
|
}
|
|
@@ -59358,11 +59540,11 @@ var DevServer = class _DevServer {
|
|
|
59358
59540
|
this.json(res, 403, { error: "Forbidden" });
|
|
59359
59541
|
return;
|
|
59360
59542
|
}
|
|
59361
|
-
if (!
|
|
59543
|
+
if (!fs34.existsSync(fullPath) || fs34.statSync(fullPath).isDirectory()) {
|
|
59362
59544
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
59363
59545
|
return;
|
|
59364
59546
|
}
|
|
59365
|
-
const content =
|
|
59547
|
+
const content = fs34.readFileSync(fullPath, "utf-8");
|
|
59366
59548
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
59367
59549
|
}
|
|
59368
59550
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -59384,9 +59566,9 @@ var DevServer = class _DevServer {
|
|
|
59384
59566
|
return;
|
|
59385
59567
|
}
|
|
59386
59568
|
try {
|
|
59387
|
-
if (
|
|
59388
|
-
|
|
59389
|
-
|
|
59569
|
+
if (fs34.existsSync(fullPath)) fs34.copyFileSync(fullPath, fullPath + ".bak");
|
|
59570
|
+
fs34.mkdirSync(path41.dirname(fullPath), { recursive: true });
|
|
59571
|
+
fs34.writeFileSync(fullPath, content, "utf-8");
|
|
59390
59572
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
59391
59573
|
this.providerLoader.reload();
|
|
59392
59574
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -59403,8 +59585,8 @@ var DevServer = class _DevServer {
|
|
|
59403
59585
|
}
|
|
59404
59586
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
59405
59587
|
const p = path41.join(dir, name);
|
|
59406
|
-
if (
|
|
59407
|
-
const source =
|
|
59588
|
+
if (fs34.existsSync(p)) {
|
|
59589
|
+
const source = fs34.readFileSync(p, "utf-8");
|
|
59408
59590
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
59409
59591
|
return;
|
|
59410
59592
|
}
|
|
@@ -59423,11 +59605,11 @@ var DevServer = class _DevServer {
|
|
|
59423
59605
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
59424
59606
|
return;
|
|
59425
59607
|
}
|
|
59426
|
-
const target =
|
|
59608
|
+
const target = fs34.existsSync(path41.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
59427
59609
|
const targetPath = path41.join(dir, target);
|
|
59428
59610
|
try {
|
|
59429
|
-
if (
|
|
59430
|
-
|
|
59611
|
+
if (fs34.existsSync(targetPath)) fs34.copyFileSync(targetPath, targetPath + ".bak");
|
|
59612
|
+
fs34.writeFileSync(targetPath, source, "utf-8");
|
|
59431
59613
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
59432
59614
|
this.providerLoader.reload();
|
|
59433
59615
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -59572,20 +59754,20 @@ var DevServer = class _DevServer {
|
|
|
59572
59754
|
let targetDir;
|
|
59573
59755
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
59574
59756
|
const jsonPath = path41.join(targetDir, "provider.json");
|
|
59575
|
-
if (
|
|
59757
|
+
if (fs34.existsSync(jsonPath)) {
|
|
59576
59758
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
59577
59759
|
return;
|
|
59578
59760
|
}
|
|
59579
59761
|
try {
|
|
59580
59762
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames });
|
|
59581
|
-
|
|
59582
|
-
|
|
59763
|
+
fs34.mkdirSync(targetDir, { recursive: true });
|
|
59764
|
+
fs34.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
59583
59765
|
const createdFiles = ["provider.json"];
|
|
59584
59766
|
if (result.files) {
|
|
59585
59767
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
59586
59768
|
const fullPath = path41.join(targetDir, relPath);
|
|
59587
|
-
|
|
59588
|
-
|
|
59769
|
+
fs34.mkdirSync(path41.dirname(fullPath), { recursive: true });
|
|
59770
|
+
fs34.writeFileSync(fullPath, content, "utf-8");
|
|
59589
59771
|
createdFiles.push(relPath);
|
|
59590
59772
|
}
|
|
59591
59773
|
}
|
|
@@ -59634,10 +59816,10 @@ var DevServer = class _DevServer {
|
|
|
59634
59816
|
}
|
|
59635
59817
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
59636
59818
|
getLatestScriptVersionDir(scriptsDir) {
|
|
59637
|
-
if (!
|
|
59638
|
-
const versions =
|
|
59819
|
+
if (!fs34.existsSync(scriptsDir)) return null;
|
|
59820
|
+
const versions = fs34.readdirSync(scriptsDir).filter((d) => {
|
|
59639
59821
|
try {
|
|
59640
|
-
return
|
|
59822
|
+
return fs34.statSync(path41.join(scriptsDir, d)).isDirectory();
|
|
59641
59823
|
} catch {
|
|
59642
59824
|
return false;
|
|
59643
59825
|
}
|
|
@@ -59659,13 +59841,13 @@ var DevServer = class _DevServer {
|
|
|
59659
59841
|
if (!sourceDir) {
|
|
59660
59842
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
59661
59843
|
}
|
|
59662
|
-
if (!
|
|
59663
|
-
|
|
59664
|
-
|
|
59844
|
+
if (!fs34.existsSync(desiredDir)) {
|
|
59845
|
+
fs34.mkdirSync(path41.dirname(desiredDir), { recursive: true });
|
|
59846
|
+
fs34.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
59665
59847
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
59666
59848
|
}
|
|
59667
59849
|
const providerJson = path41.join(desiredDir, "provider.json");
|
|
59668
|
-
if (!
|
|
59850
|
+
if (!fs34.existsSync(providerJson)) {
|
|
59669
59851
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
59670
59852
|
}
|
|
59671
59853
|
return { dir: desiredDir };
|
|
@@ -59708,10 +59890,10 @@ var DevServer = class _DevServer {
|
|
|
59708
59890
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
59709
59891
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
59710
59892
|
lines.push("");
|
|
59711
|
-
for (const file of
|
|
59893
|
+
for (const file of fs34.readdirSync(latestScriptsDir)) {
|
|
59712
59894
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
59713
59895
|
try {
|
|
59714
|
-
const content =
|
|
59896
|
+
const content = fs34.readFileSync(path41.join(latestScriptsDir, file), "utf-8");
|
|
59715
59897
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
59716
59898
|
lines.push("```javascript");
|
|
59717
59899
|
lines.push(content);
|
|
@@ -59721,14 +59903,14 @@ var DevServer = class _DevServer {
|
|
|
59721
59903
|
}
|
|
59722
59904
|
}
|
|
59723
59905
|
}
|
|
59724
|
-
const refFiles =
|
|
59906
|
+
const refFiles = fs34.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
59725
59907
|
if (refFiles.length > 0) {
|
|
59726
59908
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
59727
59909
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
59728
59910
|
lines.push("");
|
|
59729
59911
|
for (const file of refFiles) {
|
|
59730
59912
|
try {
|
|
59731
|
-
const content =
|
|
59913
|
+
const content = fs34.readFileSync(path41.join(latestScriptsDir, file), "utf-8");
|
|
59732
59914
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
59733
59915
|
lines.push("```javascript");
|
|
59734
59916
|
lines.push(content);
|
|
@@ -59773,7 +59955,7 @@ var DevServer = class _DevServer {
|
|
|
59773
59955
|
const loadGuide = (name) => {
|
|
59774
59956
|
try {
|
|
59775
59957
|
const p = path41.join(docsDir, name);
|
|
59776
|
-
if (
|
|
59958
|
+
if (fs34.existsSync(p)) return fs34.readFileSync(p, "utf-8");
|
|
59777
59959
|
} catch {
|
|
59778
59960
|
}
|
|
59779
59961
|
return null;
|
|
@@ -59954,11 +60136,11 @@ var DevServer = class _DevServer {
|
|
|
59954
60136
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
59955
60137
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
59956
60138
|
lines.push("");
|
|
59957
|
-
for (const file of
|
|
60139
|
+
for (const file of fs34.readdirSync(latestScriptsDir)) {
|
|
59958
60140
|
if (!file.endsWith(".js")) continue;
|
|
59959
60141
|
if (!targetFileNames.has(file)) continue;
|
|
59960
60142
|
try {
|
|
59961
|
-
const content =
|
|
60143
|
+
const content = fs34.readFileSync(path41.join(latestScriptsDir, file), "utf-8");
|
|
59962
60144
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
59963
60145
|
lines.push("```javascript");
|
|
59964
60146
|
lines.push(content);
|
|
@@ -59967,14 +60149,14 @@ var DevServer = class _DevServer {
|
|
|
59967
60149
|
} catch {
|
|
59968
60150
|
}
|
|
59969
60151
|
}
|
|
59970
|
-
const refFiles =
|
|
60152
|
+
const refFiles = fs34.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
59971
60153
|
if (refFiles.length > 0) {
|
|
59972
60154
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
59973
60155
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
59974
60156
|
lines.push("");
|
|
59975
60157
|
for (const file of refFiles) {
|
|
59976
60158
|
try {
|
|
59977
|
-
const content =
|
|
60159
|
+
const content = fs34.readFileSync(path41.join(latestScriptsDir, file), "utf-8");
|
|
59978
60160
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
59979
60161
|
lines.push("```javascript");
|
|
59980
60162
|
lines.push(content);
|
|
@@ -60011,7 +60193,7 @@ var DevServer = class _DevServer {
|
|
|
60011
60193
|
const loadGuide = (name) => {
|
|
60012
60194
|
try {
|
|
60013
60195
|
const p = path41.join(docsDir, name);
|
|
60014
|
-
if (
|
|
60196
|
+
if (fs34.existsSync(p)) return fs34.readFileSync(p, "utf-8");
|
|
60015
60197
|
} catch {
|
|
60016
60198
|
}
|
|
60017
60199
|
return null;
|
|
@@ -61112,8 +61294,8 @@ async function installExtension(ide, extension) {
|
|
|
61112
61294
|
const res = await fetch(extension.vsixUrl);
|
|
61113
61295
|
if (res.ok) {
|
|
61114
61296
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
61115
|
-
const
|
|
61116
|
-
|
|
61297
|
+
const fs35 = await import("fs");
|
|
61298
|
+
fs35.writeFileSync(vsixPath, buffer);
|
|
61117
61299
|
return new Promise((resolve24) => {
|
|
61118
61300
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
61119
61301
|
(0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|