@quantiya/codevibe-core 2.0.87 → 2.0.89
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.
|
@@ -23604,7 +23604,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23604
23604
|
throw logger.warn("[AppSyncClient] explicit review-scope reset rejected by old backend schema; failing closed", {
|
|
23605
23605
|
gateId: input.gateId,
|
|
23606
23606
|
taskId: input.taskId
|
|
23607
|
-
}), err;
|
|
23607
|
+
}), err.reviewScopeResetUnsupported = !0, err;
|
|
23608
23608
|
logger.warn("[AppSyncClient] submitImplementorOutput additive fields rejected by backend schema; retrying legacy input", {
|
|
23609
23609
|
gateId: input.gateId,
|
|
23610
23610
|
taskId: input.taskId,
|
|
@@ -23621,7 +23621,10 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23621
23621
|
};
|
|
23622
23622
|
response = await this.graphqlRequest(mutations.submitImplementorOutput, retryVariables);
|
|
23623
23623
|
}
|
|
23624
|
-
|
|
23624
|
+
let parsed = this.#parseOrchestrationResult(response.data?.submitImplementorOutput, "submitImplementorOutput");
|
|
23625
|
+
if (typeof parsed.gateId != "string" || parsed.gateId.length === 0 || typeof parsed.workflowState != "string" || parsed.workflowState.length === 0)
|
|
23626
|
+
throw new Error("submitImplementorOutput: result missing string `gateId` / `workflowState`");
|
|
23627
|
+
return { gateId: parsed.gateId, workflowState: parsed.workflowState };
|
|
23625
23628
|
}
|
|
23626
23629
|
/**
|
|
23627
23630
|
* §3.C.22 — submit one reviewer seat's verdict. The full `ReviewerVerdict`
|
|
@@ -23679,7 +23682,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23679
23682
|
throw new Error("getReviewerPrompt: gateId is required");
|
|
23680
23683
|
if (!Number.isInteger(seatId) || seatId < 0)
|
|
23681
23684
|
throw new Error("getReviewerPrompt: seatId must be a non-negative integer");
|
|
23682
|
-
let response = await this.graphqlRequest(queries.getReviewerPrompt, { gateId, seatId }), parsed = this.#
|
|
23685
|
+
let response = await this.graphqlRequest(queries.getReviewerPrompt, { gateId, seatId }), parsed = this.#parseOrchestrationResult(response.data?.getReviewerPrompt, "getReviewerPrompt");
|
|
23683
23686
|
if (!parsed.encPrompt || typeof parsed.encPrompt.ciphertextB64 != "string")
|
|
23684
23687
|
throw new Error("getReviewerPrompt: response missing encPrompt.ciphertextB64");
|
|
23685
23688
|
let prompt = cryptoService.decryptContent(parsed.encPrompt.ciphertextB64, sessionKeyBase64);
|
|
@@ -23751,7 +23754,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23751
23754
|
* key.
|
|
23752
23755
|
*/
|
|
23753
23756
|
async getClassBSigningPublicKey() {
|
|
23754
|
-
let response = await this.graphqlRequest(queries.getClassBSigningPublicKey, {}), parsed = this.#
|
|
23757
|
+
let response = await this.graphqlRequest(queries.getClassBSigningPublicKey, {}), parsed = this.#parseOrchestrationResult(
|
|
23755
23758
|
response.data?.getClassBSigningPublicKey,
|
|
23756
23759
|
"getClassBSigningPublicKey"
|
|
23757
23760
|
);
|
|
@@ -23767,7 +23770,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23767
23770
|
async getInReviewAssignments(taskId) {
|
|
23768
23771
|
if (typeof taskId != "string" || taskId.length === 0)
|
|
23769
23772
|
throw new Error("getInReviewAssignments: taskId is required");
|
|
23770
|
-
let response = await this.graphqlRequest(queries.getInReviewAssignments, { taskId }), parsed = this.#
|
|
23773
|
+
let response = await this.graphqlRequest(queries.getInReviewAssignments, { taskId }), parsed = this.#parseOrchestrationResult(
|
|
23771
23774
|
response.data?.getInReviewAssignments,
|
|
23772
23775
|
"getInReviewAssignments"
|
|
23773
23776
|
);
|
|
@@ -23785,7 +23788,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23785
23788
|
async getTaskGroupTracks(taskGroupId) {
|
|
23786
23789
|
if (typeof taskGroupId != "string" || taskGroupId.length === 0)
|
|
23787
23790
|
throw new Error("getTaskGroupTracks: taskGroupId is required");
|
|
23788
|
-
let response = await this.graphqlRequest(queries.getTaskGroupTracks, { taskGroupId }), parsed = this.#
|
|
23791
|
+
let response = await this.graphqlRequest(queries.getTaskGroupTracks, { taskGroupId }), parsed = this.#parseOrchestrationResult(
|
|
23789
23792
|
response.data?.getTaskGroupTracks,
|
|
23790
23793
|
"getTaskGroupTracks"
|
|
23791
23794
|
);
|
|
@@ -23804,7 +23807,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23804
23807
|
async getInFlightTeamTracks(sessionId) {
|
|
23805
23808
|
if (typeof sessionId != "string" || sessionId.length === 0)
|
|
23806
23809
|
throw new Error("getInFlightTeamTracks: sessionId is required");
|
|
23807
|
-
let response = await this.graphqlRequest(queries.getInFlightTeamTracks, { sessionId }), parsed = this.#
|
|
23810
|
+
let response = await this.graphqlRequest(queries.getInFlightTeamTracks, { sessionId }), parsed = this.#parseOrchestrationResult(
|
|
23808
23811
|
response.data?.getInFlightTeamTracks,
|
|
23809
23812
|
"getInFlightTeamTracks"
|
|
23810
23813
|
);
|
|
@@ -23825,7 +23828,7 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23825
23828
|
async getTaskGroupStatus(taskGroupId) {
|
|
23826
23829
|
if (typeof taskGroupId != "string" || taskGroupId.length === 0)
|
|
23827
23830
|
throw new Error("getTaskGroupStatus: taskGroupId is required");
|
|
23828
|
-
let response = await this.graphqlRequest(queries.getTaskGroupStatus, { taskGroupId }), parsed = this.#
|
|
23831
|
+
let response = await this.graphqlRequest(queries.getTaskGroupStatus, { taskGroupId }), parsed = this.#parseOrchestrationResult(
|
|
23829
23832
|
response.data?.getTaskGroupStatus,
|
|
23830
23833
|
"getTaskGroupStatus"
|
|
23831
23834
|
);
|
|
@@ -23989,7 +23992,11 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
23989
23992
|
}
|
|
23990
23993
|
/**
|
|
23991
23994
|
* P46b (ID-16) — parse an orchestration Lambda AWSJSON result and surface the
|
|
23992
|
-
* handler's `{errorType, errorMessage}` envelope as a thrown error.
|
|
23995
|
+
* handler's `{errorType, errorMessage}` envelope as a thrown error. SB-67: every read that went through a raw
|
|
23996
|
+
* `#parseAwsJson` now goes through here — read raw, the envelope was data (a hang on submit, an empty list on the
|
|
23997
|
+
* recovery reads). Reads parsed by hand or by `coerceAwsJsonObject` (createTaskGroup, submitMergeGateVerdict,
|
|
23998
|
+
* submitTrackVerificationOutcome, claimGroupDecision, getTaskReviewSummary) check a required field and throw an
|
|
23999
|
+
* untyped error on an envelope.
|
|
23993
24000
|
*/
|
|
23994
24001
|
#parseOrchestrationResult(raw, op) {
|
|
23995
24002
|
let parsed = this.#parseAwsJson(raw, op);
|
|
@@ -25282,11 +25289,23 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
25282
25289
|
sessionId,
|
|
25283
25290
|
lastHeartbeatAt: heartbeatAt
|
|
25284
25291
|
});
|
|
25285
|
-
|
|
25292
|
+
if (this.heartbeatTokens.get(sessionId) !== token4 || refreshed.status !== "ACTIVE" /* ACTIVE */ && (await this.updateSession({
|
|
25286
25293
|
sessionId,
|
|
25287
25294
|
lastHeartbeatAt: heartbeatAt,
|
|
25288
25295
|
status: "ACTIVE" /* ACTIVE */
|
|
25289
|
-
}), this.heartbeatTokens.get(sessionId) !== token4)
|
|
25296
|
+
}), this.heartbeatTokens.get(sessionId) !== token4))
|
|
25297
|
+
return "stopped";
|
|
25298
|
+
if (this.syncDisplayListeners.size > 0 && this.authenticated && this.currentUserId) {
|
|
25299
|
+
let userId = this.currentUserId;
|
|
25300
|
+
if (Array.from(this.syncDisplayListeners).some(
|
|
25301
|
+
(entry5) => entry5.userId === userId
|
|
25302
|
+
) && !this.companionSyncStatusSnapshot(userId)) {
|
|
25303
|
+
let refreshAbort = new AbortController(), refreshDeadline = setTimeout(() => refreshAbort.abort(), 4500);
|
|
25304
|
+
refreshDeadline.unref?.(), this.refreshCompanionSyncDisplayOnMaintenance(userId, refreshAbort.signal).catch(() => {
|
|
25305
|
+
}).finally(() => clearTimeout(refreshDeadline));
|
|
25306
|
+
}
|
|
25307
|
+
}
|
|
25308
|
+
return logger.debug("[AppSyncClient] Heartbeat sent", { sessionId }), "confirmed";
|
|
25290
25309
|
} catch (error) {
|
|
25291
25310
|
return logger.warn("[AppSyncClient] Heartbeat failed", { sessionId, error }), isRetiredSessionError(error) ? "retired" : "failed";
|
|
25292
25311
|
}
|
|
@@ -28790,22 +28809,43 @@ var LOCAL_GEMMA_ALLOWED_OUTPUT_KEYS = /* @__PURE__ */ new Set([
|
|
|
28790
28809
|
// would throw "included unsupported keys" on every browse decision.
|
|
28791
28810
|
"browseUrls",
|
|
28792
28811
|
"browseQuery"
|
|
28793
|
-
]), LOCAL_GEMMA_NULLABLE_OUTPUT_KEYS = ["clarifying_question", "advisory_summary", "browseUrls", "browseQuery"];
|
|
28794
|
-
function
|
|
28812
|
+
]), LOCAL_GEMMA_NULLABLE_OUTPUT_KEYS = ["clarifying_question", "advisory_summary", "browseUrls", "browseQuery"], LOCAL_GEMMA_DECISION_REQUIRED_KEYS = ["rationale", "clarifying_question", "advisory_summary", "browseUrls", "browseQuery", "action"], LOCAL_GEMMA_FIELD_CARRYING_ACTIONS = /* @__PURE__ */ new Set(["browse", "ask_user", "advisory_response"]);
|
|
28813
|
+
function decisionBranch(actions, fields) {
|
|
28795
28814
|
return {
|
|
28796
28815
|
type: "object",
|
|
28797
28816
|
properties: {
|
|
28798
28817
|
rationale: { type: "string" },
|
|
28799
|
-
clarifying_question:
|
|
28800
|
-
advisory_summary:
|
|
28801
|
-
browseUrls:
|
|
28802
|
-
browseQuery:
|
|
28803
|
-
action: { type: "string", enum:
|
|
28818
|
+
clarifying_question: fields.clarifying_question,
|
|
28819
|
+
advisory_summary: fields.advisory_summary,
|
|
28820
|
+
browseUrls: fields.browseUrls,
|
|
28821
|
+
browseQuery: fields.browseQuery,
|
|
28822
|
+
action: { type: "string", enum: actions }
|
|
28804
28823
|
},
|
|
28805
|
-
required: [
|
|
28824
|
+
required: [...LOCAL_GEMMA_DECISION_REQUIRED_KEYS],
|
|
28806
28825
|
additionalProperties: !1
|
|
28807
28826
|
};
|
|
28808
28827
|
}
|
|
28828
|
+
function buildLocalGemmaDecisionJsonSchema() {
|
|
28829
|
+
let nul = { type: "null" }, otherActions = [...localGemmaAllowedActions()].filter((a) => !LOCAL_GEMMA_FIELD_CARRYING_ACTIONS.has(a));
|
|
28830
|
+
return {
|
|
28831
|
+
anyOf: [
|
|
28832
|
+
decisionBranch(["browse"], {
|
|
28833
|
+
clarifying_question: nul,
|
|
28834
|
+
advisory_summary: nul,
|
|
28835
|
+
browseUrls: { type: ["array", "null"], items: { type: "string" } },
|
|
28836
|
+
browseQuery: { type: ["string", "null"] }
|
|
28837
|
+
}),
|
|
28838
|
+
decisionBranch(["ask_user"], { clarifying_question: { type: "string" }, advisory_summary: nul, browseUrls: nul, browseQuery: nul }),
|
|
28839
|
+
decisionBranch(["advisory_response"], {
|
|
28840
|
+
clarifying_question: nul,
|
|
28841
|
+
advisory_summary: { type: ["string", "null"] },
|
|
28842
|
+
browseUrls: nul,
|
|
28843
|
+
browseQuery: nul
|
|
28844
|
+
}),
|
|
28845
|
+
decisionBranch(otherActions, { clarifying_question: nul, advisory_summary: nul, browseUrls: nul, browseQuery: nul })
|
|
28846
|
+
]
|
|
28847
|
+
};
|
|
28848
|
+
}
|
|
28809
28849
|
var LOCAL_GEMMA_DECISION_JSON_SCHEMA = buildLocalGemmaDecisionJsonSchema();
|
|
28810
28850
|
var LOCAL_GEMMA_MAX_USER_PROMPT_CHARS = 4e3, LOCAL_GEMMA_MAX_CLARIFICATIONS = 4, LOCAL_GEMMA_MAX_CLARIFICATION_QUESTION_CHARS = 300, LOCAL_GEMMA_MAX_CLARIFICATION_ANSWER_CHARS = 900, LOCAL_GEMMA_MAX_CANONICAL_CONTEXT_CHARS = 6e3, LOCAL_GEMMA_MAX_RENDERED_PROMPT_CHARS = 24e3;
|
|
28811
28851
|
function truncatePlannerTextPreservingEnds(text2, maxChars) {
|
|
@@ -29163,7 +29203,7 @@ function parseLocalGemmaPlannerDecision(raw) {
|
|
|
29163
29203
|
throw validationError("Gemma planner browse output must not include advisory_summary or clarifying_question", obj, canDegrade);
|
|
29164
29204
|
} else {
|
|
29165
29205
|
let hasRealBrowseUrls = Array.isArray(obj.browseUrls) && obj.browseUrls.some(isRealHttpUrl), hasRealBrowseQuery = typeof obj.browseQuery == "string" && obj.browseQuery.trim().length > 0, userFacingPlannerText = typeof obj.advisory_summary == "string" && obj.advisory_summary.trim().length > 0 || typeof obj.clarifying_question == "string" && obj.clarifying_question.trim().length > 0, taskStartingAction = obj.action === "start_task" || obj.action === "team_decompose";
|
|
29166
|
-
if ((hasRealBrowseUrls || hasRealBrowseQuery) && (userFacingPlannerText || taskStartingAction || obj.action === "refuse" || obj.action === "ask_user"))
|
|
29206
|
+
if ((hasRealBrowseUrls || hasRealBrowseQuery) && (userFacingPlannerText || taskStartingAction || obj.action === "advisory_response" && hasRealBrowseQuery || obj.action === "refuse" || obj.action === "ask_user"))
|
|
29167
29207
|
throw new PlannerOutputUnparseableError(
|
|
29168
29208
|
"Gemma planner non-browse output must not combine browse fields with user-facing or task-starting planner output",
|
|
29169
29209
|
{ kind: "validation" }
|
|
@@ -67655,6 +67695,9 @@ function classifyImplementorRoundFailure(err) {
|
|
|
67655
67695
|
return AUTHORITY_REFUSAL_LABEL[err.refusal.category] ?? "the implementor was refused authority";
|
|
67656
67696
|
if (err instanceof StaleShadowRootError)
|
|
67657
67697
|
return `the recorded workspace-copy folder ${err.stalePath} is missing and its contents could not be accounted for (they may have been moved). Run \`codevibe doctor\` to review and clear it`;
|
|
67698
|
+
let engine = err;
|
|
67699
|
+
if (engine && engine.name === "AppSyncGraphQLError" && typeof engine.errorType == "string")
|
|
67700
|
+
return engine.errorType === "ClientError" && String(engine.responseMessage ?? "").startsWith("payload too large") ? "the change is too large to submit for review" : "the review service rejected the submission";
|
|
67658
67701
|
let msg = err instanceof Error ? err.message.toLowerCase() : "";
|
|
67659
67702
|
return msg.includes("enoent") || msg.includes("spawn") || msg.includes("command not found") || msg.includes("not installed") ? "the coding agent could not be started" : "an unexpected error occurred";
|
|
67660
67703
|
}
|
|
@@ -68777,6 +68820,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
68777
68820
|
this.inFlightImplementorGates = /* @__PURE__ */ new Set();
|
|
68778
68821
|
/** Gates whose implementor output has been submitted. */
|
|
68779
68822
|
this.submittedOutputGates = /* @__PURE__ */ new Set();
|
|
68823
|
+
/**
|
|
68824
|
+
* SB-67 (Stage 1 R1-F1) — gates whose round failed after its submission started. The engine can dispatch reviewers
|
|
68825
|
+
* before it reports an error; a late dispatch for one of these gates belongs to a discarded task and is dropped.
|
|
68826
|
+
*/
|
|
68827
|
+
this.abandonedSubmitGates = /* @__PURE__ */ new Set();
|
|
68780
68828
|
/**
|
|
68781
68829
|
* PHASE-CP-10-MIN (#585) #C10M-16 / Codex-H1 — the per-task ACTIVE
|
|
68782
68830
|
* implementor context. `runImplementorRound` populates it at spawn (wiring
|
|
@@ -71382,7 +71430,13 @@ ${section}`);
|
|
|
71382
71430
|
reviewScopeReset: args.reviewScopeReset
|
|
71383
71431
|
});
|
|
71384
71432
|
if (args.reviewScopeReset && this.reviewScopeResetTasks.delete(args.taskId), this.teamRunIsHalted(args.teamAuthority)) return;
|
|
71385
|
-
if (this.submittedOutputGates.add(gateId), result &&
|
|
71433
|
+
if (this.submittedOutputGates.add(gateId), result?.replayedAfterEngineError === !0 && result.workflowState === "halted" && !isEngineEmptyArtifact(files))
|
|
71434
|
+
logger.info("[QuorumLoop] submission confirmed by the engine replay of an already-resolved gate", {
|
|
71435
|
+
gateId,
|
|
71436
|
+
taskId: args.taskId,
|
|
71437
|
+
workflowState: result.workflowState
|
|
71438
|
+
});
|
|
71439
|
+
else if (result && (result.workflowState === "halted" || result.workflowState === "idle")) {
|
|
71386
71440
|
let crashedEmpty = files.length === 0 && exit.exitCode !== 0, reason = files.length === 0 ? crashedEmpty ? "The coding agent exited with an error before making any changes \u2014 nothing to review. Re-run the task; if this repeats, check the desktop log." : "The implementor produced no changes \u2014 nothing to review." : "The task was halted before review (no reviewer quorum ran).";
|
|
71387
71441
|
(crashedEmpty ? logger.warn.bind(logger) : logger.info.bind(logger))("[QuorumLoop] execute-first born-halt surfaced synchronously (#EF-1)", {
|
|
71388
71442
|
gateId,
|
|
@@ -71398,7 +71452,11 @@ ${section}`);
|
|
|
71398
71452
|
}
|
|
71399
71453
|
} catch (err) {
|
|
71400
71454
|
if (this.teamRunIsHalted(args.teamAuthority)) return;
|
|
71401
|
-
if (
|
|
71455
|
+
if (
|
|
71456
|
+
// SB-67 (Stage 2 R1-F2): only an implementor failure can be a provider quota; once the submission started,
|
|
71457
|
+
// an error is the engine's (its own `HTTP 429/503` text must not read as the coding agent's usage limit).
|
|
71458
|
+
!submissionStarted && classifyImplementorQuotaFailure(void 0, err.message ?? "")
|
|
71459
|
+
) {
|
|
71402
71460
|
logger.info("[QuorumLoop] implementor round threw a quota error \u2014 continuation fork (defensive)", {
|
|
71403
71461
|
gateId,
|
|
71404
71462
|
taskId: args.taskId
|
|
@@ -71416,8 +71474,8 @@ ${section}`);
|
|
|
71416
71474
|
});
|
|
71417
71475
|
let reason = classifyImplementorRoundFailure(err);
|
|
71418
71476
|
this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`);
|
|
71419
|
-
let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId);
|
|
71420
|
-
this.emitProgress(
|
|
71477
|
+
let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId) && err?.reviewScopeResetUnsupported === !0;
|
|
71478
|
+
submissionStarted && !preserveResetForRetry && this.abandonedSubmitGates.add(gateId), this.emitProgress(
|
|
71421
71479
|
{
|
|
71422
71480
|
phase: "round_failed",
|
|
71423
71481
|
round: args.roundNumber,
|
|
@@ -73158,10 +73216,10 @@ ${section}`);
|
|
|
73158
73216
|
* error propagates (the caller surfaces it fail-closed).
|
|
73159
73217
|
*/
|
|
73160
73218
|
async submitImplementorOutputWithRetry(args) {
|
|
73161
|
-
let lastErr = null;
|
|
73219
|
+
let lastErr = null, replayedAfterEngineError = !1;
|
|
73162
73220
|
for (let attempt = 0; attempt < SUBMIT_OUTPUT_MAX_ATTEMPTS; attempt++)
|
|
73163
73221
|
try {
|
|
73164
|
-
|
|
73222
|
+
let result = await this.deps.appsyncClient.submitImplementorOutput(
|
|
73165
73223
|
{
|
|
73166
73224
|
taskId: args.taskId,
|
|
73167
73225
|
gateId: args.gateId,
|
|
@@ -73173,8 +73231,9 @@ ${section}`);
|
|
|
73173
73231
|
},
|
|
73174
73232
|
args.sessionKey
|
|
73175
73233
|
);
|
|
73234
|
+
return replayedAfterEngineError ? { ...result, replayedAfterEngineError } : result;
|
|
73176
73235
|
} catch (err) {
|
|
73177
|
-
if (lastErr = err, !isNotFoundError(lastErr) || attempt === SUBMIT_OUTPUT_MAX_ATTEMPTS - 1)
|
|
73236
|
+
if (lastErr = err, isPossiblyAfterWriteSubmitError(lastErr) && (replayedAfterEngineError = !0), isDefinitiveSubmitRejection(lastErr) || !(isNotFoundError(lastErr) || isPossiblyAfterWriteSubmitError(lastErr)) || attempt === SUBMIT_OUTPUT_MAX_ATTEMPTS - 1)
|
|
73178
73237
|
throw lastErr;
|
|
73179
73238
|
await this.sleep(SUBMIT_OUTPUT_BASE_DELAY_MS * Math.pow(2, attempt));
|
|
73180
73239
|
}
|
|
@@ -73182,6 +73241,13 @@ ${section}`);
|
|
|
73182
73241
|
}
|
|
73183
73242
|
// ─── §3.C.21 — REVIEWER_DISPATCH → spawn one seat ───────────────────────
|
|
73184
73243
|
async handleReviewerDispatch(payload) {
|
|
73244
|
+
if (this.abandonedSubmitGates.has(payload.gateId)) {
|
|
73245
|
+
logger.info("[QuorumLoop] ReviewerDispatch for an abandoned submission \u2014 dropped", {
|
|
73246
|
+
gateId: payload.gateId,
|
|
73247
|
+
seatId: payload.seatId
|
|
73248
|
+
});
|
|
73249
|
+
return;
|
|
73250
|
+
}
|
|
73185
73251
|
let dispatchTaskId = this.taskByGateId.get(payload.gateId), originEpoch = this.originEpochFor(dispatchTaskId), seat = numericSeatId(payload.seatId);
|
|
73186
73252
|
if (seat === null) {
|
|
73187
73253
|
logger.warn("[QuorumLoop] ReviewerDispatch with non-numeric seat \u2014 dropped", {
|
|
@@ -73219,6 +73285,10 @@ ${section}`);
|
|
|
73219
73285
|
*/
|
|
73220
73286
|
async spawnOneSeat(args) {
|
|
73221
73287
|
let key = seatKey(args.gateId, args.seatId);
|
|
73288
|
+
if (this.abandonedSubmitGates.has(args.gateId)) {
|
|
73289
|
+
logger.info("[QuorumLoop] seat spawn dropped (abandoned submission)", { key });
|
|
73290
|
+
return;
|
|
73291
|
+
}
|
|
73222
73292
|
if (this.runningSeats.has(key) || this.submittedSeats.has(key)) {
|
|
73223
73293
|
logger.info("[QuorumLoop] seat spawn no-op (already running/submitted)", { key });
|
|
73224
73294
|
return;
|
|
@@ -75937,6 +76007,27 @@ function diffCapturedProgress(round, files) {
|
|
|
75937
76007
|
deleted
|
|
75938
76008
|
};
|
|
75939
76009
|
}
|
|
76010
|
+
var SUBMIT_DEFINITIVE_ERROR_TYPES = /* @__PURE__ */ new Set([
|
|
76011
|
+
"ClientError",
|
|
76012
|
+
"SessionError",
|
|
76013
|
+
"Unauthorized",
|
|
76014
|
+
"CryptoError",
|
|
76015
|
+
"BudgetExhausted",
|
|
76016
|
+
"NotImplemented"
|
|
76017
|
+
]), RUST_WHITESPACE_ONLY = /^[\t\n\v\f\r \u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]*$/;
|
|
76018
|
+
function isEngineEmptyArtifact(files) {
|
|
76019
|
+
return files.every(
|
|
76020
|
+
(f) => RUST_WHITESPACE_ONLY.test(f.content) && f.change_kind.trim().toLowerCase() !== "deleted"
|
|
76021
|
+
);
|
|
76022
|
+
}
|
|
76023
|
+
function isDefinitiveSubmitRejection(err) {
|
|
76024
|
+
let e = err;
|
|
76025
|
+
return e.reviewScopeResetUnsupported === !0 || e.name === "AppSyncGraphQLError" && typeof e.errorType == "string" && SUBMIT_DEFINITIVE_ERROR_TYPES.has(e.errorType);
|
|
76026
|
+
}
|
|
76027
|
+
function isPossiblyAfterWriteSubmitError(err) {
|
|
76028
|
+
let e = err;
|
|
76029
|
+
return e.name === "AppSyncGraphQLError" && typeof e.errorType == "string" && !isDefinitiveSubmitRejection(err);
|
|
76030
|
+
}
|
|
75940
76031
|
function isNotFoundError(err) {
|
|
75941
76032
|
let m = err.message.toLowerCase();
|
|
75942
76033
|
return m.includes("notfound") || m.includes("not found") || m.includes("not yet written") || m.includes("not present") || m.includes("gatenotfound");
|
|
@@ -77259,7 +77350,7 @@ function OrchestrationApp(props) {
|
|
|
77259
77350
|
setLiveRuntimeKind(kind), setLiveRuntimeLabel(props.plannerLabel ?? "");
|
|
77260
77351
|
});
|
|
77261
77352
|
}, [props.plannerPipeline, props.plannerLabel]);
|
|
77262
|
-
let [syncDisplay, setSyncDisplay] = React22.useState(null), syncDisplayRef = React22.useRef(syncDisplay), syncOwner = state.session.userId;
|
|
77353
|
+
let [syncDisplay, setSyncDisplay] = React22.useState(null), [syncBootstrapSettledFor, setSyncBootstrapSettledFor] = React22.useState(null), syncDisplayRef = React22.useRef(syncDisplay), syncOwner = state.session.userId;
|
|
77263
77354
|
React22.useEffect(() => {
|
|
77264
77355
|
let source2 = props.companionSyncStateSource;
|
|
77265
77356
|
if (!source2) return;
|
|
@@ -77267,16 +77358,19 @@ function OrchestrationApp(props) {
|
|
|
77267
77358
|
if (!active) return;
|
|
77268
77359
|
clearTimeout(expiry);
|
|
77269
77360
|
let display = { userId: syncOwner, state: next };
|
|
77270
|
-
syncDisplayRef.current = display, setSyncDisplay(display), next && (expiry = setTimeout(() => update(null), Math.max(0, next.validUntilEpochMs - Date.now())), expiry.unref?.());
|
|
77361
|
+
syncDisplayRef.current = display, setSyncDisplay(display), next && (setSyncBootstrapSettledFor(syncOwner), expiry = setTimeout(() => update(null), Math.max(0, next.validUntilEpochMs - Date.now())), expiry.unref?.());
|
|
77271
77362
|
};
|
|
77272
|
-
update(null);
|
|
77363
|
+
setSyncBootstrapSettledFor(null), update(null);
|
|
77273
77364
|
try {
|
|
77274
77365
|
unsubscribe = source2.subscribeCompanionSyncState(syncOwner, update);
|
|
77275
77366
|
} catch {
|
|
77367
|
+
active && setSyncBootstrapSettledFor(syncOwner);
|
|
77276
77368
|
}
|
|
77277
77369
|
let deadline = setTimeout(() => abort.abort(), 4500);
|
|
77278
77370
|
return deadline.unref?.(), Promise.resolve().then(() => source2.getCompanionSyncState(abort.signal)).catch(() => {
|
|
77279
|
-
}).finally(() =>
|
|
77371
|
+
}).finally(() => {
|
|
77372
|
+
clearTimeout(deadline), active && setSyncBootstrapSettledFor(syncOwner);
|
|
77373
|
+
}), () => {
|
|
77280
77374
|
active = !1, clearTimeout(expiry), clearTimeout(deadline), abort.abort(), unsubscribe?.();
|
|
77281
77375
|
};
|
|
77282
77376
|
}, [props.companionSyncStateSource, syncOwner]);
|
|
@@ -77555,7 +77649,7 @@ ${formatImplementorPolicy(detected, updated, props.tier)}`
|
|
|
77555
77649
|
tier: props.tier,
|
|
77556
77650
|
plannerRuntimeKind: liveRuntimeKind,
|
|
77557
77651
|
plannerLabel: liveRuntimeLabel,
|
|
77558
|
-
companionSyncBadge: props.companionSyncStateSource ? companionSyncBadge(syncDisplay?.userId === syncOwner ? syncDisplay.state : null) : null
|
|
77652
|
+
companionSyncBadge: props.companionSyncStateSource && (syncDisplay?.userId === syncOwner && syncDisplay.state || syncBootstrapSettledFor === syncOwner) ? companionSyncBadge(syncDisplay?.userId === syncOwner ? syncDisplay.state : null) : null
|
|
77559
77653
|
}),
|
|
77560
77654
|
// CP-12 W3 §3.5 — minimal multi-track status node, mounted ONLY when a team
|
|
77561
77655
|
// is active. Single-track / Companion sessions leave `state.team`
|
|
@@ -83839,7 +83933,7 @@ var INTENT_CLASSIFIER_JSON_SCHEMA = {
|
|
|
83839
83933
|
rationale: { type: "string" }
|
|
83840
83934
|
},
|
|
83841
83935
|
required: ["action", "is_code_or_disk_mutation", "confidence", "requires_file_read", "rationale"]
|
|
83842
|
-
}, DEFAULT_INTENT_TIMEOUT_MS =
|
|
83936
|
+
}, DEFAULT_INTENT_TIMEOUT_MS = 3e4, INTENT_MAX_OUTPUT_TOKENS = 256;
|
|
83843
83937
|
function buildIntentClassifierPrompt(prompt, clarifications) {
|
|
83844
83938
|
return [
|
|
83845
83939
|
"You are a strict code/workspace intent classifier for CodeVibe.",
|
|
@@ -86656,7 +86750,7 @@ async function runOrchestrationShellSession(args) {
|
|
|
86656
86750
|
{ teardownDeadlineExpired: !0 }
|
|
86657
86751
|
) : void 0,
|
|
86658
86752
|
start: () => {
|
|
86659
|
-
shellSubmissionsFenced = !0, shellSyncRecovery.stop(), fenceHostedSessionIngress(), taskOrdinalsAtEarlyRelease = store.getState().taskOrdinals.size, earlySessionWorkRelease = releaseSessionWorkBeforeRetirement();
|
|
86753
|
+
shellSubmissionsFenced = !0, activeBrowseAbortController?.abort(), shellSyncRecovery.stop(), fenceHostedSessionIngress(), taskOrdinalsAtEarlyRelease = store.getState().taskOrdinals.size, earlySessionWorkRelease = releaseSessionWorkBeforeRetirement();
|
|
86660
86754
|
let splitLocalDurableRetirement = typeof args.localExecutor?.disposeDurableSessionResources == "function", workspaceShutdown = startWorkspaceShutdownOperations({
|
|
86661
86755
|
...args.plannerAdapter || args.localAdvisoryRunner ? {
|
|
86662
86756
|
clearPlannerSession: () => {
|
|
@@ -91284,6 +91378,13 @@ async function handleShellUserInput(deps) {
|
|
|
91284
91378
|
} finally {
|
|
91285
91379
|
stopClassifyRelabel?.();
|
|
91286
91380
|
}
|
|
91381
|
+
if (browseSignal?.aborted) {
|
|
91382
|
+
logger.info(
|
|
91383
|
+
"[orchestration-shell] Planner classify turn aborted via browseSignal; returning silently",
|
|
91384
|
+
{ prompt: plannerInput.prompt }
|
|
91385
|
+
), clearPendingClarificationIfPresent(store);
|
|
91386
|
+
return;
|
|
91387
|
+
}
|
|
91287
91388
|
logger.info("[orchestration-shell] Planner classified input", {
|
|
91288
91389
|
prompt: plannerInput.prompt,
|
|
91289
91390
|
action: decision.action,
|
|
@@ -91296,8 +91397,16 @@ async function handleShellUserInput(deps) {
|
|
|
91296
91397
|
if ((decision.action === "start_task" || decision.action === "browse") && args.localAdvisoryRunner && process.env.CODEVIBE_INTENT_CLASSIFIER !== "regex") {
|
|
91297
91398
|
let gemmaIntent = await classifyPromptIntentWithGemma(
|
|
91298
91399
|
{ prompt: plannerInput.prompt, clarifications: plannerInput.clarifications },
|
|
91299
|
-
args.localAdvisoryRunner
|
|
91400
|
+
args.localAdvisoryRunner,
|
|
91401
|
+
...browseSignal ? [{ signal: browseSignal }] : []
|
|
91300
91402
|
);
|
|
91403
|
+
if (browseSignal?.aborted) {
|
|
91404
|
+
logger.info(
|
|
91405
|
+
"[orchestration-shell] Gemma intent classifier aborted via browseSignal; returning silently",
|
|
91406
|
+
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
91407
|
+
), clearPendingClarificationIfPresent(store);
|
|
91408
|
+
return;
|
|
91409
|
+
}
|
|
91301
91410
|
if (gemmaIntent.source === "model")
|
|
91302
91411
|
gemmaEvaluatedIntent = !0, decision.action === "browse" ? gemmaIntent.is_code_or_disk_mutation && (logger.info(
|
|
91303
91412
|
"[orchestration-shell] Gemma intent classifier: promoting browse to start_task with code/disk mutation",
|
|
@@ -91314,6 +91423,12 @@ async function handleShellUserInput(deps) {
|
|
|
91314
91423
|
), decision = {
|
|
91315
91424
|
action: "familiarize",
|
|
91316
91425
|
rationale: decision.rationale ? `${decision.rationale} (demoted to familiarize via Gemma intent classifier)` : gemmaIntent.rationale
|
|
91426
|
+
}) : gemmaIntent.action === "browse" && !gemmaIntent.requires_file_read ? (logger.info(
|
|
91427
|
+
"[orchestration-shell] Gemma intent classifier: demoting start_task to browse",
|
|
91428
|
+
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
91429
|
+
), decision = {
|
|
91430
|
+
action: "browse",
|
|
91431
|
+
rationale: decision.rationale ? `${decision.rationale} (demoted to browse via Gemma intent classifier)` : gemmaIntent.rationale
|
|
91317
91432
|
}) : (logger.info(
|
|
91318
91433
|
"[orchestration-shell] Gemma intent classifier: demoting start_task to advisory_response",
|
|
91319
91434
|
{ prompt: plannerInput.prompt, rationale: gemmaIntent.rationale }
|
|
@@ -20,6 +20,7 @@ export interface GemmaIntentPort {
|
|
|
20
20
|
}>;
|
|
21
21
|
}
|
|
22
22
|
export declare const INTENT_CLASSIFIER_JSON_SCHEMA: Record<string, unknown>;
|
|
23
|
+
export declare const DEFAULT_INTENT_TIMEOUT_MS = 30000;
|
|
23
24
|
export declare function buildIntentClassifierPrompt(prompt: string, clarifications?: {
|
|
24
25
|
question: string;
|
|
25
26
|
answer: string;
|
|
@@ -57,6 +57,8 @@ export declare function failureReasonTemplate(agentKind: ReviewerAgentKind, reas
|
|
|
57
57
|
* "blocked by the local authority allowlist", etc.).
|
|
58
58
|
* - A spawn/start failure (ENOENT / "spawn" / "not found" on the agent binary)
|
|
59
59
|
* → a generic "the agent could not be started" label.
|
|
60
|
+
* - The engine's typed rejection of a submission (SB-67) → "the change is too large to submit for review"
|
|
61
|
+
* for PayloadTooLarge, else "the review service rejected the submission".
|
|
60
62
|
* - Anything else → a generic "an unexpected error occurred" label.
|
|
61
63
|
*
|
|
62
64
|
* Exported for the sanitization test (proves no raw message leaks).
|
|
@@ -1027,6 +1029,11 @@ export declare class QuorumLoop {
|
|
|
1027
1029
|
private readonly inFlightImplementorGates;
|
|
1028
1030
|
/** Gates whose implementor output has been submitted. */
|
|
1029
1031
|
private readonly submittedOutputGates;
|
|
1032
|
+
/**
|
|
1033
|
+
* SB-67 (Stage 1 R1-F1) — gates whose round failed after its submission started. The engine can dispatch reviewers
|
|
1034
|
+
* before it reports an error; a late dispatch for one of these gates belongs to a discarded task and is dropped.
|
|
1035
|
+
*/
|
|
1036
|
+
private readonly abandonedSubmitGates;
|
|
1030
1037
|
/**
|
|
1031
1038
|
* PHASE-CP-10-MIN (#585) #C10M-16 / Codex-H1 — the per-task ACTIVE
|
|
1032
1039
|
* implementor context. `runImplementorRound` populates it at spawn (wiring
|
|
@@ -3087,4 +3094,8 @@ export declare class QuorumLoop {
|
|
|
3087
3094
|
_replaceShadowForRound0UnlockedForTests(taskId: string): Promise<void>;
|
|
3088
3095
|
_ensureShadowUnlockedForTests(taskId: string): Promise<WorkspaceShadow>;
|
|
3089
3096
|
}
|
|
3097
|
+
export declare function isEngineEmptyArtifact(files: readonly {
|
|
3098
|
+
change_kind: string;
|
|
3099
|
+
content: string;
|
|
3100
|
+
}[]): boolean;
|
|
3090
3101
|
export { reviewerAgentToLeAgent, renderAgenticResolveBrief };
|
|
@@ -67,35 +67,44 @@ export declare class PlannerOutputUnparseableError extends Error {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
export declare function localGemmaAllowedActions(): ReadonlySet<PlannerDecision['action']>;
|
|
70
|
-
|
|
70
|
+
type NullField = {
|
|
71
|
+
type: 'null';
|
|
72
|
+
};
|
|
73
|
+
type StringField = {
|
|
74
|
+
type: 'string';
|
|
75
|
+
};
|
|
76
|
+
type NullableStringField = {
|
|
77
|
+
type: ['string', 'null'];
|
|
78
|
+
};
|
|
79
|
+
type NullableUrlsField = {
|
|
80
|
+
type: ['array', 'null'];
|
|
81
|
+
items: {
|
|
82
|
+
type: 'string';
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/** One per-action branch of the planner decision schema (planner parity D-15). */
|
|
86
|
+
export interface LocalGemmaDecisionBranchSchema {
|
|
71
87
|
type: 'object';
|
|
72
88
|
properties: {
|
|
73
|
-
rationale:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
advisory_summary: {
|
|
80
|
-
type: ['string', 'null'];
|
|
81
|
-
};
|
|
82
|
-
browseUrls: {
|
|
83
|
-
type: ['array', 'null'];
|
|
84
|
-
items: {
|
|
85
|
-
type: 'string';
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
browseQuery: {
|
|
89
|
-
type: ['string', 'null'];
|
|
90
|
-
};
|
|
89
|
+
rationale: StringField;
|
|
90
|
+
clarifying_question: StringField | NullableStringField | NullField;
|
|
91
|
+
advisory_summary: NullableStringField | NullField;
|
|
92
|
+
browseUrls: NullableUrlsField | NullField;
|
|
93
|
+
browseQuery: NullableStringField | NullField;
|
|
91
94
|
action: {
|
|
92
95
|
type: 'string';
|
|
93
96
|
enum: PlannerDecision['action'][];
|
|
94
97
|
};
|
|
95
98
|
};
|
|
96
99
|
required: string[];
|
|
97
|
-
additionalProperties:
|
|
100
|
+
additionalProperties: false;
|
|
101
|
+
}
|
|
102
|
+
/** The planner decision schema: exactly one branch per action family (planner parity D-15). */
|
|
103
|
+
export interface LocalGemmaDecisionJsonSchema {
|
|
104
|
+
anyOf: LocalGemmaDecisionBranchSchema[];
|
|
98
105
|
}
|
|
106
|
+
/** Every action the decision schema can emit, in branch order (each exactly once). */
|
|
107
|
+
export declare function localGemmaDecisionSchemaActions(schema?: LocalGemmaDecisionJsonSchema): PlannerDecision['action'][];
|
|
99
108
|
/**
|
|
100
109
|
* The ONE planner decision schema (both runtimes). Its canonical SHA-256 is allow-listed by
|
|
101
110
|
* planner-proxy (`lambda/planner-proxy/schemas.ts`); a change here needs the backend
|
package/package.json
CHANGED