@adhdev/daemon-standalone 1.0.49-rc.1 → 1.0.49-rc.10
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 +314 -49
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/index-BeC2kIKA.js +116 -0
- package/public/assets/index-CqyS0XiL.css +1 -0
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +7 -3
- package/vendor/mcp-server/index.js.map +1 -1
- package/public/assets/index-BjPWjmsH.css +0 -1
- package/public/assets/index-C5f45LAh.js +0 -116
package/dist/index.js
CHANGED
|
@@ -37056,10 +37056,10 @@ var require_dist3 = __commonJS({
|
|
|
37056
37056
|
}
|
|
37057
37057
|
function getDaemonBuildInfo() {
|
|
37058
37058
|
if (cached2) return cached2;
|
|
37059
|
-
const commit = readInjected(true ? "
|
|
37060
|
-
const commitShort = readInjected(true ? "
|
|
37061
|
-
const version2 = readInjected(true ? "1.0.49-rc.
|
|
37062
|
-
const builtAt = readInjected(true ? "2026-08-
|
|
37059
|
+
const commit = readInjected(true ? "85491e20f327dc51eb20e6b0674af0041e0c5f5e" : void 0) ?? "unknown";
|
|
37060
|
+
const commitShort = readInjected(true ? "85491e20" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
37061
|
+
const version2 = readInjected(true ? "1.0.49-rc.10" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
37062
|
+
const builtAt = readInjected(true ? "2026-08-14T23:22:28.218Z" : void 0);
|
|
37063
37063
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
37064
37064
|
return cached2;
|
|
37065
37065
|
}
|
|
@@ -42270,6 +42270,8 @@ ${error48.message || ""}`;
|
|
|
42270
42270
|
interpolateArgs: () => interpolateArgs,
|
|
42271
42271
|
interpolateString: () => interpolateString,
|
|
42272
42272
|
isMeshTaskDifficulty: () => isMeshTaskDifficulty,
|
|
42273
|
+
isPhantomDaemonEntry: () => isPhantomDaemonEntry,
|
|
42274
|
+
isRawDaemonDoId: () => isRawDaemonDoId,
|
|
42273
42275
|
joinRepoPath: () => joinRepoPath,
|
|
42274
42276
|
machineCoreFromDaemonId: () => machineCoreFromDaemonId,
|
|
42275
42277
|
meshNodeIdMatches: () => meshNodeIdMatches,
|
|
@@ -42565,6 +42567,18 @@ ${error48.message || ""}`;
|
|
|
42565
42567
|
if (!left || !right) return false;
|
|
42566
42568
|
return left === right;
|
|
42567
42569
|
}
|
|
42570
|
+
function isRawDaemonDoId(id) {
|
|
42571
|
+
const trimmed = readString2(id);
|
|
42572
|
+
return !!trimmed && /^[0-9a-f]{64}$/i.test(trimmed);
|
|
42573
|
+
}
|
|
42574
|
+
function isPhantomDaemonEntry(entry) {
|
|
42575
|
+
if (!entry) return false;
|
|
42576
|
+
if (!isRawDaemonDoId(entry.id)) return false;
|
|
42577
|
+
const hasMachineEvidence = Boolean(
|
|
42578
|
+
readString2(entry.machineNickname) || readString2(entry.nickname) || readString2(entry.hostname) || readString2(entry.platform) || readString2(entry.machine?.hostname) || readString2(entry.machine?.platform) || readString2(entry.machineId) || Array.isArray(entry.sessions) && entry.sessions.length > 0
|
|
42579
|
+
);
|
|
42580
|
+
return !hasMachineEvidence;
|
|
42581
|
+
}
|
|
42568
42582
|
function machineCoreFromDaemonId(id) {
|
|
42569
42583
|
const trimmed = readString2(id);
|
|
42570
42584
|
if (!trimmed) return void 0;
|
|
@@ -55444,6 +55458,8 @@ ${rendered}`, "utf-8");
|
|
|
55444
55458
|
});
|
|
55445
55459
|
function readProviderPriorityFromPolicy(policy) {
|
|
55446
55460
|
const record2 = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
|
|
55461
|
+
const derived = deriveProviderPriorityFromSlots(record2.slots);
|
|
55462
|
+
if (derived.length) return derived;
|
|
55447
55463
|
const raw = record2.providerPriority;
|
|
55448
55464
|
if (Array.isArray(raw)) {
|
|
55449
55465
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -55454,7 +55470,7 @@ ${rendered}`, "utf-8");
|
|
|
55454
55470
|
});
|
|
55455
55471
|
if (explicit.length) return explicit;
|
|
55456
55472
|
}
|
|
55457
|
-
return
|
|
55473
|
+
return [];
|
|
55458
55474
|
}
|
|
55459
55475
|
function normalizeProviderRoles(value) {
|
|
55460
55476
|
if (!Array.isArray(value)) return [];
|
|
@@ -55536,7 +55552,7 @@ ${rendered}`, "utf-8");
|
|
|
55536
55552
|
const workspace = readStringValue(node.workspace, node.repoRoot, node.repo_root);
|
|
55537
55553
|
const workspaceName = workspace ? workingDirBasename(workspace) : void 0;
|
|
55538
55554
|
const host = readStringValue(node.machineName, node.machine_name, node.hostname, node.host, node.daemonId, node.daemon_id, node.machineId, node.machine_id);
|
|
55539
|
-
const provider = providerPriority[0] || (Array.isArray(node.providers) ? readStringValue(...node.providers) : void 0);
|
|
55555
|
+
const provider = readProviderPriorityFromPolicy(node.policy)[0] || providerPriority[0] || (Array.isArray(node.providers) ? readStringValue(...node.providers) : void 0);
|
|
55540
55556
|
const parts = [workspaceName, host, provider].filter(Boolean);
|
|
55541
55557
|
if (parts.length > 0) return parts.join(" \xB7 ");
|
|
55542
55558
|
return nodeId || "unidentified mesh node";
|
|
@@ -57712,7 +57728,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57712
57728
|
init_mesh_work_queue();
|
|
57713
57729
|
}
|
|
57714
57730
|
});
|
|
57715
|
-
function
|
|
57731
|
+
function directQuotaEntryFor(node, providerType) {
|
|
57716
57732
|
const facts = node?.nodeFacts;
|
|
57717
57733
|
if (!facts || typeof facts !== "object") return null;
|
|
57718
57734
|
const reportedAt = Number(facts.reportedAt);
|
|
@@ -57721,6 +57737,14 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57721
57737
|
if (!quota || typeof quota !== "object") return null;
|
|
57722
57738
|
return { facts: { reportedAt }, quota };
|
|
57723
57739
|
}
|
|
57740
|
+
function quotaEntryFor(node, providerType, context) {
|
|
57741
|
+
const direct = directQuotaEntryFor(node, providerType);
|
|
57742
|
+
if (direct) return direct;
|
|
57743
|
+
const sourceNodeId = typeof node?.clonedFromNodeId === "string" ? node.clonedFromNodeId.trim() : "";
|
|
57744
|
+
if (!sourceNodeId || !Array.isArray(context?.nodes)) return null;
|
|
57745
|
+
const sourceNode = context.nodes.find((candidate) => candidate !== node && meshNodeIdMatches(candidate, sourceNodeId));
|
|
57746
|
+
return sourceNode ? directQuotaEntryFor(sourceNode, providerType) : null;
|
|
57747
|
+
}
|
|
57724
57748
|
function quotaSnapshotAgeMs(facts, quota, now = Date.now()) {
|
|
57725
57749
|
const updatedAt = Number(quota.updatedAt);
|
|
57726
57750
|
if (!Number.isFinite(updatedAt) || updatedAt <= 0) return Number.POSITIVE_INFINITY;
|
|
@@ -57743,10 +57767,23 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57743
57767
|
const reporterNowMs = Number(quota.updatedAt) + ageMs2;
|
|
57744
57768
|
return resetsAt - reporterNowMs < imminentMs;
|
|
57745
57769
|
}
|
|
57746
|
-
function
|
|
57747
|
-
const
|
|
57770
|
+
function isRetainedWindowTrustworthy(window, facts, quota, policy, now) {
|
|
57771
|
+
const resetsAt = Number(window?.resetsAt);
|
|
57772
|
+
if (!Number.isFinite(resetsAt) || resetsAt <= 0) {
|
|
57773
|
+
return isQuotaSnapshotFresh(facts, quota, policy, now);
|
|
57774
|
+
}
|
|
57775
|
+
const ageMs2 = quotaSnapshotAgeMs(facts, quota, now);
|
|
57776
|
+
if (!Number.isFinite(ageMs2)) return false;
|
|
57777
|
+
const reporterNowMs = Number(quota.updatedAt) + ageMs2;
|
|
57778
|
+
if (!Number.isFinite(reporterNowMs)) return false;
|
|
57779
|
+
return resetsAt > reporterNowMs;
|
|
57780
|
+
}
|
|
57781
|
+
function evaluateProviderQuotaGate(node, providerType, policy, now = Date.now(), context) {
|
|
57782
|
+
const entry = quotaEntryFor(node, providerType, context);
|
|
57748
57783
|
if (!entry) return null;
|
|
57749
57784
|
const { facts, quota } = entry;
|
|
57785
|
+
let sessionTrustworthy = true;
|
|
57786
|
+
let weeklyTrustworthy = true;
|
|
57750
57787
|
if (quota.status !== "ok") {
|
|
57751
57788
|
if (quota.status === "error" && quota.metadata?.failureKind === "quota-exhausted" && isQuotaSnapshotFresh(facts, quota, policy, now)) {
|
|
57752
57789
|
return {
|
|
@@ -57756,12 +57793,15 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57756
57793
|
thresholdPercent: 0
|
|
57757
57794
|
};
|
|
57758
57795
|
}
|
|
57796
|
+
if (quota.metadata?.lastGoodWindows !== true) return null;
|
|
57797
|
+
sessionTrustworthy = isRetainedWindowTrustworthy(quota.session, facts, quota, policy, now);
|
|
57798
|
+
weeklyTrustworthy = isRetainedWindowTrustworthy(quota.weekly, facts, quota, policy, now);
|
|
57799
|
+
} else if (!isQuotaSnapshotFresh(facts, quota, policy, now)) {
|
|
57759
57800
|
return null;
|
|
57760
57801
|
}
|
|
57761
|
-
if (!isQuotaSnapshotFresh(facts, quota, policy, now)) return null;
|
|
57762
57802
|
const resolved = resolveQuotaRoutingPolicy(policy);
|
|
57763
57803
|
const session = remainingPercent(quota.session);
|
|
57764
|
-
if (session !== void 0 && session < resolved.sessionMinRemainingPercent && !isSessionResetImminent(quota.session, facts, quota, resolved.sessionResetImminentMs, now)) {
|
|
57804
|
+
if (sessionTrustworthy && session !== void 0 && session < resolved.sessionMinRemainingPercent && !isSessionResetImminent(quota.session, facts, quota, resolved.sessionResetImminentMs, now)) {
|
|
57765
57805
|
return {
|
|
57766
57806
|
reason: PROVIDER_QUOTA_SESSION_LOW_SKIP_REASON,
|
|
57767
57807
|
window: "session",
|
|
@@ -57770,7 +57810,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57770
57810
|
};
|
|
57771
57811
|
}
|
|
57772
57812
|
const weekly = remainingPercent(quota.weekly);
|
|
57773
|
-
if (weekly !== void 0 && weekly < resolved.weeklyMinRemainingPercent) {
|
|
57813
|
+
if (weeklyTrustworthy && weekly !== void 0 && weekly < resolved.weeklyMinRemainingPercent) {
|
|
57774
57814
|
return {
|
|
57775
57815
|
reason: PROVIDER_QUOTA_WEEKLY_LOW_SKIP_REASON,
|
|
57776
57816
|
window: "weekly",
|
|
@@ -57780,8 +57820,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57780
57820
|
}
|
|
57781
57821
|
return null;
|
|
57782
57822
|
}
|
|
57783
|
-
function expiryRiskForRanking(node, providerType, axis, policy, now = Date.now()) {
|
|
57784
|
-
const entry = quotaEntryFor(node, providerType);
|
|
57823
|
+
function expiryRiskForRanking(node, providerType, axis, policy, now = Date.now(), context) {
|
|
57824
|
+
const entry = quotaEntryFor(node, providerType, context);
|
|
57785
57825
|
if (!entry) return void 0;
|
|
57786
57826
|
const { facts, quota } = entry;
|
|
57787
57827
|
if (quota.status !== "ok") return void 0;
|
|
@@ -57800,19 +57840,19 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57800
57840
|
const elapsedFraction = Math.min(1, Math.max(0, 1 - (resetsAt - reporterNowMs) / windowMs));
|
|
57801
57841
|
return { remainingPercent: remaining, risk: remaining * elapsedFraction };
|
|
57802
57842
|
}
|
|
57803
|
-
function rankProvidersByQuotaGate(node, orderedProviderTypes, policy, now = Date.now()) {
|
|
57843
|
+
function rankProvidersByQuotaGate(node, orderedProviderTypes, policy, now = Date.now(), context) {
|
|
57804
57844
|
const clear = [];
|
|
57805
57845
|
const gated = [];
|
|
57806
57846
|
for (const providerType of orderedProviderTypes) {
|
|
57807
|
-
const block2 = evaluateProviderQuotaGate(node, providerType, policy, now);
|
|
57847
|
+
const block2 = evaluateProviderQuotaGate(node, providerType, policy, now, context);
|
|
57808
57848
|
if (block2) gated.push({ providerType, block: block2 });
|
|
57809
57849
|
else clear.push(providerType);
|
|
57810
57850
|
}
|
|
57811
|
-
const weeklyByProvider = new Map(clear.map((p) => [p, expiryRiskForRanking(node, p, "weekly", policy, now)]));
|
|
57851
|
+
const weeklyByProvider = new Map(clear.map((p) => [p, expiryRiskForRanking(node, p, "weekly", policy, now, context)]));
|
|
57812
57852
|
const headroomPercent = resolveQuotaRoutingPolicy(policy).sessionAxisWeeklyHeadroomPercent;
|
|
57813
57853
|
const weeklyMeasured = [...weeklyByProvider.values()].filter((w) => w !== void 0);
|
|
57814
57854
|
const sessionAxisActive = weeklyMeasured.length > 0 && weeklyMeasured.every((w) => w.remainingPercent > headroomPercent);
|
|
57815
|
-
const sessionByProvider = sessionAxisActive ? new Map(clear.map((p) => [p, expiryRiskForRanking(node, p, "session", policy, now)])) : void 0;
|
|
57855
|
+
const sessionByProvider = sessionAxisActive ? new Map(clear.map((p) => [p, expiryRiskForRanking(node, p, "session", policy, now, context)])) : void 0;
|
|
57816
57856
|
clear.sort((a, b) => {
|
|
57817
57857
|
const wa = weeklyByProvider.get(a);
|
|
57818
57858
|
const wb = weeklyByProvider.get(b);
|
|
@@ -57835,13 +57875,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57835
57875
|
});
|
|
57836
57876
|
return { clear, gated };
|
|
57837
57877
|
}
|
|
57838
|
-
function resolveRecoveryRelaunchProvider(node, failedProviderType, nodeProviderTypes = [], policy, now = Date.now()) {
|
|
57878
|
+
function resolveRecoveryRelaunchProvider(node, failedProviderType, nodeProviderTypes = [], policy, now = Date.now(), context) {
|
|
57839
57879
|
if (!failedProviderType) return { action: "block" };
|
|
57840
|
-
const block2 = evaluateProviderQuotaGate(node, failedProviderType, policy, now);
|
|
57880
|
+
const block2 = evaluateProviderQuotaGate(node, failedProviderType, policy, now, context);
|
|
57841
57881
|
if (!block2) return { action: "keep", providerType: failedProviderType };
|
|
57842
57882
|
const alternatives = nodeProviderTypes.filter((p) => p && p !== failedProviderType);
|
|
57843
57883
|
if (alternatives.length) {
|
|
57844
|
-
const ranked = rankProvidersByQuotaGate(node, alternatives, policy, now);
|
|
57884
|
+
const ranked = rankProvidersByQuotaGate(node, alternatives, policy, now, context);
|
|
57845
57885
|
if (ranked.clear.length) {
|
|
57846
57886
|
return { action: "fallback", providerType: ranked.clear[0], block: block2 };
|
|
57847
57887
|
}
|
|
@@ -57856,9 +57896,9 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57856
57896
|
}
|
|
57857
57897
|
return `QUOTA GATE: skipping recovery relaunch for node ${nodeId} \u2014 ${cause} and the node has no gate-clear alternative${taskId ? `; task ${taskId}` : ""} stays queued until a quota window resets`;
|
|
57858
57898
|
}
|
|
57859
|
-
function quotaRiskSnapshotForCandidates(node, orderedProviderTypes, policy, now = Date.now()) {
|
|
57899
|
+
function quotaRiskSnapshotForCandidates(node, orderedProviderTypes, policy, now = Date.now(), context) {
|
|
57860
57900
|
return orderedProviderTypes.map((providerType) => {
|
|
57861
|
-
const w = expiryRiskForRanking(node, providerType, "weekly", policy, now);
|
|
57901
|
+
const w = expiryRiskForRanking(node, providerType, "weekly", policy, now, context);
|
|
57862
57902
|
return {
|
|
57863
57903
|
providerType,
|
|
57864
57904
|
...w ? { remainingPercent: w.remainingPercent, risk: w.risk } : {}
|
|
@@ -57902,6 +57942,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
57902
57942
|
var init_mesh_quota_routing = __esm2({
|
|
57903
57943
|
"src/mesh/mesh-quota-routing.ts"() {
|
|
57904
57944
|
"use strict";
|
|
57945
|
+
init_dist();
|
|
57905
57946
|
init_repo_mesh_types();
|
|
57906
57947
|
PROVIDER_QUOTA_SESSION_LOW_SKIP_REASON = "provider_quota_session_low";
|
|
57907
57948
|
PROVIDER_QUOTA_WEEKLY_LOW_SKIP_REASON = "provider_quota_weekly_low";
|
|
@@ -61941,7 +61982,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
61941
61982
|
LOG2.info("MeshQueue", `Deferring queue claim for node ${nodeId} (${sessionId}): an auto fast-forward is mutating its workspace \u2014 task left pending, claim re-fires next tick`);
|
|
61942
61983
|
return false;
|
|
61943
61984
|
}
|
|
61944
|
-
const quotaClaimBlock = evaluateProviderQuotaGate(node, providerType, mesh?.policy?.quotaRouting ?? null);
|
|
61985
|
+
const quotaClaimBlock = evaluateProviderQuotaGate(node, providerType, mesh?.policy?.quotaRouting ?? null, Date.now(), mesh);
|
|
61945
61986
|
if (quotaClaimBlock) {
|
|
61946
61987
|
if (quotaClaimBlock.reason === PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON) {
|
|
61947
61988
|
LOG2.info("MeshQueue", `QUOTA GATE: deferring queue claim for node ${nodeId} (${sessionId}): provider '${providerType}' reported its quota EXHAUSTED \u2014 task left pending until the quota resets`);
|
|
@@ -62418,7 +62459,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
62418
62459
|
retractActionableSkipIfPreviouslyNotified(meshId, taskId);
|
|
62419
62460
|
}
|
|
62420
62461
|
}
|
|
62421
|
-
async function resolveUsableProvider(components, nodeId, node, meshId, requiredTags, task, quotaRouting) {
|
|
62462
|
+
async function resolveUsableProvider(components, nodeId, node, meshId, requiredTags, task, quotaRouting, quotaFactsContext) {
|
|
62422
62463
|
const providerLoader = components.providerLoader;
|
|
62423
62464
|
if (!providerLoader) return { reason: "provider_loader_unavailable" };
|
|
62424
62465
|
const slots = resolveNodeCapabilitySlots(node, meshId);
|
|
@@ -62466,8 +62507,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
62466
62507
|
if (!candidates.length) {
|
|
62467
62508
|
return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
|
|
62468
62509
|
}
|
|
62469
|
-
const ranked = rankProvidersByQuotaGate(node, candidates.map((c) => c.providerType), quotaRouting);
|
|
62470
|
-
const riskSnapshot = quotaRiskSnapshotForCandidates(node, ranked.clear, quotaRouting);
|
|
62510
|
+
const ranked = rankProvidersByQuotaGate(node, candidates.map((c) => c.providerType), quotaRouting, Date.now(), quotaFactsContext);
|
|
62511
|
+
const riskSnapshot = quotaRiskSnapshotForCandidates(node, ranked.clear, quotaRouting, Date.now(), quotaFactsContext);
|
|
62471
62512
|
if (!ranked.clear.length) {
|
|
62472
62513
|
const detail = ranked.gated.map((g) => `${g.providerType}: ${g.block.reason}`).join("; ");
|
|
62473
62514
|
LOG2.info("MeshQueue", `QUOTA GATE: every usable provider on node ${nodeId} is quota-gated (${detail}); leaving the task queued until a quota window resets`);
|
|
@@ -62718,7 +62759,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
62718
62759
|
}
|
|
62719
62760
|
autoLaunchInProgress.add(launchKey);
|
|
62720
62761
|
try {
|
|
62721
|
-
const resolved = await resolveUsableProvider(components, nodeId, node, meshId, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags }, mesh?.policy?.quotaRouting ?? null);
|
|
62762
|
+
const resolved = await resolveUsableProvider(components, nodeId, node, meshId, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags }, mesh?.policy?.quotaRouting ?? null, mesh);
|
|
62722
62763
|
if (!resolved.providerType) {
|
|
62723
62764
|
markSkip(nodeId, resolved.reason || "provider_unusable");
|
|
62724
62765
|
continue;
|
|
@@ -66393,7 +66434,9 @@ ${cleanBody}`;
|
|
|
66393
66434
|
node,
|
|
66394
66435
|
recoveryContext.failedProviderType,
|
|
66395
66436
|
resolveNodeCapabilitySlots(node, args.meshId).map((s2) => s2.provider),
|
|
66396
|
-
mesh?.policy?.quotaRouting ?? null
|
|
66437
|
+
mesh?.policy?.quotaRouting ?? null,
|
|
66438
|
+
Date.now(),
|
|
66439
|
+
mesh
|
|
66397
66440
|
) : { action: "block" };
|
|
66398
66441
|
const relaunchProviderType = relaunch.action === "block" ? null : relaunch.providerType;
|
|
66399
66442
|
if (node) {
|
|
@@ -68805,6 +68848,17 @@ ${cleanBody}`;
|
|
|
68805
68848
|
return void 0;
|
|
68806
68849
|
}
|
|
68807
68850
|
}
|
|
68851
|
+
function localGeneratingLabelIsContradicted(components, sessionId) {
|
|
68852
|
+
try {
|
|
68853
|
+
const probe = resolveLiveTurnPendingEvidence(components, sessionId);
|
|
68854
|
+
if (!probe) return false;
|
|
68855
|
+
if (probe()) return false;
|
|
68856
|
+
LOG2.info("MeshReconcile", `Session ${sessionId} reports FSM status 'generating' but its adapter has no live turn evidence \u2014 treating the label as stale so the early transcript-evidence rescue may evaluate it (the completion arm was likely orphaned by a continuity cancel)`);
|
|
68857
|
+
return true;
|
|
68858
|
+
} catch {
|
|
68859
|
+
return false;
|
|
68860
|
+
}
|
|
68861
|
+
}
|
|
68808
68862
|
async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds = []) {
|
|
68809
68863
|
const sessionId = readNonEmptyString(row.assignedSessionId);
|
|
68810
68864
|
if (!sessionId) return false;
|
|
@@ -68820,7 +68874,9 @@ ${cleanBody}`;
|
|
|
68820
68874
|
}
|
|
68821
68875
|
}
|
|
68822
68876
|
const verdict = resolveSessionBusyVerdict(components, sessionId);
|
|
68823
|
-
if (verdict === "GENERATING")
|
|
68877
|
+
if (verdict === "GENERATING" && !localGeneratingLabelIsContradicted(components, sessionId)) {
|
|
68878
|
+
return false;
|
|
68879
|
+
}
|
|
68824
68880
|
if (verdict === "UNKNOWN") {
|
|
68825
68881
|
const nodeId = readNonEmptyString(row.assignedNodeId);
|
|
68826
68882
|
const node = (mesh.nodes ?? []).find((n) => n.id === nodeId);
|
|
@@ -93228,6 +93284,45 @@ ${marker}`,
|
|
|
93228
93284
|
init_config();
|
|
93229
93285
|
init_install();
|
|
93230
93286
|
init_logger();
|
|
93287
|
+
var SEMVER_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
93288
|
+
var NUMERIC_IDENTIFIER = /^\d+$/;
|
|
93289
|
+
function parseSemver(version2) {
|
|
93290
|
+
if (typeof version2 !== "string") return null;
|
|
93291
|
+
const match = version2.trim().replace(/^v/, "").match(SEMVER_PATTERN);
|
|
93292
|
+
if (!match) return null;
|
|
93293
|
+
return {
|
|
93294
|
+
major: Number(match[1]),
|
|
93295
|
+
minor: Number(match[2]),
|
|
93296
|
+
patch: Number(match[3]),
|
|
93297
|
+
prerelease: match[4] ? match[4].split(".") : []
|
|
93298
|
+
};
|
|
93299
|
+
}
|
|
93300
|
+
function comparePrerelease(a, b) {
|
|
93301
|
+
if (a.length === 0 && b.length === 0) return 0;
|
|
93302
|
+
if (a.length === 0) return 1;
|
|
93303
|
+
if (b.length === 0) return -1;
|
|
93304
|
+
for (let i = 0; i < Math.min(a.length, b.length); i += 1) {
|
|
93305
|
+
const idA = a[i];
|
|
93306
|
+
const idB = b[i];
|
|
93307
|
+
if (idA === idB) continue;
|
|
93308
|
+
const numA = NUMERIC_IDENTIFIER.test(idA);
|
|
93309
|
+
const numB = NUMERIC_IDENTIFIER.test(idB);
|
|
93310
|
+
if (numA && numB) return Number(idA) < Number(idB) ? -1 : 1;
|
|
93311
|
+
if (numA) return -1;
|
|
93312
|
+
if (numB) return 1;
|
|
93313
|
+
return idA < idB ? -1 : 1;
|
|
93314
|
+
}
|
|
93315
|
+
return a.length === b.length ? 0 : a.length < b.length ? -1 : 1;
|
|
93316
|
+
}
|
|
93317
|
+
function compareSemver(a, b) {
|
|
93318
|
+
const pa = parseSemver(a);
|
|
93319
|
+
const pb = parseSemver(b);
|
|
93320
|
+
if (!pa || !pb) return null;
|
|
93321
|
+
if (pa.major !== pb.major) return pa.major < pb.major ? -1 : 1;
|
|
93322
|
+
if (pa.minor !== pb.minor) return pa.minor < pb.minor ? -1 : 1;
|
|
93323
|
+
if (pa.patch !== pb.patch) return pa.patch < pb.patch ? -1 : 1;
|
|
93324
|
+
return comparePrerelease(pa.prerelease, pb.prerelease);
|
|
93325
|
+
}
|
|
93231
93326
|
init_track_identity();
|
|
93232
93327
|
var daemonLifecycleHandlers = {
|
|
93233
93328
|
daemon_upgrade: async (ctx, args) => {
|
|
@@ -93236,10 +93331,22 @@ ${marker}`,
|
|
|
93236
93331
|
const isStandalone = ctx.deps.packageName === "@adhdev/daemon-standalone" || process.argv[1]?.includes("daemon-standalone");
|
|
93237
93332
|
const pkgName = isStandalone ? "@adhdev/daemon-standalone" : "adhdev";
|
|
93238
93333
|
const npmSurface = resolveCurrentGlobalInstallSurface({ packageName: pkgName });
|
|
93239
|
-
|
|
93240
|
-
|
|
93334
|
+
const requestedChannelRaw = args?.channel ?? args?.updatePolicy?.channel ?? null;
|
|
93335
|
+
const requestedChannel = typeof requestedChannelRaw === "string" && requestedChannelRaw.trim() ? requestedChannelRaw.trim().toLowerCase() : null;
|
|
93336
|
+
const requestedNpmTag = typeof args?.npmTag === "string" && args.npmTag.trim() ? args.npmTag.trim().toLowerCase() : null;
|
|
93337
|
+
if (requestedChannel || requestedNpmTag) {
|
|
93338
|
+
LOG2.info("Upgrade", `Ignoring deprecated channel hint (channel=${requestedChannel ?? "-"}, npmTag=${requestedNpmTag ?? "-"}) \u2014 upgrade target is the build track '${TRACK}'`);
|
|
93241
93339
|
}
|
|
93242
93340
|
const npmTag = IDENTITY.npmTag;
|
|
93341
|
+
const channelOverride = requestedChannel && requestedChannel !== TRACK && !(TRACK === "preview" && requestedChannel === "next") && !(TRACK === "stable" && requestedChannel === "latest") || requestedNpmTag && requestedNpmTag !== npmTag ? {
|
|
93342
|
+
requestedChannel,
|
|
93343
|
+
requestedNpmTag,
|
|
93344
|
+
effectiveChannel: TRACK,
|
|
93345
|
+
effectiveNpmTag: npmTag,
|
|
93346
|
+
ignored: true,
|
|
93347
|
+
reason: `The requested channel/tag was IGNORED. Since Phase 3 the release channel is a build-time identity of the installed binary, so this daemon can only upgrade on its own '${TRACK}' track (${pkgName}@${npmTag}). Switching tracks requires installing the other track's package, not an upgrade argument.`
|
|
93348
|
+
} : null;
|
|
93349
|
+
const withChannelNotice = (payload) => channelOverride ? { ...payload, channelOverride } : payload;
|
|
93243
93350
|
const latest = resolveNpmPublishedVersion(pkgName, npmTag, npmSurface);
|
|
93244
93351
|
LOG2.info("Upgrade", `Latest ${pkgName}@${npmTag}: v${latest}`);
|
|
93245
93352
|
let currentInstalled = null;
|
|
@@ -93256,11 +93363,39 @@ ${marker}`,
|
|
|
93256
93363
|
const runningVersion = typeof ctx.deps.statusVersion === "string" ? ctx.deps.statusVersion.trim().replace(/^v/, "") : null;
|
|
93257
93364
|
if (currentInstalled === latest && runningVersion === latest) {
|
|
93258
93365
|
LOG2.info("Upgrade", `Already on ${TRACK} track version v${latest}; skipping install`);
|
|
93259
|
-
return { success: true, upgraded: false, alreadyLatest: true, outcome: "already_latest", version: latest, targetVersion: latest, channel: TRACK, npmTag };
|
|
93366
|
+
return withChannelNotice({ success: true, upgraded: false, alreadyLatest: true, outcome: "already_latest", version: latest, targetVersion: latest, channel: TRACK, npmTag });
|
|
93260
93367
|
}
|
|
93261
93368
|
if (currentInstalled === latest && runningVersion && runningVersion !== latest) {
|
|
93262
93369
|
LOG2.info("Upgrade", `Installed package is v${latest}, but running daemon is v${runningVersion}; scheduling restart`);
|
|
93263
93370
|
}
|
|
93371
|
+
const direction = runningVersion ? compareSemver(latest, runningVersion) : null;
|
|
93372
|
+
if (direction !== null && direction < 0 && args?.allowDowngrade !== true) {
|
|
93373
|
+
LOG2.warn("Upgrade", `Refusing downgrade: running v${runningVersion} is NEWER than ${TRACK} track target v${latest} (${pkgName}@${npmTag}). Pass allowDowngrade to override.`);
|
|
93374
|
+
return withChannelNotice({
|
|
93375
|
+
success: false,
|
|
93376
|
+
upgraded: false,
|
|
93377
|
+
restarting: false,
|
|
93378
|
+
code: "downgrade_refused",
|
|
93379
|
+
outcome: "downgrade_refused",
|
|
93380
|
+
// Everything the caller needs to see WHY it would go
|
|
93381
|
+
// backwards, without a second round-trip: the incident that
|
|
93382
|
+
// motivated this guard was diagnosable only because someone
|
|
93383
|
+
// noticed the version in the response was lower than the
|
|
93384
|
+
// node's actual version.
|
|
93385
|
+
version: runningVersion,
|
|
93386
|
+
currentVersion: runningVersion,
|
|
93387
|
+
installedVersion: currentInstalled,
|
|
93388
|
+
targetVersion: latest,
|
|
93389
|
+
channel: TRACK,
|
|
93390
|
+
npmTag,
|
|
93391
|
+
packageName: pkgName,
|
|
93392
|
+
reason: `Upgrade refused: it would DOWNGRADE this daemon from v${runningVersion} to v${latest}. The ${TRACK} track dist-tag ${pkgName}@${npmTag} currently resolves to v${latest}, which is older than what is running. This usually means the daemon is resolving the wrong track's package \u2014 check that the npm install surface (global prefix) matches the running build's track. Pass allowDowngrade:true to force the rollback anyway.`,
|
|
93393
|
+
clientHint: "Downgrade refused \u2014 no restart happened and the daemon is untouched. Fix the install surface/track pin, or pass allowDowngrade:true to roll back deliberately."
|
|
93394
|
+
});
|
|
93395
|
+
}
|
|
93396
|
+
if (direction !== null && direction < 0) {
|
|
93397
|
+
LOG2.warn("Upgrade", `allowDowngrade set \u2014 proceeding with DOWNGRADE from v${runningVersion} to v${latest} on the ${TRACK} track`);
|
|
93398
|
+
}
|
|
93264
93399
|
spawnDetachedDaemonUpgradeHelper({
|
|
93265
93400
|
packageName: pkgName,
|
|
93266
93401
|
targetVersion: latest,
|
|
@@ -93274,7 +93409,7 @@ ${marker}`,
|
|
|
93274
93409
|
LOG2.info("Upgrade", "Exiting daemon so detached upgrader can continue...");
|
|
93275
93410
|
process.exit(0);
|
|
93276
93411
|
}, 3e3);
|
|
93277
|
-
return {
|
|
93412
|
+
return withChannelNotice({
|
|
93278
93413
|
success: true,
|
|
93279
93414
|
upgraded: true,
|
|
93280
93415
|
version: latest,
|
|
@@ -93283,9 +93418,16 @@ ${marker}`,
|
|
|
93283
93418
|
npmTag,
|
|
93284
93419
|
outcome: "scheduled",
|
|
93285
93420
|
targetVersion: latest,
|
|
93421
|
+
// No `currentVersion` here on purpose: this response is about a
|
|
93422
|
+
// SCHEDULED move, and daemon-upgrade-scheduled-intent.test.ts
|
|
93423
|
+
// pins that it must not read as "already on the target". The
|
|
93424
|
+
// pre-upgrade version belongs on the refusal payload, where it
|
|
93425
|
+
// is the actual diagnosis. Only the deliberate-override marker
|
|
93426
|
+
// is added, so an intentional rollback stays self-evident.
|
|
93427
|
+
...direction !== null && direction < 0 ? { downgrade: true } : {},
|
|
93286
93428
|
upgradeLogPath: getUpgradeLogPath(),
|
|
93287
93429
|
clientHint: `Upgrade to v${latest} SCHEDULED, not completed \u2014 the detached helper installs and restarts the daemon after this response, and a failure rolls back to the previous version. Check upgradeLogPath (or get_status_metadata.upgradeFailure after the restart) for the actual outcome.`
|
|
93288
|
-
};
|
|
93430
|
+
});
|
|
93289
93431
|
} catch (e) {
|
|
93290
93432
|
LOG2.error("Upgrade", `Failed: ${e.message}`);
|
|
93291
93433
|
return { success: false, error: e.message };
|
|
@@ -97037,6 +97179,8 @@ ${marker}`,
|
|
|
97037
97179
|
var CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS = 2e4;
|
|
97038
97180
|
var MISSING_ASSISTANT_TRANSCRIPT_GROWTH_QUIET_MS = 6e4;
|
|
97039
97181
|
var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4e3;
|
|
97182
|
+
var CANCELLED_COMPLETION_RECHECK_MS = 1500;
|
|
97183
|
+
var CANCELLED_COMPLETION_RECHECK_MAX_ATTEMPTS = 4;
|
|
97040
97184
|
var PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
|
|
97041
97185
|
var ANTIGRAVITY_HOLD_QUIET_DWELL_MS = 3e3;
|
|
97042
97186
|
var ANTIGRAVITY_HOLD_HARD_CAP_MS = 5 * 6e4;
|
|
@@ -98095,7 +98239,7 @@ ${buttons.join("\n")}`;
|
|
|
98095
98239
|
timestamp: Date.now(),
|
|
98096
98240
|
taskId,
|
|
98097
98241
|
finalSummary,
|
|
98098
|
-
evidenceLevel: "
|
|
98242
|
+
evidenceLevel: "reported",
|
|
98099
98243
|
completionDiagnostic: { source: "pre_cleanup_transcript_completion" }
|
|
98100
98244
|
});
|
|
98101
98245
|
return true;
|
|
@@ -98144,7 +98288,7 @@ ${buttons.join("\n")}`;
|
|
|
98144
98288
|
timestamp: Date.now(),
|
|
98145
98289
|
taskId,
|
|
98146
98290
|
finalSummary,
|
|
98147
|
-
evidenceLevel: "
|
|
98291
|
+
evidenceLevel: "reported",
|
|
98148
98292
|
completionDiagnostic: { source: diagnosticSource }
|
|
98149
98293
|
});
|
|
98150
98294
|
return true;
|
|
@@ -98586,6 +98730,64 @@ ${buttons.join("\n")}`;
|
|
|
98586
98730
|
host.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
98587
98731
|
}
|
|
98588
98732
|
}
|
|
98733
|
+
init_logger();
|
|
98734
|
+
function armCancelledCompletionRecheck(host, pending, reason) {
|
|
98735
|
+
if (reason === "new_pty_output") return;
|
|
98736
|
+
const now = Date.now();
|
|
98737
|
+
const prior = host.cancelledCompletionRecheck;
|
|
98738
|
+
const carriedPending = prior?.pending ?? pending;
|
|
98739
|
+
const attempts = prior ? prior.attempts : 0;
|
|
98740
|
+
if (attempts >= CANCELLED_COMPLETION_RECHECK_MAX_ATTEMPTS) {
|
|
98741
|
+
clearCancelledCompletionRecheck(host);
|
|
98742
|
+
LOG2.debug("CLI", `[${host.type}] cancelled-completion recheck budget exhausted (${reason}) \u2014 deferring to the next FSM completion edge`);
|
|
98743
|
+
return;
|
|
98744
|
+
}
|
|
98745
|
+
host.cancelledCompletionRecheck = {
|
|
98746
|
+
pending: carriedPending,
|
|
98747
|
+
reason,
|
|
98748
|
+
attempts,
|
|
98749
|
+
firstCancelledAt: prior?.firstCancelledAt ?? now
|
|
98750
|
+
};
|
|
98751
|
+
if (host.cancelledCompletionRecheckTimer) clearTimeout(host.cancelledCompletionRecheckTimer);
|
|
98752
|
+
host.cancelledCompletionRecheckTimer = setTimeout(
|
|
98753
|
+
() => runCancelledCompletionRecheck(host),
|
|
98754
|
+
CANCELLED_COMPLETION_RECHECK_MS
|
|
98755
|
+
);
|
|
98756
|
+
}
|
|
98757
|
+
function clearCancelledCompletionRecheck(host) {
|
|
98758
|
+
if (host.cancelledCompletionRecheckTimer) {
|
|
98759
|
+
clearTimeout(host.cancelledCompletionRecheckTimer);
|
|
98760
|
+
host.cancelledCompletionRecheckTimer = null;
|
|
98761
|
+
}
|
|
98762
|
+
host.cancelledCompletionRecheck = null;
|
|
98763
|
+
}
|
|
98764
|
+
function runCancelledCompletionRecheck(host) {
|
|
98765
|
+
host.cancelledCompletionRecheckTimer = null;
|
|
98766
|
+
const watch3 = host.cancelledCompletionRecheck;
|
|
98767
|
+
if (!watch3) return;
|
|
98768
|
+
if (host.completedDebouncePending) {
|
|
98769
|
+
clearCancelledCompletionRecheck(host);
|
|
98770
|
+
return;
|
|
98771
|
+
}
|
|
98772
|
+
watch3.attempts += 1;
|
|
98773
|
+
LOG2.info("CLI", `[${host.type}] re-checking completion cancelled by ${watch3.reason} (attempt ${watch3.attempts}/${CANCELLED_COMPLETION_RECHECK_MAX_ATTEMPTS}, ${Date.now() - watch3.firstCancelledAt}ms since cancel)`);
|
|
98774
|
+
if (host.completionTraceOn()) host.recordCompletionGateTrace("cancel_recheck", {
|
|
98775
|
+
reason: watch3.reason,
|
|
98776
|
+
attempt: watch3.attempts,
|
|
98777
|
+
sinceCancelMs: Date.now() - watch3.firstCancelledAt,
|
|
98778
|
+
busyEpoch: host.busyEpoch
|
|
98779
|
+
});
|
|
98780
|
+
const lastOutputAt = host.adapter.getStatus({ allowParse: false })?.lastOutputAt;
|
|
98781
|
+
host.completedDebouncePending = {
|
|
98782
|
+
...watch3.pending,
|
|
98783
|
+
busyEpochAtArm: host.busyEpoch,
|
|
98784
|
+
lastOutputAtArm: typeof lastOutputAt === "number" && Number.isFinite(lastOutputAt) ? lastOutputAt : watch3.pending.lastOutputAtArm
|
|
98785
|
+
};
|
|
98786
|
+
host.flushCompletedDebounceIfFinalized();
|
|
98787
|
+
if (host.cancelledCompletionRecheck === watch3 && host.completedDebouncePending) {
|
|
98788
|
+
clearCancelledCompletionRecheck(host);
|
|
98789
|
+
}
|
|
98790
|
+
}
|
|
98589
98791
|
init_contracts2();
|
|
98590
98792
|
var MAX_TRACKED_MESSAGES = 2e3;
|
|
98591
98793
|
function hasUsableTimestamp(message) {
|
|
@@ -99745,11 +99947,20 @@ ${buttons.join("\n")}`;
|
|
|
99745
99947
|
clearTimeout(this.autoApproveBusyTimer);
|
|
99746
99948
|
this.autoApproveBusyTimer = null;
|
|
99747
99949
|
}
|
|
99950
|
+
this.clearCancelledCompletionRecheck();
|
|
99748
99951
|
this.appliedEffectKeys.clear();
|
|
99749
99952
|
closeSqliteProbeCache(this.sqliteProbeCache);
|
|
99750
99953
|
}
|
|
99751
99954
|
completedDebounceTimer = null;
|
|
99752
99955
|
completedDebouncePending = null;
|
|
99956
|
+
/**
|
|
99957
|
+
* (CANCEL-BLIP-ORPHAN) Re-verification watch for an arm the continuity cancel just
|
|
99958
|
+
* deleted — the cancelled arm's snapshot plus a bounded recheck budget, so a
|
|
99959
|
+
* sub-second PTY blip cannot permanently orphan the completion. Full rationale:
|
|
99960
|
+
* completion/cancel-recheck.ts.
|
|
99961
|
+
*/
|
|
99962
|
+
cancelledCompletionRecheck = null;
|
|
99963
|
+
cancelledCompletionRecheckTimer = null;
|
|
99753
99964
|
lastExternalCompletionProbe = null;
|
|
99754
99965
|
// (NATIVE-TURN-SIGNAL) Terminal markers from the last native transcript read. Refreshed
|
|
99755
99966
|
// on every completion probe; null when the provider surfaces none.
|
|
@@ -100196,6 +100407,17 @@ ${buttons.join("\n")}`;
|
|
|
100196
100407
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
100197
100408
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|
|
100198
100409
|
}
|
|
100410
|
+
/**
|
|
100411
|
+
* (CANCEL-BLIP-ORPHAN) Post-cancel completion re-verification. The judgment and its
|
|
100412
|
+
* full rationale live in completion/cancel-recheck.ts; these are the host-dispatched
|
|
100413
|
+
* seams, matching the status-transition / evidence / stall-rescue moves.
|
|
100414
|
+
*/
|
|
100415
|
+
armCancelledCompletionRecheck(pending, reason) {
|
|
100416
|
+
armCancelledCompletionRecheck(this, pending, reason);
|
|
100417
|
+
}
|
|
100418
|
+
clearCancelledCompletionRecheck() {
|
|
100419
|
+
clearCancelledCompletionRecheck(this);
|
|
100420
|
+
}
|
|
100199
100421
|
// EVTTRACE (observation-only): is this a mesh worker session whose completion
|
|
100200
100422
|
// events must route to a coordinator? Used purely to gate trace logging so a
|
|
100201
100423
|
// non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
|
|
@@ -100727,6 +100949,7 @@ ${buttons.join("\n")}`;
|
|
|
100727
100949
|
if (this.completionTraceOn()) this.recordCompletionGateTrace("cancel", { blockReason: decision.reason, ...decision.trace });
|
|
100728
100950
|
this.completedDebouncePending = null;
|
|
100729
100951
|
this.completedDebounceTimer = null;
|
|
100952
|
+
this.armCancelledCompletionRecheck(pending, decision.reason);
|
|
100730
100953
|
return;
|
|
100731
100954
|
}
|
|
100732
100955
|
this.applyCompletionArmPatch(pending, decision.armPatch);
|
|
@@ -100784,6 +101007,7 @@ ${buttons.join("\n")}`;
|
|
|
100784
101007
|
});
|
|
100785
101008
|
this.completedDebouncePending = null;
|
|
100786
101009
|
this.completedDebounceTimer = null;
|
|
101010
|
+
this.clearCancelledCompletionRecheck();
|
|
100787
101011
|
this.generatingStartedAt = 0;
|
|
100788
101012
|
this.lastApprovalEventFingerprint = "";
|
|
100789
101013
|
this.markCurrentTurnStartupGraceCollapseSatisfied();
|
|
@@ -100810,7 +101034,7 @@ ${buttons.join("\n")}`;
|
|
|
100810
101034
|
timestamp: pending.timestamp,
|
|
100811
101035
|
taskId: pending.taskId,
|
|
100812
101036
|
finalSummary,
|
|
100813
|
-
evidenceLevel: "
|
|
101037
|
+
evidenceLevel: "reported",
|
|
100814
101038
|
completionDiagnostic: {
|
|
100815
101039
|
source: "clean_final_assistant",
|
|
100816
101040
|
cleanPath: true,
|
|
@@ -100838,6 +101062,7 @@ ${buttons.join("\n")}`;
|
|
|
100838
101062
|
});
|
|
100839
101063
|
this.completedDebouncePending = null;
|
|
100840
101064
|
this.completedDebounceTimer = null;
|
|
101065
|
+
this.clearCancelledCompletionRecheck();
|
|
100841
101066
|
this.generatingStartedAt = 0;
|
|
100842
101067
|
this.lastApprovalEventFingerprint = "";
|
|
100843
101068
|
this.markCurrentTurnStartupGraceCollapseSatisfied();
|
|
@@ -100949,7 +101174,7 @@ ${buttons.join("\n")}`;
|
|
|
100949
101174
|
* • prior emit was WEAK → re-arm ONE-SHOT, but only across a real generating→idle
|
|
100950
101175
|
* transition: require busyEpoch to have advanced past the weak emit's epoch, so a
|
|
100951
101176
|
* static idle screen cannot re-fire the same weak frame. The genuine re-emit passes
|
|
100952
|
-
* evidenceLevel:'
|
|
101177
|
+
* evidenceLevel:'reported' (non-weak), overwriting the latch → any subsequent idle
|
|
100953
101178
|
* tick hits the now-genuine latch and is suppressed. Never a third emit.
|
|
100954
101179
|
*/
|
|
100955
101180
|
shouldSuppressCompletionReEmit(taskId) {
|
|
@@ -110583,7 +110808,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
110583
110808
|
...slots.length ? { slots } : {}
|
|
110584
110809
|
};
|
|
110585
110810
|
if (providerRoles.length) migrateProviderRolesToSlots2(policy);
|
|
110586
|
-
|
|
110811
|
+
syncProviderPriorityFromSlots(policy);
|
|
110587
110812
|
const role = normalizeMeshDaemonRole(args?.role);
|
|
110588
110813
|
const daemonId = typeof args?.daemonId === "string" && args.daemonId.trim() ? args.daemonId.trim() : void 0;
|
|
110589
110814
|
const machineId = typeof args?.machineId === "string" && args.machineId.trim() ? args.machineId.trim() : void 0;
|
|
@@ -110635,10 +110860,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
110635
110860
|
else delete policy.providerRoles;
|
|
110636
110861
|
}
|
|
110637
110862
|
migrateProviderRolesToSlots2(policy);
|
|
110638
|
-
|
|
110639
|
-
|
|
110640
|
-
syncProviderPriorityFromSlots(policy, finalSlots);
|
|
110641
|
-
}
|
|
110863
|
+
const finalSlots = Object.prototype.hasOwnProperty.call(policy, "slots") ? policy.slots : getMesh2(meshId)?.nodes.find((n) => n.id === nodeId)?.policy?.slots;
|
|
110864
|
+
syncProviderPriorityFromSlots(policy, finalSlots);
|
|
110642
110865
|
const patch = { policy };
|
|
110643
110866
|
if (typeof args?.systemPrompt === "string") {
|
|
110644
110867
|
const trimmed = args.systemPrompt.trim();
|
|
@@ -110663,9 +110886,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
110663
110886
|
...inlineNode.policy && typeof inlineNode.policy === "object" && !Array.isArray(inlineNode.policy) ? inlineNode.policy : {},
|
|
110664
110887
|
...patch.policy
|
|
110665
110888
|
};
|
|
110666
|
-
|
|
110667
|
-
syncProviderPriorityFromSlots(inlineNode.policy);
|
|
110668
|
-
}
|
|
110889
|
+
syncProviderPriorityFromSlots(inlineNode.policy);
|
|
110669
110890
|
if (Object.prototype.hasOwnProperty.call(patch, "systemPrompt")) {
|
|
110670
110891
|
const sp = patch.systemPrompt;
|
|
110671
110892
|
if (typeof sp === "string" && sp.trim()) inlineNode.systemPrompt = sp;
|
|
@@ -113669,6 +113890,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
113669
113890
|
init_dist();
|
|
113670
113891
|
init_mesh_events();
|
|
113671
113892
|
init_mesh_reconcile_identity();
|
|
113893
|
+
init_mesh_reconcile_acked_hold();
|
|
113672
113894
|
init_mesh_fast_forward();
|
|
113673
113895
|
var import_node_child_process7 = require("child_process");
|
|
113674
113896
|
var import_node_util5 = require("util");
|
|
@@ -115671,11 +115893,20 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
115671
115893
|
LOG2.warn("Mesh", `[Refinery] Failed to append async refine ledger entry: ${e?.message || e}`);
|
|
115672
115894
|
}
|
|
115673
115895
|
}
|
|
115896
|
+
function resolveRefineResumeDispatchGraceMs() {
|
|
115897
|
+
return resolveTunedReconcileMs("MESH_REFINE_RESUME_DISPATCH_GRACE_MS", 6e4, 0, 10 * 6e4);
|
|
115898
|
+
}
|
|
115899
|
+
function resolveRefineResumeZombieCutoffMs() {
|
|
115900
|
+
return resolveTunedReconcileMs("MESH_REFINE_RESUME_ZOMBIE_CUTOFF_MS", 24 * 60 * 6e4, 5 * 6e4, 30 * 24 * 60 * 6e4);
|
|
115901
|
+
}
|
|
115674
115902
|
async function resumePendingRefineJobsOnStartup(self) {
|
|
115675
115903
|
try {
|
|
115676
115904
|
const { listMeshes: listMeshes2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
115677
115905
|
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
115678
115906
|
const meshIds = listMeshes2().map((m) => m.id).filter(Boolean);
|
|
115907
|
+
const nowMs = Date.now();
|
|
115908
|
+
const dispatchGraceMs = resolveRefineResumeDispatchGraceMs();
|
|
115909
|
+
const zombieCutoffMs = resolveRefineResumeZombieCutoffMs();
|
|
115679
115910
|
for (const meshId of meshIds) {
|
|
115680
115911
|
const entries = readLedgerEntries2(meshId, { kind: ["task_dispatched", "task_completed", "task_failed"] });
|
|
115681
115912
|
const terminal = /* @__PURE__ */ new Set();
|
|
@@ -115693,10 +115924,44 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
115693
115924
|
if (!jobId || terminal.has(`${e.nodeId}:${jobId}`)) continue;
|
|
115694
115925
|
const key2 = buildRefineJobKey(self, meshId, e.nodeId);
|
|
115695
115926
|
if (self.runningRefineJobs.has(key2)) continue;
|
|
115927
|
+
const dispatchedAtMs = new Date(e.timestamp).getTime();
|
|
115928
|
+
const ageMs2 = Number.isFinite(dispatchedAtMs) ? nowMs - dispatchedAtMs : void 0;
|
|
115929
|
+
if (ageMs2 !== void 0 && ageMs2 >= 0 && ageMs2 < dispatchGraceMs) {
|
|
115930
|
+
LOG2.info("Mesh", `[Refinery] Deferring resume of refine job for node ${e.nodeId} (jobId=${jobId}) \u2014 dispatched ${ageMs2}ms ago, within the ${dispatchGraceMs}ms grace window; may still be running.`);
|
|
115931
|
+
continue;
|
|
115932
|
+
}
|
|
115933
|
+
if (ageMs2 !== void 0 && ageMs2 >= zombieCutoffMs) {
|
|
115934
|
+
const node = e.payload?.refineJob;
|
|
115935
|
+
const coordinatorDaemonId2 = node?.targetCoordinatorDaemonId;
|
|
115936
|
+
const coordinatorSessionId2 = node?.targetCoordinatorSessionId;
|
|
115937
|
+
const zombieHandle = buildRefineJobHandle(self, {
|
|
115938
|
+
meshId,
|
|
115939
|
+
nodeId: e.nodeId,
|
|
115940
|
+
jobId,
|
|
115941
|
+
interactionId: typeof node?.interactionId === "string" ? node.interactionId : void 0,
|
|
115942
|
+
status: "failed",
|
|
115943
|
+
startedAt: typeof node?.startedAt === "string" ? node.startedAt : e.timestamp,
|
|
115944
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
115945
|
+
coordinatorDaemonId: coordinatorDaemonId2,
|
|
115946
|
+
coordinatorSessionId: coordinatorSessionId2
|
|
115947
|
+
});
|
|
115948
|
+
LOG2.warn("Mesh", `[Refinery] Closing out stale refine job for node ${e.nodeId} (jobId=${jobId}) as failed \u2014 dispatched ${ageMs2}ms ago, past the ${zombieCutoffMs}ms zombie cutoff with no terminal entry; not resuming.`);
|
|
115949
|
+
const zombieResult = {
|
|
115950
|
+
success: false,
|
|
115951
|
+
code: "resume_abandoned_stale_dispatch",
|
|
115952
|
+
error: `Refine job dispatched at ${e.timestamp} never reached a terminal state and exceeded the ${zombieCutoffMs}ms zombie cutoff on daemon restart; closed out without resuming.`
|
|
115953
|
+
};
|
|
115954
|
+
await appendRefineJobLedger(self, "task_failed", zombieHandle, zombieResult);
|
|
115955
|
+
queueRefineJobEvent(self, "refine:failed", zombieHandle, zombieResult);
|
|
115956
|
+
continue;
|
|
115957
|
+
}
|
|
115696
115958
|
const coordinatorDaemonId = e.payload?.refineJob?.targetCoordinatorDaemonId;
|
|
115959
|
+
const coordinatorSessionId = e.payload?.refineJob?.targetCoordinatorSessionId;
|
|
115697
115960
|
LOG2.info("Mesh", `[Refinery] Auto-resuming interrupted refine job for node ${e.nodeId} (jobId=${jobId})`);
|
|
115698
115961
|
void startMeshRefineJob(self, meshId, e.nodeId, {
|
|
115699
|
-
|
|
115962
|
+
jobId,
|
|
115963
|
+
coordinatorDaemonId,
|
|
115964
|
+
coordinatorSessionId
|
|
115700
115965
|
});
|
|
115701
115966
|
}
|
|
115702
115967
|
}
|
|
@@ -117420,7 +117685,7 @@ ${e?.stderr || ""}`;
|
|
|
117420
117685
|
const terminal = self.terminalRefineJobs.get(key2);
|
|
117421
117686
|
const alreadyRunning = self.runningRefineJobs.get(key2);
|
|
117422
117687
|
if (alreadyRunning) return { ...alreadyRunning, duplicate: true };
|
|
117423
|
-
const jobId = `refine_${createInteractionId()}`;
|
|
117688
|
+
const jobId = typeof args?.jobId === "string" && args.jobId.trim() ? args.jobId.trim() : `refine_${createInteractionId()}`;
|
|
117424
117689
|
const interactionId = createInteractionId();
|
|
117425
117690
|
const placeholder = buildRefineJobHandle(self, { meshId, nodeId, jobId, interactionId, retryOfJobId: terminal?.jobId });
|
|
117426
117691
|
self.runningRefineJobs.set(key2, placeholder);
|