@adhdev/daemon-standalone 1.0.45-rc.8 → 1.0.45-rc.9
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 +297 -69
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/index-digx-PVW.js +116 -0
- package/public/index.html +1 -1
- package/public/assets/index-CH6cVfIs.js +0 -116
package/dist/index.js
CHANGED
|
@@ -37027,10 +37027,10 @@ var require_dist3 = __commonJS({
|
|
|
37027
37027
|
}
|
|
37028
37028
|
function getDaemonBuildInfo() {
|
|
37029
37029
|
if (cached2) return cached2;
|
|
37030
|
-
const commit = readInjected(true ? "
|
|
37031
|
-
const commitShort = readInjected(true ? "
|
|
37032
|
-
const version2 = readInjected(true ? "1.0.45-rc.
|
|
37033
|
-
const builtAt = readInjected(true ? "2026-08-
|
|
37030
|
+
const commit = readInjected(true ? "6a45bfebc577345264d61b02a71a657bbc313033" : void 0) ?? "unknown";
|
|
37031
|
+
const commitShort = readInjected(true ? "6a45bfeb" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
37032
|
+
const version2 = readInjected(true ? "1.0.45-rc.9" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
37033
|
+
const builtAt = readInjected(true ? "2026-08-13T03:05:02.343Z" : void 0);
|
|
37034
37034
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
37035
37035
|
return cached2;
|
|
37036
37036
|
}
|
|
@@ -40041,6 +40041,13 @@ child.on('exit', () => process.exit(0));
|
|
|
40041
40041
|
metadata: { source: "oauth" }
|
|
40042
40042
|
};
|
|
40043
40043
|
}
|
|
40044
|
+
async function readErrorBody(response) {
|
|
40045
|
+
try {
|
|
40046
|
+
return await response.text?.() ?? "";
|
|
40047
|
+
} catch {
|
|
40048
|
+
return "";
|
|
40049
|
+
}
|
|
40050
|
+
}
|
|
40044
40051
|
function retryAfterMs(header, nowMs) {
|
|
40045
40052
|
if (!header) {
|
|
40046
40053
|
return void 0;
|
|
@@ -40084,11 +40091,28 @@ child.on('exit', () => process.exit(0));
|
|
|
40084
40091
|
},
|
|
40085
40092
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
40086
40093
|
});
|
|
40087
|
-
if (response.status === 401
|
|
40094
|
+
if (response.status === 401) {
|
|
40095
|
+
return quotaFailure(
|
|
40096
|
+
"kimi",
|
|
40097
|
+
"error",
|
|
40098
|
+
"Kimi usage request was rejected (HTTP 401)",
|
|
40099
|
+
{ source: "oauth", failureKind: "unauthorized" }
|
|
40100
|
+
);
|
|
40101
|
+
}
|
|
40102
|
+
if (response.status === 403) {
|
|
40103
|
+
const body = await readErrorBody(response);
|
|
40104
|
+
if (USAGE_LIMIT_BODY_PATTERN.test(body)) {
|
|
40105
|
+
return quotaFailure(
|
|
40106
|
+
"kimi",
|
|
40107
|
+
"error",
|
|
40108
|
+
"Kimi usage limit reached (HTTP 403) \u2014 quota refreshes at the next reset/billing cycle",
|
|
40109
|
+
{ source: "oauth", failureKind: "quota-exhausted" }
|
|
40110
|
+
);
|
|
40111
|
+
}
|
|
40088
40112
|
return quotaFailure(
|
|
40089
40113
|
"kimi",
|
|
40090
40114
|
"error",
|
|
40091
|
-
|
|
40115
|
+
"Kimi usage request was rejected (HTTP 403)",
|
|
40092
40116
|
{ source: "oauth", failureKind: "unauthorized" }
|
|
40093
40117
|
);
|
|
40094
40118
|
}
|
|
@@ -40122,6 +40146,7 @@ child.on('exit', () => process.exit(0));
|
|
|
40122
40146
|
var DEFAULT_BASE_URL;
|
|
40123
40147
|
var REQUEST_TIMEOUT_MS2;
|
|
40124
40148
|
var EXPIRY_SKEW_SECONDS;
|
|
40149
|
+
var USAGE_LIMIT_BODY_PATTERN;
|
|
40125
40150
|
var init_kimi = __esm2({
|
|
40126
40151
|
"src/quota/fetchers/kimi.ts"() {
|
|
40127
40152
|
"use strict";
|
|
@@ -40133,6 +40158,7 @@ child.on('exit', () => process.exit(0));
|
|
|
40133
40158
|
DEFAULT_BASE_URL = "https://api.kimi.com/coding/v1";
|
|
40134
40159
|
REQUEST_TIMEOUT_MS2 = 1e4;
|
|
40135
40160
|
EXPIRY_SKEW_SECONDS = 5;
|
|
40161
|
+
USAGE_LIMIT_BODY_PATTERN = /usage limit|quota\s*(exhausted|refresh)|billing cycle/i;
|
|
40136
40162
|
}
|
|
40137
40163
|
});
|
|
40138
40164
|
function opencodeCommand(env2) {
|
|
@@ -60592,7 +60618,17 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
60592
60618
|
const entry = quotaEntryFor(node, providerType);
|
|
60593
60619
|
if (!entry) return null;
|
|
60594
60620
|
const { facts, quota } = entry;
|
|
60595
|
-
if (quota.status !== "ok")
|
|
60621
|
+
if (quota.status !== "ok") {
|
|
60622
|
+
if (quota.status === "error" && quota.metadata?.failureKind === "quota-exhausted" && isQuotaSnapshotFresh(facts, quota, policy, now)) {
|
|
60623
|
+
return {
|
|
60624
|
+
reason: PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON,
|
|
60625
|
+
window: "unknown",
|
|
60626
|
+
remainingPercent: 0,
|
|
60627
|
+
thresholdPercent: 0
|
|
60628
|
+
};
|
|
60629
|
+
}
|
|
60630
|
+
return null;
|
|
60631
|
+
}
|
|
60596
60632
|
if (!isQuotaSnapshotFresh(facts, quota, policy, now)) return null;
|
|
60597
60633
|
const resolved = resolveQuotaRoutingPolicy(policy);
|
|
60598
60634
|
const session = remainingPercent(quota.session);
|
|
@@ -60637,12 +60673,14 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
60637
60673
|
}
|
|
60638
60674
|
var PROVIDER_QUOTA_SESSION_LOW_SKIP_REASON;
|
|
60639
60675
|
var PROVIDER_QUOTA_WEEKLY_LOW_SKIP_REASON;
|
|
60676
|
+
var PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON;
|
|
60640
60677
|
var init_mesh_quota_routing = __esm2({
|
|
60641
60678
|
"src/mesh/mesh-quota-routing.ts"() {
|
|
60642
60679
|
"use strict";
|
|
60643
60680
|
init_repo_mesh_types();
|
|
60644
60681
|
PROVIDER_QUOTA_SESSION_LOW_SKIP_REASON = "provider_quota_session_low";
|
|
60645
60682
|
PROVIDER_QUOTA_WEEKLY_LOW_SKIP_REASON = "provider_quota_weekly_low";
|
|
60683
|
+
PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON = "provider_quota_exhausted";
|
|
60646
60684
|
}
|
|
60647
60685
|
});
|
|
60648
60686
|
function isAnthropicProvider(providerType) {
|
|
@@ -61212,10 +61250,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
61212
61250
|
// busy counterpart SLOT_MODEL_BUSY_SKIP_REASON is deliberately NOT listed:
|
|
61213
61251
|
// that one clears on its own when the slot goes idle.
|
|
61214
61252
|
SLOT_MODEL_ABSENT_SKIP_REASON
|
|
61215
|
-
// QUOTA GATE: 'provider_quota_session_low' / 'provider_quota_weekly_low'
|
|
61216
|
-
// deliberately NOT listed either — an
|
|
61217
|
-
//
|
|
61218
|
-
// queue and the coordinator is
|
|
61253
|
+
// QUOTA GATE: 'provider_quota_session_low' / 'provider_quota_weekly_low' /
|
|
61254
|
+
// 'provider_quota_exhausted' are deliberately NOT listed either — an
|
|
61255
|
+
// exhausted quota window RESETS, so the block self-resolves exactly like
|
|
61256
|
+
// the slot-busy case; the task waits in the queue and the coordinator is
|
|
61257
|
+
// not paged (mesh-quota-routing.ts).
|
|
61219
61258
|
];
|
|
61220
61259
|
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
61221
61260
|
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
@@ -61720,7 +61759,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
61720
61759
|
}
|
|
61721
61760
|
const quotaClaimBlock = evaluateProviderQuotaGate(node, providerType, mesh?.policy?.quotaRouting ?? null);
|
|
61722
61761
|
if (quotaClaimBlock) {
|
|
61723
|
-
|
|
61762
|
+
if (quotaClaimBlock.reason === PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON) {
|
|
61763
|
+
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`);
|
|
61764
|
+
} else {
|
|
61765
|
+
LOG2.info("MeshQueue", `QUOTA GATE: deferring queue claim for node ${nodeId} (${sessionId}): provider '${providerType}' has ${quotaClaimBlock.remainingPercent.toFixed(1)}% ${quotaClaimBlock.window} quota remaining (< ${quotaClaimBlock.thresholdPercent}% threshold) \u2014 task left pending until the window resets`);
|
|
61766
|
+
}
|
|
61724
61767
|
return false;
|
|
61725
61768
|
}
|
|
61726
61769
|
const inlineBootstrapNode = (() => {
|
|
@@ -62465,7 +62508,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
62465
62508
|
}
|
|
62466
62509
|
const quotaBlock = evaluateProviderQuotaGate(node, resolved.providerType, mesh?.policy?.quotaRouting ?? null);
|
|
62467
62510
|
if (quotaBlock) {
|
|
62468
|
-
|
|
62511
|
+
if (quotaBlock.reason === PROVIDER_QUOTA_EXHAUSTED_SKIP_REASON) {
|
|
62512
|
+
LOG2.info("MeshQueue", `QUOTA GATE: provider '${resolved.providerType}' on node ${nodeId} reported its quota EXHAUSTED (task ${task.id}); leaving the task queued until the quota resets`);
|
|
62513
|
+
} else {
|
|
62514
|
+
LOG2.info("MeshQueue", `QUOTA GATE: provider '${resolved.providerType}' on node ${nodeId} has ${quotaBlock.remainingPercent.toFixed(1)}% ${quotaBlock.window} quota remaining (< ${quotaBlock.thresholdPercent}% threshold, task ${task.id}); leaving the task queued until the window resets`);
|
|
62515
|
+
}
|
|
62469
62516
|
markSkip(nodeId, quotaBlock.reason, { providerType: resolved.providerType });
|
|
62470
62517
|
continue;
|
|
62471
62518
|
}
|
|
@@ -75563,6 +75610,9 @@ ${cont}` : cont;
|
|
|
75563
75610
|
var import_session_host_core8;
|
|
75564
75611
|
var missingBackgroundSourceWarned;
|
|
75565
75612
|
var FORCE_SUBMIT_SETTLE_MS;
|
|
75613
|
+
var WIN32_INJECT_ENTER_MAX_RETRIES;
|
|
75614
|
+
var WIN32_INJECT_ENTER_RETRY_DELAY_MS;
|
|
75615
|
+
var WIN32_INJECT_COMPOSER_TAIL_LINES;
|
|
75566
75616
|
var ProviderCliAdapter;
|
|
75567
75617
|
var init_provider_cli_adapter = __esm2({
|
|
75568
75618
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
@@ -75589,6 +75639,9 @@ ${cont}` : cont;
|
|
|
75589
75639
|
init_provider_cli_shared();
|
|
75590
75640
|
missingBackgroundSourceWarned = /* @__PURE__ */ new Set();
|
|
75591
75641
|
FORCE_SUBMIT_SETTLE_MS = 150;
|
|
75642
|
+
WIN32_INJECT_ENTER_MAX_RETRIES = 2;
|
|
75643
|
+
WIN32_INJECT_ENTER_RETRY_DELAY_MS = 300;
|
|
75644
|
+
WIN32_INJECT_COMPOSER_TAIL_LINES = 8;
|
|
75592
75645
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
75593
75646
|
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory(), owningSessionId) {
|
|
75594
75647
|
this.extraArgs = extraArgs;
|
|
@@ -75736,6 +75789,9 @@ ${cont}` : cont;
|
|
|
75736
75789
|
pendingOutboundStaleTimer = null;
|
|
75737
75790
|
// Submit retry timer — PTY-level, not state machine
|
|
75738
75791
|
submitRetryTimer = null;
|
|
75792
|
+
// WIN32-INJECT-ENTER-RETRY: pending bare-ENTER resend for a mesh_send_keys
|
|
75793
|
+
// injection whose submit may have been swallowed by win32 ConPTY.
|
|
75794
|
+
injectEnterRetryTimer = null;
|
|
75739
75795
|
// PTY-WRITE-SERIALIZE: a single per-session tail promise that serializes every
|
|
75740
75796
|
// PTY write. Each writeToPty() call chains its actual write after the previous
|
|
75741
75797
|
// one and returns a promise that resolves only after ITS write completes, so
|
|
@@ -76295,6 +76351,10 @@ ${lastSnapshot}`;
|
|
|
76295
76351
|
clearTimeout(this.submitRetryTimer);
|
|
76296
76352
|
this.submitRetryTimer = null;
|
|
76297
76353
|
}
|
|
76354
|
+
if (this.injectEnterRetryTimer) {
|
|
76355
|
+
clearTimeout(this.injectEnterRetryTimer);
|
|
76356
|
+
this.injectEnterRetryTimer = null;
|
|
76357
|
+
}
|
|
76298
76358
|
if (this.pendingOutputParseTimer) {
|
|
76299
76359
|
clearTimeout(this.pendingOutputParseTimer);
|
|
76300
76360
|
this.pendingOutputParseTimer = null;
|
|
@@ -77109,6 +77169,10 @@ ${lastSnapshot}`;
|
|
|
77109
77169
|
clearTimeout(this.submitRetryTimer);
|
|
77110
77170
|
this.submitRetryTimer = null;
|
|
77111
77171
|
}
|
|
77172
|
+
if (this.injectEnterRetryTimer) {
|
|
77173
|
+
clearTimeout(this.injectEnterRetryTimer);
|
|
77174
|
+
this.injectEnterRetryTimer = null;
|
|
77175
|
+
}
|
|
77112
77176
|
this.engine.onTurnStarted(turnScope);
|
|
77113
77177
|
this.engine.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
|
|
77114
77178
|
const normalizedPromptSnippet = normalizePromptText(this.engine.submitRetryPromptSnippet);
|
|
@@ -77672,7 +77736,17 @@ ${lastSnapshot}`;
|
|
|
77672
77736
|
LOG2.warn("CLI", `[${this.cliType}] send_keys refused (actionable_modal): keys=${encoded.keys.join(",")} \u2014 use mesh_approve`);
|
|
77673
77737
|
return { ok: false, refused: "actionable_modal", keys: encoded.keys, hasDestructive: encoded.hasDestructive };
|
|
77674
77738
|
}
|
|
77739
|
+
if (this.injectEnterRetryTimer) {
|
|
77740
|
+
clearTimeout(this.injectEnterRetryTimer);
|
|
77741
|
+
this.injectEnterRetryTimer = null;
|
|
77742
|
+
}
|
|
77675
77743
|
await this.writeToPty(encoded.sequence);
|
|
77744
|
+
if (process.platform === "win32" && encoded.submits) {
|
|
77745
|
+
const snippet2 = extractPromptRetrySnippet(
|
|
77746
|
+
items.map((it) => "text" in it ? it.text : "").join("\n")
|
|
77747
|
+
);
|
|
77748
|
+
if (snippet2) this.scheduleWin32InjectEnterRetry(snippet2, 1);
|
|
77749
|
+
}
|
|
77676
77750
|
LOG2.info("CLI", `[${this.cliType}] send_keys injected keys=${encoded.keys.join(",") || "(text-only)"} bytes=${Buffer.byteLength(encoded.sequence, "utf8")} destructive=${encoded.hasDestructive}`);
|
|
77677
77751
|
return {
|
|
77678
77752
|
ok: true,
|
|
@@ -77689,6 +77763,30 @@ ${lastSnapshot}`;
|
|
|
77689
77763
|
const str2 = Buffer.isBuffer(data) ? data.toString("utf8") : data;
|
|
77690
77764
|
await this.writeToPty(str2);
|
|
77691
77765
|
}
|
|
77766
|
+
/**
|
|
77767
|
+
* WIN32-INJECT-ENTER-RETRY: resend the bare submit key while the injected
|
|
77768
|
+
* text still stands in the composer (bottom viewport lines). Stops the
|
|
77769
|
+
* instant the text leaves that region — proof the submit was consumed —
|
|
77770
|
+
* so a delayed (not lost) original ENTER is never doubled. Bounded by
|
|
77771
|
+
* WIN32_INJECT_ENTER_MAX_RETRIES; see the constants' comment for the
|
|
77772
|
+
* rationale. Never logs the snippet (it is user text).
|
|
77773
|
+
*/
|
|
77774
|
+
scheduleWin32InjectEnterRetry(snippet2, attempt) {
|
|
77775
|
+
this.injectEnterRetryTimer = setTimeout(() => {
|
|
77776
|
+
this.injectEnterRetryTimer = null;
|
|
77777
|
+
if (!this.ptyProcess) return;
|
|
77778
|
+
const screenLines = this.terminalScreen.getText().split("\n");
|
|
77779
|
+
const composerRegion = screenLines.slice(-WIN32_INJECT_COMPOSER_TAIL_LINES).join("\n");
|
|
77780
|
+
if (!promptLikelyVisible(composerRegion, snippet2)) return;
|
|
77781
|
+
LOG2.info("CLI", `[${this.cliType}] send_keys ENTER retry (attempt ${attempt}/${WIN32_INJECT_ENTER_MAX_RETRIES}): injected text still in composer`);
|
|
77782
|
+
void this.writeToPty(MESH_SEND_KEY_ENCODING.ENTER).catch((error48) => {
|
|
77783
|
+
LOG2.warn("CLI", `[${this.cliType}] send_keys ENTER retry write failed: ${error48?.message || error48}`);
|
|
77784
|
+
});
|
|
77785
|
+
if (attempt < WIN32_INJECT_ENTER_MAX_RETRIES) {
|
|
77786
|
+
this.scheduleWin32InjectEnterRetry(snippet2, attempt + 1);
|
|
77787
|
+
}
|
|
77788
|
+
}, WIN32_INJECT_ENTER_RETRY_DELAY_MS);
|
|
77789
|
+
}
|
|
77692
77790
|
resolveModal(buttonIndex) {
|
|
77693
77791
|
this.engine.resolveModal(buttonIndex);
|
|
77694
77792
|
}
|
|
@@ -113434,8 +113532,19 @@ ${asText(streams.stderr)}
|
|
|
113434
113532
|
});
|
|
113435
113533
|
}
|
|
113436
113534
|
function buildSubmodulePublishRequiredNextStep(entries) {
|
|
113437
|
-
const
|
|
113438
|
-
|
|
113535
|
+
const convergeable = entries.filter((entry) => entry.equivalentPublishedCommit);
|
|
113536
|
+
const publishable = entries.filter((entry) => !entry.equivalentPublishedCommit);
|
|
113537
|
+
const parts = [];
|
|
113538
|
+
if (convergeable.length > 0) {
|
|
113539
|
+
const refs = convergeable.map((entry) => `${entry.path}: ${entry.commit} \u2192 ${entry.equivalentPublishedCommit}`).join(", ");
|
|
113540
|
+
parts.push(`Converge the submodule gitlink(s) to the already-published equivalent commit(s) (${refs}): a commit with an identical tree already exists on the submodule remote main branch, so publishing the local same-content twin is wrong. Retarget the gitlink to the published commit, commit the root pointer update, then rerun mesh_refine_node.`);
|
|
113541
|
+
}
|
|
113542
|
+
if (publishable.length > 0) {
|
|
113543
|
+
const refs = publishable.map((entry) => `${entry.path}@${entry.commit}`).join(", ");
|
|
113544
|
+
parts.push(`Ask the user for explicit approval to push/publish the unreachable submodule commit(s) (${refs}) to the configured submodule remote main branch, then rerun mesh_refine_node.`);
|
|
113545
|
+
}
|
|
113546
|
+
parts.push("Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main.");
|
|
113547
|
+
return parts.join(" ");
|
|
113439
113548
|
}
|
|
113440
113549
|
function resolveRefineryAutoPublishSubmoduleMainCommits(mesh, workspace) {
|
|
113441
113550
|
if (mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true) {
|
|
@@ -113989,6 +114098,47 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
113989
114098
|
return false;
|
|
113990
114099
|
}
|
|
113991
114100
|
}
|
|
114101
|
+
function resolveSubmoduleRemoteMainRef(submoduleRepoPath) {
|
|
114102
|
+
try {
|
|
114103
|
+
const sym = (0, import_node_child_process9.execFileSync)(GIT3, ["symbolic-ref", "-q", "refs/remotes/origin/HEAD"], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
|
|
114104
|
+
if (sym) return sym;
|
|
114105
|
+
} catch {
|
|
114106
|
+
}
|
|
114107
|
+
for (const branch of ["main", "master"]) {
|
|
114108
|
+
try {
|
|
114109
|
+
(0, import_node_child_process9.execFileSync)(GIT3, ["rev-parse", "--verify", "-q", `refs/remotes/origin/${branch}`], { cwd: submoduleRepoPath, stdio: ["ignore", "pipe", "pipe"] });
|
|
114110
|
+
return `refs/remotes/origin/${branch}`;
|
|
114111
|
+
} catch {
|
|
114112
|
+
}
|
|
114113
|
+
}
|
|
114114
|
+
return void 0;
|
|
114115
|
+
}
|
|
114116
|
+
function findEquivalentPublishedSubmoduleCommit(submoduleRepoPath, baseCommit, branchCommit, remoteRef) {
|
|
114117
|
+
try {
|
|
114118
|
+
const mergeTreeOut = (0, import_node_child_process9.execFileSync)(GIT3, ["merge-tree", "--write-tree", baseCommit, branchCommit], {
|
|
114119
|
+
cwd: submoduleRepoPath,
|
|
114120
|
+
encoding: "utf8",
|
|
114121
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
114122
|
+
});
|
|
114123
|
+
const mergedTree = mergeTreeOut.trim().split(/\s+/)[0] || "";
|
|
114124
|
+
if (!mergedTree) return void 0;
|
|
114125
|
+
const candidates = (0, import_node_child_process9.execFileSync)(GIT3, ["rev-list", "--max-count=100", remoteRef, "--not", baseCommit], {
|
|
114126
|
+
cwd: submoduleRepoPath,
|
|
114127
|
+
encoding: "utf8"
|
|
114128
|
+
}).split("\n").map((s2) => s2.trim()).filter(Boolean);
|
|
114129
|
+
for (const candidate of candidates) {
|
|
114130
|
+
try {
|
|
114131
|
+
(0, import_node_child_process9.execFileSync)(GIT3, ["merge-base", "--is-ancestor", baseCommit, candidate], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
114132
|
+
} catch {
|
|
114133
|
+
continue;
|
|
114134
|
+
}
|
|
114135
|
+
const tree = (0, import_node_child_process9.execFileSync)(GIT3, ["rev-parse", `${candidate}^{tree}`], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
|
|
114136
|
+
if (tree === mergedTree) return candidate;
|
|
114137
|
+
}
|
|
114138
|
+
} catch {
|
|
114139
|
+
}
|
|
114140
|
+
return void 0;
|
|
114141
|
+
}
|
|
113992
114142
|
function ensureSubmoduleCommitLocal(submoduleRepoPath, baseSubmoduleRepoPath, commit) {
|
|
113993
114143
|
if (!commit) return;
|
|
113994
114144
|
try {
|
|
@@ -114025,6 +114175,21 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
114025
114175
|
continue;
|
|
114026
114176
|
}
|
|
114027
114177
|
sawDiverged = true;
|
|
114178
|
+
try {
|
|
114179
|
+
(0, import_node_child_process9.execFileSync)(GIT3, ["-c", "protocol.file.allow=always", "fetch", "-q", "origin"], { cwd: submoduleRepoPath, stdio: ["ignore", "ignore", "pipe"] });
|
|
114180
|
+
} catch {
|
|
114181
|
+
}
|
|
114182
|
+
const remoteMainRef = resolveSubmoduleRemoteMainRef(submoduleRepoPath);
|
|
114183
|
+
const publishedEquivalent = remoteMainRef ? findEquivalentPublishedSubmoduleCommit(submoduleRepoPath, baseCommit, branchCommit, remoteMainRef) : void 0;
|
|
114184
|
+
if (publishedEquivalent) {
|
|
114185
|
+
try {
|
|
114186
|
+
(0, import_node_child_process9.execFileSync)(GIT3, ["checkout", "-q", "--detach", publishedEquivalent], { cwd: submoduleRepoPath, stdio: ["ignore", "ignore", "pipe"] });
|
|
114187
|
+
} catch {
|
|
114188
|
+
}
|
|
114189
|
+
gitlinks.push({ path: path54, baseCommit, branchCommit, rebasedCommit: publishedEquivalent, action: "converged_to_published" });
|
|
114190
|
+
resolutions.push({ path: path54, baseCommit, branchCommit, rebasedCommit: publishedEquivalent });
|
|
114191
|
+
continue;
|
|
114192
|
+
}
|
|
114028
114193
|
let rebasedCommit;
|
|
114029
114194
|
try {
|
|
114030
114195
|
(0, import_node_child_process9.execFileSync)(GIT3, ["checkout", "-q", "--detach", branchCommit], { cwd: submoduleRepoPath, stdio: ["ignore", "ignore", "pipe"] });
|
|
@@ -114422,6 +114587,19 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
114422
114587
|
await runGit3(submodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
|
|
114423
114588
|
return true;
|
|
114424
114589
|
};
|
|
114590
|
+
const findEquivalentPublishedCommit = async (submodulePath, commit, remoteRef) => {
|
|
114591
|
+
try {
|
|
114592
|
+
const targetTree = (await runGit3(submodulePath, ["rev-parse", `${commit}^{tree}`])).trim();
|
|
114593
|
+
if (!targetTree) return void 0;
|
|
114594
|
+
const candidates = (await runGit3(submodulePath, ["rev-list", "--max-count=100", remoteRef])).split("\n").map((s2) => s2.trim()).filter(Boolean);
|
|
114595
|
+
for (const candidate of candidates) {
|
|
114596
|
+
const tree = (await runGit3(submodulePath, ["rev-parse", `${candidate}^{tree}`])).trim();
|
|
114597
|
+
if (tree === targetTree) return candidate;
|
|
114598
|
+
}
|
|
114599
|
+
} catch {
|
|
114600
|
+
}
|
|
114601
|
+
return void 0;
|
|
114602
|
+
};
|
|
114425
114603
|
const treeOutput = await runGit3(repoRoot, ["ls-tree", "-r", "-z", mergedTree]);
|
|
114426
114604
|
const gitlinks = treeOutput.split("\0").filter(Boolean).map((record2) => {
|
|
114427
114605
|
const match = /^160000\s+commit\s+([0-9a-f]{40})\t(.+)$/.exec(record2);
|
|
@@ -114455,11 +114633,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
114455
114633
|
entry.localReachable = false;
|
|
114456
114634
|
if (options.allowAutoPublishSubmoduleMainCommits === true && options.worktreeRoot) {
|
|
114457
114635
|
try {
|
|
114458
|
-
const imported = await importCommitFromWorktreeSubmodule(
|
|
114459
|
-
submodulePath,
|
|
114460
|
-
(0, import_path17.resolve)(options.worktreeRoot, gitlink.path),
|
|
114461
|
-
gitlink.commit
|
|
114462
|
-
);
|
|
114636
|
+
const imported = await importCommitFromWorktreeSubmodule(submodulePath, (0, import_path17.resolve)(options.worktreeRoot, gitlink.path), gitlink.commit);
|
|
114463
114637
|
if (imported) {
|
|
114464
114638
|
entry.localReachable = true;
|
|
114465
114639
|
entry.importedFromWorktree = true;
|
|
@@ -114502,36 +114676,48 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
114502
114676
|
} catch (e) {
|
|
114503
114677
|
entry.remoteReachable = false;
|
|
114504
114678
|
entry.remoteMainReachable = false;
|
|
114505
|
-
|
|
114506
|
-
|
|
114507
|
-
|
|
114508
|
-
|
|
114509
|
-
entry.
|
|
114510
|
-
|
|
114511
|
-
|
|
114512
|
-
|
|
114513
|
-
entry.
|
|
114514
|
-
|
|
114515
|
-
|
|
114516
|
-
|
|
114517
|
-
|
|
114518
|
-
|
|
114519
|
-
|
|
114520
|
-
entry.
|
|
114521
|
-
entry.
|
|
114522
|
-
|
|
114523
|
-
|
|
114524
|
-
|
|
114525
|
-
|
|
114526
|
-
|
|
114527
|
-
|
|
114528
|
-
|
|
114529
|
-
|
|
114679
|
+
const equivalentPublished = await findEquivalentPublishedCommit(submodulePath, gitlink.commit, `refs/remotes/origin/${submoduleDefaultBranch}`);
|
|
114680
|
+
if (equivalentPublished) {
|
|
114681
|
+
entry.equivalentPublishedCommit = equivalentPublished;
|
|
114682
|
+
entry.publishRequired = false;
|
|
114683
|
+
entry.error = `Submodule commit ${gitlink.commit} is not reachable from origin/${submoduleDefaultBranch}, but an equivalent commit ${equivalentPublished} (identical tree) is already published there; converge the gitlink to the published commit instead of publishing a same-content twin.`;
|
|
114684
|
+
if (options.allowAutoPublishSubmoduleMainCommits === true) {
|
|
114685
|
+
entry.autoPublishAllowed = true;
|
|
114686
|
+
entry.autoPublishAttempted = false;
|
|
114687
|
+
entry.autoPublishSkippedReason = `an equivalent commit (${equivalentPublished}) is already published on origin/${submoduleDefaultBranch}; publishing a same-content twin is wrong \u2014 converge the gitlink to the published commit instead`;
|
|
114688
|
+
}
|
|
114689
|
+
} else {
|
|
114690
|
+
entry.publishRequired = true;
|
|
114691
|
+
const details = truncateValidationOutput(e?.stderr || e?.message || String(e));
|
|
114692
|
+
entry.error = `Submodule remote main reachability check failed for origin/${submoduleDefaultBranch}: ${details}`;
|
|
114693
|
+
if (options.allowAutoPublishSubmoduleMainCommits === true && entry.localReachable === true) {
|
|
114694
|
+
entry.autoPublishAllowed = true;
|
|
114695
|
+
entry.autoPublishAttempted = true;
|
|
114696
|
+
try {
|
|
114697
|
+
const publish = await publishCommitToRemoteMain(submodulePath, gitlink.commit, submoduleDefaultBranch);
|
|
114698
|
+
entry.autoPublishRefspec = publish.refspec;
|
|
114699
|
+
entry.publishStdout = truncateValidationOutput(publish.stdout);
|
|
114700
|
+
entry.publishStderr = truncateValidationOutput(publish.stderr);
|
|
114701
|
+
entry.autoPublishSucceeded = true;
|
|
114702
|
+
await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, submoduleDefaultBranch);
|
|
114703
|
+
entry.fetchedFromOrigin = true;
|
|
114704
|
+
entry.remoteReachable = true;
|
|
114705
|
+
entry.remoteMainReachable = true;
|
|
114706
|
+
entry.autoPublishVerified = true;
|
|
114707
|
+
entry.publishRequired = false;
|
|
114708
|
+
entry.reachable = true;
|
|
114709
|
+
entry.error = void 0;
|
|
114710
|
+
} catch (publishError) {
|
|
114711
|
+
entry.autoPublishSucceeded = false;
|
|
114712
|
+
entry.autoPublishVerified = false;
|
|
114713
|
+
const publishDetails = truncateValidationOutput(publishError?.stderr || publishError?.message || String(publishError));
|
|
114714
|
+
entry.error = `Submodule auto-publish to origin/${submoduleDefaultBranch} failed or could not be verified: ${publishDetails}`;
|
|
114715
|
+
}
|
|
114716
|
+
} else if (options.allowAutoPublishSubmoduleMainCommits === true) {
|
|
114717
|
+
entry.autoPublishAllowed = true;
|
|
114718
|
+
entry.autoPublishAttempted = false;
|
|
114719
|
+
entry.autoPublishSkippedReason = entry.autoPublishSkippedReason || `candidate commit is not reachable in the source checkout or worktree submodule, so Refinery cannot push it to origin/${submoduleDefaultBranch}`;
|
|
114530
114720
|
}
|
|
114531
|
-
} else if (options.allowAutoPublishSubmoduleMainCommits === true) {
|
|
114532
|
-
entry.autoPublishAllowed = true;
|
|
114533
|
-
entry.autoPublishAttempted = false;
|
|
114534
|
-
entry.autoPublishSkippedReason = entry.autoPublishSkippedReason || `candidate commit is not reachable in the source checkout or worktree submodule, so Refinery cannot push it to origin/${submoduleDefaultBranch}`;
|
|
114535
114721
|
}
|
|
114536
114722
|
}
|
|
114537
114723
|
} catch (e) {
|
|
@@ -115100,18 +115286,49 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
115100
115286
|
const resolved = await refineResolveRefsStage(self, meshId, nodeId, args, refineStages);
|
|
115101
115287
|
if (resolved.kind === "terminal") return resolved.result;
|
|
115102
115288
|
const ctx = resolved.ctx;
|
|
115103
|
-
const
|
|
115104
|
-
|
|
115105
|
-
|
|
115106
|
-
|
|
115107
|
-
|
|
115108
|
-
|
|
115109
|
-
|
|
115110
|
-
|
|
115111
|
-
|
|
115112
|
-
|
|
115113
|
-
|
|
115114
|
-
|
|
115289
|
+
const leaseKey = `${ctx.repoRoot}::${ctx.baseBranch}`;
|
|
115290
|
+
const leaseHolder = buildRefineJobKey(self, meshId, nodeId);
|
|
115291
|
+
if (self.refineBaseLeases.has(leaseKey) && self.refineBaseLeases.get(leaseKey) !== leaseHolder) {
|
|
115292
|
+
recordMeshRefineStage(refineStages, "base_lease", "skipped", Date.now(), {
|
|
115293
|
+
leaseKey,
|
|
115294
|
+
heldBy: self.refineBaseLeases.get(leaseKey),
|
|
115295
|
+
retryable: true
|
|
115296
|
+
});
|
|
115297
|
+
return {
|
|
115298
|
+
success: false,
|
|
115299
|
+
code: "base_locked",
|
|
115300
|
+
convergenceStatus: "blocked_review",
|
|
115301
|
+
retryable: true,
|
|
115302
|
+
error: `Another refine holds the base lease for ${ctx.baseBranch} in this repo; retry after it completes.`,
|
|
115303
|
+
branch: ctx.branch,
|
|
115304
|
+
into: ctx.baseBranch,
|
|
115305
|
+
refineStages,
|
|
115306
|
+
finalBranchConvergenceState: {
|
|
115307
|
+
branch: ctx.branch,
|
|
115308
|
+
baseBranch: ctx.baseBranch,
|
|
115309
|
+
merged: false,
|
|
115310
|
+
removed: false,
|
|
115311
|
+
status: "blocked_review"
|
|
115312
|
+
}
|
|
115313
|
+
};
|
|
115314
|
+
}
|
|
115315
|
+
self.refineBaseLeases.set(leaseKey, leaseHolder);
|
|
115316
|
+
try {
|
|
115317
|
+
const syncBase = await refineSyncBaseStage(self, ctx);
|
|
115318
|
+
if (syncBase.kind === "terminal") return syncBase.result;
|
|
115319
|
+
const validation = await refineValidationStage(self, ctx);
|
|
115320
|
+
if (validation.kind === "terminal") return validation.result;
|
|
115321
|
+
const patchEquivalence = await refinePatchEquivalenceStage(self, ctx);
|
|
115322
|
+
if (patchEquivalence.kind === "terminal") return patchEquivalence.result;
|
|
115323
|
+
const submoduleReachability = await refineSubmoduleReachabilityStage(self, ctx);
|
|
115324
|
+
if (submoduleReachability.kind === "terminal") return submoduleReachability.result;
|
|
115325
|
+
const effectiveDiff = await refineEffectiveDiffStage(self, ctx);
|
|
115326
|
+
if (effectiveDiff.kind === "terminal") return effectiveDiff.result;
|
|
115327
|
+
const merge3 = await refineMergeAndFinalizeStage(self, ctx);
|
|
115328
|
+
return merge3.result;
|
|
115329
|
+
} finally {
|
|
115330
|
+
if (self.refineBaseLeases.get(leaseKey) === leaseHolder) self.refineBaseLeases.delete(leaseKey);
|
|
115331
|
+
}
|
|
115115
115332
|
} catch (e) {
|
|
115116
115333
|
return { success: false, error: e.message, refineStages };
|
|
115117
115334
|
}
|
|
@@ -115631,6 +115848,7 @@ ${tail}` : ""
|
|
|
115631
115848
|
unreachable: submoduleReachability.unreachable.map((entry) => ({
|
|
115632
115849
|
path: entry.path,
|
|
115633
115850
|
commit: entry.commit,
|
|
115851
|
+
equivalentPublishedCommit: entry.equivalentPublishedCommit,
|
|
115634
115852
|
publishRequired: entry.publishRequired === true,
|
|
115635
115853
|
autoPublishAllowed: entry.autoPublishAllowed,
|
|
115636
115854
|
autoPublishAttempted: entry.autoPublishAttempted,
|
|
@@ -115649,15 +115867,23 @@ ${tail}` : ""
|
|
|
115649
115867
|
});
|
|
115650
115868
|
if (submoduleReachability.status === "failed") {
|
|
115651
115869
|
const nextStep = buildSubmodulePublishRequiredNextStep(submoduleReachability.unreachable);
|
|
115870
|
+
const convergeToPublished = submoduleReachability.unreachable.length > 0 && submoduleReachability.unreachable.every((entry) => !!entry.equivalentPublishedCommit);
|
|
115871
|
+
const blockedReason = convergeToPublished ? "submodule_converge_to_published" : "submodule_publish_required";
|
|
115652
115872
|
return { kind: "terminal", result: {
|
|
115653
115873
|
success: false,
|
|
115654
115874
|
code: "submodule_reachability_failed",
|
|
115655
115875
|
convergenceStatus: "blocked_review",
|
|
115656
|
-
publishRequired:
|
|
115657
|
-
|
|
115658
|
-
|
|
115876
|
+
publishRequired: !convergeToPublished,
|
|
115877
|
+
...convergeToPublished ? { convergeToPublished: true } : {},
|
|
115878
|
+
blockedReason,
|
|
115879
|
+
error: convergeToPublished ? "Refinery submodule reachability preflight found submodule gitlink commit(s) that are not reachable from their configured remote main branch, but each has an equivalent commit (identical tree) already published there; converge the gitlink(s) to the published commit(s) instead of publishing same-content twins. Merge/refine cleanup was not attempted." : "Refinery submodule reachability preflight failed because one or more submodule gitlink commits are not reachable from their configured remote main branch; merge/refine cleanup was not attempted.",
|
|
115659
115880
|
nextStep,
|
|
115660
|
-
nextSteps: [
|
|
115881
|
+
nextSteps: convergeToPublished ? [
|
|
115882
|
+
"Do NOT publish the local submodule commit(s): an equivalent commit (identical tree) is already published on the submodule remote main branch for every unreachable gitlink.",
|
|
115883
|
+
"Retarget each submodule gitlink to the already-published equivalent commit shown in the evidence (equivalentPublishedCommit), commit the root pointer update, and push the submodule checkout to that commit.",
|
|
115884
|
+
"Rerun mesh_refine_node after the gitlink points at the published commit.",
|
|
115885
|
+
"Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main."
|
|
115886
|
+
] : [
|
|
115661
115887
|
"Ask the user for explicit approval before pushing or publishing any submodule commit.",
|
|
115662
115888
|
"Push/publish each unreachable submodule commit to the configured submodule remote main branch shown in the evidence.",
|
|
115663
115889
|
"Rerun mesh_refine_node after remote reachability is confirmed.",
|
|
@@ -115666,6 +115892,7 @@ ${tail}` : ""
|
|
|
115666
115892
|
unreachableSubmoduleCommits: submoduleReachability.unreachable.map((entry) => ({
|
|
115667
115893
|
path: entry.path,
|
|
115668
115894
|
commit: entry.commit,
|
|
115895
|
+
equivalentPublishedCommit: entry.equivalentPublishedCommit,
|
|
115669
115896
|
remote: entry.remote,
|
|
115670
115897
|
remoteUrl: entry.remoteUrl,
|
|
115671
115898
|
remoteReachable: entry.remoteReachable,
|
|
@@ -115694,7 +115921,7 @@ ${tail}` : ""
|
|
|
115694
115921
|
patchEquivalence: "passed",
|
|
115695
115922
|
submoduleReachability: "failed",
|
|
115696
115923
|
status: "blocked_review",
|
|
115697
|
-
reason:
|
|
115924
|
+
reason: blockedReason,
|
|
115698
115925
|
nextStep
|
|
115699
115926
|
}
|
|
115700
115927
|
} };
|
|
@@ -115811,7 +116038,8 @@ ${hintLines.join("\n")}` : "",
|
|
|
115811
116038
|
const { meshId, nodeId, args, repoRoot, baseHead, node, branch, baseBranch, sourceNode, validationSummary, patchEquivalence, submoduleReachability, mesh, refineStages, execFileAsync: execFileAsync6 } = ctx;
|
|
115812
116039
|
const leaseKey = `${repoRoot}::${baseBranch}`;
|
|
115813
116040
|
const leaseHolder = buildRefineJobKey(self, meshId, nodeId);
|
|
115814
|
-
|
|
116041
|
+
const alreadyHeld = self.refineBaseLeases.get(leaseKey) === leaseHolder;
|
|
116042
|
+
if (!alreadyHeld && self.refineBaseLeases.has(leaseKey)) {
|
|
115815
116043
|
recordMeshRefineStage(refineStages, "base_lease", "skipped", Date.now(), {
|
|
115816
116044
|
leaseKey,
|
|
115817
116045
|
heldBy: self.refineBaseLeases.get(leaseKey),
|
|
@@ -115838,11 +116066,11 @@ ${hintLines.join("\n")}` : "",
|
|
|
115838
116066
|
}
|
|
115839
116067
|
} };
|
|
115840
116068
|
}
|
|
115841
|
-
self.refineBaseLeases.set(leaseKey, leaseHolder);
|
|
116069
|
+
if (!alreadyHeld) self.refineBaseLeases.set(leaseKey, leaseHolder);
|
|
115842
116070
|
try {
|
|
115843
116071
|
return await runRefineMergeAndFinalizeLocked(self, ctx);
|
|
115844
116072
|
} finally {
|
|
115845
|
-
if (self.refineBaseLeases.get(leaseKey) === leaseHolder) self.refineBaseLeases.delete(leaseKey);
|
|
116073
|
+
if (!alreadyHeld && self.refineBaseLeases.get(leaseKey) === leaseHolder) self.refineBaseLeases.delete(leaseKey);
|
|
115846
116074
|
}
|
|
115847
116075
|
}
|
|
115848
116076
|
async function runRefineMergeAndFinalizeLocked(self, ctx) {
|