@adhdev/daemon-core 0.9.82-rc.261 → 0.9.82-rc.263
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/build-info.d.ts +37 -0
- package/dist/commands/router.d.ts +116 -0
- package/dist/git/git-status.d.ts +7 -0
- package/dist/git/git-types.d.ts +19 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +971 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +967 -69
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-active-work.d.ts +18 -0
- package/dist/mesh/mesh-fast-forward.d.ts +41 -1
- package/dist/mesh/mesh-ledger.d.ts +1 -1
- package/dist/mesh/mesh-runtime-store.d.ts +6 -0
- package/dist/mesh/mesh-work-queue.d.ts +6 -0
- package/package.json +1 -1
- package/src/build-info.ts +73 -0
- package/src/commands/router.ts +805 -9
- package/src/git/git-status.ts +73 -1
- package/src/git/git-types.ts +20 -0
- package/src/index.ts +5 -2
- package/src/mesh/mesh-active-work.ts +31 -0
- package/src/mesh/mesh-fast-forward.ts +418 -17
- package/src/mesh/mesh-ledger.ts +1 -0
- package/src/mesh/mesh-runtime-store.ts +19 -0
- package/src/mesh/mesh-work-queue.ts +13 -0
package/dist/index.js
CHANGED
|
@@ -256,6 +256,29 @@ var init_git_executor = __esm({
|
|
|
256
256
|
}
|
|
257
257
|
});
|
|
258
258
|
|
|
259
|
+
// src/build-info.ts
|
|
260
|
+
function readInjected(value) {
|
|
261
|
+
if (typeof value !== "string") return void 0;
|
|
262
|
+
const trimmed = value.trim();
|
|
263
|
+
if (!trimmed || trimmed === "unknown") return void 0;
|
|
264
|
+
return trimmed;
|
|
265
|
+
}
|
|
266
|
+
function getDaemonBuildInfo() {
|
|
267
|
+
if (cached) return cached;
|
|
268
|
+
const commit = readInjected(true ? "2cf602f99ce68b3d3f1af02b429f6fb7a7c8e686" : void 0) ?? "unknown";
|
|
269
|
+
const commitShort = readInjected(true ? "2cf602f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
270
|
+
const version = readInjected(true ? "0.9.82-rc.263" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
271
|
+
const builtAt = readInjected(true ? "2026-06-14T13:48:10.699Z" : void 0);
|
|
272
|
+
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
273
|
+
return cached;
|
|
274
|
+
}
|
|
275
|
+
var cached;
|
|
276
|
+
var init_build_info = __esm({
|
|
277
|
+
"src/build-info.ts"() {
|
|
278
|
+
"use strict";
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
259
282
|
// src/git/git-status.ts
|
|
260
283
|
async function getGitRepoStatus(workspace, options = {}) {
|
|
261
284
|
const lastCheckedAt = Date.now();
|
|
@@ -278,6 +301,7 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
278
301
|
}
|
|
279
302
|
const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
|
|
280
303
|
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
|
|
304
|
+
const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options);
|
|
281
305
|
return {
|
|
282
306
|
workspace: repo.workspace,
|
|
283
307
|
repoRoot: repo.repoRoot,
|
|
@@ -301,7 +325,8 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
301
325
|
conflictFiles: parsed.conflictFiles,
|
|
302
326
|
stashCount,
|
|
303
327
|
lastCheckedAt,
|
|
304
|
-
submodules
|
|
328
|
+
submodules,
|
|
329
|
+
...daemonBuildBehind ? { daemonBuildBehind } : {}
|
|
305
330
|
};
|
|
306
331
|
} catch (error) {
|
|
307
332
|
if (error instanceof GitCommandError) {
|
|
@@ -314,6 +339,35 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
314
339
|
);
|
|
315
340
|
}
|
|
316
341
|
}
|
|
342
|
+
async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
343
|
+
const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
|
|
344
|
+
if (!build.commit || build.commit === "unknown") return void 0;
|
|
345
|
+
const scopes = [
|
|
346
|
+
{ scope: "root", repoPath: repo.repoRoot || repo.workspace }
|
|
347
|
+
];
|
|
348
|
+
for (const sub of submodules || []) {
|
|
349
|
+
if (sub.repoPath && !sub.error) scopes.push({ scope: sub.path, repoPath: sub.repoPath });
|
|
350
|
+
}
|
|
351
|
+
for (const { scope, repoPath } of scopes) {
|
|
352
|
+
try {
|
|
353
|
+
await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
|
|
354
|
+
const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
|
|
355
|
+
const head = headResult.stdout.trim();
|
|
356
|
+
if (!head || head === build.commit) continue;
|
|
357
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
|
|
358
|
+
return {
|
|
359
|
+
buildCommit: build.commit,
|
|
360
|
+
buildCommitShort: build.commitShort,
|
|
361
|
+
head,
|
|
362
|
+
scope,
|
|
363
|
+
warning: `Live daemon was built from ${build.commitShort} which is behind ${scope === "root" ? "workspace" : scope} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.`
|
|
364
|
+
};
|
|
365
|
+
} catch {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return void 0;
|
|
370
|
+
}
|
|
317
371
|
async function readPorcelainStatus(repo, options) {
|
|
318
372
|
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
319
373
|
return parsePorcelainV2Status(statusOutput.stdout);
|
|
@@ -530,6 +584,7 @@ var init_git_status = __esm({
|
|
|
530
584
|
"src/git/git-status.ts"() {
|
|
531
585
|
"use strict";
|
|
532
586
|
init_git_executor();
|
|
587
|
+
init_build_info();
|
|
533
588
|
}
|
|
534
589
|
});
|
|
535
590
|
|
|
@@ -2386,8 +2441,8 @@ function readLedgerFromStore(meshId) {
|
|
|
2386
2441
|
}
|
|
2387
2442
|
function getCachedRawEntries(meshId) {
|
|
2388
2443
|
const now = Date.now();
|
|
2389
|
-
const
|
|
2390
|
-
if (
|
|
2444
|
+
const cached2 = ledgerReadCache.get(meshId);
|
|
2445
|
+
if (cached2 && now - cached2.cachedAt < LEDGER_CACHE_TTL_MS) return cached2.entries;
|
|
2391
2446
|
let entries;
|
|
2392
2447
|
try {
|
|
2393
2448
|
entries = readLedgerFromStore(meshId);
|
|
@@ -2650,6 +2705,7 @@ __export(mesh_work_queue_exports, {
|
|
|
2650
2705
|
cancelTask: () => cancelTask,
|
|
2651
2706
|
claimNextTask: () => claimNextTask,
|
|
2652
2707
|
cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
|
|
2708
|
+
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
2653
2709
|
describeTaskDependencyState: () => describeTaskDependencyState,
|
|
2654
2710
|
enqueueTask: () => enqueueTask,
|
|
2655
2711
|
getActiveDirectDispatches: () => getActiveDirectDispatches,
|
|
@@ -3058,6 +3114,13 @@ function markStaleDirectDispatches(meshId, olderThanMs = 60 * 6e4) {
|
|
|
3058
3114
|
} catch {
|
|
3059
3115
|
}
|
|
3060
3116
|
}
|
|
3117
|
+
function deleteDirectDispatchesByTaskId(meshId, taskIds) {
|
|
3118
|
+
try {
|
|
3119
|
+
return MeshRuntimeStore.getInstance().deleteDirectDispatchesByTaskId(meshId, taskIds);
|
|
3120
|
+
} catch {
|
|
3121
|
+
return 0;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3061
3124
|
function recordMeshToolCall(opts) {
|
|
3062
3125
|
try {
|
|
3063
3126
|
return MeshRuntimeStore.getInstance().recordMeshToolCall(opts);
|
|
@@ -3691,6 +3754,24 @@ var init_mesh_runtime_store = __esm({
|
|
|
3691
3754
|
deleteDirectDispatches(meshId) {
|
|
3692
3755
|
this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ?`).run(meshId);
|
|
3693
3756
|
}
|
|
3757
|
+
/**
|
|
3758
|
+
* Delete specific direct dispatch rows by taskId for a mesh. Used by the staleDirect prune
|
|
3759
|
+
* path to remove orphaned/terminal dispatch records whose node/session is no longer in the
|
|
3760
|
+
* live mesh. Returns the number of rows actually deleted. No-op for an empty taskId list.
|
|
3761
|
+
*/
|
|
3762
|
+
deleteDirectDispatchesByTaskId(meshId, taskIds) {
|
|
3763
|
+
const ids = (taskIds || []).map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean);
|
|
3764
|
+
if (!ids.length) return 0;
|
|
3765
|
+
const stmt = this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ? AND task_id = ?`);
|
|
3766
|
+
let deleted = 0;
|
|
3767
|
+
const run = this.db.transaction((rows) => {
|
|
3768
|
+
for (const taskId of rows) {
|
|
3769
|
+
deleted += stmt.run(meshId, taskId).changes;
|
|
3770
|
+
}
|
|
3771
|
+
});
|
|
3772
|
+
run(ids);
|
|
3773
|
+
return deleted;
|
|
3774
|
+
}
|
|
3694
3775
|
markStaleDirectDispatches(meshId, olderThanMs) {
|
|
3695
3776
|
const cutoff = new Date(Date.now() - olderThanMs).toISOString();
|
|
3696
3777
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -5359,11 +5440,14 @@ async function fastForwardMeshNode(args) {
|
|
|
5359
5440
|
const trigger = normalizeOptionalString(args.trigger) || "manual";
|
|
5360
5441
|
const updateSubmodules = args.updateSubmodules === true;
|
|
5361
5442
|
const dryRun = args.dryRun === true || args.execute !== true;
|
|
5362
|
-
const
|
|
5443
|
+
const mode = args.mode === "push" ? "push" : "merge";
|
|
5444
|
+
const pushSubmodules = mode === "push" && args.pushSubmodules === true;
|
|
5445
|
+
const plannedSteps = buildPlannedSteps(mode, updateSubmodules, pushSubmodules);
|
|
5363
5446
|
const base = {
|
|
5364
5447
|
...nodeId ? { nodeId } : {},
|
|
5365
5448
|
...meshId ? { meshId } : {},
|
|
5366
5449
|
workspace,
|
|
5450
|
+
mode,
|
|
5367
5451
|
dryRun,
|
|
5368
5452
|
updateSubmodules,
|
|
5369
5453
|
plannedSteps,
|
|
@@ -5377,13 +5461,24 @@ async function fastForwardMeshNode(args) {
|
|
|
5377
5461
|
submoduleIgnorePaths: args.submoduleIgnorePaths,
|
|
5378
5462
|
timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
|
|
5379
5463
|
});
|
|
5464
|
+
if (mode === "push") {
|
|
5465
|
+
return pushMeshNode(base, args, current, {
|
|
5466
|
+
pushSubmodules,
|
|
5467
|
+
allowAutoPublishSubmoduleMainCommits: args.allowAutoPublishSubmoduleMainCommits === true
|
|
5468
|
+
});
|
|
5469
|
+
}
|
|
5380
5470
|
const earlyBlockers = collectPreflightBlockers(current, requestedBranch);
|
|
5381
5471
|
if (earlyBlockers.length > 0) {
|
|
5472
|
+
const blockCode = chooseBlockCode(current, earlyBlockers);
|
|
5382
5473
|
const result2 = {
|
|
5383
|
-
...block(base,
|
|
5474
|
+
...block(base, blockCode, earlyBlockers),
|
|
5384
5475
|
current,
|
|
5385
|
-
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(
|
|
5476
|
+
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(blockCode))
|
|
5386
5477
|
};
|
|
5478
|
+
if (blockCode === "branch_ahead" && current.ahead > 0 && current.behind === 0 && otherBlockersAreOnlyAhead(earlyBlockers)) {
|
|
5479
|
+
result2.code = "ahead_needs_push";
|
|
5480
|
+
result2.nextStep = 'Local branch is ahead of origin with nothing to merge. Re-run mesh_fast_forward_node with mode="push" (execute=true) to ff-only push the local commits to origin.';
|
|
5481
|
+
}
|
|
5387
5482
|
await appendFastForwardLedger(result2, "blocked");
|
|
5388
5483
|
return result2;
|
|
5389
5484
|
}
|
|
@@ -5494,7 +5589,246 @@ async function fastForwardMeshNode(args) {
|
|
|
5494
5589
|
await appendFastForwardLedger(result, success ? "executed" : "failed");
|
|
5495
5590
|
return result;
|
|
5496
5591
|
}
|
|
5497
|
-
function
|
|
5592
|
+
async function pushMeshNode(base, args, current, options) {
|
|
5593
|
+
const workspace = base.workspace;
|
|
5594
|
+
const requestedBranch = normalizeOptionalString(args.branch);
|
|
5595
|
+
const dryRun = base.dryRun;
|
|
5596
|
+
const blockers = collectPushPreflightBlockers(current, requestedBranch);
|
|
5597
|
+
if (blockers.length > 0) {
|
|
5598
|
+
const code2 = choosePushBlockCode(current, blockers);
|
|
5599
|
+
const result2 = {
|
|
5600
|
+
...block(base, code2, blockers),
|
|
5601
|
+
current,
|
|
5602
|
+
preStatus: current,
|
|
5603
|
+
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(code2))
|
|
5604
|
+
};
|
|
5605
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5606
|
+
return result2;
|
|
5607
|
+
}
|
|
5608
|
+
const target = parseUpstreamTarget(current.upstream || "");
|
|
5609
|
+
if (!target) {
|
|
5610
|
+
const result2 = {
|
|
5611
|
+
...block(base, "upstream_unparseable", ["upstream_unparseable"]),
|
|
5612
|
+
current,
|
|
5613
|
+
preStatus: current,
|
|
5614
|
+
finalBranchConvergenceState: buildConvergenceState(current, "blocked")
|
|
5615
|
+
};
|
|
5616
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5617
|
+
return result2;
|
|
5618
|
+
}
|
|
5619
|
+
const refspec = `HEAD:refs/heads/${target.remoteBranch}`;
|
|
5620
|
+
const pushTarget = { remote: target.remote, remoteBranch: target.remoteBranch, refspec };
|
|
5621
|
+
if (current.ahead <= 0) {
|
|
5622
|
+
const result2 = {
|
|
5623
|
+
...base,
|
|
5624
|
+
success: true,
|
|
5625
|
+
code: "nothing_to_push",
|
|
5626
|
+
allowed: true,
|
|
5627
|
+
willRun: false,
|
|
5628
|
+
executed: false,
|
|
5629
|
+
blockingReasons: [],
|
|
5630
|
+
current,
|
|
5631
|
+
preStatus: current,
|
|
5632
|
+
postStatus: current,
|
|
5633
|
+
pushTarget,
|
|
5634
|
+
finalBranchConvergenceState: buildConvergenceState(current, "up_to_date")
|
|
5635
|
+
};
|
|
5636
|
+
await appendFastForwardLedger(result2, "noop");
|
|
5637
|
+
return result2;
|
|
5638
|
+
}
|
|
5639
|
+
const descendant = await verifyUpstreamIsAncestorOfHead(workspace, current.upstream || "", args.timeoutMs);
|
|
5640
|
+
if (!descendant.ok) {
|
|
5641
|
+
const result2 = {
|
|
5642
|
+
...block(base, "non_fast_forward_push", ["head_is_not_descendant_of_upstream"]),
|
|
5643
|
+
current,
|
|
5644
|
+
preStatus: current,
|
|
5645
|
+
pushTarget,
|
|
5646
|
+
operationError: descendant.error,
|
|
5647
|
+
nextStep: "origin/<branch> has commits not in local HEAD; a ff-only push would lose them. Converge by rebasing onto origin first, then re-run. This operation never force-pushes.",
|
|
5648
|
+
finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
|
|
5649
|
+
};
|
|
5650
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5651
|
+
return result2;
|
|
5652
|
+
}
|
|
5653
|
+
if (dryRun) {
|
|
5654
|
+
const result2 = {
|
|
5655
|
+
...base,
|
|
5656
|
+
success: true,
|
|
5657
|
+
code: "push_available",
|
|
5658
|
+
allowed: true,
|
|
5659
|
+
willRun: false,
|
|
5660
|
+
executed: false,
|
|
5661
|
+
blockingReasons: [],
|
|
5662
|
+
current,
|
|
5663
|
+
preStatus: current,
|
|
5664
|
+
pushTarget,
|
|
5665
|
+
...options.pushSubmodules ? { submodulePushes: await planSubmodulePushes(current, options, args.timeoutMs) } : {},
|
|
5666
|
+
finalBranchConvergenceState: buildConvergenceState(current, "push_available")
|
|
5667
|
+
};
|
|
5668
|
+
await appendFastForwardLedger(result2, "dry_run");
|
|
5669
|
+
return result2;
|
|
5670
|
+
}
|
|
5671
|
+
try {
|
|
5672
|
+
await runGit(workspace, ["push", target.remote, refspec], { timeoutMs: args.timeoutMs ?? 3e4 });
|
|
5673
|
+
} catch (error) {
|
|
5674
|
+
const result2 = {
|
|
5675
|
+
...block(base, "push_ff_only_failed", ["push_ff_only_failed"]),
|
|
5676
|
+
current,
|
|
5677
|
+
preStatus: current,
|
|
5678
|
+
pushTarget,
|
|
5679
|
+
operationError: formatGitError2(error),
|
|
5680
|
+
finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
|
|
5681
|
+
};
|
|
5682
|
+
await appendFastForwardLedger(result2, "failed");
|
|
5683
|
+
return result2;
|
|
5684
|
+
}
|
|
5685
|
+
let submodulePushes;
|
|
5686
|
+
if (options.pushSubmodules) {
|
|
5687
|
+
submodulePushes = await executeSubmodulePushes(current, options, args.timeoutMs);
|
|
5688
|
+
}
|
|
5689
|
+
const postStatus = await getGitRepoStatus(workspace, {
|
|
5690
|
+
...STATUS_OPTIONS,
|
|
5691
|
+
submoduleIgnorePaths: args.submoduleIgnorePaths,
|
|
5692
|
+
timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
|
|
5693
|
+
});
|
|
5694
|
+
const submodulePushFailed = (submodulePushes || []).some((entry) => !entry.pushed && !entry.skipped);
|
|
5695
|
+
const blockingReasons = [];
|
|
5696
|
+
if (postStatus.ahead !== 0) blockingReasons.push("post_branch_ahead");
|
|
5697
|
+
if (submodulePushFailed) blockingReasons.push("submodule_push_failed");
|
|
5698
|
+
const success = blockingReasons.length === 0;
|
|
5699
|
+
const code = success ? "push_applied" : submodulePushFailed && postStatus.ahead === 0 ? "push_applied_submodule_push_failed" : "post_push_verify_failed";
|
|
5700
|
+
const result = {
|
|
5701
|
+
...base,
|
|
5702
|
+
success,
|
|
5703
|
+
code,
|
|
5704
|
+
allowed: true,
|
|
5705
|
+
willRun: true,
|
|
5706
|
+
executed: true,
|
|
5707
|
+
blockingReasons,
|
|
5708
|
+
current,
|
|
5709
|
+
preStatus: current,
|
|
5710
|
+
postStatus,
|
|
5711
|
+
pushTarget,
|
|
5712
|
+
...submodulePushes ? { submodulePushes } : {},
|
|
5713
|
+
finalBranchConvergenceState: buildConvergenceState(postStatus, success ? "pushed" : "post_verify_failed")
|
|
5714
|
+
};
|
|
5715
|
+
await appendFastForwardLedger(result, success ? "executed" : "failed");
|
|
5716
|
+
return result;
|
|
5717
|
+
}
|
|
5718
|
+
function collectPushPreflightBlockers(status, requestedBranch) {
|
|
5719
|
+
const blockers = [];
|
|
5720
|
+
if (!status.isGitRepo) blockers.push("not_git_repo");
|
|
5721
|
+
if (!status.branch) blockers.push("detached_head_or_unknown_branch");
|
|
5722
|
+
if (requestedBranch && status.branch !== requestedBranch) blockers.push("branch_mismatch");
|
|
5723
|
+
if (!status.upstream) blockers.push("upstream_missing");
|
|
5724
|
+
if (status.upstreamStatus !== "fresh") blockers.push("upstream_not_fresh");
|
|
5725
|
+
if (status.hasConflicts) blockers.push("conflicts_present");
|
|
5726
|
+
if (status.staged > 0) blockers.push("staged_changes_present");
|
|
5727
|
+
if (status.modified > 0) blockers.push("modified_changes_present");
|
|
5728
|
+
if (status.untracked > 0) blockers.push("untracked_changes_present");
|
|
5729
|
+
if (status.deleted > 0) blockers.push("deleted_changes_present");
|
|
5730
|
+
if (status.renamed > 0) blockers.push("renamed_changes_present");
|
|
5731
|
+
if (status.stashCount > 0) blockers.push("stash_entries_present");
|
|
5732
|
+
if (status.ahead > 0 && status.behind > 0) blockers.push("branch_diverged_from_upstream");
|
|
5733
|
+
else if (status.behind > 0) blockers.push("branch_behind_upstream");
|
|
5734
|
+
return blockers;
|
|
5735
|
+
}
|
|
5736
|
+
function choosePushBlockCode(status, blockers) {
|
|
5737
|
+
if (blockers.includes("not_git_repo")) return "not_git_repo";
|
|
5738
|
+
if (blockers.includes("branch_mismatch")) return "branch_mismatch";
|
|
5739
|
+
if (blockers.includes("upstream_missing")) return "upstream_missing";
|
|
5740
|
+
if (blockers.includes("upstream_not_fresh")) return "upstream_not_fresh";
|
|
5741
|
+
if (blockers.includes("branch_diverged_from_upstream")) return "branch_diverged";
|
|
5742
|
+
if (blockers.includes("branch_behind_upstream")) return "non_fast_forward_push";
|
|
5743
|
+
if (blockers.some((reason) => reason.includes("changes") || reason.includes("conflicts") || reason.includes("stash"))) return "dirty_worktree";
|
|
5744
|
+
return "preflight_blocked";
|
|
5745
|
+
}
|
|
5746
|
+
function parseUpstreamTarget(upstream) {
|
|
5747
|
+
const trimmed = upstream.trim();
|
|
5748
|
+
const slash = trimmed.indexOf("/");
|
|
5749
|
+
if (slash <= 0 || slash >= trimmed.length - 1) return null;
|
|
5750
|
+
return { remote: trimmed.slice(0, slash), remoteBranch: trimmed.slice(slash + 1) };
|
|
5751
|
+
}
|
|
5752
|
+
async function verifyUpstreamIsAncestorOfHead(workspace, upstream, timeoutMs) {
|
|
5753
|
+
if (!upstream) return { ok: false, error: "missing upstream" };
|
|
5754
|
+
try {
|
|
5755
|
+
await runGit(workspace, ["merge-base", "--is-ancestor", upstream, "HEAD"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5756
|
+
return { ok: true };
|
|
5757
|
+
} catch (error) {
|
|
5758
|
+
return { ok: false, error: formatGitError2(error) };
|
|
5759
|
+
}
|
|
5760
|
+
}
|
|
5761
|
+
async function planSubmodulePushes(status, options, timeoutMs) {
|
|
5762
|
+
return resolveSubmodulePushes(status, options, false, timeoutMs);
|
|
5763
|
+
}
|
|
5764
|
+
async function executeSubmodulePushes(status, options, timeoutMs) {
|
|
5765
|
+
return resolveSubmodulePushes(status, options, true, timeoutMs);
|
|
5766
|
+
}
|
|
5767
|
+
async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
|
|
5768
|
+
const submodules = Array.isArray(status.submodules) ? status.submodules : [];
|
|
5769
|
+
const results = [];
|
|
5770
|
+
for (const submodule of submodules) {
|
|
5771
|
+
const base = {
|
|
5772
|
+
path: submodule.path,
|
|
5773
|
+
commit: submodule.commit,
|
|
5774
|
+
remote: "origin",
|
|
5775
|
+
remoteBranch: "main",
|
|
5776
|
+
pushed: false,
|
|
5777
|
+
skipped: true,
|
|
5778
|
+
code: "submodule_push_skipped"
|
|
5779
|
+
};
|
|
5780
|
+
if (!options.allowAutoPublishSubmoduleMainCommits) {
|
|
5781
|
+
results.push({ ...base, code: "submodule_push_policy_disabled", error: "allowAutoPublishSubmoduleMainCommits is not enabled" });
|
|
5782
|
+
continue;
|
|
5783
|
+
}
|
|
5784
|
+
if (submodule.error || submodule.dirty) {
|
|
5785
|
+
results.push({ ...base, code: "submodule_not_clean", error: submodule.error || "submodule worktree is dirty" });
|
|
5786
|
+
continue;
|
|
5787
|
+
}
|
|
5788
|
+
const repoPath = submodule.repoPath;
|
|
5789
|
+
if (!repoPath || !submodule.commit) {
|
|
5790
|
+
results.push({ ...base, code: "submodule_status_incomplete" });
|
|
5791
|
+
continue;
|
|
5792
|
+
}
|
|
5793
|
+
try {
|
|
5794
|
+
await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5795
|
+
} catch (error) {
|
|
5796
|
+
results.push({ ...base, code: "submodule_fetch_failed", error: formatGitError2(error) });
|
|
5797
|
+
continue;
|
|
5798
|
+
}
|
|
5799
|
+
let alreadyReachable = false;
|
|
5800
|
+
try {
|
|
5801
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5802
|
+
alreadyReachable = true;
|
|
5803
|
+
} catch {
|
|
5804
|
+
}
|
|
5805
|
+
if (alreadyReachable) {
|
|
5806
|
+
results.push({ ...base, pushed: false, skipped: true, code: "submodule_already_reachable" });
|
|
5807
|
+
continue;
|
|
5808
|
+
}
|
|
5809
|
+
try {
|
|
5810
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", "refs/remotes/origin/main", submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5811
|
+
} catch (error) {
|
|
5812
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_non_fast_forward", error: formatGitError2(error) });
|
|
5813
|
+
continue;
|
|
5814
|
+
}
|
|
5815
|
+
const refspec = `${submodule.commit}:refs/heads/main`;
|
|
5816
|
+
if (!execute) {
|
|
5817
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_available", refspec });
|
|
5818
|
+
continue;
|
|
5819
|
+
}
|
|
5820
|
+
try {
|
|
5821
|
+
await runGit(repoPath, ["push", "origin", refspec], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5822
|
+
await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5823
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5824
|
+
results.push({ ...base, pushed: true, skipped: false, code: "submodule_pushed", refspec });
|
|
5825
|
+
} catch (error) {
|
|
5826
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_failed", refspec, error: formatGitError2(error) });
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
return results;
|
|
5830
|
+
}
|
|
5831
|
+
function buildPlannedSteps(mode, updateSubmodules, pushSubmodules) {
|
|
5498
5832
|
const steps = [
|
|
5499
5833
|
{
|
|
5500
5834
|
operation: "refresh_upstream",
|
|
@@ -5507,20 +5841,49 @@ function buildPlannedSteps(updateSubmodules) {
|
|
|
5507
5841
|
description: "Require clean staged/modified/untracked/deleted/renamed/conflict/stash/submodule state.",
|
|
5508
5842
|
safe: true,
|
|
5509
5843
|
willMutateWorktree: false
|
|
5510
|
-
}
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5844
|
+
}
|
|
5845
|
+
];
|
|
5846
|
+
if (mode === "push") {
|
|
5847
|
+
steps.push({
|
|
5848
|
+
operation: "verify_push_descendant",
|
|
5849
|
+
description: "Require HEAD to be a descendant of origin/<branch> (origin/<branch> is an ancestor of HEAD); refuse any non-fast-forward push.",
|
|
5514
5850
|
safe: true,
|
|
5515
5851
|
willMutateWorktree: false
|
|
5516
|
-
}
|
|
5517
|
-
{
|
|
5518
|
-
operation: "
|
|
5519
|
-
description: "
|
|
5852
|
+
});
|
|
5853
|
+
steps.push({
|
|
5854
|
+
operation: "push_ff_only",
|
|
5855
|
+
description: "Run git push origin HEAD:<branch> as a strict ff-only push; never --force, --force-with-lease, reset, or rebase. Does not mutate the worktree.",
|
|
5520
5856
|
safe: true,
|
|
5521
|
-
willMutateWorktree:
|
|
5857
|
+
willMutateWorktree: false
|
|
5858
|
+
});
|
|
5859
|
+
if (pushSubmodules) {
|
|
5860
|
+
steps.push({
|
|
5861
|
+
operation: "push_submodules_ff_only",
|
|
5862
|
+
description: "For each submodule, if allowAutoPublishSubmoduleMainCommits is enabled and the submodule HEAD is a descendant of its origin main, ff-only push it to submodule origin main; otherwise skip.",
|
|
5863
|
+
safe: true,
|
|
5864
|
+
willMutateWorktree: false
|
|
5865
|
+
});
|
|
5522
5866
|
}
|
|
5523
|
-
|
|
5867
|
+
steps.push({
|
|
5868
|
+
operation: "verify_post_status",
|
|
5869
|
+
description: "Re-read daemon-owned git status and report final branch convergence state.",
|
|
5870
|
+
safe: true,
|
|
5871
|
+
willMutateWorktree: false
|
|
5872
|
+
});
|
|
5873
|
+
return steps;
|
|
5874
|
+
}
|
|
5875
|
+
steps.push({
|
|
5876
|
+
operation: "verify_fast_forward",
|
|
5877
|
+
description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
|
|
5878
|
+
safe: true,
|
|
5879
|
+
willMutateWorktree: false
|
|
5880
|
+
});
|
|
5881
|
+
steps.push({
|
|
5882
|
+
operation: "merge_ff_only",
|
|
5883
|
+
description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
|
|
5884
|
+
safe: true,
|
|
5885
|
+
willMutateWorktree: true
|
|
5886
|
+
});
|
|
5524
5887
|
if (updateSubmodules) {
|
|
5525
5888
|
steps.push({
|
|
5526
5889
|
operation: "submodule_update",
|
|
@@ -5537,6 +5900,10 @@ function buildPlannedSteps(updateSubmodules) {
|
|
|
5537
5900
|
});
|
|
5538
5901
|
return steps;
|
|
5539
5902
|
}
|
|
5903
|
+
function otherBlockersAreOnlyAhead(blockers) {
|
|
5904
|
+
const aheadOnly = /* @__PURE__ */ new Set(["branch_has_local_commits"]);
|
|
5905
|
+
return blockers.every((reason) => aheadOnly.has(reason));
|
|
5906
|
+
}
|
|
5540
5907
|
function collectPreflightBlockers(status, requestedBranch) {
|
|
5541
5908
|
const blockers = [];
|
|
5542
5909
|
if (!status.isGitRepo) blockers.push("not_git_repo");
|
|
@@ -5593,7 +5960,7 @@ function chooseBlockCode(status, blockers) {
|
|
|
5593
5960
|
return "preflight_blocked";
|
|
5594
5961
|
}
|
|
5595
5962
|
function codeToConvergenceStatus(code) {
|
|
5596
|
-
if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward") return "not_mergeable";
|
|
5963
|
+
if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward" || code === "non_fast_forward_push" || code === "upstream_unparseable") return "not_mergeable";
|
|
5597
5964
|
if (code === "dirty_worktree" || code === "submodule_not_clean") return "blocked_review";
|
|
5598
5965
|
return "blocked";
|
|
5599
5966
|
}
|
|
@@ -5676,6 +6043,7 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5676
6043
|
...result.nodeId ? { nodeId: result.nodeId } : {},
|
|
5677
6044
|
payload: {
|
|
5678
6045
|
operation: "mesh_fast_forward_node",
|
|
6046
|
+
mode: result.mode,
|
|
5679
6047
|
trigger: result.trigger || "manual",
|
|
5680
6048
|
outcome,
|
|
5681
6049
|
code: result.code,
|
|
@@ -5686,6 +6054,7 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5686
6054
|
executed: result.executed,
|
|
5687
6055
|
branch: result.postStatus?.branch ?? result.current?.branch,
|
|
5688
6056
|
upstream: result.postStatus?.upstream ?? result.current?.upstream,
|
|
6057
|
+
...result.pushTarget ? { pushTarget: result.pushTarget } : {},
|
|
5689
6058
|
before: result.current ? {
|
|
5690
6059
|
headCommit: result.current.headCommit,
|
|
5691
6060
|
ahead: result.current.ahead,
|
|
@@ -5696,6 +6065,16 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5696
6065
|
ahead: result.postStatus.ahead,
|
|
5697
6066
|
behind: result.postStatus.behind
|
|
5698
6067
|
} : void 0,
|
|
6068
|
+
...result.submodulePushes ? {
|
|
6069
|
+
submodulePushes: result.submodulePushes.map((entry) => ({
|
|
6070
|
+
path: entry.path,
|
|
6071
|
+
commit: entry.commit,
|
|
6072
|
+
pushed: entry.pushed,
|
|
6073
|
+
skipped: entry.skipped,
|
|
6074
|
+
code: entry.code,
|
|
6075
|
+
...entry.refspec ? { refspec: entry.refspec } : {}
|
|
6076
|
+
}))
|
|
6077
|
+
} : {},
|
|
5699
6078
|
blockingReasons: result.blockingReasons
|
|
5700
6079
|
}
|
|
5701
6080
|
});
|
|
@@ -6866,8 +7245,8 @@ var init_mesh_routing = __esm({
|
|
|
6866
7245
|
// src/mesh/mesh-events-coordinator.ts
|
|
6867
7246
|
function getCachedMeshByWorkspace(workspace) {
|
|
6868
7247
|
const now = Date.now();
|
|
6869
|
-
const
|
|
6870
|
-
if (
|
|
7248
|
+
const cached2 = meshByWorkspaceCache.get(workspace);
|
|
7249
|
+
if (cached2 && now - cached2.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached2.mesh;
|
|
6871
7250
|
const mesh = getMeshByRepo(workspace);
|
|
6872
7251
|
meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
|
|
6873
7252
|
return mesh;
|
|
@@ -11759,10 +12138,10 @@ ${lastSnapshot}`;
|
|
|
11759
12138
|
return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
11760
12139
|
}
|
|
11761
12140
|
getFreshParsedStatusCache() {
|
|
11762
|
-
const
|
|
12141
|
+
const cached2 = this.parsedStatusCache;
|
|
11763
12142
|
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
11764
|
-
if (
|
|
11765
|
-
return
|
|
12143
|
+
if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.engine.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.engine.currentStatus && cached2.activeModal === this.engine.activeModal && cached2.cliName === this.cliName) {
|
|
12144
|
+
return cached2.result;
|
|
11766
12145
|
}
|
|
11767
12146
|
return null;
|
|
11768
12147
|
}
|
|
@@ -12222,10 +12601,10 @@ ${lastSnapshot}`;
|
|
|
12222
12601
|
getScriptParsedStatus() {
|
|
12223
12602
|
const screenText = this.readTerminalScreenText();
|
|
12224
12603
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
12225
|
-
const
|
|
12604
|
+
const cached2 = this.parsedStatusCache;
|
|
12226
12605
|
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
12227
|
-
if (!this.providerOwnsTranscript() &&
|
|
12228
|
-
return
|
|
12606
|
+
if (!this.providerOwnsTranscript() && cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.engine.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === parseScreenText && cached2.currentStatus === this.engine.currentStatus && cached2.activeModal === this.engine.activeModal && cached2.cliName === this.cliName) {
|
|
12607
|
+
return cached2.result;
|
|
12229
12608
|
}
|
|
12230
12609
|
const parsed = this.runParseSession();
|
|
12231
12610
|
if (!parsed || !Array.isArray(parsed.messages)) {
|
|
@@ -14091,6 +14470,7 @@ __export(index_exports, {
|
|
|
14091
14470
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
14092
14471
|
NodePtyTransportFactory: () => NodePtyTransportFactory,
|
|
14093
14472
|
P2pRelayFailureError: () => P2pRelayFailureError,
|
|
14473
|
+
PRUNABLE_ORPHAN_STALE_REASONS: () => PRUNABLE_ORPHAN_STALE_REASONS,
|
|
14094
14474
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
14095
14475
|
ProviderInstanceManager: () => ProviderInstanceManager,
|
|
14096
14476
|
ProviderLoader: () => ProviderLoader,
|
|
@@ -14144,6 +14524,7 @@ __export(index_exports, {
|
|
|
14144
14524
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
14145
14525
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
14146
14526
|
classifyP2pRelayFailure: () => classifyP2pRelayFailure,
|
|
14527
|
+
classifyStaleDirectForPrune: () => classifyStaleDirectForPrune,
|
|
14147
14528
|
cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
|
|
14148
14529
|
clearDebugTrace: () => clearDebugTrace,
|
|
14149
14530
|
clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
|
|
@@ -14163,6 +14544,7 @@ __export(index_exports, {
|
|
|
14163
14544
|
createNativeHistoryDispatcher: () => createNativeHistoryDispatcher,
|
|
14164
14545
|
createSessionDelivery: () => createSessionDelivery,
|
|
14165
14546
|
createWorktree: () => createWorktree,
|
|
14547
|
+
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
14166
14548
|
deleteMesh: () => deleteMesh,
|
|
14167
14549
|
deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems,
|
|
14168
14550
|
describeTaskDependencyState: () => describeTaskDependencyState,
|
|
@@ -14191,6 +14573,7 @@ __export(index_exports, {
|
|
|
14191
14573
|
getAvailableIdeIds: () => getAvailableIdeIds,
|
|
14192
14574
|
getCoordinatorForSession: () => getCoordinatorForSession,
|
|
14193
14575
|
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
14576
|
+
getDaemonBuildInfo: () => getDaemonBuildInfo,
|
|
14194
14577
|
getDaemonDataDir: () => getDaemonDataDir,
|
|
14195
14578
|
getDaemonLogDir: () => getDaemonLogDir,
|
|
14196
14579
|
getDebugRuntimeConfig: () => getDebugRuntimeConfig,
|
|
@@ -17037,6 +17420,17 @@ function buildMeshActiveWork(opts) {
|
|
|
17037
17420
|
}
|
|
17038
17421
|
return { activeWork: records, staleDirectWork, staleDirectWorkNote, terminalDirectWork, summary };
|
|
17039
17422
|
}
|
|
17423
|
+
var PRUNABLE_ORPHAN_STALE_REASONS = /* @__PURE__ */ new Set([
|
|
17424
|
+
"direct task node is no longer in the live mesh",
|
|
17425
|
+
"direct task session is not present in live session records",
|
|
17426
|
+
"direct task has no node id"
|
|
17427
|
+
]);
|
|
17428
|
+
function classifyStaleDirectForPrune(record, opts = {}) {
|
|
17429
|
+
if (record.staleDispatchUnacknowledged === true) return "preserve_unacknowledged";
|
|
17430
|
+
if (record.terminal === true) return opts.includeTerminal ? "prunable_terminal" : "preserve_active";
|
|
17431
|
+
if (record.staleReason && PRUNABLE_ORPHAN_STALE_REASONS.has(record.staleReason)) return "prunable_orphan";
|
|
17432
|
+
return "preserve_active";
|
|
17433
|
+
}
|
|
17040
17434
|
function buildCompactStaleDirectWorkSummary(staleDirectWork, opts = {}) {
|
|
17041
17435
|
const sampleLimit = Math.max(0, Math.min(10, Math.floor(opts.sampleLimit ?? 3)));
|
|
17042
17436
|
const reasonCounts = {};
|
|
@@ -20260,9 +20654,9 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
20260
20654
|
for (const file of files.slice().sort()) {
|
|
20261
20655
|
const filePath = path12.join(dir, file);
|
|
20262
20656
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
20263
|
-
const
|
|
20657
|
+
const cached2 = savedHistoryFileSummaryCache.get(filePath);
|
|
20264
20658
|
const persisted = persistedEntries.get(file);
|
|
20265
|
-
const reusableEntry =
|
|
20659
|
+
const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
|
|
20266
20660
|
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file);
|
|
20267
20661
|
const nextEntry = reusableEntry || {
|
|
20268
20662
|
signature,
|
|
@@ -20714,23 +21108,23 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
20714
21108
|
savedHistorySessionCache.delete(sanitized);
|
|
20715
21109
|
return { sessions: [], hasMore: false };
|
|
20716
21110
|
}
|
|
20717
|
-
const
|
|
21111
|
+
const cached2 = savedHistorySessionCache.get(sanitized);
|
|
20718
21112
|
const offset = Math.max(0, options.offset || 0);
|
|
20719
21113
|
const limit = Math.max(1, options.limit || 30);
|
|
20720
21114
|
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
20721
21115
|
let cacheWasInvalidated = false;
|
|
20722
|
-
if (
|
|
20723
|
-
const cacheLooksPersisted =
|
|
20724
|
-
const cacheStillValid = cacheLooksPersisted ?
|
|
21116
|
+
if (cached2) {
|
|
21117
|
+
const cacheLooksPersisted = cached2.signature.startsWith("index:");
|
|
21118
|
+
const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
|
|
20725
21119
|
const files2 = listHistoryFiles(dir);
|
|
20726
21120
|
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
20727
|
-
return
|
|
21121
|
+
return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
20728
21122
|
})();
|
|
20729
21123
|
if (cacheStillValid) {
|
|
20730
|
-
const sliced2 =
|
|
21124
|
+
const sliced2 = cached2.summaries.slice(offset, offset + limit);
|
|
20731
21125
|
return {
|
|
20732
21126
|
sessions: sliced2,
|
|
20733
|
-
hasMore:
|
|
21127
|
+
hasMore: cached2.summaries.length > offset + limit
|
|
20734
21128
|
};
|
|
20735
21129
|
}
|
|
20736
21130
|
cacheWasInvalidated = true;
|
|
@@ -37319,8 +37713,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
37319
37713
|
return null;
|
|
37320
37714
|
}
|
|
37321
37715
|
registerProviderScriptRootSafely(path30.dirname(path30.dirname(providerDir)));
|
|
37322
|
-
const
|
|
37323
|
-
if (
|
|
37716
|
+
const cached2 = this.scriptsCache.get(dir);
|
|
37717
|
+
if (cached2) return cached2;
|
|
37324
37718
|
const scriptsJs = path30.join(dir, "scripts.js");
|
|
37325
37719
|
if (fs20.existsSync(scriptsJs)) {
|
|
37326
37720
|
try {
|
|
@@ -39318,6 +39712,9 @@ function buildStatusSnapshot(options) {
|
|
|
39318
39712
|
};
|
|
39319
39713
|
}
|
|
39320
39714
|
|
|
39715
|
+
// src/commands/router.ts
|
|
39716
|
+
init_build_info();
|
|
39717
|
+
|
|
39321
39718
|
// src/commands/upgrade-helper.ts
|
|
39322
39719
|
var import_child_process7 = require("child_process");
|
|
39323
39720
|
var import_child_process8 = require("child_process");
|
|
@@ -40103,13 +40500,13 @@ function sanitizeInlineMesh(inlineMesh) {
|
|
|
40103
40500
|
nodes
|
|
40104
40501
|
};
|
|
40105
40502
|
}
|
|
40106
|
-
function reconcileInlineMeshCache(
|
|
40107
|
-
if (!
|
|
40108
|
-
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return
|
|
40109
|
-
const cachedNodes = Array.isArray(
|
|
40503
|
+
function reconcileInlineMeshCache(cached2, incoming) {
|
|
40504
|
+
if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
|
|
40505
|
+
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
|
|
40506
|
+
const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
|
|
40110
40507
|
const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
|
|
40111
|
-
if (!cachedNodes.length || !incomingNodes.length) return { ...
|
|
40112
|
-
const cachedUpdatedAt = Date.parse(readStringValue(
|
|
40508
|
+
if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
|
|
40509
|
+
const cachedUpdatedAt = Date.parse(readStringValue(cached2.updatedAt, cached2.updated_at) || "");
|
|
40113
40510
|
const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
|
|
40114
40511
|
const preserveCachedMembership = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
|
|
40115
40512
|
const cachedById = /* @__PURE__ */ new Map();
|
|
@@ -40138,7 +40535,7 @@ function reconcileInlineMeshCache(cached, incoming) {
|
|
|
40138
40535
|
}
|
|
40139
40536
|
}
|
|
40140
40537
|
return {
|
|
40141
|
-
...
|
|
40538
|
+
...cached2,
|
|
40142
40539
|
...incoming,
|
|
40143
40540
|
nodes
|
|
40144
40541
|
};
|
|
@@ -40749,8 +41146,37 @@ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead)
|
|
|
40749
41146
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
40750
41147
|
});
|
|
40751
41148
|
const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
|
|
40752
|
-
|
|
40753
|
-
|
|
41149
|
+
let mergedTree = "";
|
|
41150
|
+
let mergeTreeStdout = "";
|
|
41151
|
+
let gitlinkTrivialFastForward;
|
|
41152
|
+
try {
|
|
41153
|
+
mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
|
|
41154
|
+
mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
|
|
41155
|
+
} catch (mergeTreeErr) {
|
|
41156
|
+
const output = `${mergeTreeErr?.message || ""}
|
|
41157
|
+
${mergeTreeErr?.stdout || ""}
|
|
41158
|
+
${mergeTreeErr?.stderr || ""}`;
|
|
41159
|
+
const isSubmoduleConflict = /(submodule|160000)/i.test(output) || /Recursive merging with submodules/i.test(output);
|
|
41160
|
+
if (!isSubmoduleConflict) throw mergeTreeErr;
|
|
41161
|
+
const evaluation = evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead);
|
|
41162
|
+
if (!evaluation.trivial) {
|
|
41163
|
+
return {
|
|
41164
|
+
status: "failed",
|
|
41165
|
+
equivalent: false,
|
|
41166
|
+
baseHead,
|
|
41167
|
+
branchHead,
|
|
41168
|
+
mergeBase: mergeBase || void 0,
|
|
41169
|
+
durationMs: Date.now() - startedAt,
|
|
41170
|
+
error: mergeTreeErr?.message || String(mergeTreeErr),
|
|
41171
|
+
stdout: truncateValidationOutput(mergeTreeErr?.stdout),
|
|
41172
|
+
stderr: truncateValidationOutput(mergeTreeErr?.stderr),
|
|
41173
|
+
gitlinkTrivialFastForward: { resolved: false, gitlinks: evaluation.gitlinks, reason: evaluation.reason },
|
|
41174
|
+
actionableHint: buildPatchEquivalenceSubmoduleConflictHint(repoRoot, baseHead, branchHead, output)
|
|
41175
|
+
};
|
|
41176
|
+
}
|
|
41177
|
+
mergedTree = synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, evaluation.gitlinks) || "";
|
|
41178
|
+
gitlinkTrivialFastForward = { resolved: true, gitlinks: evaluation.gitlinks };
|
|
41179
|
+
}
|
|
40754
41180
|
if (!mergeBase || !mergedTree) {
|
|
40755
41181
|
return {
|
|
40756
41182
|
status: "failed",
|
|
@@ -40761,7 +41187,8 @@ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead)
|
|
|
40761
41187
|
mergedTree: mergedTree || void 0,
|
|
40762
41188
|
durationMs: Date.now() - startedAt,
|
|
40763
41189
|
error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
|
|
40764
|
-
stdout: truncateValidationOutput(mergeTreeStdout)
|
|
41190
|
+
stdout: truncateValidationOutput(mergeTreeStdout),
|
|
41191
|
+
gitlinkTrivialFastForward
|
|
40765
41192
|
};
|
|
40766
41193
|
}
|
|
40767
41194
|
const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
|
|
@@ -40776,7 +41203,8 @@ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead)
|
|
|
40776
41203
|
mergedTree,
|
|
40777
41204
|
expectedPatchId,
|
|
40778
41205
|
actualPatchId,
|
|
40779
|
-
durationMs: Date.now() - startedAt
|
|
41206
|
+
durationMs: Date.now() - startedAt,
|
|
41207
|
+
gitlinkTrivialFastForward
|
|
40780
41208
|
};
|
|
40781
41209
|
} catch (e) {
|
|
40782
41210
|
return {
|
|
@@ -40799,6 +41227,65 @@ ${e?.stderr || ""}`
|
|
|
40799
41227
|
};
|
|
40800
41228
|
}
|
|
40801
41229
|
}
|
|
41230
|
+
async function runMeshRefineEffectiveDiffGate(repoRoot, baseHead, branchHead) {
|
|
41231
|
+
const startedAt = Date.now();
|
|
41232
|
+
try {
|
|
41233
|
+
const { execFileSync: execFileSync6 } = await import("child_process");
|
|
41234
|
+
const git = (args, opts) => execFileSync6("git", args, {
|
|
41235
|
+
cwd: opts?.cwd || repoRoot,
|
|
41236
|
+
encoding: "utf8",
|
|
41237
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
41238
|
+
});
|
|
41239
|
+
const rawDiff = git(["diff", "--raw", baseHead, branchHead]).trim();
|
|
41240
|
+
if (rawDiff) {
|
|
41241
|
+
const changedPaths = rawDiff.split("\n").map((line) => line.split(" ").slice(1).join(" ").trim()).filter(Boolean).slice(0, 50);
|
|
41242
|
+
return {
|
|
41243
|
+
status: "passed",
|
|
41244
|
+
hasEffectiveDiff: true,
|
|
41245
|
+
baseHead,
|
|
41246
|
+
branchHead,
|
|
41247
|
+
changedPaths,
|
|
41248
|
+
durationMs: Date.now() - startedAt
|
|
41249
|
+
};
|
|
41250
|
+
}
|
|
41251
|
+
const submoduleHints = [];
|
|
41252
|
+
try {
|
|
41253
|
+
const status = git(["submodule", "status"]);
|
|
41254
|
+
for (const line of status.split("\n")) {
|
|
41255
|
+
const trimmed = line.trimEnd();
|
|
41256
|
+
if (!trimmed) continue;
|
|
41257
|
+
if (trimmed.startsWith("+")) {
|
|
41258
|
+
const parts = trimmed.slice(1).trim().split(/\s+/);
|
|
41259
|
+
const path39 = parts[1] || parts[0] || "(unknown)";
|
|
41260
|
+
submoduleHints.push({
|
|
41261
|
+
path: path39,
|
|
41262
|
+
reason: "submodule checked-out commit differs from the committed gitlink (pointer bump not committed on the root branch)"
|
|
41263
|
+
});
|
|
41264
|
+
}
|
|
41265
|
+
}
|
|
41266
|
+
} catch {
|
|
41267
|
+
}
|
|
41268
|
+
return {
|
|
41269
|
+
status: "failed",
|
|
41270
|
+
hasEffectiveDiff: false,
|
|
41271
|
+
baseHead,
|
|
41272
|
+
branchHead,
|
|
41273
|
+
...submoduleHints.length ? { submoduleHints } : {},
|
|
41274
|
+
durationMs: Date.now() - startedAt
|
|
41275
|
+
};
|
|
41276
|
+
} catch (e) {
|
|
41277
|
+
return {
|
|
41278
|
+
status: "skipped",
|
|
41279
|
+
hasEffectiveDiff: true,
|
|
41280
|
+
baseHead,
|
|
41281
|
+
branchHead,
|
|
41282
|
+
durationMs: Date.now() - startedAt,
|
|
41283
|
+
error: e?.message || String(e),
|
|
41284
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
41285
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
41286
|
+
};
|
|
41287
|
+
}
|
|
41288
|
+
}
|
|
40802
41289
|
function buildPatchEquivalenceSubmoduleConflictHint(repoRoot, baseHead, branchHead, output) {
|
|
40803
41290
|
if (!/(submodule|160000)/i.test(output) || !/(conflict|failed to merge)/i.test(output)) return void 0;
|
|
40804
41291
|
const conflicts = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path39) => ({
|
|
@@ -40855,6 +41342,135 @@ function readTreeObject(repoRoot, ref, path39) {
|
|
|
40855
41342
|
return void 0;
|
|
40856
41343
|
}
|
|
40857
41344
|
}
|
|
41345
|
+
function resolveGitDir(repoRoot) {
|
|
41346
|
+
const out = (0, import_node_child_process6.execFileSync)("git", ["rev-parse", "--absolute-git-dir"], {
|
|
41347
|
+
cwd: repoRoot,
|
|
41348
|
+
encoding: "utf8",
|
|
41349
|
+
maxBuffer: 1024 * 1024
|
|
41350
|
+
}).trim();
|
|
41351
|
+
return out;
|
|
41352
|
+
}
|
|
41353
|
+
function isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit) {
|
|
41354
|
+
if (!baseCommit || !branchCommit) return false;
|
|
41355
|
+
if (baseCommit === branchCommit) return true;
|
|
41356
|
+
try {
|
|
41357
|
+
if (!fs23.existsSync(submoduleRepoPath)) return false;
|
|
41358
|
+
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
41359
|
+
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
41360
|
+
(0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
41361
|
+
return true;
|
|
41362
|
+
} catch {
|
|
41363
|
+
return false;
|
|
41364
|
+
}
|
|
41365
|
+
}
|
|
41366
|
+
function readChangedPathKinds(repoRoot, fromRef, toRef) {
|
|
41367
|
+
try {
|
|
41368
|
+
const output = (0, import_node_child_process6.execFileSync)("git", ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
|
|
41369
|
+
cwd: repoRoot,
|
|
41370
|
+
encoding: "utf8",
|
|
41371
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
41372
|
+
});
|
|
41373
|
+
const result = [];
|
|
41374
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41375
|
+
for (const line of output.split("\n")) {
|
|
41376
|
+
if (!line.trim()) continue;
|
|
41377
|
+
const metaAndPath = line.split(" ");
|
|
41378
|
+
const meta = metaAndPath[0] || "";
|
|
41379
|
+
const path39 = metaAndPath[metaAndPath.length - 1]?.trim();
|
|
41380
|
+
if (!path39 || seen.has(path39)) continue;
|
|
41381
|
+
seen.add(path39);
|
|
41382
|
+
const parts = meta.split(/\s+/);
|
|
41383
|
+
const isGitlink = !!(parts[0]?.includes("160000") || parts[1]?.includes("160000"));
|
|
41384
|
+
result.push({ path: path39, isGitlink });
|
|
41385
|
+
}
|
|
41386
|
+
return result;
|
|
41387
|
+
} catch {
|
|
41388
|
+
return [];
|
|
41389
|
+
}
|
|
41390
|
+
}
|
|
41391
|
+
function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
41392
|
+
const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path39) => {
|
|
41393
|
+
const baseCommit = readTreeObject(repoRoot, baseHead, path39);
|
|
41394
|
+
const branchCommit = readTreeObject(repoRoot, branchHead, path39);
|
|
41395
|
+
const submoduleRepoPath = (0, import_path10.resolve)(repoRoot, path39);
|
|
41396
|
+
const fastForward = !!baseCommit && !!branchCommit && isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit);
|
|
41397
|
+
return { path: path39, baseCommit, branchCommit, fastForward };
|
|
41398
|
+
});
|
|
41399
|
+
if (changedGitlinks.length === 0) {
|
|
41400
|
+
return { trivial: false, reason: "no_changed_gitlinks", gitlinks: changedGitlinks };
|
|
41401
|
+
}
|
|
41402
|
+
const nonFastForward = changedGitlinks.filter((entry) => !entry.fastForward);
|
|
41403
|
+
if (nonFastForward.length > 0) {
|
|
41404
|
+
return {
|
|
41405
|
+
trivial: false,
|
|
41406
|
+
reason: `diverged_gitlinks:${nonFastForward.map((entry) => entry.path).join(",")}`,
|
|
41407
|
+
gitlinks: changedGitlinks
|
|
41408
|
+
};
|
|
41409
|
+
}
|
|
41410
|
+
let mergeBase = "";
|
|
41411
|
+
try {
|
|
41412
|
+
mergeBase = (0, import_node_child_process6.execFileSync)("git", ["merge-base", baseHead, branchHead], {
|
|
41413
|
+
cwd: repoRoot,
|
|
41414
|
+
encoding: "utf8",
|
|
41415
|
+
maxBuffer: 1024 * 1024
|
|
41416
|
+
}).trim();
|
|
41417
|
+
} catch {
|
|
41418
|
+
return { trivial: false, reason: "merge_base_unresolved", gitlinks: changedGitlinks };
|
|
41419
|
+
}
|
|
41420
|
+
if (!mergeBase) {
|
|
41421
|
+
return { trivial: false, reason: "merge_base_unresolved", gitlinks: changedGitlinks };
|
|
41422
|
+
}
|
|
41423
|
+
const baseSideChanges = readChangedPathKinds(repoRoot, mergeBase, baseHead);
|
|
41424
|
+
const branchSideChanges = readChangedPathKinds(repoRoot, mergeBase, branchHead);
|
|
41425
|
+
const baseChangedPaths = new Map(baseSideChanges.map((entry) => [entry.path, entry]));
|
|
41426
|
+
const overlapping = branchSideChanges.filter((entry) => baseChangedPaths.has(entry.path));
|
|
41427
|
+
const nonGitlinkOverlap = overlapping.filter((entry) => {
|
|
41428
|
+
const baseEntry = baseChangedPaths.get(entry.path);
|
|
41429
|
+
return !(entry.isGitlink && baseEntry?.isGitlink);
|
|
41430
|
+
});
|
|
41431
|
+
if (nonGitlinkOverlap.length > 0) {
|
|
41432
|
+
return {
|
|
41433
|
+
trivial: false,
|
|
41434
|
+
reason: `non_gitlink_overlap:${nonGitlinkOverlap.map((entry) => entry.path).join(",")}`,
|
|
41435
|
+
gitlinks: changedGitlinks
|
|
41436
|
+
};
|
|
41437
|
+
}
|
|
41438
|
+
return { trivial: true, gitlinks: changedGitlinks };
|
|
41439
|
+
}
|
|
41440
|
+
function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, gitlinks) {
|
|
41441
|
+
try {
|
|
41442
|
+
const baseTree = (0, import_node_child_process6.execFileSync)("git", ["rev-parse", `${baseHead}^{tree}`], {
|
|
41443
|
+
cwd: repoRoot,
|
|
41444
|
+
encoding: "utf8",
|
|
41445
|
+
maxBuffer: 1024 * 1024
|
|
41446
|
+
}).trim();
|
|
41447
|
+
if (!baseTree) return void 0;
|
|
41448
|
+
const updates = gitlinks.filter((entry) => entry.branchCommit).map((entry) => `160000 commit ${entry.branchCommit} ${entry.path}`).join("\n");
|
|
41449
|
+
if (!updates) return baseTree;
|
|
41450
|
+
const tmpIndex = (0, import_path10.join)(resolveGitDir(repoRoot), `adhdev-refine-ff-${baseHead.slice(0, 12)}-${branchHead.slice(0, 12)}.index`);
|
|
41451
|
+
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
41452
|
+
try {
|
|
41453
|
+
(0, import_node_child_process6.execFileSync)("git", ["read-tree", baseTree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
41454
|
+
(0, import_node_child_process6.execFileSync)("git", ["update-index", "--index-info"], {
|
|
41455
|
+
cwd: repoRoot,
|
|
41456
|
+
env,
|
|
41457
|
+
input: `${updates}
|
|
41458
|
+
`,
|
|
41459
|
+
encoding: "utf8",
|
|
41460
|
+
stdio: ["pipe", "ignore", "ignore"]
|
|
41461
|
+
});
|
|
41462
|
+
const newTree = (0, import_node_child_process6.execFileSync)("git", ["write-tree"], { cwd: repoRoot, env, encoding: "utf8" }).trim();
|
|
41463
|
+
return newTree || void 0;
|
|
41464
|
+
} finally {
|
|
41465
|
+
try {
|
|
41466
|
+
fs23.rmSync(tmpIndex, { force: true });
|
|
41467
|
+
} catch {
|
|
41468
|
+
}
|
|
41469
|
+
}
|
|
41470
|
+
} catch {
|
|
41471
|
+
return void 0;
|
|
41472
|
+
}
|
|
41473
|
+
}
|
|
40858
41474
|
async function alignRefinerySubmodulesAfterMerge(repoRoot, previousBaseHead, currentHead, options = {}) {
|
|
40859
41475
|
const startedAt = Date.now();
|
|
40860
41476
|
const changedGitlinkPaths = readChangedGitlinkPaths(repoRoot, previousBaseHead, currentHead).filter((path39) => !(options.submoduleIgnorePaths || []).includes(path39));
|
|
@@ -41522,6 +42138,10 @@ var DaemonCommandRouter = class {
|
|
|
41522
42138
|
runningRefineJobs = /* @__PURE__ */ new Map();
|
|
41523
42139
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
|
41524
42140
|
terminalRefineJobs = /* @__PURE__ */ new Map();
|
|
42141
|
+
/** In-memory async batch Refinery jobs keyed by meshId (one batch convergence per mesh at a time). */
|
|
42142
|
+
runningRefineBatchJobs = /* @__PURE__ */ new Map();
|
|
42143
|
+
/** Terminal async batch Refinery jobs preserve the last batch outcome for late readers. */
|
|
42144
|
+
terminalRefineBatchJobs = /* @__PURE__ */ new Map();
|
|
41525
42145
|
constructor(deps) {
|
|
41526
42146
|
this.deps = deps;
|
|
41527
42147
|
}
|
|
@@ -41599,13 +42219,13 @@ var DaemonCommandRouter = class {
|
|
|
41599
42219
|
};
|
|
41600
42220
|
}
|
|
41601
42221
|
getCachedAggregateMeshStatus(meshId, mesh, options) {
|
|
41602
|
-
const
|
|
41603
|
-
if (!
|
|
41604
|
-
if (
|
|
41605
|
-
let snapshot = this.cloneJsonValue(
|
|
42222
|
+
const cached2 = this.aggregateMeshStatusCache.get(meshId);
|
|
42223
|
+
if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
|
|
42224
|
+
if (cached2.queueRevision !== getMeshQueueRevision(meshId)) return null;
|
|
42225
|
+
let snapshot = this.cloneJsonValue(cached2.snapshot);
|
|
41606
42226
|
snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
|
|
41607
42227
|
if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
41608
|
-
const ageMs = Math.max(0, Date.now() -
|
|
42228
|
+
const ageMs = Math.max(0, Date.now() - cached2.builtAt);
|
|
41609
42229
|
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
41610
42230
|
snapshot.sourceOfTruth = {
|
|
41611
42231
|
...sourceOfTruth,
|
|
@@ -41616,7 +42236,7 @@ var DaemonCommandRouter = class {
|
|
|
41616
42236
|
source: "memory",
|
|
41617
42237
|
refreshReason: "memory_cache_hit",
|
|
41618
42238
|
ageMs,
|
|
41619
|
-
cachedAt: new Date(
|
|
42239
|
+
cachedAt: new Date(cached2.builtAt).toISOString(),
|
|
41620
42240
|
returnedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41621
42241
|
}
|
|
41622
42242
|
};
|
|
@@ -41660,9 +42280,9 @@ var DaemonCommandRouter = class {
|
|
|
41660
42280
|
warmInlineMeshCache(meshId, inlineMesh) {
|
|
41661
42281
|
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
41662
42282
|
const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
|
|
41663
|
-
const
|
|
41664
|
-
if (
|
|
41665
|
-
const merged = reconcileInlineMeshCache(
|
|
42283
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
42284
|
+
if (cached2) {
|
|
42285
|
+
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
41666
42286
|
this.inlineMeshCache.set(meshId, merged);
|
|
41667
42287
|
return merged;
|
|
41668
42288
|
}
|
|
@@ -41672,14 +42292,14 @@ var DaemonCommandRouter = class {
|
|
|
41672
42292
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
41673
42293
|
const preferInline = options?.preferInline === true;
|
|
41674
42294
|
if (preferInline) {
|
|
41675
|
-
const
|
|
41676
|
-
if (
|
|
42295
|
+
const cached3 = this.getCachedInlineMesh(meshId);
|
|
42296
|
+
if (cached3) {
|
|
41677
42297
|
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
41678
|
-
const merged = reconcileInlineMeshCache(
|
|
42298
|
+
const merged = reconcileInlineMeshCache(cached3, inlineMesh);
|
|
41679
42299
|
this.inlineMeshCache.set(meshId, sanitizeInlineMesh(merged));
|
|
41680
42300
|
return { mesh: merged, inline: true, source: "inline_cache" };
|
|
41681
42301
|
}
|
|
41682
|
-
return { mesh:
|
|
42302
|
+
return { mesh: cached3, inline: true, source: "inline_cache" };
|
|
41683
42303
|
}
|
|
41684
42304
|
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
41685
42305
|
this.warmInlineMeshCache(meshId, inlineMesh);
|
|
@@ -41692,8 +42312,8 @@ var DaemonCommandRouter = class {
|
|
|
41692
42312
|
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
41693
42313
|
} catch {
|
|
41694
42314
|
}
|
|
41695
|
-
const
|
|
41696
|
-
if (
|
|
42315
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
42316
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
41697
42317
|
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
41698
42318
|
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
41699
42319
|
}
|
|
@@ -42000,6 +42620,8 @@ var DaemonCommandRouter = class {
|
|
|
42000
42620
|
const skippedSessionIds = [];
|
|
42001
42621
|
const skippedLiveSessionIds = [];
|
|
42002
42622
|
const skippedCoordinatorSessionIds = [];
|
|
42623
|
+
const skippedLiveSessionReasons = [];
|
|
42624
|
+
const actedLiveDelegateSessionIds = [];
|
|
42003
42625
|
const deleteUnsupportedSessionIds = [];
|
|
42004
42626
|
const recordsRemainSessionIds = [];
|
|
42005
42627
|
const errors = [];
|
|
@@ -42033,16 +42655,31 @@ var DaemonCommandRouter = class {
|
|
|
42033
42655
|
const surfaceKind = getSessionHostSurfaceKind(record);
|
|
42034
42656
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
42035
42657
|
const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
|
|
42658
|
+
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
42659
|
+
const recordMeshNodeFor = readStringValue(record?.meta?.meshNodeFor);
|
|
42660
|
+
const delegateBoundToThisNode = !!recordNodeId && recordNodeId === args.nodeId && (!recordMeshNodeFor || recordMeshNodeFor === args.meshId);
|
|
42036
42661
|
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
42037
42662
|
skippedSessionIds.push(sessionId);
|
|
42038
42663
|
skippedCoordinatorSessionIds.push(sessionId);
|
|
42039
42664
|
continue;
|
|
42040
42665
|
}
|
|
42041
|
-
if (!hasExplicitSessionIds && liveRuntime) {
|
|
42666
|
+
if (!hasExplicitSessionIds && liveRuntime && !delegateBoundToThisNode) {
|
|
42667
|
+
skippedSessionIds.push(sessionId);
|
|
42668
|
+
skippedLiveSessionIds.push(sessionId);
|
|
42669
|
+
const matchedByWorkspaceOnly = !recordNodeId;
|
|
42670
|
+
const reason = recordNodeId && recordNodeId !== args.nodeId ? `live_delegate_bound_to_other_node:${recordNodeId}` : matchedByWorkspaceOnly ? "live_session_matched_by_workspace_only_no_node_binding" : "live_session_not_bound_to_this_node";
|
|
42671
|
+
skippedLiveSessionReasons.push({ sessionId, reason });
|
|
42672
|
+
continue;
|
|
42673
|
+
}
|
|
42674
|
+
if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode && args.mode === "delete_stopped") {
|
|
42042
42675
|
skippedSessionIds.push(sessionId);
|
|
42043
42676
|
skippedLiveSessionIds.push(sessionId);
|
|
42677
|
+
skippedLiveSessionReasons.push({ sessionId, reason: "live_delegate_preserved_by_delete_stopped_mode_use_stop_or_stop_and_delete" });
|
|
42044
42678
|
continue;
|
|
42045
42679
|
}
|
|
42680
|
+
if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode) {
|
|
42681
|
+
actedLiveDelegateSessionIds.push(sessionId);
|
|
42682
|
+
}
|
|
42046
42683
|
try {
|
|
42047
42684
|
if (args.mode === "stop") {
|
|
42048
42685
|
if (!completed) {
|
|
@@ -42104,6 +42741,8 @@ var DaemonCommandRouter = class {
|
|
|
42104
42741
|
skippedSessionIds,
|
|
42105
42742
|
skippedLiveSessionIds,
|
|
42106
42743
|
skippedCoordinatorSessionIds,
|
|
42744
|
+
...actedLiveDelegateSessionIds.length ? { actedLiveDelegateSessionIds } : {},
|
|
42745
|
+
...skippedLiveSessionReasons.length ? { skippedLiveSessionReasons } : {},
|
|
42107
42746
|
...deleteUnsupported ? {
|
|
42108
42747
|
deleteUnsupported: true,
|
|
42109
42748
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -42751,6 +43390,48 @@ ${tail}` : ""
|
|
|
42751
43390
|
}
|
|
42752
43391
|
};
|
|
42753
43392
|
}
|
|
43393
|
+
const effectiveDiffStarted = Date.now();
|
|
43394
|
+
const effectiveDiff = await runMeshRefineEffectiveDiffGate(repoRoot, baseHead, branchHead);
|
|
43395
|
+
recordMeshRefineStage(refineStages, "effective_diff", effectiveDiff.status, effectiveDiffStarted, {
|
|
43396
|
+
hasEffectiveDiff: effectiveDiff.hasEffectiveDiff,
|
|
43397
|
+
changedPaths: effectiveDiff.changedPaths,
|
|
43398
|
+
submoduleHints: effectiveDiff.submoduleHints,
|
|
43399
|
+
...effectiveDiff.error ? { error: effectiveDiff.error } : {}
|
|
43400
|
+
});
|
|
43401
|
+
if (effectiveDiff.status === "failed" && !effectiveDiff.hasEffectiveDiff) {
|
|
43402
|
+
const hintLines = (effectiveDiff.submoduleHints || []).map((h) => ` - ${h.path}: ${h.reason}`);
|
|
43403
|
+
const message = [
|
|
43404
|
+
`Refinery no-op guard: branch '${branch}' has no effective root-tree diff against '${baseBranch}' (${baseHead.slice(0, 12)}); nothing would merge.`,
|
|
43405
|
+
"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.",
|
|
43406
|
+
hintLines.length ? `Submodules with uncommitted pointer bumps:
|
|
43407
|
+
${hintLines.join("\n")}` : "",
|
|
43408
|
+
`Fix: commit the submodule pointer bump on '${branch}' (git add <submodule-path> && git commit), then re-run refine.`
|
|
43409
|
+
].filter(Boolean).join("\n");
|
|
43410
|
+
return {
|
|
43411
|
+
success: false,
|
|
43412
|
+
code: "no_effective_diff",
|
|
43413
|
+
convergenceStatus: "blocked_review",
|
|
43414
|
+
error: message,
|
|
43415
|
+
branch,
|
|
43416
|
+
into: baseBranch,
|
|
43417
|
+
validationSummary,
|
|
43418
|
+
patchEquivalence,
|
|
43419
|
+
effectiveDiff,
|
|
43420
|
+
refineStages,
|
|
43421
|
+
finalBranchConvergenceState: {
|
|
43422
|
+
branch,
|
|
43423
|
+
baseBranch,
|
|
43424
|
+
merged: false,
|
|
43425
|
+
removed: false,
|
|
43426
|
+
validation: "passed",
|
|
43427
|
+
patchEquivalence: "passed",
|
|
43428
|
+
effectiveDiff: "no_effective_diff",
|
|
43429
|
+
status: "blocked_review",
|
|
43430
|
+
reason: "no_effective_diff",
|
|
43431
|
+
...effectiveDiff.submoduleHints?.length ? { submoduleHints: effectiveDiff.submoduleHints } : {}
|
|
43432
|
+
}
|
|
43433
|
+
};
|
|
43434
|
+
}
|
|
42754
43435
|
let mergeResult;
|
|
42755
43436
|
const mergeStarted = Date.now();
|
|
42756
43437
|
try {
|
|
@@ -42989,8 +43670,8 @@ ${tail}` : ""
|
|
|
42989
43670
|
const repoRootBaseRef = /* @__PURE__ */ new Map();
|
|
42990
43671
|
const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
|
|
42991
43672
|
const resolveBaseRef = async (repoRoot) => {
|
|
42992
|
-
const
|
|
42993
|
-
if (
|
|
43673
|
+
const cached2 = repoRootBaseRef.get(repoRoot);
|
|
43674
|
+
if (cached2) return cached2;
|
|
42994
43675
|
let baseBranch = "main";
|
|
42995
43676
|
try {
|
|
42996
43677
|
const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
@@ -43092,6 +43773,17 @@ ${tail}` : ""
|
|
|
43092
43773
|
note: "Dry-run: no validation, rebase, or merge was executed. Re-run with execute=true to converge nodes in this order."
|
|
43093
43774
|
};
|
|
43094
43775
|
}
|
|
43776
|
+
return this.runMeshRefineBatchConvergence(meshId, orderedNodes, ordering, args);
|
|
43777
|
+
}
|
|
43778
|
+
/**
|
|
43779
|
+
* Convergence core shared by the synchronous batch entry and the async batch job.
|
|
43780
|
+
* Refines each node in order: the per-node refine pipeline fetches origin/<base>
|
|
43781
|
+
* fresh, so each merged sibling advances the base before the next node's auto-rebase
|
|
43782
|
+
* + patch-equivalence re-check. A blocked/failed node is isolated; the batch
|
|
43783
|
+
* continues with the remaining nodes. Does NOT touch the per-node merge logic — it
|
|
43784
|
+
* only sequences calls to executeMeshRefineNodeSynchronously and aggregates outcomes.
|
|
43785
|
+
*/
|
|
43786
|
+
async runMeshRefineBatchConvergence(meshId, orderedNodes, ordering, args) {
|
|
43095
43787
|
const results = [];
|
|
43096
43788
|
for (const node of orderedNodes) {
|
|
43097
43789
|
let result;
|
|
@@ -43146,6 +43838,204 @@ ${tail}` : ""
|
|
|
43146
43838
|
}
|
|
43147
43839
|
};
|
|
43148
43840
|
}
|
|
43841
|
+
buildRefineBatchJobKey(meshId) {
|
|
43842
|
+
return `${meshId}::batch`;
|
|
43843
|
+
}
|
|
43844
|
+
buildRefineBatchJobHandle(args) {
|
|
43845
|
+
return {
|
|
43846
|
+
success: true,
|
|
43847
|
+
async: true,
|
|
43848
|
+
batch: true,
|
|
43849
|
+
status: args.status || "accepted",
|
|
43850
|
+
jobId: args.jobId || `refine_batch_${createInteractionId()}`,
|
|
43851
|
+
interactionId: args.interactionId || createInteractionId(),
|
|
43852
|
+
meshId: args.meshId,
|
|
43853
|
+
batchLabel: `batch:${args.nodeIds.length} node${args.nodeIds.length === 1 ? "" : "s"}`,
|
|
43854
|
+
nodeIds: args.nodeIds,
|
|
43855
|
+
nodeCount: args.nodeIds.length,
|
|
43856
|
+
order: args.order,
|
|
43857
|
+
startedAt: args.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
43858
|
+
...args.completedAt ? { completedAt: args.completedAt } : {},
|
|
43859
|
+
...args.coordinatorDaemonId ? { targetCoordinatorDaemonId: args.coordinatorDaemonId } : {},
|
|
43860
|
+
eventDelivery: { pendingEvents: true, ledger: true },
|
|
43861
|
+
evidence: {
|
|
43862
|
+
pendingEventsCommand: "get_pending_mesh_events",
|
|
43863
|
+
ledgerCommand: "get_mesh_ledger_slice",
|
|
43864
|
+
taskHistoryKind: args.status === "completed" ? "task_completed" : args.status === "failed" ? "task_failed" : "task_dispatched"
|
|
43865
|
+
}
|
|
43866
|
+
};
|
|
43867
|
+
}
|
|
43868
|
+
/**
|
|
43869
|
+
* Emit a batch Refinery terminal/accepted event through the SAME pending-event +
|
|
43870
|
+
* forward mechanism single-node refine uses (queueRefineJobEvent), so the
|
|
43871
|
+
* coordinator's existing refine:accepted/completed/failed handling and message
|
|
43872
|
+
* renderer apply unchanged. The aggregate per-node results ride along in `result`.
|
|
43873
|
+
*/
|
|
43874
|
+
queueRefineBatchJobEvent(event, handle, result) {
|
|
43875
|
+
const metadataEvent = {
|
|
43876
|
+
source: "refine_mesh_node_async_job",
|
|
43877
|
+
batch: true,
|
|
43878
|
+
jobId: handle.jobId,
|
|
43879
|
+
interactionId: handle.interactionId,
|
|
43880
|
+
meshId: handle.meshId,
|
|
43881
|
+
nodeId: handle.batchLabel,
|
|
43882
|
+
nodeIds: handle.nodeIds,
|
|
43883
|
+
workspace: void 0,
|
|
43884
|
+
status: handle.status,
|
|
43885
|
+
startedAt: handle.startedAt,
|
|
43886
|
+
completedAt: handle.completedAt,
|
|
43887
|
+
order: handle.order,
|
|
43888
|
+
...result ? { result } : {}
|
|
43889
|
+
};
|
|
43890
|
+
const eventPayload = {
|
|
43891
|
+
event,
|
|
43892
|
+
meshId: handle.meshId,
|
|
43893
|
+
nodeLabel: handle.batchLabel,
|
|
43894
|
+
nodeId: handle.batchLabel,
|
|
43895
|
+
metadataEvent,
|
|
43896
|
+
queuedAt: Date.now(),
|
|
43897
|
+
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {}
|
|
43898
|
+
};
|
|
43899
|
+
if (typeof this.deps.instanceManager?.getByCategory === "function") {
|
|
43900
|
+
const forwarded = handleMeshForwardEvent(
|
|
43901
|
+
{ instanceManager: this.deps.instanceManager },
|
|
43902
|
+
{
|
|
43903
|
+
event,
|
|
43904
|
+
meshId: handle.meshId,
|
|
43905
|
+
nodeId: handle.batchLabel,
|
|
43906
|
+
jobId: handle.jobId,
|
|
43907
|
+
interactionId: handle.interactionId,
|
|
43908
|
+
status: handle.status,
|
|
43909
|
+
startedAt: handle.startedAt,
|
|
43910
|
+
completedAt: handle.completedAt,
|
|
43911
|
+
...result ? { result } : {}
|
|
43912
|
+
}
|
|
43913
|
+
);
|
|
43914
|
+
if (forwarded?.success === true) return;
|
|
43915
|
+
LOG.warn("Mesh", `[Refinery] Failed to forward async refine batch event ${event}: ${forwarded?.error || "unknown error"}`);
|
|
43916
|
+
}
|
|
43917
|
+
queuePendingMeshCoordinatorEvent(eventPayload);
|
|
43918
|
+
}
|
|
43919
|
+
async appendRefineBatchJobLedger(kind, handle, result) {
|
|
43920
|
+
try {
|
|
43921
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
43922
|
+
appendLedgerEntry2(handle.meshId, {
|
|
43923
|
+
kind,
|
|
43924
|
+
nodeId: handle.batchLabel,
|
|
43925
|
+
payload: {
|
|
43926
|
+
source: "refine_mesh_node_async_job",
|
|
43927
|
+
refineJob: {
|
|
43928
|
+
batch: true,
|
|
43929
|
+
jobId: handle.jobId,
|
|
43930
|
+
interactionId: handle.interactionId,
|
|
43931
|
+
status: handle.status,
|
|
43932
|
+
meshId: handle.meshId,
|
|
43933
|
+
nodeIds: handle.nodeIds,
|
|
43934
|
+
order: handle.order,
|
|
43935
|
+
targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId,
|
|
43936
|
+
startedAt: handle.startedAt,
|
|
43937
|
+
completedAt: handle.completedAt
|
|
43938
|
+
},
|
|
43939
|
+
async: true,
|
|
43940
|
+
batch: true,
|
|
43941
|
+
...result ? {
|
|
43942
|
+
success: result.success === true,
|
|
43943
|
+
result
|
|
43944
|
+
} : {}
|
|
43945
|
+
}
|
|
43946
|
+
});
|
|
43947
|
+
} catch (e) {
|
|
43948
|
+
LOG.warn("Mesh", `[Refinery] Failed to append async refine batch ledger entry: ${e?.message || e}`);
|
|
43949
|
+
}
|
|
43950
|
+
}
|
|
43951
|
+
async finishMeshRefineBatchJob(handle, orderedNodes, ordering, args) {
|
|
43952
|
+
const key = this.buildRefineBatchJobKey(handle.meshId);
|
|
43953
|
+
let result;
|
|
43954
|
+
try {
|
|
43955
|
+
result = await this.runMeshRefineBatchConvergence(handle.meshId, orderedNodes, ordering, args);
|
|
43956
|
+
} catch (e) {
|
|
43957
|
+
result = { success: false, error: e?.message || String(e), batch: true };
|
|
43958
|
+
}
|
|
43959
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43960
|
+
const summary = result.summary && typeof result.summary === "object" ? result.summary : void 0;
|
|
43961
|
+
const allConverged = result.allConverged === true;
|
|
43962
|
+
const isTerminalSuccess = result.success === true && allConverged;
|
|
43963
|
+
const nextStep = typeof result.nextStep === "string" && result.nextStep ? result.nextStep : isTerminalSuccess ? "All batched nodes converged onto base. Continue from the updated mesh state." : "Resolve blocked_review / not_mergeable nodes (see per-node code/stage/error in result.results), then re-run mesh_refine_batch for the remaining nodes.";
|
|
43964
|
+
const normalizedResult = {
|
|
43965
|
+
...result,
|
|
43966
|
+
batch: true,
|
|
43967
|
+
nextStep,
|
|
43968
|
+
...summary ? {
|
|
43969
|
+
convergenceStatus: allConverged ? "all_converged" : "partial"
|
|
43970
|
+
} : {}
|
|
43971
|
+
};
|
|
43972
|
+
const terminalHandle = this.buildRefineBatchJobHandle({
|
|
43973
|
+
meshId: handle.meshId,
|
|
43974
|
+
nodeIds: handle.nodeIds,
|
|
43975
|
+
order: handle.order,
|
|
43976
|
+
status: isTerminalSuccess ? "completed" : "failed",
|
|
43977
|
+
startedAt: handle.startedAt,
|
|
43978
|
+
completedAt,
|
|
43979
|
+
jobId: handle.jobId,
|
|
43980
|
+
interactionId: handle.interactionId,
|
|
43981
|
+
coordinatorDaemonId: handle.targetCoordinatorDaemonId
|
|
43982
|
+
});
|
|
43983
|
+
const terminal = { ...terminalHandle, result: normalizedResult };
|
|
43984
|
+
this.terminalRefineBatchJobs.set(key, terminal);
|
|
43985
|
+
this.runningRefineBatchJobs.delete(key);
|
|
43986
|
+
this.invalidateAggregateMeshStatus(handle.meshId);
|
|
43987
|
+
await this.appendRefineBatchJobLedger(isTerminalSuccess ? "task_completed" : "task_failed", terminalHandle, normalizedResult);
|
|
43988
|
+
this.queueRefineBatchJobEvent(isTerminalSuccess ? "refine:completed" : "refine:failed", terminalHandle, normalizedResult);
|
|
43989
|
+
}
|
|
43990
|
+
/**
|
|
43991
|
+
* Async entry for the batch Refinery execute path. Mirrors startMeshRefineJob:
|
|
43992
|
+
* resolves the plan synchronously (so target/ordering errors and the dry-run shape
|
|
43993
|
+
* stay synchronous), then for execute=true registers an in-flight batch job, returns
|
|
43994
|
+
* {async:true, status:'accepted', batch:true, ...plan} immediately, and runs the
|
|
43995
|
+
* convergence loop in the background — emitting the same terminal refine event.
|
|
43996
|
+
* Idempotent: a batch already in flight for this mesh returns the running handle
|
|
43997
|
+
* with duplicate:true rather than spawning a second background job.
|
|
43998
|
+
*/
|
|
43999
|
+
async startMeshRefineBatchJob(meshId, requestedNodeIds, args) {
|
|
44000
|
+
const plan = await this.batchRefineMeshNodes(meshId, requestedNodeIds, { ...args, dryRun: true, execute: false });
|
|
44001
|
+
const planRecord = plan;
|
|
44002
|
+
if (planRecord.success !== true) return plan;
|
|
44003
|
+
if (args?.dryRun === true && args?.execute !== true) return plan;
|
|
44004
|
+
const order = Array.isArray(planRecord.order) ? planRecord.order.filter((v) => typeof v === "string") : [];
|
|
44005
|
+
const nodeIds = order.slice();
|
|
44006
|
+
if (nodeIds.length === 0) {
|
|
44007
|
+
return { ...planRecord, success: true, batch: true, dryRun: false, async: false };
|
|
44008
|
+
}
|
|
44009
|
+
const key = this.buildRefineBatchJobKey(meshId);
|
|
44010
|
+
const running = this.runningRefineBatchJobs.get(key);
|
|
44011
|
+
if (running) return { ...running, duplicate: true };
|
|
44012
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
44013
|
+
const mesh = meshRecord?.mesh;
|
|
44014
|
+
const allNodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
44015
|
+
const orderedNodes = nodeIds.map((id) => allNodes.find((n) => n.id === id || n.nodeId === id)).filter((n) => !!n);
|
|
44016
|
+
if (orderedNodes.length === 0) {
|
|
44017
|
+
return { success: false, error: "Batch nodes no longer resolvable in mesh", batch: true };
|
|
44018
|
+
}
|
|
44019
|
+
const ordering = {
|
|
44020
|
+
order,
|
|
44021
|
+
rationale: planRecord.orderingRationale
|
|
44022
|
+
};
|
|
44023
|
+
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
|
|
44024
|
+
const handle = this.buildRefineBatchJobHandle({ meshId, nodeIds, order, coordinatorDaemonId });
|
|
44025
|
+
this.runningRefineBatchJobs.set(key, handle);
|
|
44026
|
+
await this.appendRefineBatchJobLedger("task_dispatched", handle);
|
|
44027
|
+
this.queueRefineBatchJobEvent("refine:accepted", handle);
|
|
44028
|
+
setImmediate(() => {
|
|
44029
|
+
void this.finishMeshRefineBatchJob(handle, orderedNodes, ordering, args);
|
|
44030
|
+
});
|
|
44031
|
+
return {
|
|
44032
|
+
...handle,
|
|
44033
|
+
order,
|
|
44034
|
+
orderingRationale: planRecord.orderingRationale,
|
|
44035
|
+
plan: planRecord.plan,
|
|
44036
|
+
note: "Batch convergence accepted and running in the background. Completion/failure (with per-node results) will be delivered as a terminal refine event; do not poll repeatedly."
|
|
44037
|
+
};
|
|
44038
|
+
}
|
|
43149
44039
|
async finishMeshRefineJob(handle, args) {
|
|
43150
44040
|
const key = this.buildRefineJobKey(handle.meshId, handle.targetNodeId);
|
|
43151
44041
|
let result;
|
|
@@ -43679,7 +44569,7 @@ ${tail}` : ""
|
|
|
43679
44569
|
version: this.deps.statusVersion || "unknown",
|
|
43680
44570
|
profile: "metadata"
|
|
43681
44571
|
});
|
|
43682
|
-
return { success: true, status: snapshot };
|
|
44572
|
+
return { success: true, status: snapshot, daemonBuild: getDaemonBuildInfo() };
|
|
43683
44573
|
}
|
|
43684
44574
|
case "get_machine_runtime_stats": {
|
|
43685
44575
|
return {
|
|
@@ -44649,6 +45539,7 @@ ${tail}` : ""
|
|
|
44649
45539
|
let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
44650
45540
|
let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
|
|
44651
45541
|
let nodeDaemonId;
|
|
45542
|
+
let allowAutoPublishSubmoduleMainCommits = false;
|
|
44652
45543
|
if (meshId && nodeId) {
|
|
44653
45544
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
44654
45545
|
const mesh = meshRecord?.mesh;
|
|
@@ -44659,6 +45550,7 @@ ${tail}` : ""
|
|
|
44659
45550
|
if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
|
|
44660
45551
|
submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
|
|
44661
45552
|
}
|
|
45553
|
+
allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
|
|
44662
45554
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
44663
45555
|
}
|
|
44664
45556
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
@@ -44679,7 +45571,10 @@ ${tail}` : ""
|
|
|
44679
45571
|
execute: args?.execute === true,
|
|
44680
45572
|
dryRun: args?.dryRun === true,
|
|
44681
45573
|
updateSubmodules: args?.updateSubmodules === true,
|
|
44682
|
-
submoduleIgnorePaths
|
|
45574
|
+
submoduleIgnorePaths,
|
|
45575
|
+
mode: args?.mode === "push" ? "push" : "merge",
|
|
45576
|
+
pushSubmodules: args?.pushSubmodules === true,
|
|
45577
|
+
allowAutoPublishSubmoduleMainCommits
|
|
44683
45578
|
});
|
|
44684
45579
|
return result;
|
|
44685
45580
|
}
|
|
@@ -44693,7 +45588,9 @@ ${tail}` : ""
|
|
|
44693
45588
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
44694
45589
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
44695
45590
|
const requestedNodeIds = Array.isArray(args?.nodeIds) ? args.nodeIds.filter((v) => typeof v === "string" && v.trim().length > 0).map((v) => v.trim()) : void 0;
|
|
44696
|
-
|
|
45591
|
+
const isDryRun = args?.dryRun !== false && args?.execute !== true;
|
|
45592
|
+
if (isDryRun) return this.batchRefineMeshNodes(meshId, requestedNodeIds, args);
|
|
45593
|
+
return this.startMeshRefineBatchJob(meshId, requestedNodeIds, args);
|
|
44697
45594
|
}
|
|
44698
45595
|
case "remove_mesh_node": {
|
|
44699
45596
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -46377,6 +47274,7 @@ var DaemonStatusReporter = class {
|
|
|
46377
47274
|
};
|
|
46378
47275
|
|
|
46379
47276
|
// src/index.ts
|
|
47277
|
+
init_build_info();
|
|
46380
47278
|
init_logger();
|
|
46381
47279
|
init_debug_config();
|
|
46382
47280
|
|
|
@@ -54648,6 +55546,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
54648
55546
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
54649
55547
|
NodePtyTransportFactory,
|
|
54650
55548
|
P2pRelayFailureError,
|
|
55549
|
+
PRUNABLE_ORPHAN_STALE_REASONS,
|
|
54651
55550
|
ProviderCliAdapter,
|
|
54652
55551
|
ProviderInstanceManager,
|
|
54653
55552
|
ProviderLoader,
|
|
@@ -54701,6 +55600,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
54701
55600
|
classifyChatMessageVisibility,
|
|
54702
55601
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
54703
55602
|
classifyP2pRelayFailure,
|
|
55603
|
+
classifyStaleDirectForPrune,
|
|
54704
55604
|
cleanupTerminalDirectDispatches,
|
|
54705
55605
|
clearDebugTrace,
|
|
54706
55606
|
clearPendingMeshCoordinatorEvents,
|
|
@@ -54720,6 +55620,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
54720
55620
|
createNativeHistoryDispatcher,
|
|
54721
55621
|
createSessionDelivery,
|
|
54722
55622
|
createWorktree,
|
|
55623
|
+
deleteDirectDispatchesByTaskId,
|
|
54723
55624
|
deleteMesh,
|
|
54724
55625
|
deriveMeshReviewInboxItems,
|
|
54725
55626
|
describeTaskDependencyState,
|
|
@@ -54748,6 +55649,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
54748
55649
|
getAvailableIdeIds,
|
|
54749
55650
|
getCoordinatorForSession,
|
|
54750
55651
|
getCurrentDaemonLogPath,
|
|
55652
|
+
getDaemonBuildInfo,
|
|
54751
55653
|
getDaemonDataDir,
|
|
54752
55654
|
getDaemonLogDir,
|
|
54753
55655
|
getDebugRuntimeConfig,
|