@adhdev/daemon-core 0.9.82-rc.262 → 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/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 +490 -64
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +486 -64
- 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 +49 -2
- 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.mjs
CHANGED
|
@@ -251,6 +251,29 @@ var init_git_executor = __esm({
|
|
|
251
251
|
}
|
|
252
252
|
});
|
|
253
253
|
|
|
254
|
+
// src/build-info.ts
|
|
255
|
+
function readInjected(value) {
|
|
256
|
+
if (typeof value !== "string") return void 0;
|
|
257
|
+
const trimmed = value.trim();
|
|
258
|
+
if (!trimmed || trimmed === "unknown") return void 0;
|
|
259
|
+
return trimmed;
|
|
260
|
+
}
|
|
261
|
+
function getDaemonBuildInfo() {
|
|
262
|
+
if (cached) return cached;
|
|
263
|
+
const commit = readInjected(true ? "2cf602f99ce68b3d3f1af02b429f6fb7a7c8e686" : void 0) ?? "unknown";
|
|
264
|
+
const commitShort = readInjected(true ? "2cf602f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
265
|
+
const version = readInjected(true ? "0.9.82-rc.263" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
266
|
+
const builtAt = readInjected(true ? "2026-06-14T13:48:10.699Z" : void 0);
|
|
267
|
+
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
268
|
+
return cached;
|
|
269
|
+
}
|
|
270
|
+
var cached;
|
|
271
|
+
var init_build_info = __esm({
|
|
272
|
+
"src/build-info.ts"() {
|
|
273
|
+
"use strict";
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
254
277
|
// src/git/git-status.ts
|
|
255
278
|
async function getGitRepoStatus(workspace, options = {}) {
|
|
256
279
|
const lastCheckedAt = Date.now();
|
|
@@ -273,6 +296,7 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
273
296
|
}
|
|
274
297
|
const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
|
|
275
298
|
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
|
|
299
|
+
const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options);
|
|
276
300
|
return {
|
|
277
301
|
workspace: repo.workspace,
|
|
278
302
|
repoRoot: repo.repoRoot,
|
|
@@ -296,7 +320,8 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
296
320
|
conflictFiles: parsed.conflictFiles,
|
|
297
321
|
stashCount,
|
|
298
322
|
lastCheckedAt,
|
|
299
|
-
submodules
|
|
323
|
+
submodules,
|
|
324
|
+
...daemonBuildBehind ? { daemonBuildBehind } : {}
|
|
300
325
|
};
|
|
301
326
|
} catch (error) {
|
|
302
327
|
if (error instanceof GitCommandError) {
|
|
@@ -309,6 +334,35 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
309
334
|
);
|
|
310
335
|
}
|
|
311
336
|
}
|
|
337
|
+
async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
338
|
+
const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
|
|
339
|
+
if (!build.commit || build.commit === "unknown") return void 0;
|
|
340
|
+
const scopes = [
|
|
341
|
+
{ scope: "root", repoPath: repo.repoRoot || repo.workspace }
|
|
342
|
+
];
|
|
343
|
+
for (const sub of submodules || []) {
|
|
344
|
+
if (sub.repoPath && !sub.error) scopes.push({ scope: sub.path, repoPath: sub.repoPath });
|
|
345
|
+
}
|
|
346
|
+
for (const { scope, repoPath } of scopes) {
|
|
347
|
+
try {
|
|
348
|
+
await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
|
|
349
|
+
const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
|
|
350
|
+
const head = headResult.stdout.trim();
|
|
351
|
+
if (!head || head === build.commit) continue;
|
|
352
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
|
|
353
|
+
return {
|
|
354
|
+
buildCommit: build.commit,
|
|
355
|
+
buildCommitShort: build.commitShort,
|
|
356
|
+
head,
|
|
357
|
+
scope,
|
|
358
|
+
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.`
|
|
359
|
+
};
|
|
360
|
+
} catch {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return void 0;
|
|
365
|
+
}
|
|
312
366
|
async function readPorcelainStatus(repo, options) {
|
|
313
367
|
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
314
368
|
return parsePorcelainV2Status(statusOutput.stdout);
|
|
@@ -525,6 +579,7 @@ var init_git_status = __esm({
|
|
|
525
579
|
"src/git/git-status.ts"() {
|
|
526
580
|
"use strict";
|
|
527
581
|
init_git_executor();
|
|
582
|
+
init_build_info();
|
|
528
583
|
}
|
|
529
584
|
});
|
|
530
585
|
|
|
@@ -2385,8 +2440,8 @@ function readLedgerFromStore(meshId) {
|
|
|
2385
2440
|
}
|
|
2386
2441
|
function getCachedRawEntries(meshId) {
|
|
2387
2442
|
const now = Date.now();
|
|
2388
|
-
const
|
|
2389
|
-
if (
|
|
2443
|
+
const cached2 = ledgerReadCache.get(meshId);
|
|
2444
|
+
if (cached2 && now - cached2.cachedAt < LEDGER_CACHE_TTL_MS) return cached2.entries;
|
|
2390
2445
|
let entries;
|
|
2391
2446
|
try {
|
|
2392
2447
|
entries = readLedgerFromStore(meshId);
|
|
@@ -2645,6 +2700,7 @@ __export(mesh_work_queue_exports, {
|
|
|
2645
2700
|
cancelTask: () => cancelTask,
|
|
2646
2701
|
claimNextTask: () => claimNextTask,
|
|
2647
2702
|
cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
|
|
2703
|
+
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
2648
2704
|
describeTaskDependencyState: () => describeTaskDependencyState,
|
|
2649
2705
|
enqueueTask: () => enqueueTask,
|
|
2650
2706
|
getActiveDirectDispatches: () => getActiveDirectDispatches,
|
|
@@ -3054,6 +3110,13 @@ function markStaleDirectDispatches(meshId, olderThanMs = 60 * 6e4) {
|
|
|
3054
3110
|
} catch {
|
|
3055
3111
|
}
|
|
3056
3112
|
}
|
|
3113
|
+
function deleteDirectDispatchesByTaskId(meshId, taskIds) {
|
|
3114
|
+
try {
|
|
3115
|
+
return MeshRuntimeStore.getInstance().deleteDirectDispatchesByTaskId(meshId, taskIds);
|
|
3116
|
+
} catch {
|
|
3117
|
+
return 0;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3057
3120
|
function recordMeshToolCall(opts) {
|
|
3058
3121
|
try {
|
|
3059
3122
|
return MeshRuntimeStore.getInstance().recordMeshToolCall(opts);
|
|
@@ -3685,6 +3748,24 @@ var init_mesh_runtime_store = __esm({
|
|
|
3685
3748
|
deleteDirectDispatches(meshId) {
|
|
3686
3749
|
this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ?`).run(meshId);
|
|
3687
3750
|
}
|
|
3751
|
+
/**
|
|
3752
|
+
* Delete specific direct dispatch rows by taskId for a mesh. Used by the staleDirect prune
|
|
3753
|
+
* path to remove orphaned/terminal dispatch records whose node/session is no longer in the
|
|
3754
|
+
* live mesh. Returns the number of rows actually deleted. No-op for an empty taskId list.
|
|
3755
|
+
*/
|
|
3756
|
+
deleteDirectDispatchesByTaskId(meshId, taskIds) {
|
|
3757
|
+
const ids = (taskIds || []).map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean);
|
|
3758
|
+
if (!ids.length) return 0;
|
|
3759
|
+
const stmt = this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ? AND task_id = ?`);
|
|
3760
|
+
let deleted = 0;
|
|
3761
|
+
const run = this.db.transaction((rows) => {
|
|
3762
|
+
for (const taskId of rows) {
|
|
3763
|
+
deleted += stmt.run(meshId, taskId).changes;
|
|
3764
|
+
}
|
|
3765
|
+
});
|
|
3766
|
+
run(ids);
|
|
3767
|
+
return deleted;
|
|
3768
|
+
}
|
|
3688
3769
|
markStaleDirectDispatches(meshId, olderThanMs) {
|
|
3689
3770
|
const cutoff = new Date(Date.now() - olderThanMs).toISOString();
|
|
3690
3771
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -5353,11 +5434,14 @@ async function fastForwardMeshNode(args) {
|
|
|
5353
5434
|
const trigger = normalizeOptionalString(args.trigger) || "manual";
|
|
5354
5435
|
const updateSubmodules = args.updateSubmodules === true;
|
|
5355
5436
|
const dryRun = args.dryRun === true || args.execute !== true;
|
|
5356
|
-
const
|
|
5437
|
+
const mode = args.mode === "push" ? "push" : "merge";
|
|
5438
|
+
const pushSubmodules = mode === "push" && args.pushSubmodules === true;
|
|
5439
|
+
const plannedSteps = buildPlannedSteps(mode, updateSubmodules, pushSubmodules);
|
|
5357
5440
|
const base = {
|
|
5358
5441
|
...nodeId ? { nodeId } : {},
|
|
5359
5442
|
...meshId ? { meshId } : {},
|
|
5360
5443
|
workspace,
|
|
5444
|
+
mode,
|
|
5361
5445
|
dryRun,
|
|
5362
5446
|
updateSubmodules,
|
|
5363
5447
|
plannedSteps,
|
|
@@ -5371,13 +5455,24 @@ async function fastForwardMeshNode(args) {
|
|
|
5371
5455
|
submoduleIgnorePaths: args.submoduleIgnorePaths,
|
|
5372
5456
|
timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
|
|
5373
5457
|
});
|
|
5458
|
+
if (mode === "push") {
|
|
5459
|
+
return pushMeshNode(base, args, current, {
|
|
5460
|
+
pushSubmodules,
|
|
5461
|
+
allowAutoPublishSubmoduleMainCommits: args.allowAutoPublishSubmoduleMainCommits === true
|
|
5462
|
+
});
|
|
5463
|
+
}
|
|
5374
5464
|
const earlyBlockers = collectPreflightBlockers(current, requestedBranch);
|
|
5375
5465
|
if (earlyBlockers.length > 0) {
|
|
5466
|
+
const blockCode = chooseBlockCode(current, earlyBlockers);
|
|
5376
5467
|
const result2 = {
|
|
5377
|
-
...block(base,
|
|
5468
|
+
...block(base, blockCode, earlyBlockers),
|
|
5378
5469
|
current,
|
|
5379
|
-
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(
|
|
5470
|
+
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(blockCode))
|
|
5380
5471
|
};
|
|
5472
|
+
if (blockCode === "branch_ahead" && current.ahead > 0 && current.behind === 0 && otherBlockersAreOnlyAhead(earlyBlockers)) {
|
|
5473
|
+
result2.code = "ahead_needs_push";
|
|
5474
|
+
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.';
|
|
5475
|
+
}
|
|
5381
5476
|
await appendFastForwardLedger(result2, "blocked");
|
|
5382
5477
|
return result2;
|
|
5383
5478
|
}
|
|
@@ -5488,7 +5583,246 @@ async function fastForwardMeshNode(args) {
|
|
|
5488
5583
|
await appendFastForwardLedger(result, success ? "executed" : "failed");
|
|
5489
5584
|
return result;
|
|
5490
5585
|
}
|
|
5491
|
-
function
|
|
5586
|
+
async function pushMeshNode(base, args, current, options) {
|
|
5587
|
+
const workspace = base.workspace;
|
|
5588
|
+
const requestedBranch = normalizeOptionalString(args.branch);
|
|
5589
|
+
const dryRun = base.dryRun;
|
|
5590
|
+
const blockers = collectPushPreflightBlockers(current, requestedBranch);
|
|
5591
|
+
if (blockers.length > 0) {
|
|
5592
|
+
const code2 = choosePushBlockCode(current, blockers);
|
|
5593
|
+
const result2 = {
|
|
5594
|
+
...block(base, code2, blockers),
|
|
5595
|
+
current,
|
|
5596
|
+
preStatus: current,
|
|
5597
|
+
finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(code2))
|
|
5598
|
+
};
|
|
5599
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5600
|
+
return result2;
|
|
5601
|
+
}
|
|
5602
|
+
const target = parseUpstreamTarget(current.upstream || "");
|
|
5603
|
+
if (!target) {
|
|
5604
|
+
const result2 = {
|
|
5605
|
+
...block(base, "upstream_unparseable", ["upstream_unparseable"]),
|
|
5606
|
+
current,
|
|
5607
|
+
preStatus: current,
|
|
5608
|
+
finalBranchConvergenceState: buildConvergenceState(current, "blocked")
|
|
5609
|
+
};
|
|
5610
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5611
|
+
return result2;
|
|
5612
|
+
}
|
|
5613
|
+
const refspec = `HEAD:refs/heads/${target.remoteBranch}`;
|
|
5614
|
+
const pushTarget = { remote: target.remote, remoteBranch: target.remoteBranch, refspec };
|
|
5615
|
+
if (current.ahead <= 0) {
|
|
5616
|
+
const result2 = {
|
|
5617
|
+
...base,
|
|
5618
|
+
success: true,
|
|
5619
|
+
code: "nothing_to_push",
|
|
5620
|
+
allowed: true,
|
|
5621
|
+
willRun: false,
|
|
5622
|
+
executed: false,
|
|
5623
|
+
blockingReasons: [],
|
|
5624
|
+
current,
|
|
5625
|
+
preStatus: current,
|
|
5626
|
+
postStatus: current,
|
|
5627
|
+
pushTarget,
|
|
5628
|
+
finalBranchConvergenceState: buildConvergenceState(current, "up_to_date")
|
|
5629
|
+
};
|
|
5630
|
+
await appendFastForwardLedger(result2, "noop");
|
|
5631
|
+
return result2;
|
|
5632
|
+
}
|
|
5633
|
+
const descendant = await verifyUpstreamIsAncestorOfHead(workspace, current.upstream || "", args.timeoutMs);
|
|
5634
|
+
if (!descendant.ok) {
|
|
5635
|
+
const result2 = {
|
|
5636
|
+
...block(base, "non_fast_forward_push", ["head_is_not_descendant_of_upstream"]),
|
|
5637
|
+
current,
|
|
5638
|
+
preStatus: current,
|
|
5639
|
+
pushTarget,
|
|
5640
|
+
operationError: descendant.error,
|
|
5641
|
+
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.",
|
|
5642
|
+
finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
|
|
5643
|
+
};
|
|
5644
|
+
await appendFastForwardLedger(result2, "blocked");
|
|
5645
|
+
return result2;
|
|
5646
|
+
}
|
|
5647
|
+
if (dryRun) {
|
|
5648
|
+
const result2 = {
|
|
5649
|
+
...base,
|
|
5650
|
+
success: true,
|
|
5651
|
+
code: "push_available",
|
|
5652
|
+
allowed: true,
|
|
5653
|
+
willRun: false,
|
|
5654
|
+
executed: false,
|
|
5655
|
+
blockingReasons: [],
|
|
5656
|
+
current,
|
|
5657
|
+
preStatus: current,
|
|
5658
|
+
pushTarget,
|
|
5659
|
+
...options.pushSubmodules ? { submodulePushes: await planSubmodulePushes(current, options, args.timeoutMs) } : {},
|
|
5660
|
+
finalBranchConvergenceState: buildConvergenceState(current, "push_available")
|
|
5661
|
+
};
|
|
5662
|
+
await appendFastForwardLedger(result2, "dry_run");
|
|
5663
|
+
return result2;
|
|
5664
|
+
}
|
|
5665
|
+
try {
|
|
5666
|
+
await runGit(workspace, ["push", target.remote, refspec], { timeoutMs: args.timeoutMs ?? 3e4 });
|
|
5667
|
+
} catch (error) {
|
|
5668
|
+
const result2 = {
|
|
5669
|
+
...block(base, "push_ff_only_failed", ["push_ff_only_failed"]),
|
|
5670
|
+
current,
|
|
5671
|
+
preStatus: current,
|
|
5672
|
+
pushTarget,
|
|
5673
|
+
operationError: formatGitError2(error),
|
|
5674
|
+
finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
|
|
5675
|
+
};
|
|
5676
|
+
await appendFastForwardLedger(result2, "failed");
|
|
5677
|
+
return result2;
|
|
5678
|
+
}
|
|
5679
|
+
let submodulePushes;
|
|
5680
|
+
if (options.pushSubmodules) {
|
|
5681
|
+
submodulePushes = await executeSubmodulePushes(current, options, args.timeoutMs);
|
|
5682
|
+
}
|
|
5683
|
+
const postStatus = await getGitRepoStatus(workspace, {
|
|
5684
|
+
...STATUS_OPTIONS,
|
|
5685
|
+
submoduleIgnorePaths: args.submoduleIgnorePaths,
|
|
5686
|
+
timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
|
|
5687
|
+
});
|
|
5688
|
+
const submodulePushFailed = (submodulePushes || []).some((entry) => !entry.pushed && !entry.skipped);
|
|
5689
|
+
const blockingReasons = [];
|
|
5690
|
+
if (postStatus.ahead !== 0) blockingReasons.push("post_branch_ahead");
|
|
5691
|
+
if (submodulePushFailed) blockingReasons.push("submodule_push_failed");
|
|
5692
|
+
const success = blockingReasons.length === 0;
|
|
5693
|
+
const code = success ? "push_applied" : submodulePushFailed && postStatus.ahead === 0 ? "push_applied_submodule_push_failed" : "post_push_verify_failed";
|
|
5694
|
+
const result = {
|
|
5695
|
+
...base,
|
|
5696
|
+
success,
|
|
5697
|
+
code,
|
|
5698
|
+
allowed: true,
|
|
5699
|
+
willRun: true,
|
|
5700
|
+
executed: true,
|
|
5701
|
+
blockingReasons,
|
|
5702
|
+
current,
|
|
5703
|
+
preStatus: current,
|
|
5704
|
+
postStatus,
|
|
5705
|
+
pushTarget,
|
|
5706
|
+
...submodulePushes ? { submodulePushes } : {},
|
|
5707
|
+
finalBranchConvergenceState: buildConvergenceState(postStatus, success ? "pushed" : "post_verify_failed")
|
|
5708
|
+
};
|
|
5709
|
+
await appendFastForwardLedger(result, success ? "executed" : "failed");
|
|
5710
|
+
return result;
|
|
5711
|
+
}
|
|
5712
|
+
function collectPushPreflightBlockers(status, requestedBranch) {
|
|
5713
|
+
const blockers = [];
|
|
5714
|
+
if (!status.isGitRepo) blockers.push("not_git_repo");
|
|
5715
|
+
if (!status.branch) blockers.push("detached_head_or_unknown_branch");
|
|
5716
|
+
if (requestedBranch && status.branch !== requestedBranch) blockers.push("branch_mismatch");
|
|
5717
|
+
if (!status.upstream) blockers.push("upstream_missing");
|
|
5718
|
+
if (status.upstreamStatus !== "fresh") blockers.push("upstream_not_fresh");
|
|
5719
|
+
if (status.hasConflicts) blockers.push("conflicts_present");
|
|
5720
|
+
if (status.staged > 0) blockers.push("staged_changes_present");
|
|
5721
|
+
if (status.modified > 0) blockers.push("modified_changes_present");
|
|
5722
|
+
if (status.untracked > 0) blockers.push("untracked_changes_present");
|
|
5723
|
+
if (status.deleted > 0) blockers.push("deleted_changes_present");
|
|
5724
|
+
if (status.renamed > 0) blockers.push("renamed_changes_present");
|
|
5725
|
+
if (status.stashCount > 0) blockers.push("stash_entries_present");
|
|
5726
|
+
if (status.ahead > 0 && status.behind > 0) blockers.push("branch_diverged_from_upstream");
|
|
5727
|
+
else if (status.behind > 0) blockers.push("branch_behind_upstream");
|
|
5728
|
+
return blockers;
|
|
5729
|
+
}
|
|
5730
|
+
function choosePushBlockCode(status, blockers) {
|
|
5731
|
+
if (blockers.includes("not_git_repo")) return "not_git_repo";
|
|
5732
|
+
if (blockers.includes("branch_mismatch")) return "branch_mismatch";
|
|
5733
|
+
if (blockers.includes("upstream_missing")) return "upstream_missing";
|
|
5734
|
+
if (blockers.includes("upstream_not_fresh")) return "upstream_not_fresh";
|
|
5735
|
+
if (blockers.includes("branch_diverged_from_upstream")) return "branch_diverged";
|
|
5736
|
+
if (blockers.includes("branch_behind_upstream")) return "non_fast_forward_push";
|
|
5737
|
+
if (blockers.some((reason) => reason.includes("changes") || reason.includes("conflicts") || reason.includes("stash"))) return "dirty_worktree";
|
|
5738
|
+
return "preflight_blocked";
|
|
5739
|
+
}
|
|
5740
|
+
function parseUpstreamTarget(upstream) {
|
|
5741
|
+
const trimmed = upstream.trim();
|
|
5742
|
+
const slash = trimmed.indexOf("/");
|
|
5743
|
+
if (slash <= 0 || slash >= trimmed.length - 1) return null;
|
|
5744
|
+
return { remote: trimmed.slice(0, slash), remoteBranch: trimmed.slice(slash + 1) };
|
|
5745
|
+
}
|
|
5746
|
+
async function verifyUpstreamIsAncestorOfHead(workspace, upstream, timeoutMs) {
|
|
5747
|
+
if (!upstream) return { ok: false, error: "missing upstream" };
|
|
5748
|
+
try {
|
|
5749
|
+
await runGit(workspace, ["merge-base", "--is-ancestor", upstream, "HEAD"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5750
|
+
return { ok: true };
|
|
5751
|
+
} catch (error) {
|
|
5752
|
+
return { ok: false, error: formatGitError2(error) };
|
|
5753
|
+
}
|
|
5754
|
+
}
|
|
5755
|
+
async function planSubmodulePushes(status, options, timeoutMs) {
|
|
5756
|
+
return resolveSubmodulePushes(status, options, false, timeoutMs);
|
|
5757
|
+
}
|
|
5758
|
+
async function executeSubmodulePushes(status, options, timeoutMs) {
|
|
5759
|
+
return resolveSubmodulePushes(status, options, true, timeoutMs);
|
|
5760
|
+
}
|
|
5761
|
+
async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
|
|
5762
|
+
const submodules = Array.isArray(status.submodules) ? status.submodules : [];
|
|
5763
|
+
const results = [];
|
|
5764
|
+
for (const submodule of submodules) {
|
|
5765
|
+
const base = {
|
|
5766
|
+
path: submodule.path,
|
|
5767
|
+
commit: submodule.commit,
|
|
5768
|
+
remote: "origin",
|
|
5769
|
+
remoteBranch: "main",
|
|
5770
|
+
pushed: false,
|
|
5771
|
+
skipped: true,
|
|
5772
|
+
code: "submodule_push_skipped"
|
|
5773
|
+
};
|
|
5774
|
+
if (!options.allowAutoPublishSubmoduleMainCommits) {
|
|
5775
|
+
results.push({ ...base, code: "submodule_push_policy_disabled", error: "allowAutoPublishSubmoduleMainCommits is not enabled" });
|
|
5776
|
+
continue;
|
|
5777
|
+
}
|
|
5778
|
+
if (submodule.error || submodule.dirty) {
|
|
5779
|
+
results.push({ ...base, code: "submodule_not_clean", error: submodule.error || "submodule worktree is dirty" });
|
|
5780
|
+
continue;
|
|
5781
|
+
}
|
|
5782
|
+
const repoPath = submodule.repoPath;
|
|
5783
|
+
if (!repoPath || !submodule.commit) {
|
|
5784
|
+
results.push({ ...base, code: "submodule_status_incomplete" });
|
|
5785
|
+
continue;
|
|
5786
|
+
}
|
|
5787
|
+
try {
|
|
5788
|
+
await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5789
|
+
} catch (error) {
|
|
5790
|
+
results.push({ ...base, code: "submodule_fetch_failed", error: formatGitError2(error) });
|
|
5791
|
+
continue;
|
|
5792
|
+
}
|
|
5793
|
+
let alreadyReachable = false;
|
|
5794
|
+
try {
|
|
5795
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5796
|
+
alreadyReachable = true;
|
|
5797
|
+
} catch {
|
|
5798
|
+
}
|
|
5799
|
+
if (alreadyReachable) {
|
|
5800
|
+
results.push({ ...base, pushed: false, skipped: true, code: "submodule_already_reachable" });
|
|
5801
|
+
continue;
|
|
5802
|
+
}
|
|
5803
|
+
try {
|
|
5804
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", "refs/remotes/origin/main", submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5805
|
+
} catch (error) {
|
|
5806
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_non_fast_forward", error: formatGitError2(error) });
|
|
5807
|
+
continue;
|
|
5808
|
+
}
|
|
5809
|
+
const refspec = `${submodule.commit}:refs/heads/main`;
|
|
5810
|
+
if (!execute) {
|
|
5811
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_available", refspec });
|
|
5812
|
+
continue;
|
|
5813
|
+
}
|
|
5814
|
+
try {
|
|
5815
|
+
await runGit(repoPath, ["push", "origin", refspec], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5816
|
+
await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
|
|
5817
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
|
|
5818
|
+
results.push({ ...base, pushed: true, skipped: false, code: "submodule_pushed", refspec });
|
|
5819
|
+
} catch (error) {
|
|
5820
|
+
results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_failed", refspec, error: formatGitError2(error) });
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
return results;
|
|
5824
|
+
}
|
|
5825
|
+
function buildPlannedSteps(mode, updateSubmodules, pushSubmodules) {
|
|
5492
5826
|
const steps = [
|
|
5493
5827
|
{
|
|
5494
5828
|
operation: "refresh_upstream",
|
|
@@ -5501,20 +5835,49 @@ function buildPlannedSteps(updateSubmodules) {
|
|
|
5501
5835
|
description: "Require clean staged/modified/untracked/deleted/renamed/conflict/stash/submodule state.",
|
|
5502
5836
|
safe: true,
|
|
5503
5837
|
willMutateWorktree: false
|
|
5504
|
-
}
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5838
|
+
}
|
|
5839
|
+
];
|
|
5840
|
+
if (mode === "push") {
|
|
5841
|
+
steps.push({
|
|
5842
|
+
operation: "verify_push_descendant",
|
|
5843
|
+
description: "Require HEAD to be a descendant of origin/<branch> (origin/<branch> is an ancestor of HEAD); refuse any non-fast-forward push.",
|
|
5508
5844
|
safe: true,
|
|
5509
5845
|
willMutateWorktree: false
|
|
5510
|
-
}
|
|
5511
|
-
{
|
|
5512
|
-
operation: "
|
|
5513
|
-
description: "
|
|
5846
|
+
});
|
|
5847
|
+
steps.push({
|
|
5848
|
+
operation: "push_ff_only",
|
|
5849
|
+
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.",
|
|
5514
5850
|
safe: true,
|
|
5515
|
-
willMutateWorktree:
|
|
5851
|
+
willMutateWorktree: false
|
|
5852
|
+
});
|
|
5853
|
+
if (pushSubmodules) {
|
|
5854
|
+
steps.push({
|
|
5855
|
+
operation: "push_submodules_ff_only",
|
|
5856
|
+
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.",
|
|
5857
|
+
safe: true,
|
|
5858
|
+
willMutateWorktree: false
|
|
5859
|
+
});
|
|
5516
5860
|
}
|
|
5517
|
-
|
|
5861
|
+
steps.push({
|
|
5862
|
+
operation: "verify_post_status",
|
|
5863
|
+
description: "Re-read daemon-owned git status and report final branch convergence state.",
|
|
5864
|
+
safe: true,
|
|
5865
|
+
willMutateWorktree: false
|
|
5866
|
+
});
|
|
5867
|
+
return steps;
|
|
5868
|
+
}
|
|
5869
|
+
steps.push({
|
|
5870
|
+
operation: "verify_fast_forward",
|
|
5871
|
+
description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
|
|
5872
|
+
safe: true,
|
|
5873
|
+
willMutateWorktree: false
|
|
5874
|
+
});
|
|
5875
|
+
steps.push({
|
|
5876
|
+
operation: "merge_ff_only",
|
|
5877
|
+
description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
|
|
5878
|
+
safe: true,
|
|
5879
|
+
willMutateWorktree: true
|
|
5880
|
+
});
|
|
5518
5881
|
if (updateSubmodules) {
|
|
5519
5882
|
steps.push({
|
|
5520
5883
|
operation: "submodule_update",
|
|
@@ -5531,6 +5894,10 @@ function buildPlannedSteps(updateSubmodules) {
|
|
|
5531
5894
|
});
|
|
5532
5895
|
return steps;
|
|
5533
5896
|
}
|
|
5897
|
+
function otherBlockersAreOnlyAhead(blockers) {
|
|
5898
|
+
const aheadOnly = /* @__PURE__ */ new Set(["branch_has_local_commits"]);
|
|
5899
|
+
return blockers.every((reason) => aheadOnly.has(reason));
|
|
5900
|
+
}
|
|
5534
5901
|
function collectPreflightBlockers(status, requestedBranch) {
|
|
5535
5902
|
const blockers = [];
|
|
5536
5903
|
if (!status.isGitRepo) blockers.push("not_git_repo");
|
|
@@ -5587,7 +5954,7 @@ function chooseBlockCode(status, blockers) {
|
|
|
5587
5954
|
return "preflight_blocked";
|
|
5588
5955
|
}
|
|
5589
5956
|
function codeToConvergenceStatus(code) {
|
|
5590
|
-
if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward") return "not_mergeable";
|
|
5957
|
+
if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward" || code === "non_fast_forward_push" || code === "upstream_unparseable") return "not_mergeable";
|
|
5591
5958
|
if (code === "dirty_worktree" || code === "submodule_not_clean") return "blocked_review";
|
|
5592
5959
|
return "blocked";
|
|
5593
5960
|
}
|
|
@@ -5670,6 +6037,7 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5670
6037
|
...result.nodeId ? { nodeId: result.nodeId } : {},
|
|
5671
6038
|
payload: {
|
|
5672
6039
|
operation: "mesh_fast_forward_node",
|
|
6040
|
+
mode: result.mode,
|
|
5673
6041
|
trigger: result.trigger || "manual",
|
|
5674
6042
|
outcome,
|
|
5675
6043
|
code: result.code,
|
|
@@ -5680,6 +6048,7 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5680
6048
|
executed: result.executed,
|
|
5681
6049
|
branch: result.postStatus?.branch ?? result.current?.branch,
|
|
5682
6050
|
upstream: result.postStatus?.upstream ?? result.current?.upstream,
|
|
6051
|
+
...result.pushTarget ? { pushTarget: result.pushTarget } : {},
|
|
5683
6052
|
before: result.current ? {
|
|
5684
6053
|
headCommit: result.current.headCommit,
|
|
5685
6054
|
ahead: result.current.ahead,
|
|
@@ -5690,6 +6059,16 @@ async function appendFastForwardLedger(result, outcome) {
|
|
|
5690
6059
|
ahead: result.postStatus.ahead,
|
|
5691
6060
|
behind: result.postStatus.behind
|
|
5692
6061
|
} : void 0,
|
|
6062
|
+
...result.submodulePushes ? {
|
|
6063
|
+
submodulePushes: result.submodulePushes.map((entry) => ({
|
|
6064
|
+
path: entry.path,
|
|
6065
|
+
commit: entry.commit,
|
|
6066
|
+
pushed: entry.pushed,
|
|
6067
|
+
skipped: entry.skipped,
|
|
6068
|
+
code: entry.code,
|
|
6069
|
+
...entry.refspec ? { refspec: entry.refspec } : {}
|
|
6070
|
+
}))
|
|
6071
|
+
} : {},
|
|
5693
6072
|
blockingReasons: result.blockingReasons
|
|
5694
6073
|
}
|
|
5695
6074
|
});
|
|
@@ -6860,8 +7239,8 @@ var init_mesh_routing = __esm({
|
|
|
6860
7239
|
import { existsSync as existsSync14 } from "fs";
|
|
6861
7240
|
function getCachedMeshByWorkspace(workspace) {
|
|
6862
7241
|
const now = Date.now();
|
|
6863
|
-
const
|
|
6864
|
-
if (
|
|
7242
|
+
const cached2 = meshByWorkspaceCache.get(workspace);
|
|
7243
|
+
if (cached2 && now - cached2.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached2.mesh;
|
|
6865
7244
|
const mesh = getMeshByRepo(workspace);
|
|
6866
7245
|
meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
|
|
6867
7246
|
return mesh;
|
|
@@ -11754,10 +12133,10 @@ ${lastSnapshot}`;
|
|
|
11754
12133
|
return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
11755
12134
|
}
|
|
11756
12135
|
getFreshParsedStatusCache() {
|
|
11757
|
-
const
|
|
12136
|
+
const cached2 = this.parsedStatusCache;
|
|
11758
12137
|
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
11759
|
-
if (
|
|
11760
|
-
return
|
|
12138
|
+
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) {
|
|
12139
|
+
return cached2.result;
|
|
11761
12140
|
}
|
|
11762
12141
|
return null;
|
|
11763
12142
|
}
|
|
@@ -12217,10 +12596,10 @@ ${lastSnapshot}`;
|
|
|
12217
12596
|
getScriptParsedStatus() {
|
|
12218
12597
|
const screenText = this.readTerminalScreenText();
|
|
12219
12598
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
12220
|
-
const
|
|
12599
|
+
const cached2 = this.parsedStatusCache;
|
|
12221
12600
|
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
12222
|
-
if (!this.providerOwnsTranscript() &&
|
|
12223
|
-
return
|
|
12601
|
+
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) {
|
|
12602
|
+
return cached2.result;
|
|
12224
12603
|
}
|
|
12225
12604
|
const parsed = this.runParseSession();
|
|
12226
12605
|
if (!parsed || !Array.isArray(parsed.messages)) {
|
|
@@ -16701,6 +17080,17 @@ function buildMeshActiveWork(opts) {
|
|
|
16701
17080
|
}
|
|
16702
17081
|
return { activeWork: records, staleDirectWork, staleDirectWorkNote, terminalDirectWork, summary };
|
|
16703
17082
|
}
|
|
17083
|
+
var PRUNABLE_ORPHAN_STALE_REASONS = /* @__PURE__ */ new Set([
|
|
17084
|
+
"direct task node is no longer in the live mesh",
|
|
17085
|
+
"direct task session is not present in live session records",
|
|
17086
|
+
"direct task has no node id"
|
|
17087
|
+
]);
|
|
17088
|
+
function classifyStaleDirectForPrune(record, opts = {}) {
|
|
17089
|
+
if (record.staleDispatchUnacknowledged === true) return "preserve_unacknowledged";
|
|
17090
|
+
if (record.terminal === true) return opts.includeTerminal ? "prunable_terminal" : "preserve_active";
|
|
17091
|
+
if (record.staleReason && PRUNABLE_ORPHAN_STALE_REASONS.has(record.staleReason)) return "prunable_orphan";
|
|
17092
|
+
return "preserve_active";
|
|
17093
|
+
}
|
|
16704
17094
|
function buildCompactStaleDirectWorkSummary(staleDirectWork, opts = {}) {
|
|
16705
17095
|
const sampleLimit = Math.max(0, Math.min(10, Math.floor(opts.sampleLimit ?? 3)));
|
|
16706
17096
|
const reasonCounts = {};
|
|
@@ -19924,9 +20314,9 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
19924
20314
|
for (const file of files.slice().sort()) {
|
|
19925
20315
|
const filePath = path12.join(dir, file);
|
|
19926
20316
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
19927
|
-
const
|
|
20317
|
+
const cached2 = savedHistoryFileSummaryCache.get(filePath);
|
|
19928
20318
|
const persisted = persistedEntries.get(file);
|
|
19929
|
-
const reusableEntry =
|
|
20319
|
+
const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
|
|
19930
20320
|
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file);
|
|
19931
20321
|
const nextEntry = reusableEntry || {
|
|
19932
20322
|
signature,
|
|
@@ -20378,23 +20768,23 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
20378
20768
|
savedHistorySessionCache.delete(sanitized);
|
|
20379
20769
|
return { sessions: [], hasMore: false };
|
|
20380
20770
|
}
|
|
20381
|
-
const
|
|
20771
|
+
const cached2 = savedHistorySessionCache.get(sanitized);
|
|
20382
20772
|
const offset = Math.max(0, options.offset || 0);
|
|
20383
20773
|
const limit = Math.max(1, options.limit || 30);
|
|
20384
20774
|
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
20385
20775
|
let cacheWasInvalidated = false;
|
|
20386
|
-
if (
|
|
20387
|
-
const cacheLooksPersisted =
|
|
20388
|
-
const cacheStillValid = cacheLooksPersisted ?
|
|
20776
|
+
if (cached2) {
|
|
20777
|
+
const cacheLooksPersisted = cached2.signature.startsWith("index:");
|
|
20778
|
+
const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
|
|
20389
20779
|
const files2 = listHistoryFiles(dir);
|
|
20390
20780
|
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
20391
|
-
return
|
|
20781
|
+
return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
20392
20782
|
})();
|
|
20393
20783
|
if (cacheStillValid) {
|
|
20394
|
-
const sliced2 =
|
|
20784
|
+
const sliced2 = cached2.summaries.slice(offset, offset + limit);
|
|
20395
20785
|
return {
|
|
20396
20786
|
sessions: sliced2,
|
|
20397
|
-
hasMore:
|
|
20787
|
+
hasMore: cached2.summaries.length > offset + limit
|
|
20398
20788
|
};
|
|
20399
20789
|
}
|
|
20400
20790
|
cacheWasInvalidated = true;
|
|
@@ -36988,8 +37378,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
36988
37378
|
return null;
|
|
36989
37379
|
}
|
|
36990
37380
|
registerProviderScriptRootSafely(path30.dirname(path30.dirname(providerDir)));
|
|
36991
|
-
const
|
|
36992
|
-
if (
|
|
37381
|
+
const cached2 = this.scriptsCache.get(dir);
|
|
37382
|
+
if (cached2) return cached2;
|
|
36993
37383
|
const scriptsJs = path30.join(dir, "scripts.js");
|
|
36994
37384
|
if (fs20.existsSync(scriptsJs)) {
|
|
36995
37385
|
try {
|
|
@@ -38987,6 +39377,9 @@ function buildStatusSnapshot(options) {
|
|
|
38987
39377
|
};
|
|
38988
39378
|
}
|
|
38989
39379
|
|
|
39380
|
+
// src/commands/router.ts
|
|
39381
|
+
init_build_info();
|
|
39382
|
+
|
|
38990
39383
|
// src/commands/upgrade-helper.ts
|
|
38991
39384
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
38992
39385
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -39772,13 +40165,13 @@ function sanitizeInlineMesh(inlineMesh) {
|
|
|
39772
40165
|
nodes
|
|
39773
40166
|
};
|
|
39774
40167
|
}
|
|
39775
|
-
function reconcileInlineMeshCache(
|
|
39776
|
-
if (!
|
|
39777
|
-
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return
|
|
39778
|
-
const cachedNodes = Array.isArray(
|
|
40168
|
+
function reconcileInlineMeshCache(cached2, incoming) {
|
|
40169
|
+
if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
|
|
40170
|
+
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
|
|
40171
|
+
const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
|
|
39779
40172
|
const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
|
|
39780
|
-
if (!cachedNodes.length || !incomingNodes.length) return { ...
|
|
39781
|
-
const cachedUpdatedAt = Date.parse(readStringValue(
|
|
40173
|
+
if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
|
|
40174
|
+
const cachedUpdatedAt = Date.parse(readStringValue(cached2.updatedAt, cached2.updated_at) || "");
|
|
39782
40175
|
const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
|
|
39783
40176
|
const preserveCachedMembership = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
|
|
39784
40177
|
const cachedById = /* @__PURE__ */ new Map();
|
|
@@ -39807,7 +40200,7 @@ function reconcileInlineMeshCache(cached, incoming) {
|
|
|
39807
40200
|
}
|
|
39808
40201
|
}
|
|
39809
40202
|
return {
|
|
39810
|
-
...
|
|
40203
|
+
...cached2,
|
|
39811
40204
|
...incoming,
|
|
39812
40205
|
nodes
|
|
39813
40206
|
};
|
|
@@ -41491,13 +41884,13 @@ var DaemonCommandRouter = class {
|
|
|
41491
41884
|
};
|
|
41492
41885
|
}
|
|
41493
41886
|
getCachedAggregateMeshStatus(meshId, mesh, options) {
|
|
41494
|
-
const
|
|
41495
|
-
if (!
|
|
41496
|
-
if (
|
|
41497
|
-
let snapshot = this.cloneJsonValue(
|
|
41887
|
+
const cached2 = this.aggregateMeshStatusCache.get(meshId);
|
|
41888
|
+
if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
|
|
41889
|
+
if (cached2.queueRevision !== getMeshQueueRevision(meshId)) return null;
|
|
41890
|
+
let snapshot = this.cloneJsonValue(cached2.snapshot);
|
|
41498
41891
|
snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
|
|
41499
41892
|
if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
|
|
41500
|
-
const ageMs = Math.max(0, Date.now() -
|
|
41893
|
+
const ageMs = Math.max(0, Date.now() - cached2.builtAt);
|
|
41501
41894
|
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
41502
41895
|
snapshot.sourceOfTruth = {
|
|
41503
41896
|
...sourceOfTruth,
|
|
@@ -41508,7 +41901,7 @@ var DaemonCommandRouter = class {
|
|
|
41508
41901
|
source: "memory",
|
|
41509
41902
|
refreshReason: "memory_cache_hit",
|
|
41510
41903
|
ageMs,
|
|
41511
|
-
cachedAt: new Date(
|
|
41904
|
+
cachedAt: new Date(cached2.builtAt).toISOString(),
|
|
41512
41905
|
returnedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41513
41906
|
}
|
|
41514
41907
|
};
|
|
@@ -41552,9 +41945,9 @@ var DaemonCommandRouter = class {
|
|
|
41552
41945
|
warmInlineMeshCache(meshId, inlineMesh) {
|
|
41553
41946
|
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
41554
41947
|
const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
|
|
41555
|
-
const
|
|
41556
|
-
if (
|
|
41557
|
-
const merged = reconcileInlineMeshCache(
|
|
41948
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
41949
|
+
if (cached2) {
|
|
41950
|
+
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
41558
41951
|
this.inlineMeshCache.set(meshId, merged);
|
|
41559
41952
|
return merged;
|
|
41560
41953
|
}
|
|
@@ -41564,14 +41957,14 @@ var DaemonCommandRouter = class {
|
|
|
41564
41957
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
41565
41958
|
const preferInline = options?.preferInline === true;
|
|
41566
41959
|
if (preferInline) {
|
|
41567
|
-
const
|
|
41568
|
-
if (
|
|
41960
|
+
const cached3 = this.getCachedInlineMesh(meshId);
|
|
41961
|
+
if (cached3) {
|
|
41569
41962
|
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
41570
|
-
const merged = reconcileInlineMeshCache(
|
|
41963
|
+
const merged = reconcileInlineMeshCache(cached3, inlineMesh);
|
|
41571
41964
|
this.inlineMeshCache.set(meshId, sanitizeInlineMesh(merged));
|
|
41572
41965
|
return { mesh: merged, inline: true, source: "inline_cache" };
|
|
41573
41966
|
}
|
|
41574
|
-
return { mesh:
|
|
41967
|
+
return { mesh: cached3, inline: true, source: "inline_cache" };
|
|
41575
41968
|
}
|
|
41576
41969
|
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
41577
41970
|
this.warmInlineMeshCache(meshId, inlineMesh);
|
|
@@ -41584,8 +41977,8 @@ var DaemonCommandRouter = class {
|
|
|
41584
41977
|
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
41585
41978
|
} catch {
|
|
41586
41979
|
}
|
|
41587
|
-
const
|
|
41588
|
-
if (
|
|
41980
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
41981
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
41589
41982
|
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
41590
41983
|
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
41591
41984
|
}
|
|
@@ -41892,6 +42285,8 @@ var DaemonCommandRouter = class {
|
|
|
41892
42285
|
const skippedSessionIds = [];
|
|
41893
42286
|
const skippedLiveSessionIds = [];
|
|
41894
42287
|
const skippedCoordinatorSessionIds = [];
|
|
42288
|
+
const skippedLiveSessionReasons = [];
|
|
42289
|
+
const actedLiveDelegateSessionIds = [];
|
|
41895
42290
|
const deleteUnsupportedSessionIds = [];
|
|
41896
42291
|
const recordsRemainSessionIds = [];
|
|
41897
42292
|
const errors = [];
|
|
@@ -41925,16 +42320,31 @@ var DaemonCommandRouter = class {
|
|
|
41925
42320
|
const surfaceKind = getSessionHostSurfaceKind(record);
|
|
41926
42321
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
41927
42322
|
const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
|
|
42323
|
+
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
42324
|
+
const recordMeshNodeFor = readStringValue(record?.meta?.meshNodeFor);
|
|
42325
|
+
const delegateBoundToThisNode = !!recordNodeId && recordNodeId === args.nodeId && (!recordMeshNodeFor || recordMeshNodeFor === args.meshId);
|
|
41928
42326
|
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
41929
42327
|
skippedSessionIds.push(sessionId);
|
|
41930
42328
|
skippedCoordinatorSessionIds.push(sessionId);
|
|
41931
42329
|
continue;
|
|
41932
42330
|
}
|
|
41933
|
-
if (!hasExplicitSessionIds && liveRuntime) {
|
|
42331
|
+
if (!hasExplicitSessionIds && liveRuntime && !delegateBoundToThisNode) {
|
|
42332
|
+
skippedSessionIds.push(sessionId);
|
|
42333
|
+
skippedLiveSessionIds.push(sessionId);
|
|
42334
|
+
const matchedByWorkspaceOnly = !recordNodeId;
|
|
42335
|
+
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";
|
|
42336
|
+
skippedLiveSessionReasons.push({ sessionId, reason });
|
|
42337
|
+
continue;
|
|
42338
|
+
}
|
|
42339
|
+
if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode && args.mode === "delete_stopped") {
|
|
41934
42340
|
skippedSessionIds.push(sessionId);
|
|
41935
42341
|
skippedLiveSessionIds.push(sessionId);
|
|
42342
|
+
skippedLiveSessionReasons.push({ sessionId, reason: "live_delegate_preserved_by_delete_stopped_mode_use_stop_or_stop_and_delete" });
|
|
41936
42343
|
continue;
|
|
41937
42344
|
}
|
|
42345
|
+
if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode) {
|
|
42346
|
+
actedLiveDelegateSessionIds.push(sessionId);
|
|
42347
|
+
}
|
|
41938
42348
|
try {
|
|
41939
42349
|
if (args.mode === "stop") {
|
|
41940
42350
|
if (!completed) {
|
|
@@ -41996,6 +42406,8 @@ var DaemonCommandRouter = class {
|
|
|
41996
42406
|
skippedSessionIds,
|
|
41997
42407
|
skippedLiveSessionIds,
|
|
41998
42408
|
skippedCoordinatorSessionIds,
|
|
42409
|
+
...actedLiveDelegateSessionIds.length ? { actedLiveDelegateSessionIds } : {},
|
|
42410
|
+
...skippedLiveSessionReasons.length ? { skippedLiveSessionReasons } : {},
|
|
41999
42411
|
...deleteUnsupported ? {
|
|
42000
42412
|
deleteUnsupported: true,
|
|
42001
42413
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -42923,8 +43335,8 @@ ${hintLines.join("\n")}` : "",
|
|
|
42923
43335
|
const repoRootBaseRef = /* @__PURE__ */ new Map();
|
|
42924
43336
|
const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
|
|
42925
43337
|
const resolveBaseRef = async (repoRoot) => {
|
|
42926
|
-
const
|
|
42927
|
-
if (
|
|
43338
|
+
const cached2 = repoRootBaseRef.get(repoRoot);
|
|
43339
|
+
if (cached2) return cached2;
|
|
42928
43340
|
let baseBranch = "main";
|
|
42929
43341
|
try {
|
|
42930
43342
|
const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
@@ -43822,7 +44234,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
43822
44234
|
version: this.deps.statusVersion || "unknown",
|
|
43823
44235
|
profile: "metadata"
|
|
43824
44236
|
});
|
|
43825
|
-
return { success: true, status: snapshot };
|
|
44237
|
+
return { success: true, status: snapshot, daemonBuild: getDaemonBuildInfo() };
|
|
43826
44238
|
}
|
|
43827
44239
|
case "get_machine_runtime_stats": {
|
|
43828
44240
|
return {
|
|
@@ -44792,6 +45204,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
44792
45204
|
let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
44793
45205
|
let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
|
|
44794
45206
|
let nodeDaemonId;
|
|
45207
|
+
let allowAutoPublishSubmoduleMainCommits = false;
|
|
44795
45208
|
if (meshId && nodeId) {
|
|
44796
45209
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
44797
45210
|
const mesh = meshRecord?.mesh;
|
|
@@ -44802,6 +45215,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
44802
45215
|
if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
|
|
44803
45216
|
submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
|
|
44804
45217
|
}
|
|
45218
|
+
allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
|
|
44805
45219
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
44806
45220
|
}
|
|
44807
45221
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
@@ -44822,7 +45236,10 @@ ${hintLines.join("\n")}` : "",
|
|
|
44822
45236
|
execute: args?.execute === true,
|
|
44823
45237
|
dryRun: args?.dryRun === true,
|
|
44824
45238
|
updateSubmodules: args?.updateSubmodules === true,
|
|
44825
|
-
submoduleIgnorePaths
|
|
45239
|
+
submoduleIgnorePaths,
|
|
45240
|
+
mode: args?.mode === "push" ? "push" : "merge",
|
|
45241
|
+
pushSubmodules: args?.pushSubmodules === true,
|
|
45242
|
+
allowAutoPublishSubmoduleMainCommits
|
|
44826
45243
|
});
|
|
44827
45244
|
return result;
|
|
44828
45245
|
}
|
|
@@ -46522,6 +46939,7 @@ var DaemonStatusReporter = class {
|
|
|
46522
46939
|
};
|
|
46523
46940
|
|
|
46524
46941
|
// src/index.ts
|
|
46942
|
+
init_build_info();
|
|
46525
46943
|
init_logger();
|
|
46526
46944
|
init_debug_config();
|
|
46527
46945
|
|
|
@@ -54799,6 +55217,7 @@ export {
|
|
|
54799
55217
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
54800
55218
|
NodePtyTransportFactory,
|
|
54801
55219
|
P2pRelayFailureError,
|
|
55220
|
+
PRUNABLE_ORPHAN_STALE_REASONS,
|
|
54802
55221
|
ProviderCliAdapter,
|
|
54803
55222
|
ProviderInstanceManager,
|
|
54804
55223
|
ProviderLoader,
|
|
@@ -54852,6 +55271,7 @@ export {
|
|
|
54852
55271
|
classifyChatMessageVisibility,
|
|
54853
55272
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
54854
55273
|
classifyP2pRelayFailure,
|
|
55274
|
+
classifyStaleDirectForPrune,
|
|
54855
55275
|
cleanupTerminalDirectDispatches,
|
|
54856
55276
|
clearDebugTrace,
|
|
54857
55277
|
clearPendingMeshCoordinatorEvents,
|
|
@@ -54871,6 +55291,7 @@ export {
|
|
|
54871
55291
|
createNativeHistoryDispatcher,
|
|
54872
55292
|
createSessionDelivery,
|
|
54873
55293
|
createWorktree,
|
|
55294
|
+
deleteDirectDispatchesByTaskId,
|
|
54874
55295
|
deleteMesh,
|
|
54875
55296
|
deriveMeshReviewInboxItems,
|
|
54876
55297
|
describeTaskDependencyState,
|
|
@@ -54899,6 +55320,7 @@ export {
|
|
|
54899
55320
|
getAvailableIdeIds,
|
|
54900
55321
|
getCoordinatorForSession,
|
|
54901
55322
|
getCurrentDaemonLogPath,
|
|
55323
|
+
getDaemonBuildInfo,
|
|
54902
55324
|
getDaemonDataDir,
|
|
54903
55325
|
getDaemonLogDir,
|
|
54904
55326
|
getDebugRuntimeConfig,
|