@algosuite/vo-mcp 0.2.0-beta.40 → 0.2.0-beta.43
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/agent-auth-probe-cli.mjs +13 -2
- package/dist/cli.js +9 -2
- package/dist/cli.js.map +2 -2
- package/dist/runner-cli.js +119 -22
- package/dist/runner-cli.js.map +3 -3
- package/dist/runner-supervisor.js +13 -2
- package/dist/runner-supervisor.js.map +2 -2
- package/dist/set-key-cli.js +12 -4
- package/dist/set-key-cli.js.map +2 -2
- package/package.json +1 -1
package/dist/runner-cli.js
CHANGED
|
@@ -2416,7 +2416,7 @@ async function fetchInstallationToken({ req, required = false, readOnly = false,
|
|
|
2416
2416
|
const json = await res.json();
|
|
2417
2417
|
if (!json || !json.token) return fail("missing token");
|
|
2418
2418
|
if (readOnly && json.scope !== "read") return fail("control plane did not confirm a read-only grant");
|
|
2419
|
-
return { token: json.token, expiresAt: json.expires_at || null };
|
|
2419
|
+
return { token: json.token, expiresAt: json.expires_at || null, ...typeof json.ci_readable === "boolean" ? { ciReadable: json.ci_readable } : {} };
|
|
2420
2420
|
} catch (err) {
|
|
2421
2421
|
if (required) throw err;
|
|
2422
2422
|
return null;
|
|
@@ -2479,7 +2479,18 @@ async function resumeCodeTaskRequest(req, taskId, { automaticRateLimit = false,
|
|
|
2479
2479
|
onUnauthorized();
|
|
2480
2480
|
throw new Error("resume unauthorized (401)");
|
|
2481
2481
|
}
|
|
2482
|
-
if (!res.ok)
|
|
2482
|
+
if (!res.ok) {
|
|
2483
|
+
let code = null;
|
|
2484
|
+
try {
|
|
2485
|
+
const body = await res.json();
|
|
2486
|
+
code = typeof body?.error === "string" ? body.error : null;
|
|
2487
|
+
} catch {
|
|
2488
|
+
}
|
|
2489
|
+
const err = new Error(`resume failed: HTTP ${res.status}${code ? ` (${code})` : ""}`);
|
|
2490
|
+
err.status = res.status;
|
|
2491
|
+
err.code = code;
|
|
2492
|
+
throw err;
|
|
2493
|
+
}
|
|
2483
2494
|
const json = await res.json();
|
|
2484
2495
|
return json && json.task ? json.task : null;
|
|
2485
2496
|
}
|
|
@@ -3921,6 +3932,12 @@ var init_agent_token_usage = __esm({
|
|
|
3921
3932
|
});
|
|
3922
3933
|
|
|
3923
3934
|
// ../../scripts/virtual-office/code-runner/claude-result-event.mjs
|
|
3935
|
+
function cappedRunLastMessage(evt, lastProgress) {
|
|
3936
|
+
const summary = String(evt?.summary || "").trim();
|
|
3937
|
+
const salvage = String(lastProgress || "").trim();
|
|
3938
|
+
if (!salvage || !CAPPED_RESULT_SUBTYPES.includes(summary)) return null;
|
|
3939
|
+
return salvage;
|
|
3940
|
+
}
|
|
3924
3941
|
function buildResultEvent(evt) {
|
|
3925
3942
|
const isError = Boolean(evt.is_error) || evt.subtype === "error_max_turns" || evt.subtype === "error_during_execution";
|
|
3926
3943
|
return {
|
|
@@ -3933,10 +3950,12 @@ function buildResultEvent(evt) {
|
|
|
3933
3950
|
modelUsage: extractModelUsage(evt)
|
|
3934
3951
|
};
|
|
3935
3952
|
}
|
|
3953
|
+
var CAPPED_RESULT_SUBTYPES;
|
|
3936
3954
|
var init_claude_result_event = __esm({
|
|
3937
3955
|
"../../scripts/virtual-office/code-runner/claude-result-event.mjs"() {
|
|
3938
3956
|
"use strict";
|
|
3939
3957
|
init_agent_token_usage();
|
|
3958
|
+
CAPPED_RESULT_SUBTYPES = Object.freeze(["error_max_budget_usd", "error_max_turns"]);
|
|
3940
3959
|
}
|
|
3941
3960
|
});
|
|
3942
3961
|
|
|
@@ -4250,7 +4269,7 @@ function runAgentTask({
|
|
|
4250
4269
|
} catch {
|
|
4251
4270
|
}
|
|
4252
4271
|
let buffer = "";
|
|
4253
|
-
let result = { ok: false, costUsd: null, costBasis, summary: "", numTurns: null, tokenUsage: null, modelUsage: null, executionStarted: false, killed: false };
|
|
4272
|
+
let result = { ok: false, costUsd: null, costBasis, summary: "", lastAgentMessage: null, numTurns: null, tokenUsage: null, modelUsage: null, executionStarted: false, killed: false };
|
|
4254
4273
|
child.once("spawn", () => {
|
|
4255
4274
|
result = { ...result, executionStarted: true };
|
|
4256
4275
|
Promise.resolve(onSpawn()).catch(() => {
|
|
@@ -4285,6 +4304,9 @@ function runAgentTask({
|
|
|
4285
4304
|
costUsd: evt.costUsd,
|
|
4286
4305
|
costBasis: result.costBasis,
|
|
4287
4306
|
summary,
|
|
4307
|
+
// A budget/turn-capped run's honest last message, kept OUT of summary (see
|
|
4308
|
+
// claude-result-event.cappedRunLastMessage) and surfaced in the PR body.
|
|
4309
|
+
lastAgentMessage: cappedRunLastMessage(evt, lastProgress),
|
|
4288
4310
|
numTurns: evt.numTurns,
|
|
4289
4311
|
// MUST be listed explicitly. This assignment spreads the PREVIOUS
|
|
4290
4312
|
// result and then names each field it carries forward, so anything
|
|
@@ -4423,6 +4445,7 @@ var init_claude_runner = __esm({
|
|
|
4423
4445
|
init_orphan_agent_reaper();
|
|
4424
4446
|
init_agent_token_usage();
|
|
4425
4447
|
init_claude_stream_event();
|
|
4448
|
+
init_claude_result_event();
|
|
4426
4449
|
init_claude_auth_check();
|
|
4427
4450
|
ClaudeRunner = class {
|
|
4428
4451
|
get enforcesBudgetCap() {
|
|
@@ -4527,7 +4550,14 @@ var init_agent_key_store = __esm({
|
|
|
4527
4550
|
"oai-compat": ["VO_CODE_RUNNER_OAI_API_KEY"],
|
|
4528
4551
|
// Sovereign local inference (Ollama / LM Studio). The key is OPTIONAL — most
|
|
4529
4552
|
// local servers need none — and exists for locally secured endpoints only.
|
|
4530
|
-
local: ["VO_CODE_RUNNER_LOCAL_API_KEY"]
|
|
4553
|
+
local: ["VO_CODE_RUNNER_LOCAL_API_KEY"],
|
|
4554
|
+
// AlgoHQ cloud consensus (ADR-002 moat plane) entitlement token. Not a model
|
|
4555
|
+
// key: it authorises the runner's `vo_consensus_judgment` / `vo_verify_answer`
|
|
4556
|
+
// tools against the moat. On an npm-installed runner the local consensus
|
|
4557
|
+
// engine is never present (it is a workspace-only package), so WITHOUT this
|
|
4558
|
+
// token every consensus call answers `unimplemented /
|
|
4559
|
+
// consensus-engine-package-not-installed` (2026-08-16 finding, task fbd8659b).
|
|
4560
|
+
moat: ["VO_ENTITLEMENT_TOKEN"]
|
|
4531
4561
|
};
|
|
4532
4562
|
PROVIDER_ALIAS = {
|
|
4533
4563
|
claude: "anthropic",
|
|
@@ -4543,7 +4573,10 @@ var init_agent_key_store = __esm({
|
|
|
4543
4573
|
"oai-compat": "oai-compat",
|
|
4544
4574
|
local: "local",
|
|
4545
4575
|
ollama: "local",
|
|
4546
|
-
lmstudio: "local"
|
|
4576
|
+
lmstudio: "local",
|
|
4577
|
+
moat: "moat",
|
|
4578
|
+
entitlement: "moat",
|
|
4579
|
+
consensus: "moat"
|
|
4547
4580
|
};
|
|
4548
4581
|
_loadTried2 = false;
|
|
4549
4582
|
}
|
|
@@ -7260,6 +7293,11 @@ var init_dispatch_onboarding = __esm({
|
|
|
7260
7293
|
});
|
|
7261
7294
|
|
|
7262
7295
|
// ../../scripts/virtual-office/code-runner/methodology-composer.mjs
|
|
7296
|
+
function openingClause(prompt) {
|
|
7297
|
+
const text = String(prompt || "").replace(UI_ROADMAP_DISPATCH_MARKER, "").trimStart();
|
|
7298
|
+
const firstSentence = text.split(/(?<=[.!?])\s|\n/u)[0] || "";
|
|
7299
|
+
return firstSentence.slice(0, 240);
|
|
7300
|
+
}
|
|
7263
7301
|
function classifyTaskShape(task) {
|
|
7264
7302
|
const prompt = String(task?.prompt || "");
|
|
7265
7303
|
for (const rule of SHAPE_RULES) {
|
|
@@ -7318,7 +7356,11 @@ var init_methodology_composer = __esm({
|
|
|
7318
7356
|
},
|
|
7319
7357
|
{
|
|
7320
7358
|
shape: "research",
|
|
7321
|
-
|
|
7359
|
+
// Live-test finding 2026-08-16 (task cbed1006): an IMPLEMENT task whose prompt
|
|
7360
|
+
// cites an audit doc ("…exactly as recommended in docs/audits/…; per the audit")
|
|
7361
|
+
// classified as research from a keyword deep in the body. Research is decided by
|
|
7362
|
+
// the OPENING clause — the same rule the design shape already applies.
|
|
7363
|
+
matches: (_task, prompt) => /\b(investigate|research|root[- ]cause|audit|diagnose|find out why|explain why)\b/iu.test(openingClause(prompt))
|
|
7322
7364
|
},
|
|
7323
7365
|
{
|
|
7324
7366
|
shape: "design",
|
|
@@ -9051,6 +9093,9 @@ function ciFixOccurrenceKey({ repo, prNumber, headSha, repairAttempt }) {
|
|
|
9051
9093
|
function coordinationRetryDue(entry, nowMs) {
|
|
9052
9094
|
return !entry.nextRetryAt || nowMs >= entry.nextRetryAt;
|
|
9053
9095
|
}
|
|
9096
|
+
function isTerminalResumeRefusal(error) {
|
|
9097
|
+
return typeof error?.code === "string" && TERMINAL_RESUME_REFUSALS.includes(error.code);
|
|
9098
|
+
}
|
|
9054
9099
|
async function scheduleCoordinationRetry({
|
|
9055
9100
|
entry,
|
|
9056
9101
|
kind,
|
|
@@ -9061,6 +9106,14 @@ async function scheduleCoordinationRetry({
|
|
|
9061
9106
|
error,
|
|
9062
9107
|
log: log2
|
|
9063
9108
|
}) {
|
|
9109
|
+
if (kind === "resume" && isTerminalResumeRefusal(error)) {
|
|
9110
|
+
entry.needsContinuation = false;
|
|
9111
|
+
entry.continuationExhausted = true;
|
|
9112
|
+
entry.continuationRefusal = error.code;
|
|
9113
|
+
entry.continuationRefusedAt = now();
|
|
9114
|
+
log2(`watch: pr #${prNumber} automatic continuation refused by the plane (${error.code}); no retry \u2014 operator may resume explicitly with a larger cap`);
|
|
9115
|
+
return;
|
|
9116
|
+
}
|
|
9064
9117
|
const errorsKey = kind === "resume" ? "resumeErrors" : "enqueueErrors";
|
|
9065
9118
|
const attemptsKey = kind === "resume" ? "resumeAttempts" : "fixAttempts";
|
|
9066
9119
|
entry[errorsKey] = (entry[errorsKey] || 0) + 1;
|
|
@@ -9080,12 +9133,23 @@ async function scheduleCoordinationRetry({
|
|
|
9080
9133
|
}
|
|
9081
9134
|
log2(`watch: pr #${prNumber} ${kind} coordination failed ${entry[errorsKey]}x; retry in ${Math.round(delay2 / 1e3)}s: ${boundedErrorMessage(error)}`);
|
|
9082
9135
|
}
|
|
9083
|
-
var MAX_BACKOFF_MS;
|
|
9136
|
+
var MAX_BACKOFF_MS, TERMINAL_RESUME_REFUSALS;
|
|
9084
9137
|
var init_watcher_coordination = __esm({
|
|
9085
9138
|
"../../scripts/virtual-office/code-runner/watcher-coordination.mjs"() {
|
|
9086
9139
|
"use strict";
|
|
9087
9140
|
init_error_message();
|
|
9088
9141
|
MAX_BACKOFF_MS = 60 * 60 * 1e3;
|
|
9142
|
+
TERMINAL_RESUME_REFUSALS = Object.freeze([
|
|
9143
|
+
"automatic_continuation_budget_too_small",
|
|
9144
|
+
"automatic_continuation_budget_required",
|
|
9145
|
+
"continuation_spend_ceiling_reached",
|
|
9146
|
+
"continuation_budget_exhausted",
|
|
9147
|
+
"continuation_spend_unmeasured",
|
|
9148
|
+
"continuation_lineage_incomplete",
|
|
9149
|
+
"continuation_lineage_invalid",
|
|
9150
|
+
"cancelled_not_automatically_resumable",
|
|
9151
|
+
"not_resumable"
|
|
9152
|
+
]);
|
|
9089
9153
|
}
|
|
9090
9154
|
});
|
|
9091
9155
|
|
|
@@ -9201,7 +9265,7 @@ async function adoptPrOpenedTasks(tasks, {
|
|
|
9201
9265
|
if (operators.size > 0 && !operators.has(task.operator_id)) continue;
|
|
9202
9266
|
const key = watcherKey(state, task.repo, task.pr_number);
|
|
9203
9267
|
if (state[key]) continue;
|
|
9204
|
-
const partial = String(task.result || "").
|
|
9268
|
+
const partial = String(task.result || "").includes(PARTIAL_PR_CONTINUATION_MARKER);
|
|
9205
9269
|
const repairChain = task.repair_chain ?? {
|
|
9206
9270
|
root_pr_number: task.repair_pr_number ?? task.pr_number,
|
|
9207
9271
|
attempt: task.repair_pr_number ? 1 : 0,
|
|
@@ -9240,8 +9304,10 @@ var init_watcher_adoption = __esm({
|
|
|
9240
9304
|
});
|
|
9241
9305
|
|
|
9242
9306
|
// ../../scripts/virtual-office/code-runner/watcher-github-token.mjs
|
|
9243
|
-
function makeWatcherTokenProvider(client, { required = true, allowAmbient = false, now = () => Date.now()
|
|
9307
|
+
function makeWatcherTokenProvider(client, { required = true, allowAmbient = false, now = () => Date.now(), log: log2 = () => {
|
|
9308
|
+
} } = {}) {
|
|
9244
9309
|
const cache = /* @__PURE__ */ new Map();
|
|
9310
|
+
let ciUnreadableLoggedAt = null;
|
|
9245
9311
|
return async (repo) => {
|
|
9246
9312
|
const key = String(repo).toLowerCase();
|
|
9247
9313
|
const prior = cache.get(key);
|
|
@@ -9251,6 +9317,10 @@ function makeWatcherTokenProvider(client, { required = true, allowAmbient = fals
|
|
|
9251
9317
|
if (allowAmbient) return null;
|
|
9252
9318
|
throw new Error(`GitHub App read token unavailable for ${repo}`);
|
|
9253
9319
|
}
|
|
9320
|
+
if (result.ciReadable === false && (ciUnreadableLoggedAt === null || now() - ciUnreadableLoggedAt > 6 * 60 * 60 * 1e3)) {
|
|
9321
|
+
ciUnreadableLoggedAt = now();
|
|
9322
|
+
log2(`watch: the plane minted a read token for ${repo} WITHOUT CI read (ci_readable=false \u2014 the GitHub App installation has not accepted checks:read/statuses:read); PR CI stays unreadable until the operator accepts the App permission update`);
|
|
9323
|
+
}
|
|
9254
9324
|
cache.set(key, { token: result.token, at: now() });
|
|
9255
9325
|
return result.token;
|
|
9256
9326
|
};
|
|
@@ -9298,25 +9368,47 @@ var init_ci_fix_prompt = __esm({
|
|
|
9298
9368
|
});
|
|
9299
9369
|
|
|
9300
9370
|
// ../../scripts/virtual-office/code-runner/pr-watcher-github.mjs
|
|
9301
|
-
|
|
9302
|
-
const
|
|
9371
|
+
function isCiUnreadableError(err) {
|
|
9372
|
+
const text = `${err?.message || ""}
|
|
9373
|
+
${err?.stderr || ""}`;
|
|
9374
|
+
return /Resource not accessible by integration/i.test(text) && /statusCheckRollup/i.test(text);
|
|
9375
|
+
}
|
|
9376
|
+
function noteCiUnreadable(log2) {
|
|
9377
|
+
const now = Date.now();
|
|
9378
|
+
if (now - lastDiagnosticAt < DIAGNOSTIC_INTERVAL_MS) return;
|
|
9379
|
+
lastDiagnosticAt = now;
|
|
9380
|
+
log2("watch: CI status is UNREADABLE with the GitHub App read token (the installation has not granted checks:read/statuses:read \u2014 accept the App permission update on the installation). Auto-fix and merge stay dormant; untrack/resume keep working on state alone.");
|
|
9381
|
+
}
|
|
9382
|
+
async function ghViewPr(prNumber, repo, { githubToken, log: log2 = (m) => console.error(`[vo-runner] ${m}`), run = runProcess2 } = {}) {
|
|
9383
|
+
const env2 = githubToken ? { ...process.env, GH_TOKEN: githubToken } : process.env;
|
|
9384
|
+
const view = async (fields) => JSON.parse(await run("gh", [
|
|
9303
9385
|
"pr",
|
|
9304
9386
|
"view",
|
|
9305
9387
|
String(prNumber),
|
|
9306
9388
|
"-R",
|
|
9307
9389
|
repo,
|
|
9308
9390
|
"--json",
|
|
9309
|
-
|
|
9310
|
-
], {
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
})
|
|
9314
|
-
|
|
9391
|
+
fields
|
|
9392
|
+
], { timeout: 3e4, env: env2 }) || "{}");
|
|
9393
|
+
try {
|
|
9394
|
+
return await view(VIEW_FIELDS_WITH_CI);
|
|
9395
|
+
} catch (err) {
|
|
9396
|
+
if (!isCiUnreadableError(err)) throw err;
|
|
9397
|
+
noteCiUnreadable(log2);
|
|
9398
|
+
const withoutCi = await view(VIEW_FIELDS_WITHOUT_CI);
|
|
9399
|
+
return { ...withoutCi, statusCheckRollup: null, ciUnreadable: true, ciUnreadableReason: CI_UNREADABLE_REASON };
|
|
9400
|
+
}
|
|
9315
9401
|
}
|
|
9402
|
+
var VIEW_FIELDS_WITH_CI, VIEW_FIELDS_WITHOUT_CI, CI_UNREADABLE_REASON, DIAGNOSTIC_INTERVAL_MS, lastDiagnosticAt;
|
|
9316
9403
|
var init_pr_watcher_github = __esm({
|
|
9317
9404
|
"../../scripts/virtual-office/code-runner/pr-watcher-github.mjs"() {
|
|
9318
9405
|
"use strict";
|
|
9319
9406
|
init_process_runner2();
|
|
9407
|
+
VIEW_FIELDS_WITH_CI = "state,statusCheckRollup,headRefName,headRefOid,url,isDraft,mergeStateStatus";
|
|
9408
|
+
VIEW_FIELDS_WITHOUT_CI = "state,headRefName,headRefOid,url,isDraft,mergeStateStatus";
|
|
9409
|
+
CI_UNREADABLE_REASON = "app_token_missing_checks_read";
|
|
9410
|
+
DIAGNOSTIC_INTERVAL_MS = 30 * 60 * 1e3;
|
|
9411
|
+
lastDiagnosticAt = 0;
|
|
9320
9412
|
}
|
|
9321
9413
|
});
|
|
9322
9414
|
|
|
@@ -9377,7 +9469,7 @@ function parsePrCiStatus(view) {
|
|
|
9377
9469
|
else if (st !== "SUCCESS") pending = true;
|
|
9378
9470
|
}
|
|
9379
9471
|
}
|
|
9380
|
-
const ci = failedChecks.length > 0 ? "failing" : pending ? "pending" : "passing";
|
|
9472
|
+
const ci = view?.ciUnreadable ? "unknown" : failedChecks.length > 0 ? "failing" : pending ? "pending" : "passing";
|
|
9381
9473
|
return {
|
|
9382
9474
|
state,
|
|
9383
9475
|
ci,
|
|
@@ -9576,7 +9668,7 @@ async function runWatchCycleUnlocked({
|
|
|
9576
9668
|
try {
|
|
9577
9669
|
if (typeof reportBlocker === "function") await reportBlocker({
|
|
9578
9670
|
taskId: entry.taskId,
|
|
9579
|
-
message: entry.continuationExhausted ? `PR #${prNumber} remains a partial draft after its bounded automatic continuation; watcher is still monitoring and operator review is required before more spend.` : `PR #${prNumber} remains failing after ${entry.fixAttempts || 0} bounded repair attempt(s); watcher is still monitoring and operator review is required.`
|
|
9671
|
+
message: entry.continuationExhausted ? `PR #${prNumber} remains a partial draft after its bounded automatic continuation${entry.continuationRefusal ? ` (plane refused: ${entry.continuationRefusal})` : ""}; watcher is still monitoring and operator review is required before more spend.` : `PR #${prNumber} remains failing after ${entry.fixAttempts || 0} bounded repair attempt(s); watcher is still monitoring and operator review is required.`
|
|
9580
9672
|
});
|
|
9581
9673
|
entry.escalatedAt = now();
|
|
9582
9674
|
escalated += 1;
|
|
@@ -9611,9 +9703,10 @@ function makeWatchRunner({
|
|
|
9611
9703
|
}) {
|
|
9612
9704
|
const tokenForRepo = makeWatcherTokenProvider(client, {
|
|
9613
9705
|
required: !allowAmbientGithub,
|
|
9614
|
-
allowAmbient: allowAmbientGithub
|
|
9706
|
+
allowAmbient: allowAmbientGithub,
|
|
9707
|
+
log: log2
|
|
9615
9708
|
});
|
|
9616
|
-
const watchView = viewPr === ghViewPr ? async (prNumber, repo) => ghViewPr(prNumber, repo, { githubToken: await tokenForRepo(repo) }) : viewPr;
|
|
9709
|
+
const watchView = viewPr === ghViewPr ? async (prNumber, repo) => ghViewPr(prNumber, repo, { githubToken: await tokenForRepo(repo), log: log2 }) : viewPr;
|
|
9617
9710
|
return async () => {
|
|
9618
9711
|
const openTasks = typeof client.listPrOpenedTasks === "function" ? await client.listPrOpenedTasks() : [];
|
|
9619
9712
|
const adopted = await adoptPrOpenedTasks(openTasks, {
|
|
@@ -11526,6 +11619,9 @@ function buildPrBody(task, run, files, { armAutoMerge = false } = {}) {
|
|
|
11526
11619
|
"",
|
|
11527
11620
|
redactSecrets(String(run.summary || "")).slice(0, 2e3),
|
|
11528
11621
|
"",
|
|
11622
|
+
// A budget/turn-capped run ends with no assistant text (summary = the bare
|
|
11623
|
+
// subtype); its LAST message is the honest report the operator needs.
|
|
11624
|
+
...run.lastAgentMessage ? ["### Last agent message before the cap", "", redactSecrets(String(run.lastAgentMessage)).slice(0, 2e3), ""] : [],
|
|
11529
11625
|
"---",
|
|
11530
11626
|
armAutoMerge ? "_Opened by the AlgoHQ code-runner daemon. After CI passes, the watcher must obtain a durable consensus receipt and merge the exact verified SHA._" : "_Opened by the AlgoHQ code-runner daemon. This PR awaits the verify-before-act gate / operator review \u2014 it is NOT auto-merged._"
|
|
11531
11627
|
].filter((l) => l !== "").join("\n");
|
|
@@ -12986,6 +13082,7 @@ async function findPreservedRecovery(task, {
|
|
|
12986
13082
|
const resumedFrom = /^[0-9a-f-]{36}$/iu.test(String(task.resumed_from || "")) ? String(task.resumed_from).toLowerCase() : null;
|
|
12987
13083
|
const originalTaskId = recoveryTaskId(task.prompt) ?? resumedFrom;
|
|
12988
13084
|
if (!originalTaskId) return null;
|
|
13085
|
+
if (task.pr_branch && !recoveryTaskId(task.prompt)) return null;
|
|
12989
13086
|
for (const ledgerPath of recoveryLedgerCandidates(task.repo, clonesRoot2)) {
|
|
12990
13087
|
const entries = await readLedger(ledgerPath, readFile5);
|
|
12991
13088
|
const resolved = entries.some((entry) => RESOLVED_RECOVERY_TYPES.has(entry.type) && entry.taskId === originalTaskId);
|
|
@@ -13101,7 +13198,7 @@ function reportsBlocker(summary) {
|
|
|
13101
13198
|
return /\btask remains\s+(?:\*\*)?BLOCKED\b/i.test(text) || /(?:^|\n)\s*(?:#{1,6}\s*)?(?:\*\*)?(?:host-recovery\s+)?(?:result|outcome|status)\s*:\s*(?:\*\*)?BLOCKED\b/im.test(text);
|
|
13102
13199
|
}
|
|
13103
13200
|
function isMaxTurnExhaustion(run = {}, maxTurns) {
|
|
13104
|
-
const summary = String(run.summary || "").trim().toLowerCase();
|
|
13201
|
+
const summary = String(run.summary || "").trim().toLowerCase().split("\n")[0].trim();
|
|
13105
13202
|
if (summary === "error_max_turns" || summary === "inconclusive_max_turns") return true;
|
|
13106
13203
|
return Number.isInteger(maxTurns) && maxTurns > 0 && Number.isInteger(run.numTurns) && run.numTurns > maxTurns;
|
|
13107
13204
|
}
|