@adhdev/daemon-standalone 0.9.82-rc.406 → 0.9.82-rc.408
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +227 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +118 -108
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -30127,10 +30127,10 @@ var require_dist3 = __commonJS({
|
|
|
30127
30127
|
}
|
|
30128
30128
|
function getDaemonBuildInfo() {
|
|
30129
30129
|
if (cached2) return cached2;
|
|
30130
|
-
const commit = readInjected(true ? "
|
|
30131
|
-
const commitShort = readInjected(true ? "
|
|
30132
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30133
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
30130
|
+
const commit = readInjected(true ? "b6de7b335f9b6b6bfb202135c2ae017429182efa" : void 0) ?? "unknown";
|
|
30131
|
+
const commitShort = readInjected(true ? "b6de7b33" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30132
|
+
const version2 = readInjected(true ? "0.9.82-rc.408" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30133
|
+
const builtAt = readInjected(true ? "2026-06-28T07:54:01.430Z" : void 0);
|
|
30134
30134
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30135
30135
|
return cached2;
|
|
30136
30136
|
}
|
|
@@ -30383,6 +30383,11 @@ var require_dist3 = __commonJS({
|
|
|
30383
30383
|
};
|
|
30384
30384
|
}
|
|
30385
30385
|
});
|
|
30386
|
+
function statusCacheKey(workspace, options) {
|
|
30387
|
+
const includeSubmodules = options.includeSubmodules !== false;
|
|
30388
|
+
const refreshUpstream = options.refreshUpstream === true;
|
|
30389
|
+
return `${workspace}\0sub=${includeSubmodules ? 1 : 0}\0up=${refreshUpstream ? 1 : 0}`;
|
|
30390
|
+
}
|
|
30386
30391
|
function isTransientGitFailure(error48) {
|
|
30387
30392
|
return error48.reason === "timeout" || error48.reason === "git_command_failed";
|
|
30388
30393
|
}
|
|
@@ -30390,15 +30395,22 @@ var require_dist3 = __commonJS({
|
|
|
30390
30395
|
const lastCheckedAt = Date.now();
|
|
30391
30396
|
const includeSubmodules = options.includeSubmodules !== false;
|
|
30392
30397
|
const effectiveOptions = options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
|
|
30398
|
+
const cacheKey = statusCacheKey(workspace, options);
|
|
30399
|
+
if (!options.forceFresh) {
|
|
30400
|
+
const cached3 = lastKnownGoodStatus.get(cacheKey);
|
|
30401
|
+
if (cached3 && lastCheckedAt - cached3.cachedAt < GIT_STATUS_CACHE_TTL_MS) {
|
|
30402
|
+
return cached3.status;
|
|
30403
|
+
}
|
|
30404
|
+
}
|
|
30393
30405
|
try {
|
|
30394
30406
|
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
30395
30407
|
const status = await collectGitRepoStatus(repo, includeSubmodules, lastCheckedAt, effectiveOptions);
|
|
30396
|
-
lastKnownGoodStatus.set(
|
|
30408
|
+
lastKnownGoodStatus.set(cacheKey, { status, cachedAt: lastCheckedAt });
|
|
30397
30409
|
return status;
|
|
30398
30410
|
} catch (error48) {
|
|
30399
30411
|
const gitError = error48 instanceof GitCommandError ? error48 : new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error48 });
|
|
30400
30412
|
if (isTransientGitFailure(gitError)) {
|
|
30401
|
-
const cached3 = lastKnownGoodStatus.get(
|
|
30413
|
+
const cached3 = lastKnownGoodStatus.get(cacheKey)?.status;
|
|
30402
30414
|
if (cached3) {
|
|
30403
30415
|
return {
|
|
30404
30416
|
...cached3,
|
|
@@ -30417,19 +30429,25 @@ var require_dist3 = __commonJS({
|
|
|
30417
30429
|
let upstreamProbe = getInitialUpstreamProbe(parsed);
|
|
30418
30430
|
if (options.refreshUpstream) {
|
|
30419
30431
|
upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
|
|
30420
|
-
if (upstreamProbe.upstreamStatus === "fresh") {
|
|
30432
|
+
if (upstreamProbe.upstreamStatus === "fresh" && upstreamProbe.didFetch) {
|
|
30421
30433
|
parsed = await readPorcelainStatus(repo, options);
|
|
30422
30434
|
}
|
|
30423
30435
|
}
|
|
30424
30436
|
const head = await readHead(repo, options);
|
|
30425
30437
|
const stashCount = await readStashCount(repo, options);
|
|
30426
30438
|
let submodules;
|
|
30439
|
+
let submoduleHeadOids = /* @__PURE__ */ new Map();
|
|
30427
30440
|
if (includeSubmodules) {
|
|
30428
|
-
|
|
30441
|
+
const subResult = await getSubmoduleStatuses(repo, options);
|
|
30442
|
+
submodules = subResult.submodules;
|
|
30443
|
+
submoduleHeadOids = subResult.headOidByPath;
|
|
30429
30444
|
}
|
|
30430
30445
|
const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
|
|
30431
30446
|
const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
|
|
30432
|
-
const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options
|
|
30447
|
+
const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options, {
|
|
30448
|
+
rootHeadOid: parsed.headOid,
|
|
30449
|
+
submoduleHeadOids
|
|
30450
|
+
});
|
|
30433
30451
|
return {
|
|
30434
30452
|
workspace: repo.workspace,
|
|
30435
30453
|
repoRoot: repo.repoRoot,
|
|
@@ -30532,25 +30550,50 @@ var require_dist3 = __commonJS({
|
|
|
30532
30550
|
changeImpactConfigCache.set(repoRoot, { sourceKey: loaded.sourceKey, config: config2 });
|
|
30533
30551
|
return { config: config2, sourceKey: loaded.sourceKey };
|
|
30534
30552
|
}
|
|
30535
|
-
async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
30553
|
+
async function detectDaemonBuildBehind(repo, submodules, options, headOids = { rootHeadOid: null, submoduleHeadOids: /* @__PURE__ */ new Map() }) {
|
|
30536
30554
|
const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
|
|
30537
30555
|
if (!build.commit || build.commit === "unknown") return void 0;
|
|
30538
30556
|
const { config: config2, sourceKey: configKey } = resolveChangeImpactConfigForRepo(repo.repoRoot, options);
|
|
30539
30557
|
const policy = resolveChangeImpactPolicy(config2);
|
|
30540
30558
|
const scopes = [
|
|
30541
|
-
{ scope: "root", repoPath: repo.repoRoot || repo.workspace }
|
|
30559
|
+
{ scope: "root", repoPath: repo.repoRoot || repo.workspace, knownHeadOid: headOids.rootHeadOid }
|
|
30542
30560
|
];
|
|
30543
30561
|
for (const sub of submodules || []) {
|
|
30544
|
-
if (sub.repoPath && !sub.error)
|
|
30562
|
+
if (sub.repoPath && !sub.error) {
|
|
30563
|
+
scopes.push({ scope: sub.path, repoPath: sub.repoPath, knownHeadOid: headOids.submoduleHeadOids.get(sub.path) ?? null });
|
|
30564
|
+
}
|
|
30545
30565
|
}
|
|
30546
|
-
for (const { scope, repoPath } of scopes) {
|
|
30566
|
+
for (const { scope, repoPath, knownHeadOid } of scopes) {
|
|
30547
30567
|
try {
|
|
30548
|
-
|
|
30549
|
-
const
|
|
30550
|
-
|
|
30551
|
-
|
|
30552
|
-
|
|
30568
|
+
let head = knownHeadOid;
|
|
30569
|
+
const ancestryKey = head ? `${repoPath}::${build.commit}::${head}` : null;
|
|
30570
|
+
if (ancestryKey) {
|
|
30571
|
+
const cachedVerdict = buildBehindAncestryCache.get(ancestryKey);
|
|
30572
|
+
if (cachedVerdict === false) continue;
|
|
30573
|
+
if (cachedVerdict === void 0) {
|
|
30574
|
+
if (head === build.commit) {
|
|
30575
|
+
buildBehindAncestryCache.set(ancestryKey, false);
|
|
30576
|
+
continue;
|
|
30577
|
+
}
|
|
30578
|
+
await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
|
|
30579
|
+
try {
|
|
30580
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
|
|
30581
|
+
} catch {
|
|
30582
|
+
buildBehindAncestryCache.set(ancestryKey, false);
|
|
30583
|
+
continue;
|
|
30584
|
+
}
|
|
30585
|
+
buildBehindAncestryCache.set(ancestryKey, true);
|
|
30586
|
+
}
|
|
30587
|
+
} else {
|
|
30588
|
+
await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
|
|
30589
|
+
const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
|
|
30590
|
+
head = headResult.stdout.trim();
|
|
30591
|
+
if (!head || head === build.commit) continue;
|
|
30592
|
+
await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
|
|
30593
|
+
buildBehindAncestryCache.set(`${repoPath}::${build.commit}::${head}`, true);
|
|
30594
|
+
}
|
|
30553
30595
|
const evalKey = `${repoPath}\0${build.commit}\0${head}\0${configKey}`;
|
|
30596
|
+
if (!head) continue;
|
|
30554
30597
|
let evaluated = changeImpactEvalCache.get(evalKey);
|
|
30555
30598
|
if (!evaluated) {
|
|
30556
30599
|
evaluated = await classifyDaemonBuildChange(repoPath, build.commit, options, policy);
|
|
@@ -30592,6 +30635,15 @@ var require_dist3 = __commonJS({
|
|
|
30592
30635
|
if (!parsed.upstream || !parsed.branch) {
|
|
30593
30636
|
return { upstreamStatus: "no_upstream" };
|
|
30594
30637
|
}
|
|
30638
|
+
const now = Date.now();
|
|
30639
|
+
const lastFetch = upstreamFetchedAt.get(repo.workspace);
|
|
30640
|
+
if (!options.forceFresh && lastFetch !== void 0 && now - lastFetch < GIT_FETCH_THROTTLE_MS) {
|
|
30641
|
+
return {
|
|
30642
|
+
upstreamStatus: "fresh",
|
|
30643
|
+
upstreamFetchedAt: lastFetch,
|
|
30644
|
+
didFetch: false
|
|
30645
|
+
};
|
|
30646
|
+
}
|
|
30595
30647
|
const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
|
|
30596
30648
|
if (!remoteName) {
|
|
30597
30649
|
return {
|
|
@@ -30601,9 +30653,12 @@ var require_dist3 = __commonJS({
|
|
|
30601
30653
|
}
|
|
30602
30654
|
try {
|
|
30603
30655
|
await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
|
|
30656
|
+
const fetchedAt = Date.now();
|
|
30657
|
+
upstreamFetchedAt.set(repo.workspace, fetchedAt);
|
|
30604
30658
|
return {
|
|
30605
30659
|
upstreamStatus: "fresh",
|
|
30606
|
-
upstreamFetchedAt:
|
|
30660
|
+
upstreamFetchedAt: fetchedAt,
|
|
30661
|
+
didFetch: true
|
|
30607
30662
|
};
|
|
30608
30663
|
} catch (error48) {
|
|
30609
30664
|
return {
|
|
@@ -30636,6 +30691,7 @@ var require_dist3 = __commonJS({
|
|
|
30636
30691
|
function parsePorcelainV2Status(output) {
|
|
30637
30692
|
const parsed = {
|
|
30638
30693
|
branch: null,
|
|
30694
|
+
headOid: null,
|
|
30639
30695
|
upstream: null,
|
|
30640
30696
|
ahead: 0,
|
|
30641
30697
|
behind: 0,
|
|
@@ -30648,6 +30704,11 @@ var require_dist3 = __commonJS({
|
|
|
30648
30704
|
};
|
|
30649
30705
|
for (const line of output.split("\n")) {
|
|
30650
30706
|
if (!line) continue;
|
|
30707
|
+
if (line.startsWith("# branch.oid ")) {
|
|
30708
|
+
const oid = line.slice("# branch.oid ".length).trim();
|
|
30709
|
+
parsed.headOid = oid && oid !== "(initial)" && /^[0-9a-f]{7,64}$/.test(oid) ? oid : null;
|
|
30710
|
+
continue;
|
|
30711
|
+
}
|
|
30651
30712
|
if (line.startsWith("# branch.head ")) {
|
|
30652
30713
|
const branch = line.slice("# branch.head ".length).trim();
|
|
30653
30714
|
parsed.branch = branch && branch !== "(detached)" ? branch : null;
|
|
@@ -30745,25 +30806,27 @@ var require_dist3 = __commonJS({
|
|
|
30745
30806
|
};
|
|
30746
30807
|
}
|
|
30747
30808
|
async function getSubmoduleStatuses(repo, options) {
|
|
30748
|
-
if (!repo.repoRoot) return [];
|
|
30809
|
+
if (!repo.repoRoot) return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
|
|
30749
30810
|
try {
|
|
30750
|
-
const submodules = await deriveSubmoduleGitlinkStatuses(repo, options);
|
|
30811
|
+
const { submodules, headOidByPath } = await deriveSubmoduleGitlinkStatuses(repo, options);
|
|
30751
30812
|
await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
|
|
30752
|
-
return submodules;
|
|
30813
|
+
return { submodules, headOidByPath };
|
|
30753
30814
|
} catch {
|
|
30754
|
-
return [];
|
|
30815
|
+
return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
|
|
30755
30816
|
}
|
|
30756
30817
|
}
|
|
30757
30818
|
async function deriveSubmoduleGitlinkStatuses(repo, options) {
|
|
30758
|
-
if (!repo.repoRoot) return [];
|
|
30819
|
+
if (!repo.repoRoot) return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
|
|
30759
30820
|
const paths = await readSubmodulePaths(repo, options);
|
|
30760
30821
|
const ignoreSet = new Set(options.submoduleIgnorePaths || []);
|
|
30761
30822
|
const lastCheckedAt = Date.now();
|
|
30823
|
+
const headOidByPath = /* @__PURE__ */ new Map();
|
|
30762
30824
|
const entries = await Promise.all(
|
|
30763
30825
|
paths.filter((path43) => !ignoreSet.has(path43)).map(async (path43) => {
|
|
30764
30826
|
const repoPath = repo.repoRoot + "/" + path43;
|
|
30765
30827
|
const expected = await readGitlinkExpectedSha(repo, path43, options);
|
|
30766
30828
|
const actual = await readSubmoduleHeadSha(repo, repoPath, options);
|
|
30829
|
+
if (actual) headOidByPath.set(path43, actual);
|
|
30767
30830
|
const outOfSync = actual === null ? true : expected !== null && expected !== actual;
|
|
30768
30831
|
return {
|
|
30769
30832
|
path: path43,
|
|
@@ -30777,7 +30840,7 @@ var require_dist3 = __commonJS({
|
|
|
30777
30840
|
};
|
|
30778
30841
|
})
|
|
30779
30842
|
);
|
|
30780
|
-
return entries;
|
|
30843
|
+
return { submodules: entries, headOidByPath };
|
|
30781
30844
|
}
|
|
30782
30845
|
async function readSubmodulePaths(repo, options) {
|
|
30783
30846
|
if (!repo.repoRoot) return [];
|
|
@@ -30834,9 +30897,13 @@ var require_dist3 = __commonJS({
|
|
|
30834
30897
|
submodule.error = formatGitError(error48);
|
|
30835
30898
|
}
|
|
30836
30899
|
}
|
|
30900
|
+
var GIT_STATUS_CACHE_TTL_MS;
|
|
30837
30901
|
var lastKnownGoodStatus;
|
|
30838
30902
|
var changeImpactEvalCache;
|
|
30839
30903
|
var changeImpactConfigCache;
|
|
30904
|
+
var buildBehindAncestryCache;
|
|
30905
|
+
var GIT_FETCH_THROTTLE_MS;
|
|
30906
|
+
var upstreamFetchedAt;
|
|
30840
30907
|
var DEFAULT_DAEMON_RUNTIME_PACKAGES;
|
|
30841
30908
|
var DEFAULT_WEB_ONLY_PACKAGES;
|
|
30842
30909
|
var DEFAULT_IMPACT_TARGETS;
|
|
@@ -30846,9 +30913,13 @@ var require_dist3 = __commonJS({
|
|
|
30846
30913
|
init_git_executor();
|
|
30847
30914
|
init_build_info();
|
|
30848
30915
|
init_change_impact_config();
|
|
30916
|
+
GIT_STATUS_CACHE_TTL_MS = 1500;
|
|
30849
30917
|
lastKnownGoodStatus = /* @__PURE__ */ new Map();
|
|
30850
30918
|
changeImpactEvalCache = /* @__PURE__ */ new Map();
|
|
30851
30919
|
changeImpactConfigCache = /* @__PURE__ */ new Map();
|
|
30920
|
+
buildBehindAncestryCache = /* @__PURE__ */ new Map();
|
|
30921
|
+
GIT_FETCH_THROTTLE_MS = 3e4;
|
|
30922
|
+
upstreamFetchedAt = /* @__PURE__ */ new Map();
|
|
30852
30923
|
DEFAULT_DAEMON_RUNTIME_PACKAGES = [
|
|
30853
30924
|
"daemon-core",
|
|
30854
30925
|
"daemon-standalone",
|
|
@@ -32733,7 +32804,7 @@ ${error48.message || ""}`;
|
|
|
32733
32804
|
const repoRoot = readString3(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
|
|
32734
32805
|
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
32735
32806
|
const upstreamStatus = readString3(status.upstreamStatus, status.upstream_status);
|
|
32736
|
-
const
|
|
32807
|
+
const upstreamFetchedAt2 = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
|
|
32737
32808
|
const upstreamFetchError = readString3(status.upstreamFetchError, status.upstream_fetch_error);
|
|
32738
32809
|
const error48 = readString3(status.error);
|
|
32739
32810
|
const staged = readNumber(status.staged) ?? 0;
|
|
@@ -32750,7 +32821,7 @@ ${error48.message || ""}`;
|
|
|
32750
32821
|
headMessage: readString3(status.headMessage) ?? null,
|
|
32751
32822
|
upstream: readString3(status.upstream) ?? null,
|
|
32752
32823
|
upstreamStatus: upstreamStatus ?? "unchecked",
|
|
32753
|
-
...
|
|
32824
|
+
...upstreamFetchedAt2 !== void 0 ? { upstreamFetchedAt: upstreamFetchedAt2 } : {},
|
|
32754
32825
|
...upstreamFetchError ? { upstreamFetchError } : {},
|
|
32755
32826
|
ahead: readNumber(status.ahead) ?? 0,
|
|
32756
32827
|
behind: readNumber(status.behind) ?? 0,
|
|
@@ -34457,6 +34528,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34457
34528
|
getQueue: () => getQueue,
|
|
34458
34529
|
hasPendingDependents: () => hasPendingDependents,
|
|
34459
34530
|
insertDirectDispatch: () => insertDirectDispatch,
|
|
34531
|
+
isTaskReadonly: () => isTaskReadonly,
|
|
34460
34532
|
markStaleDirectDispatches: () => markStaleDirectDispatches,
|
|
34461
34533
|
nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
|
|
34462
34534
|
normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
|
|
@@ -34472,6 +34544,10 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34472
34544
|
updateTaskStatus: () => updateTaskStatus,
|
|
34473
34545
|
validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
|
|
34474
34546
|
});
|
|
34547
|
+
function isTaskReadonly(task) {
|
|
34548
|
+
if (!task) return false;
|
|
34549
|
+
return task.readonly === true || task.taskMode === "live_debug_readonly";
|
|
34550
|
+
}
|
|
34475
34551
|
function hasNegationBefore(text, matchIndex) {
|
|
34476
34552
|
const before = text.slice(0, matchIndex);
|
|
34477
34553
|
const clauseStart = Math.max(
|
|
@@ -34657,13 +34733,11 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34657
34733
|
const normalized = value.trim();
|
|
34658
34734
|
return MESH_TASK_MODES.includes(normalized) ? normalized : void 0;
|
|
34659
34735
|
}
|
|
34660
|
-
function validateMeshTaskModeRequest(mode, message) {
|
|
34736
|
+
function validateMeshTaskModeRequest(mode, message, readonly2) {
|
|
34661
34737
|
const taskMode = normalizeMeshTaskMode(mode);
|
|
34662
|
-
|
|
34663
|
-
|
|
34664
|
-
|
|
34665
|
-
if (taskMode !== "live_debug_readonly") {
|
|
34666
|
-
return { valid: true, taskMode, violations: [] };
|
|
34738
|
+
const isReadonly = isTaskReadonly({ readonly: readonly2, taskMode });
|
|
34739
|
+
if (!isReadonly) {
|
|
34740
|
+
return taskMode ? { valid: true, taskMode, violations: [] } : { valid: true, violations: [] };
|
|
34667
34741
|
}
|
|
34668
34742
|
const text = message || "";
|
|
34669
34743
|
const violations = LIVE_DEBUG_READONLY_FORBIDDEN.filter((rule) => patternHasRealMutation(rule.pattern, text)).map((rule) => rule.label);
|
|
@@ -34790,7 +34864,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34790
34864
|
}
|
|
34791
34865
|
function enqueueTask(meshId, message, opts) {
|
|
34792
34866
|
requireMeshHostQueueOwner(opts);
|
|
34793
|
-
const
|
|
34867
|
+
const readonly2 = opts?.readonly === true;
|
|
34868
|
+
const modeValidation = validateMeshTaskModeRequest(opts?.taskMode, message, readonly2);
|
|
34794
34869
|
if (!modeValidation.valid) {
|
|
34795
34870
|
throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
|
|
34796
34871
|
}
|
|
@@ -34814,6 +34889,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34814
34889
|
message,
|
|
34815
34890
|
status: "pending",
|
|
34816
34891
|
taskMode: modeValidation.taskMode,
|
|
34892
|
+
...readonly2 ? { readonly: true } : {},
|
|
34817
34893
|
targetNodeId: opts?.targetNodeId,
|
|
34818
34894
|
targetSessionId: opts?.targetSessionId,
|
|
34819
34895
|
requiredTags: resolvedRequiredTags,
|
|
@@ -34832,7 +34908,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34832
34908
|
if (!missionId) return null;
|
|
34833
34909
|
const taskId = typeof opts.id === "string" ? opts.id.trim() : "";
|
|
34834
34910
|
if (!taskId) return null;
|
|
34835
|
-
const
|
|
34911
|
+
const readonly2 = opts.readonly === true;
|
|
34912
|
+
const modeValidation = validateMeshTaskModeRequest(opts.taskMode, message, readonly2);
|
|
34836
34913
|
if (!modeValidation.valid) {
|
|
34837
34914
|
throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
|
|
34838
34915
|
}
|
|
@@ -34847,6 +34924,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34847
34924
|
message,
|
|
34848
34925
|
status: "assigned",
|
|
34849
34926
|
...modeValidation.taskMode ? { taskMode: modeValidation.taskMode } : {},
|
|
34927
|
+
...readonly2 ? { readonly: true } : {},
|
|
34850
34928
|
missionId,
|
|
34851
34929
|
...opts.assignedNodeId ? { targetNodeId: opts.assignedNodeId, assignedNodeId: opts.assignedNodeId } : {},
|
|
34852
34930
|
...opts.assignedSessionId ? { targetSessionId: opts.assignedSessionId, assignedSessionId: opts.assignedSessionId } : {},
|
|
@@ -35839,7 +35917,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
35839
35917
|
return deps.every((depId) => depStatus.get(depId) === "completed");
|
|
35840
35918
|
};
|
|
35841
35919
|
const nodeConflictAllows = (candidate) => {
|
|
35842
|
-
if (candidate
|
|
35920
|
+
if (isTaskReadonly(candidate)) return true;
|
|
35843
35921
|
return !nodeBusy;
|
|
35844
35922
|
};
|
|
35845
35923
|
const nodeIsWorktree = opts?.nodeIsWorktree === true;
|
|
@@ -39069,7 +39147,7 @@ ${rendered}`, "utf-8");
|
|
|
39069
39147
|
"use strict";
|
|
39070
39148
|
init_git_status();
|
|
39071
39149
|
init_git_executor();
|
|
39072
|
-
STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3 };
|
|
39150
|
+
STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3, forceFresh: true };
|
|
39073
39151
|
}
|
|
39074
39152
|
});
|
|
39075
39153
|
function readString6(value) {
|
|
@@ -39468,9 +39546,6 @@ ${rendered}`, "utf-8");
|
|
|
39468
39546
|
__export2(mesh_scheduling_runtime_exports, {
|
|
39469
39547
|
buildMeshSchedulingRuntime: () => buildMeshSchedulingRuntime
|
|
39470
39548
|
});
|
|
39471
|
-
function isReadonly(task) {
|
|
39472
|
-
return task.taskMode === "live_debug_readonly";
|
|
39473
|
-
}
|
|
39474
39549
|
function isAssigned(task) {
|
|
39475
39550
|
return task.status === "assigned";
|
|
39476
39551
|
}
|
|
@@ -39479,8 +39554,8 @@ ${rendered}`, "utf-8");
|
|
|
39479
39554
|
const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
|
|
39480
39555
|
const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks);
|
|
39481
39556
|
const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
|
|
39482
|
-
const activeWriteAssigned = assignedTasks.filter((t) => !
|
|
39483
|
-
const activeReadonlyAssigned = assignedTasks.filter(
|
|
39557
|
+
const activeWriteAssigned = assignedTasks.filter((t) => !isTaskReadonly(t)).length;
|
|
39558
|
+
const activeReadonlyAssigned = assignedTasks.filter(isTaskReadonly).length;
|
|
39484
39559
|
const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
|
|
39485
39560
|
const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
|
|
39486
39561
|
const writeAssignedByNode = /* @__PURE__ */ new Map();
|
|
@@ -39490,7 +39565,7 @@ ${rendered}`, "utf-8");
|
|
|
39490
39565
|
const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
|
|
39491
39566
|
if (!nodeId) continue;
|
|
39492
39567
|
assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
|
|
39493
|
-
if (!
|
|
39568
|
+
if (!isTaskReadonly(task)) {
|
|
39494
39569
|
writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
|
|
39495
39570
|
}
|
|
39496
39571
|
const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
|
|
@@ -39563,6 +39638,7 @@ ${rendered}`, "utf-8");
|
|
|
39563
39638
|
"use strict";
|
|
39564
39639
|
init_repo_mesh_types();
|
|
39565
39640
|
init_dist();
|
|
39641
|
+
init_mesh_work_queue();
|
|
39566
39642
|
}
|
|
39567
39643
|
});
|
|
39568
39644
|
function readNonEmptyString2(value) {
|
|
@@ -41970,10 +42046,10 @@ Next step: ${nextStep}`;
|
|
|
41970
42046
|
return { mode: "remote", daemonId, coordinatorDaemonId };
|
|
41971
42047
|
}
|
|
41972
42048
|
function activeWriteAssignedCount(meshId) {
|
|
41973
|
-
return getQueue(meshId, { status: ["assigned"] }).filter((task) => task
|
|
42049
|
+
return getQueue(meshId, { status: ["assigned"] }).filter((task) => !isTaskReadonly(task)).length;
|
|
41974
42050
|
}
|
|
41975
42051
|
function activeReadonlyAssignedCount(meshId) {
|
|
41976
|
-
return getQueue(meshId, { status: ["assigned"] }).filter(
|
|
42052
|
+
return getQueue(meshId, { status: ["assigned"] }).filter(isTaskReadonly).length;
|
|
41977
42053
|
}
|
|
41978
42054
|
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
41979
42055
|
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
@@ -42149,8 +42225,8 @@ Next step: ${nextStep}`;
|
|
|
42149
42225
|
);
|
|
42150
42226
|
const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks, schedulingOverride?.readonlyMultiplier);
|
|
42151
42227
|
for (const task of pending) {
|
|
42152
|
-
const
|
|
42153
|
-
if (
|
|
42228
|
+
const isReadonly = isTaskReadonly(task);
|
|
42229
|
+
if (isReadonly) {
|
|
42154
42230
|
if (activeReadonlyAssignedCount(meshId) >= maxReadonlyParallelTasks) {
|
|
42155
42231
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_readonly_parallel_tasks_reached" });
|
|
42156
42232
|
continue;
|
|
@@ -42232,7 +42308,7 @@ Next step: ${nextStep}`;
|
|
|
42232
42308
|
sweepExpiredCooldowns();
|
|
42233
42309
|
continue;
|
|
42234
42310
|
}
|
|
42235
|
-
if (task
|
|
42311
|
+
if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
|
|
42236
42312
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
|
|
42237
42313
|
continue;
|
|
42238
42314
|
}
|
|
@@ -42996,6 +43072,9 @@ Next step: ${nextStep}`;
|
|
|
42996
43072
|
const code = "code" in error48 ? error48.code : void 0;
|
|
42997
43073
|
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
42998
43074
|
}
|
|
43075
|
+
function runtimeTriplet() {
|
|
43076
|
+
return `${process.platform}-${process.arch}-node${process.versions.modules}`;
|
|
43077
|
+
}
|
|
42999
43078
|
function normalizeBinding(mod, ref) {
|
|
43000
43079
|
const binding = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;
|
|
43001
43080
|
if (!binding) {
|
|
@@ -43030,7 +43109,7 @@ Next step: ${nextStep}`;
|
|
|
43030
43109
|
}
|
|
43031
43110
|
cachedBinding = null;
|
|
43032
43111
|
cachedBindingError = new Error(
|
|
43033
|
-
`ghostty-vt binding unavailable (${errors.join("; ") || "no candidates tried"})`
|
|
43112
|
+
`ghostty-vt binding unavailable for runtime ${runtimeTriplet()} (${errors.join("; ") || "no candidates tried"})`
|
|
43034
43113
|
);
|
|
43035
43114
|
throw cachedBindingError;
|
|
43036
43115
|
}
|
|
@@ -46204,6 +46283,17 @@ ${cleanBody}`;
|
|
|
46204
46283
|
}
|
|
46205
46284
|
return DEFAULT_RECONCILE_INTERVAL_MS;
|
|
46206
46285
|
}
|
|
46286
|
+
function resolveTunedReconcileMs(envName, def, min, max) {
|
|
46287
|
+
const raw = readNonEmptyString2(process.env[envName]);
|
|
46288
|
+
if (raw) {
|
|
46289
|
+
const parsed = Number.parseInt(raw, 10);
|
|
46290
|
+
if (Number.isFinite(parsed) && parsed >= min && parsed <= max) return parsed;
|
|
46291
|
+
}
|
|
46292
|
+
return def;
|
|
46293
|
+
}
|
|
46294
|
+
function resolveAckedDeathDeadlineMs() {
|
|
46295
|
+
return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_DEATH_DEADLINE_MS", 8 * 6e4, 0, 60 * 6e4);
|
|
46296
|
+
}
|
|
46207
46297
|
function inFlightSynthKey(meshId, taskId) {
|
|
46208
46298
|
return `${meshId}::${taskId}`;
|
|
46209
46299
|
}
|
|
@@ -46780,15 +46870,42 @@ ${cleanBody}`;
|
|
|
46780
46870
|
function readChatPayloadStatus(payload) {
|
|
46781
46871
|
return readNonEmptyString2(payload?.status).toLowerCase();
|
|
46782
46872
|
}
|
|
46873
|
+
function realTerminalEmitPendingForTask(meshId, taskId) {
|
|
46874
|
+
let pending;
|
|
46875
|
+
try {
|
|
46876
|
+
pending = getPendingMeshCoordinatorEvents(meshId);
|
|
46877
|
+
} catch {
|
|
46878
|
+
return false;
|
|
46879
|
+
}
|
|
46880
|
+
return pending.some((e) => readNonEmptyString2(e.metadataEvent?.taskId) === taskId && (e.event === "agent:generating_completed" || e.event === "agent:stopped"));
|
|
46881
|
+
}
|
|
46882
|
+
async function reprobeWorkerStatus(components, args) {
|
|
46883
|
+
try {
|
|
46884
|
+
if (args.isLocalNode) {
|
|
46885
|
+
const r = await components.commandHandler.handle("read_chat", args.readArgs);
|
|
46886
|
+
if (r && r.success === false) return null;
|
|
46887
|
+
return readChatPayloadStatus(unwrapReadChatPayload(r));
|
|
46888
|
+
}
|
|
46889
|
+
if (components.dispatchMeshCommand) {
|
|
46890
|
+
const r = await components.dispatchMeshCommand(args.nodeDaemonId, "read_chat", args.readArgs);
|
|
46891
|
+
const p = unwrapReadChatPayload(r);
|
|
46892
|
+
if (p && p.success === false) return null;
|
|
46893
|
+
return readChatPayloadStatus(p);
|
|
46894
|
+
}
|
|
46895
|
+
} catch {
|
|
46896
|
+
return null;
|
|
46897
|
+
}
|
|
46898
|
+
return null;
|
|
46899
|
+
}
|
|
46783
46900
|
async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds, localDaemonId) {
|
|
46784
46901
|
const dispatches = getActiveDirectDispatches(mesh.id);
|
|
46785
46902
|
if (dispatches.length === 0) return;
|
|
46786
46903
|
const activeTaskKeys = new Set(
|
|
46787
46904
|
dispatches.map((d) => readNonEmptyString2(d.taskId)).filter(Boolean).map((taskId) => inFlightSynthKey(mesh.id, taskId))
|
|
46788
46905
|
);
|
|
46789
|
-
for (const key of
|
|
46906
|
+
for (const key of inFlightAckedHoldState.keys()) {
|
|
46790
46907
|
if (key.startsWith(`${mesh.id}::`) && !activeTaskKeys.has(key)) {
|
|
46791
|
-
|
|
46908
|
+
inFlightAckedHoldState.delete(key);
|
|
46792
46909
|
}
|
|
46793
46910
|
}
|
|
46794
46911
|
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
@@ -46809,35 +46926,63 @@ ${cleanBody}`;
|
|
|
46809
46926
|
...node?.workspace ? { workspace: node.workspace } : {},
|
|
46810
46927
|
...providerType ? { agentType: providerType, providerType } : {}
|
|
46811
46928
|
};
|
|
46929
|
+
const synthKey = inFlightSynthKey(mesh.id, taskId);
|
|
46930
|
+
const isAcked = dispatch.status === "acked";
|
|
46812
46931
|
let payload = null;
|
|
46932
|
+
let readFailed = false;
|
|
46813
46933
|
try {
|
|
46814
46934
|
if (isLocalNode) {
|
|
46815
46935
|
const result = await components.commandHandler.handle("read_chat", readArgs);
|
|
46816
|
-
if (result && result.success === false)
|
|
46817
|
-
|
|
46936
|
+
if (result && result.success === false) {
|
|
46937
|
+
readFailed = true;
|
|
46938
|
+
} else {
|
|
46939
|
+
payload = unwrapReadChatPayload(result);
|
|
46940
|
+
}
|
|
46818
46941
|
} else if (dispatchMeshCommand) {
|
|
46819
46942
|
const result = await dispatchMeshCommand(nodeDaemonId, "read_chat", readArgs);
|
|
46820
46943
|
payload = unwrapReadChatPayload(result);
|
|
46821
|
-
if (payload && payload.success === false)
|
|
46944
|
+
if (payload && payload.success === false) {
|
|
46945
|
+
payload = null;
|
|
46946
|
+
readFailed = true;
|
|
46947
|
+
}
|
|
46822
46948
|
} else {
|
|
46823
46949
|
continue;
|
|
46824
46950
|
}
|
|
46825
46951
|
} catch {
|
|
46952
|
+
readFailed = true;
|
|
46953
|
+
}
|
|
46954
|
+
if (!payload && !readFailed) continue;
|
|
46955
|
+
if (readFailed || !payload) {
|
|
46956
|
+
if (isAcked) {
|
|
46957
|
+
const prior = inFlightAckedHoldState.get(synthKey);
|
|
46958
|
+
const failures = (prior?.consecutiveReadFailures ?? 0) + 1;
|
|
46959
|
+
const liveConfirmedSinceAck = prior?.liveConfirmedSinceAck ?? false;
|
|
46960
|
+
inFlightAckedHoldState.set(synthKey, { liveConfirmedSinceAck, consecutiveReadFailures: failures });
|
|
46961
|
+
if (liveConfirmedSinceAck && failures >= ACKED_DEATH_CONSECUTIVE_READ_FAILURES) {
|
|
46962
|
+
LOG2.warn("MeshReconcile", `Acked-hold death signal: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read_chat failed ${failures}x consecutively after a live-confirmed ack \u2014 worker session presumed gone mid-turn; releasing the indefinite synth hold to the stranded-reclaim / orphan-prune nets`);
|
|
46963
|
+
}
|
|
46964
|
+
}
|
|
46826
46965
|
continue;
|
|
46827
46966
|
}
|
|
46828
|
-
|
|
46829
|
-
const
|
|
46967
|
+
inFlightAckedHoldState.set(synthKey, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
|
|
46968
|
+
const nowMs = Date.now();
|
|
46830
46969
|
if (readChatPayloadStatus(payload) !== "idle") {
|
|
46831
|
-
inFlightIdleObservationCounts.delete(synthKey);
|
|
46832
46970
|
continue;
|
|
46833
46971
|
}
|
|
46834
|
-
if (
|
|
46835
|
-
const
|
|
46836
|
-
|
|
46837
|
-
|
|
46838
|
-
|
|
46972
|
+
if (isAcked) {
|
|
46973
|
+
const ackedAtMs = Date.parse(readNonEmptyString2(dispatch.updatedAt));
|
|
46974
|
+
const sinceAckMs = Number.isFinite(ackedAtMs) ? nowMs - ackedAtMs : Number.POSITIVE_INFINITY;
|
|
46975
|
+
const deathDeadlineMs = resolveAckedDeathDeadlineMs();
|
|
46976
|
+
if (sinceAckMs < deathDeadlineMs) {
|
|
46977
|
+
LOG2.info("MeshReconcile", `Acked-hold: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read idle ${Number.isFinite(sinceAckMs) ? Math.round(sinceAckMs / 1e3) + "s" : "\u221E"} since the generating_started ack \u2014 HOLDING synth indefinitely (worker is alive and will emit; a later real emit is idempotent). Death backstop fires at ${Math.round(deathDeadlineMs / 1e3)}s or on consecutive read failures.`);
|
|
46839
46978
|
continue;
|
|
46840
46979
|
}
|
|
46980
|
+
LOG2.warn("MeshReconcile", `Acked-hold death deadline reached: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still idle ${Math.round(sinceAckMs / 1e3)}s after the ack (deadline ${Math.round(deathDeadlineMs / 1e3)}s) \u2014 synthesizing the missing completion as a notification-loss net (a real emit, if it ever lands, no-ops idempotently).`);
|
|
46981
|
+
}
|
|
46982
|
+
if (realTerminalEmitPendingForTask(mesh.id, taskId)) {
|
|
46983
|
+
inFlightAckedHoldState.delete(synthKey);
|
|
46984
|
+
LOG2.info("MeshReconcile", `Worker-emit priority: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) has a real terminal completion already queued \u2014 yielding synth to the worker's own emit`);
|
|
46985
|
+
continue;
|
|
46841
46986
|
}
|
|
46842
46987
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
46843
46988
|
const evidence = extractFinalAssistantSummaryEvidence(messages);
|
|
@@ -46855,6 +47000,12 @@ ${cleanBody}`;
|
|
|
46855
47000
|
}, `transcriptAt=${evidence.transcriptMessageAt} < dispatchedAt=${dispatch.dispatchedAt}`);
|
|
46856
47001
|
continue;
|
|
46857
47002
|
}
|
|
47003
|
+
const reprobeStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
|
|
47004
|
+
if (reprobeStatus && reprobeStatus !== "idle") {
|
|
47005
|
+
inFlightAckedHoldState.delete(synthKey);
|
|
47006
|
+
LOG2.info("MeshReconcile", `Live re-probe defer: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read '${reprobeStatus}' at synth-commit time \u2014 worker resumed generating; deferring synth to a later tick`);
|
|
47007
|
+
continue;
|
|
47008
|
+
}
|
|
46858
47009
|
const providerSessionId = readNonEmptyString2(payload.providerSessionId);
|
|
46859
47010
|
const coordinatorDaemonId = selfIds.find((id) => !!id);
|
|
46860
47011
|
try {
|
|
@@ -46995,8 +47146,8 @@ ${cleanBody}`;
|
|
|
46995
47146
|
}
|
|
46996
47147
|
var DEFAULT_RECONCILE_INTERVAL_MS;
|
|
46997
47148
|
var DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
|
|
46998
|
-
var
|
|
46999
|
-
var
|
|
47149
|
+
var ACKED_DEATH_CONSECUTIVE_READ_FAILURES;
|
|
47150
|
+
var inFlightAckedHoldState;
|
|
47000
47151
|
var coordinatorModalParkState;
|
|
47001
47152
|
var heldEventLedgerRecorded;
|
|
47002
47153
|
var ASSIGNED_STRANDED_DEADLINE_MS;
|
|
@@ -47024,8 +47175,8 @@ ${cleanBody}`;
|
|
|
47024
47175
|
init_chat_message_normalization();
|
|
47025
47176
|
DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
|
|
47026
47177
|
DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
|
|
47027
|
-
|
|
47028
|
-
|
|
47178
|
+
ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
|
|
47179
|
+
inFlightAckedHoldState = /* @__PURE__ */ new Map();
|
|
47029
47180
|
coordinatorModalParkState = /* @__PURE__ */ new Map();
|
|
47030
47181
|
heldEventLedgerRecorded = /* @__PURE__ */ new Set();
|
|
47031
47182
|
ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
|
|
@@ -52916,6 +53067,7 @@ ${lastSnapshot}`;
|
|
|
52916
53067
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
52917
53068
|
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
|
|
52918
53069
|
isSetupComplete: () => isSetupComplete,
|
|
53070
|
+
isTaskReadonly: () => isTaskReadonly,
|
|
52919
53071
|
isUserFacingChatMessage: () => isUserFacingChatMessage,
|
|
52920
53072
|
killIdeProcess: () => killIdeProcess,
|
|
52921
53073
|
launchIDE: () => launchIDE,
|
|
@@ -53993,7 +54145,7 @@ ${lastSnapshot}`;
|
|
|
53993
54145
|
async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
53994
54146
|
const repo = await resolveGitRepository(workspace);
|
|
53995
54147
|
const repoRoot = repo.repoRoot;
|
|
53996
|
-
const statusResult = await getGitRepoStatus(workspace);
|
|
54148
|
+
const statusResult = await getGitRepoStatus(workspace, { forceFresh: true });
|
|
53997
54149
|
if (statusResult.hasConflicts) {
|
|
53998
54150
|
throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
|
|
53999
54151
|
}
|
|
@@ -82527,7 +82679,10 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
82527
82679
|
const preStatus = await getGitRepoStatus(repoRoot, {
|
|
82528
82680
|
includeSubmodules: true,
|
|
82529
82681
|
submoduleIgnorePaths: options.submoduleIgnorePaths,
|
|
82530
|
-
timeoutMs: 15e3
|
|
82682
|
+
timeoutMs: 15e3,
|
|
82683
|
+
// Decision path — the out-of-sync submodule set drives a mutating `submodule
|
|
82684
|
+
// update`. Must not act on a TTL-cached status; bypass the C1 cache.
|
|
82685
|
+
forceFresh: true
|
|
82531
82686
|
});
|
|
82532
82687
|
const outOfSyncPaths = (preStatus.submodules || []).filter((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error).map((submodule) => submodule.path);
|
|
82533
82688
|
const updatePaths = [.../* @__PURE__ */ new Set([...changedGitlinkPaths, ...outOfSyncPaths])].sort();
|
|
@@ -82556,7 +82711,10 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
82556
82711
|
const postStatus = await getGitRepoStatus(repoRoot, {
|
|
82557
82712
|
includeSubmodules: true,
|
|
82558
82713
|
submoduleIgnorePaths: options.submoduleIgnorePaths,
|
|
82559
|
-
timeoutMs: 15e3
|
|
82714
|
+
timeoutMs: 15e3,
|
|
82715
|
+
// Re-read AFTER `submodule update` mutated the tree — MUST be fresh, never the
|
|
82716
|
+
// cached preStatus from moments ago (which would falsely report still-dirty).
|
|
82717
|
+
forceFresh: true
|
|
82560
82718
|
});
|
|
82561
82719
|
const remaining = (postStatus.submodules || []).filter((submodule) => updatePaths.includes(submodule.path) && (submodule.dirty || submodule.outOfSync || !!submodule.error));
|
|
82562
82720
|
return {
|