@quantiya/codevibe-claude-plugin 2.0.14 → 2.0.16
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/.claude-plugin/plugin.json +1 -1
- package/dist/server.js +15 -15
- package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +5 -1
- package/node_modules/@quantiya/codevibe-core/dist/index.js +239 -239
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +183 -22
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +10 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/round-scope.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/index.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/round-scope.d.ts +9 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/types.d.ts +30 -0
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/node_modules/fs-ext/build/Makefile +1 -1
- package/node_modules/fs-ext/build/Release/fs_ext.node +0 -0
- package/package.json +2 -2
|
@@ -3442,7 +3442,7 @@ var AppSyncGraphQLError = class extends Error {
|
|
|
3442
3442
|
function isRetiredSessionError(error) {
|
|
3443
3443
|
return (error instanceof Error ? error.message : String(error)).includes("RETIRED_SESSION_CANNOT_REACTIVATE");
|
|
3444
3444
|
}
|
|
3445
|
-
function
|
|
3445
|
+
function isSubmitImplementorAdditiveSchemaMismatch(error) {
|
|
3446
3446
|
return error instanceof AppSyncGraphQLError ? error.message.includes("field that is not defined for input object type 'SubmitImplementorOutputInput'") : !1;
|
|
3447
3447
|
}
|
|
3448
3448
|
var RECONNECT_CONFIG = {
|
|
@@ -4759,15 +4759,23 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
4759
4759
|
sessionId: input.sessionId,
|
|
4760
4760
|
roundNumber: input.roundNumber,
|
|
4761
4761
|
encProposal,
|
|
4762
|
-
...input.usage !== void 0 ? { usage: input.usage } : {}
|
|
4762
|
+
...input.usage !== void 0 ? { usage: input.usage } : {},
|
|
4763
|
+
// Presence is the P24 capability handshake. Updated clients always
|
|
4764
|
+
// send false or true; legacy clients omit the field entirely.
|
|
4765
|
+
reviewScopeReset: input.reviewScopeReset ?? !1
|
|
4763
4766
|
}
|
|
4764
4767
|
}, response;
|
|
4765
4768
|
try {
|
|
4766
4769
|
response = await this.graphqlRequest(mutations.submitImplementorOutput, variables);
|
|
4767
4770
|
} catch (err) {
|
|
4768
|
-
if (
|
|
4771
|
+
if (!isSubmitImplementorAdditiveSchemaMismatch(err))
|
|
4769
4772
|
throw err;
|
|
4770
|
-
|
|
4773
|
+
if (input.reviewScopeReset === !0)
|
|
4774
|
+
throw logger.warn("[AppSyncClient] explicit review-scope reset rejected by old backend schema; failing closed", {
|
|
4775
|
+
gateId: input.gateId,
|
|
4776
|
+
taskId: input.taskId
|
|
4777
|
+
}), err;
|
|
4778
|
+
logger.warn("[AppSyncClient] submitImplementorOutput additive fields rejected by backend schema; retrying legacy input", {
|
|
4771
4779
|
gateId: input.gateId,
|
|
4772
4780
|
taskId: input.taskId,
|
|
4773
4781
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -4849,7 +4857,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
4849
4857
|
gateId: parsed.gateId,
|
|
4850
4858
|
seatId: parsed.seatId,
|
|
4851
4859
|
role: parsed.role,
|
|
4852
|
-
prompt
|
|
4860
|
+
prompt,
|
|
4861
|
+
reviewScope: parsed.reviewScope
|
|
4853
4862
|
};
|
|
4854
4863
|
}
|
|
4855
4864
|
/**
|
|
@@ -9524,6 +9533,12 @@ var CATALOG = [
|
|
|
9524
9533
|
);
|
|
9525
9534
|
}
|
|
9526
9535
|
},
|
|
9536
|
+
{
|
|
9537
|
+
name: "/review-reset",
|
|
9538
|
+
blurb: "Start a fresh comprehensive baseline on the next review round (Pro/Max).",
|
|
9539
|
+
minTier: "PRO",
|
|
9540
|
+
handler: () => staticOutput("/review-reset", "PENDING \u2014 entrypoint arms comprehensive review")
|
|
9541
|
+
},
|
|
9527
9542
|
{
|
|
9528
9543
|
name: "/task",
|
|
9529
9544
|
blurb: "Run an implementation request directly, skipping planning (Pro/Max).",
|
|
@@ -46803,6 +46818,130 @@ async function runReviewer(opts) {
|
|
|
46803
46818
|
});
|
|
46804
46819
|
}
|
|
46805
46820
|
|
|
46821
|
+
// src/reviewer/round-scope.ts
|
|
46822
|
+
var REVIEW_SCOPE_ATTESTATION_INVALID = "review_scope_attestation_invalid", SCOPE_TAG_PREFIX = /^\[(?:baseline|revision|regression|late-preexisting|prior:[^\]\s]+)\](?:\s|$)/i;
|
|
46823
|
+
function parseOrigin(change) {
|
|
46824
|
+
let trimmed = change.trim(), match = /^\[(baseline|revision|regression|late-preexisting|prior:([^\]\s]+))\]\s+([\s\S]+)$/i.exec(
|
|
46825
|
+
trimmed
|
|
46826
|
+
);
|
|
46827
|
+
if (!match)
|
|
46828
|
+
return trimmed === "" || trimmed.startsWith("[") ? { kind: "invalid" } : { kind: "untagged", text: trimmed };
|
|
46829
|
+
if (match[3].trim() === "") return { kind: "invalid" };
|
|
46830
|
+
let tag = match[1].toLowerCase(), text2 = match[3].trim();
|
|
46831
|
+
return SCOPE_TAG_PREFIX.test(text2) ? { kind: "invalid" } : tag === "late-preexisting" ? { kind: "late", text: text2 } : tag.startsWith("prior:") ? {
|
|
46832
|
+
kind: "blocking",
|
|
46833
|
+
origin: "prior",
|
|
46834
|
+
priorFindingId: match[2] ?? null,
|
|
46835
|
+
text: text2
|
|
46836
|
+
} : {
|
|
46837
|
+
kind: "blocking",
|
|
46838
|
+
origin: tag,
|
|
46839
|
+
priorFindingId: null,
|
|
46840
|
+
text: text2
|
|
46841
|
+
};
|
|
46842
|
+
}
|
|
46843
|
+
function originAllowed(parsed, context) {
|
|
46844
|
+
return context.mode === "comprehensive" ? parsed.origin === "baseline" : parsed.origin === "baseline" ? !1 : parsed.origin !== "prior" ? !0 : context.prior_findings.some((finding) => finding.finding_id === parsed.priorFindingId);
|
|
46845
|
+
}
|
|
46846
|
+
function scopeIdentity(context) {
|
|
46847
|
+
let { prior_findings: _priorFindings, ...identity } = context;
|
|
46848
|
+
return identity;
|
|
46849
|
+
}
|
|
46850
|
+
function enforceReviewRoundScope(verdict, context) {
|
|
46851
|
+
if (context.mode === "delta" && verdict.verdict === "REJECT")
|
|
46852
|
+
return {
|
|
46853
|
+
...verdict,
|
|
46854
|
+
verdict: "ESCALATE",
|
|
46855
|
+
reasoning: REVIEW_SCOPE_ATTESTATION_INVALID,
|
|
46856
|
+
suggested_changes: [],
|
|
46857
|
+
residual_observations: [...verdict.residual_observations, verdict.reasoning],
|
|
46858
|
+
review_scope: {
|
|
46859
|
+
context: scopeIdentity(context),
|
|
46860
|
+
blocking_findings: [],
|
|
46861
|
+
late_preexisting_findings: []
|
|
46862
|
+
}
|
|
46863
|
+
};
|
|
46864
|
+
if (verdict.verdict !== "REVISE")
|
|
46865
|
+
return {
|
|
46866
|
+
...verdict,
|
|
46867
|
+
review_scope: {
|
|
46868
|
+
context: scopeIdentity(context),
|
|
46869
|
+
blocking_findings: [],
|
|
46870
|
+
late_preexisting_findings: []
|
|
46871
|
+
}
|
|
46872
|
+
};
|
|
46873
|
+
let blockingChanges = [], blockingFindings = [], lateFindings = [], invalid = !1;
|
|
46874
|
+
for (let change of verdict.suggested_changes) {
|
|
46875
|
+
let parsed = parseOrigin(change);
|
|
46876
|
+
if (parsed.kind === "invalid") {
|
|
46877
|
+
invalid = !0;
|
|
46878
|
+
continue;
|
|
46879
|
+
}
|
|
46880
|
+
if (parsed.kind === "late") {
|
|
46881
|
+
if (context.mode === "comprehensive") {
|
|
46882
|
+
invalid = !0;
|
|
46883
|
+
continue;
|
|
46884
|
+
}
|
|
46885
|
+
lateFindings.push(parsed.text);
|
|
46886
|
+
continue;
|
|
46887
|
+
}
|
|
46888
|
+
if (parsed.kind === "untagged") {
|
|
46889
|
+
if (context.mode === "comprehensive") {
|
|
46890
|
+
let suggestionIndex2 = blockingChanges.length;
|
|
46891
|
+
blockingChanges.push(parsed.text), blockingFindings.push({
|
|
46892
|
+
suggestion_index: suggestionIndex2,
|
|
46893
|
+
origin: "baseline",
|
|
46894
|
+
prior_finding_id: null
|
|
46895
|
+
});
|
|
46896
|
+
} else
|
|
46897
|
+
lateFindings.push(parsed.text);
|
|
46898
|
+
continue;
|
|
46899
|
+
}
|
|
46900
|
+
if (!originAllowed(parsed, context)) {
|
|
46901
|
+
if (context.mode === "delta" && parsed.origin === "prior") {
|
|
46902
|
+
lateFindings.push(parsed.text);
|
|
46903
|
+
continue;
|
|
46904
|
+
}
|
|
46905
|
+
invalid = !0;
|
|
46906
|
+
continue;
|
|
46907
|
+
}
|
|
46908
|
+
let suggestionIndex = blockingChanges.length;
|
|
46909
|
+
blockingChanges.push(parsed.text), blockingFindings.push({
|
|
46910
|
+
suggestion_index: suggestionIndex,
|
|
46911
|
+
origin: parsed.origin,
|
|
46912
|
+
prior_finding_id: parsed.priorFindingId
|
|
46913
|
+
});
|
|
46914
|
+
}
|
|
46915
|
+
let residual = [...verdict.residual_observations, ...lateFindings], reviewScope = {
|
|
46916
|
+
context: scopeIdentity(context),
|
|
46917
|
+
blocking_findings: blockingFindings,
|
|
46918
|
+
late_preexisting_findings: lateFindings
|
|
46919
|
+
};
|
|
46920
|
+
return invalid ? {
|
|
46921
|
+
...verdict,
|
|
46922
|
+
verdict: "ESCALATE",
|
|
46923
|
+
reasoning: REVIEW_SCOPE_ATTESTATION_INVALID,
|
|
46924
|
+
suggested_changes: [],
|
|
46925
|
+
residual_observations: [...residual, ...verdict.suggested_changes],
|
|
46926
|
+
review_scope: {
|
|
46927
|
+
context: scopeIdentity(context),
|
|
46928
|
+
blocking_findings: [],
|
|
46929
|
+
late_preexisting_findings: lateFindings
|
|
46930
|
+
}
|
|
46931
|
+
} : blockingChanges.length === 0 ? {
|
|
46932
|
+
...verdict,
|
|
46933
|
+
verdict: "APPROVE",
|
|
46934
|
+
suggested_changes: [],
|
|
46935
|
+
residual_observations: residual,
|
|
46936
|
+
review_scope: reviewScope
|
|
46937
|
+
} : {
|
|
46938
|
+
...verdict,
|
|
46939
|
+
suggested_changes: blockingChanges,
|
|
46940
|
+
residual_observations: residual,
|
|
46941
|
+
review_scope: reviewScope
|
|
46942
|
+
};
|
|
46943
|
+
}
|
|
46944
|
+
|
|
46806
46945
|
// src/reviewer/provider.ts
|
|
46807
46946
|
var ReviewerErrorClass = class _ReviewerErrorClass extends Error {
|
|
46808
46947
|
constructor(detail) {
|
|
@@ -47638,6 +47777,10 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
47638
47777
|
constructor(deps) {
|
|
47639
47778
|
/** The active task this desktop is driving (set at start_task). */
|
|
47640
47779
|
this.activeTaskId = null;
|
|
47780
|
+
/** Tasks whose next automatic revise round must start a fresh review baseline. */
|
|
47781
|
+
this.reviewScopeResetTasks = /* @__PURE__ */ new Set();
|
|
47782
|
+
/** Non-terminal tasks for which `/review-reset` may arm the next revise round. */
|
|
47783
|
+
this.reviewScopeResetEligibleTasks = /* @__PURE__ */ new Set();
|
|
47641
47784
|
// [live task status timer — TUI-LIVE-TASK-STATUS-DESIGN.md §3] Per-TASK monotonic
|
|
47642
47785
|
// epoch: bumped once per `startTask` and recorded per taskId. Every progress emit
|
|
47643
47786
|
// stamps `epoch: originEpoch` resolved from its OWN task's id (never `taskEpoch`
|
|
@@ -48574,6 +48717,10 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
48574
48717
|
get activeTask() {
|
|
48575
48718
|
return this.activeTaskId;
|
|
48576
48719
|
}
|
|
48720
|
+
/** Arm an explicit, one-shot comprehensive baseline for the active task. */
|
|
48721
|
+
requestReviewScopeReset() {
|
|
48722
|
+
return !this.activeTaskId || !this.reviewScopeResetEligibleTasks.has(this.activeTaskId) ? !1 : (this.reviewScopeResetTasks.add(this.activeTaskId), !0);
|
|
48723
|
+
}
|
|
48577
48724
|
/**
|
|
48578
48725
|
* Audited-path fix (Fix 5) — the host's detected implementor agents
|
|
48579
48726
|
* (UPPERCASE `AgentKind`), as threaded into the loop at construction. Used by
|
|
@@ -48773,7 +48920,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
48773
48920
|
err: err.message
|
|
48774
48921
|
}), null;
|
|
48775
48922
|
}
|
|
48776
|
-
this.startTaskInFlight = !1, logger.info("[QuorumLoop] startTask succeeded \u2014 draining buffered GATE_DISPATCH (if any) then awaiting more", {
|
|
48923
|
+
this.startTaskInFlight = !1, this.reviewScopeResetEligibleTasks.add(taskId), logger.info("[QuorumLoop] startTask succeeded \u2014 draining buffered GATE_DISPATCH (if any) then awaiting more", {
|
|
48777
48924
|
taskId,
|
|
48778
48925
|
workflowState,
|
|
48779
48926
|
buffered: this.pendingGateDispatches.length
|
|
@@ -48839,7 +48986,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
48839
48986
|
return;
|
|
48840
48987
|
}
|
|
48841
48988
|
let taskId = this.activeTaskId, brief = this.activeBrief;
|
|
48842
|
-
await this.replaceShadowForRound0(taskId), await this.runImplementorRound({
|
|
48989
|
+
await this.replaceShadowForRound0(taskId), this.reviewScopeResetEligibleTasks.add(taskId), await this.runImplementorRound({
|
|
48843
48990
|
taskId,
|
|
48844
48991
|
gateId: payload.gateRunId,
|
|
48845
48992
|
roundNumber: 0,
|
|
@@ -49224,7 +49371,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
49224
49371
|
let stale = this.shadowsByTask.get(taskId);
|
|
49225
49372
|
stale && (await stale.assertCanDiscard(), logger.info("[QuorumLoop] replacing a stale shadow for a fresh round-0 dispatch (restart)", {
|
|
49226
49373
|
taskId
|
|
49227
|
-
}), await stale.discard(), this.shadowsByTask.get(taskId) === stale && this.shadowsByTask.delete(taskId), this.userNotesByTask.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), this.reviewedSnapshotByTask.delete(taskId));
|
|
49374
|
+
}), await stale.discard(), this.shadowsByTask.get(taskId) === stale && this.shadowsByTask.delete(taskId), this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), this.reviewedSnapshotByTask.delete(taskId));
|
|
49228
49375
|
}
|
|
49229
49376
|
/**
|
|
49230
49377
|
* CP-14 P1 — the team execution model this session SIGNALS on
|
|
@@ -49306,7 +49453,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
49306
49453
|
return;
|
|
49307
49454
|
}
|
|
49308
49455
|
this.inFlightImplementorGates.add(gateId), this.taskByGateId.set(gateId, args.taskId), args.teamAuthority && this.teamAuthorityByGateId.set(gateId, args.teamAuthority), this.roundByGateId.set(gateId, args.roundNumber);
|
|
49309
|
-
let originEpoch = this.originEpochFor(args.taskId), tickTimer = null, roundActive = !0, clearTick = () => {
|
|
49456
|
+
let originEpoch = this.originEpochFor(args.taskId), tickTimer = null, roundActive = !0, submissionStarted = !1, clearTick = () => {
|
|
49310
49457
|
roundActive = !1, tickTimer && (clearInterval(tickTimer), tickTimer = null);
|
|
49311
49458
|
}, roundBriefForSpawn = args.brief, copiedForSpawn = [];
|
|
49312
49459
|
try {
|
|
@@ -49752,16 +49899,17 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
49752
49899
|
this.emitProgressForTask(args.taskId, originEpoch, {
|
|
49753
49900
|
phase: "submitting_diff",
|
|
49754
49901
|
round: args.roundNumber
|
|
49755
|
-
});
|
|
49902
|
+
}), submissionStarted = !0;
|
|
49756
49903
|
let result = await this.submitImplementorOutputWithRetry({
|
|
49757
49904
|
taskId: args.taskId,
|
|
49758
49905
|
gateId,
|
|
49759
49906
|
roundNumber: args.roundNumber,
|
|
49760
49907
|
rawOutput,
|
|
49761
49908
|
usage: implementorUsage,
|
|
49762
|
-
sessionKey: args.sessionKey
|
|
49909
|
+
sessionKey: args.sessionKey,
|
|
49910
|
+
reviewScopeReset: args.reviewScopeReset
|
|
49763
49911
|
});
|
|
49764
|
-
if (this.teamRunIsHalted(args.teamAuthority)) return;
|
|
49912
|
+
if (args.reviewScopeReset && this.reviewScopeResetTasks.delete(args.taskId), this.teamRunIsHalted(args.teamAuthority)) return;
|
|
49765
49913
|
if (this.submittedOutputGates.add(gateId), result && (result.workflowState === "halted" || result.workflowState === "idle")) {
|
|
49766
49914
|
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).";
|
|
49767
49915
|
(crashedEmpty ? logger.warn.bind(logger) : logger.info.bind(logger))("[QuorumLoop] execute-first born-halt surfaced synchronously (#EF-1)", {
|
|
@@ -49793,7 +49941,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
49793
49941
|
this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`), this.emitProgress(
|
|
49794
49942
|
{ phase: "round_failed", round: args.roundNumber, reason, taskId: args.taskId },
|
|
49795
49943
|
originEpoch
|
|
49796
|
-
)
|
|
49944
|
+
);
|
|
49945
|
+
let reviseFeedbackId = args.reviseFeedbackId, preserveResetForRetry = submissionStarted && args.reviewScopeReset === !0 && reviseFeedbackId !== void 0 && this.reviewScopeResetTasks.has(args.taskId);
|
|
49946
|
+
preserveResetForRetry && this.seenReviseFeedbackIds.delete(reviseFeedbackId), await this.discardShadow(args.taskId, void 0, {
|
|
49947
|
+
preserveReviseContext: preserveResetForRetry
|
|
49948
|
+
});
|
|
49797
49949
|
} finally {
|
|
49798
49950
|
clearTick(), this.inFlightImplementorGates.delete(gateId);
|
|
49799
49951
|
let current = this.activeImplementorByTask.get(args.taskId);
|
|
@@ -50231,6 +50383,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50231
50383
|
}
|
|
50232
50384
|
return;
|
|
50233
50385
|
}
|
|
50386
|
+
terminalDiscard && this.reviewScopeResetEligibleTasks.delete(taskId);
|
|
50234
50387
|
let shadow = expected ?? mapped;
|
|
50235
50388
|
if (shadow)
|
|
50236
50389
|
try {
|
|
@@ -50242,7 +50395,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50242
50395
|
});
|
|
50243
50396
|
return;
|
|
50244
50397
|
}
|
|
50245
|
-
if (opts?.preserveReviseContext || (this.userNotesByTask.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), appendContextItem(this.deps.session.sessionId, {
|
|
50398
|
+
if (opts?.preserveReviseContext || (this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), appendContextItem(this.deps.session.sessionId, {
|
|
50246
50399
|
kind: "verdict",
|
|
50247
50400
|
author: { role: "engine" },
|
|
50248
50401
|
sensitivity: "user",
|
|
@@ -50309,7 +50462,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50309
50462
|
async promoteShadowLockedInner(taskId, originEpoch) {
|
|
50310
50463
|
let teamAuthority = this.teamAuthorityForTask(taskId);
|
|
50311
50464
|
if (this.teamRunIsHalted(teamAuthority)) return;
|
|
50312
|
-
this.userNotesByTask.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId);
|
|
50465
|
+
this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId);
|
|
50313
50466
|
let shadow = this.shadowsByTask.get(taskId);
|
|
50314
50467
|
if (!shadow) {
|
|
50315
50468
|
logger.info("[QuorumLoop] promote no-op \u2014 no in-memory shadow for task", { taskId });
|
|
@@ -50725,7 +50878,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50725
50878
|
sessionId: this.deps.session.sessionId,
|
|
50726
50879
|
roundNumber: args.roundNumber,
|
|
50727
50880
|
rawOutput: args.rawOutput,
|
|
50728
|
-
usage: args.usage
|
|
50881
|
+
usage: args.usage,
|
|
50882
|
+
reviewScopeReset: args.reviewScopeReset
|
|
50729
50883
|
},
|
|
50730
50884
|
args.sessionKey
|
|
50731
50885
|
);
|
|
@@ -50808,14 +50962,15 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50808
50962
|
}), await this.submitVerdict(args, this.synthesizeEscalate(args, DESKTOP_DISPATCH_ESCALATE_REASONING), null);
|
|
50809
50963
|
return;
|
|
50810
50964
|
}
|
|
50811
|
-
let promptText = null, lastErr = null;
|
|
50965
|
+
let promptText = null, reviewScope = null, lastErr = null;
|
|
50812
50966
|
for (let attempt = 0; attempt < PROMPT_FETCH_MAX_ATTEMPTS; attempt++)
|
|
50813
50967
|
try {
|
|
50814
|
-
|
|
50968
|
+
let res = await this.deps.appsyncClient.getReviewerPrompt(
|
|
50815
50969
|
args.gateId,
|
|
50816
50970
|
args.seatId,
|
|
50817
50971
|
sessionKey
|
|
50818
|
-
)
|
|
50972
|
+
);
|
|
50973
|
+
promptText = res.prompt, reviewScope = res.reviewScope ?? null;
|
|
50819
50974
|
break;
|
|
50820
50975
|
} catch (err) {
|
|
50821
50976
|
if (lastErr = err, !isNotFoundError(lastErr) || attempt === PROMPT_FETCH_MAX_ATTEMPTS - 1)
|
|
@@ -50916,7 +51071,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50916
51071
|
await seatSubstrate.teardown().catch(() => {
|
|
50917
51072
|
});
|
|
50918
51073
|
}
|
|
50919
|
-
await this.submitVerdict(args, verdict, sessionKey);
|
|
51074
|
+
reviewScope !== null && (verdict = enforceReviewRoundScope(verdict, reviewScope)), await this.submitVerdict(args, verdict, sessionKey);
|
|
50920
51075
|
} catch (err) {
|
|
50921
51076
|
logger.warn("[QuorumLoop] spawnOneSeat failed \u2014 dropped", {
|
|
50922
51077
|
key,
|
|
@@ -52508,7 +52663,9 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
52508
52663
|
phase: "revise_round",
|
|
52509
52664
|
round: payload.nextRound,
|
|
52510
52665
|
feedbackSummary: `addressing ${findingCount} ${findingCount === 1 ? "finding" : "findings"}`
|
|
52511
|
-
})
|
|
52666
|
+
});
|
|
52667
|
+
let reviewScopeReset = this.reviewScopeResetTasks.has(taskId);
|
|
52668
|
+
await this.runImplementorRound({
|
|
52512
52669
|
taskId,
|
|
52513
52670
|
gateId: payload.nextGateId,
|
|
52514
52671
|
roundNumber: payload.nextRound,
|
|
@@ -52517,6 +52674,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
52517
52674
|
sessionKey,
|
|
52518
52675
|
...teamAuthority ? { teamAuthority } : {},
|
|
52519
52676
|
...priorRationale ? { priorRationale } : {},
|
|
52677
|
+
...reviewScopeReset ? { reviewScopeReset: !0 } : {},
|
|
52678
|
+
reviseFeedbackId: payload.reviseFeedbackId,
|
|
52520
52679
|
...trackEntry ? {
|
|
52521
52680
|
validateDiffScope: {
|
|
52522
52681
|
writePaths: trackEntry.writePaths,
|
|
@@ -53111,7 +53270,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53111
53270
|
}
|
|
53112
53271
|
/** @internal — test seam to set the active task without start_task. */
|
|
53113
53272
|
_setActiveTaskForTests(taskId, brief) {
|
|
53114
|
-
this.activeTaskId = taskId, brief !== void 0 && (this.activeBrief = brief);
|
|
53273
|
+
this.activeTaskId = taskId, this.reviewScopeResetEligibleTasks.add(taskId), brief !== void 0 && (this.activeBrief = brief);
|
|
53115
53274
|
}
|
|
53116
53275
|
/** @internal — read a task's accumulated binding user notes. */
|
|
53117
53276
|
_userNotesForTests(taskId) {
|
|
@@ -57495,6 +57654,8 @@ async function handleShellUserInput(deps) {
|
|
|
57495
57654
|
}
|
|
57496
57655
|
}), output.output = "") : output.output = loaded.message;
|
|
57497
57656
|
}
|
|
57657
|
+
else if (output.command === "/review-reset" && !output.sideEffect && output.output === "PENDING \u2014 entrypoint arms comprehensive review")
|
|
57658
|
+
args.quorumLoop ? args.quorumLoop.requestReviewScopeReset() ? output.output = "The next revise round will start a fresh comprehensive review baseline." : output.output = "/review-reset requires an active task. Start a task before requesting a reset." : output.output = "/review-reset requires an orchestration session with a running loop (Pro/Max). It is unavailable in this session.";
|
|
57498
57659
|
else if (output.command === "/task" && !output.sideEffect && output.output === "PENDING \u2014 entrypoint drives startTask")
|
|
57499
57660
|
if (!args.quorumLoop)
|
|
57500
57661
|
output.output = "/task requires an orchestration session with a running loop (Pro/Max). It is unavailable in this session.";
|
|
@@ -554,6 +554,10 @@ export declare class QuorumLoop {
|
|
|
554
554
|
private readonly sleep;
|
|
555
555
|
/** The active task this desktop is driving (set at start_task). */
|
|
556
556
|
private activeTaskId;
|
|
557
|
+
/** Tasks whose next automatic revise round must start a fresh review baseline. */
|
|
558
|
+
private readonly reviewScopeResetTasks;
|
|
559
|
+
/** Non-terminal tasks for which `/review-reset` may arm the next revise round. */
|
|
560
|
+
private readonly reviewScopeResetEligibleTasks;
|
|
557
561
|
private taskEpoch;
|
|
558
562
|
private readonly epochByTaskId;
|
|
559
563
|
private readonly tokensByTaskId;
|
|
@@ -1144,6 +1148,8 @@ export declare class QuorumLoop {
|
|
|
1144
1148
|
constructor(deps: QuorumLoopDeps);
|
|
1145
1149
|
/** The current active task id (for the recovery poll). */
|
|
1146
1150
|
get activeTask(): string | null;
|
|
1151
|
+
/** Arm an explicit, one-shot comprehensive baseline for the active task. */
|
|
1152
|
+
requestReviewScopeReset(): boolean;
|
|
1147
1153
|
/**
|
|
1148
1154
|
* Audited-path fix (Fix 5) — the host's detected implementor agents
|
|
1149
1155
|
* (UPPERCASE `AgentKind`), as threaded into the loop at construction. Used by
|
|
@@ -1443,6 +1449,10 @@ export declare class QuorumLoop {
|
|
|
1443
1449
|
round: number;
|
|
1444
1450
|
text: string;
|
|
1445
1451
|
};
|
|
1452
|
+
/** Explicitly start a new comprehensive reviewer baseline. */
|
|
1453
|
+
reviewScopeReset?: boolean;
|
|
1454
|
+
/** Deterministic producer identity retained only so a failed revise can be retried. */
|
|
1455
|
+
reviseFeedbackId?: string;
|
|
1446
1456
|
}): Promise<void>;
|
|
1447
1457
|
private runImplementorRoundOwned;
|
|
1448
1458
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { AgentKind, ReviewerRole, ReviewerVerdict, VerdictId, VerdictKind, } from './types.js';
|
|
2
|
+
export { enforceReviewRoundScope, REVIEW_SCOPE_ATTESTATION_INVALID } from './round-scope.js';
|
|
2
3
|
export type { ReviewerError, ReviewerProvider, ReviewerSpec, } from './provider.js';
|
|
3
4
|
export { ReviewerErrorClass } from './provider.js';
|
|
4
5
|
export type { ParseResult, ParsedVerdict, VerdictParseError, } from './output-parser.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReviewerVerdict, ReviewScopeContext } from './types';
|
|
2
|
+
export declare const REVIEW_SCOPE_ATTESTATION_INVALID = "review_scope_attestation_invalid";
|
|
3
|
+
/**
|
|
4
|
+
* Bind a reviewer verdict to the server-authored round context. Invalid or
|
|
5
|
+
* unscoped blocking findings become a fail-closed ESCALATE. Properly declared
|
|
6
|
+
* late pre-existing findings remain visible as residual observations and can
|
|
7
|
+
* never trigger another revision.
|
|
8
|
+
*/
|
|
9
|
+
export declare function enforceReviewRoundScope(verdict: ReviewerVerdict, context: ReviewScopeContext): ReviewerVerdict;
|
|
@@ -50,6 +50,34 @@ export type VerdictKind = 'APPROVE' | 'REJECT' | 'REVISE' | 'ESCALATE';
|
|
|
50
50
|
* UUID string, no envelope.
|
|
51
51
|
*/
|
|
52
52
|
export type VerdictId = string;
|
|
53
|
+
export type ReviewScopeMode = 'comprehensive' | 'delta';
|
|
54
|
+
export type ReviewScopeResetReason = 'initial' | 'explicit' | 'seat_baseline';
|
|
55
|
+
export type ReviewFindingOrigin = 'baseline' | 'prior' | 'revision' | 'regression';
|
|
56
|
+
export interface ReviewScopePriorFinding {
|
|
57
|
+
finding_id: string;
|
|
58
|
+
text: string;
|
|
59
|
+
}
|
|
60
|
+
export interface ReviewScopeContext {
|
|
61
|
+
schema_version: number;
|
|
62
|
+
mode: ReviewScopeMode;
|
|
63
|
+
reset_reason: ReviewScopeResetReason | null;
|
|
64
|
+
candidate_sha256: string;
|
|
65
|
+
prior_candidate_sha256: string | null;
|
|
66
|
+
prior_gate_id: string | null;
|
|
67
|
+
prior_verdict_id: string | null;
|
|
68
|
+
prior_findings: ReviewScopePriorFinding[];
|
|
69
|
+
}
|
|
70
|
+
export type ReviewScopeIdentity = Omit<ReviewScopeContext, 'prior_findings'>;
|
|
71
|
+
export interface ReviewBlockingFinding {
|
|
72
|
+
suggestion_index: number;
|
|
73
|
+
origin: ReviewFindingOrigin;
|
|
74
|
+
prior_finding_id: string | null;
|
|
75
|
+
}
|
|
76
|
+
export interface ReviewScopeAttestation {
|
|
77
|
+
context: ReviewScopeIdentity;
|
|
78
|
+
blocking_findings: ReviewBlockingFinding[];
|
|
79
|
+
late_preexisting_findings: string[];
|
|
80
|
+
}
|
|
53
81
|
/**
|
|
54
82
|
* One reviewer's verdict at one gate. Records reasoning plus perf/cost
|
|
55
83
|
* metadata for telemetry (review latency, token cost per task, etc.).
|
|
@@ -104,4 +132,6 @@ export interface ReviewerVerdict {
|
|
|
104
132
|
submitted_at: string;
|
|
105
133
|
/** Canonical input/output/cache/elapsed usage snapshot. Additive post-launch. */
|
|
106
134
|
usage?: InvocationUsageSnapshot;
|
|
135
|
+
/** P24 server-bound review scope and finding provenance. Append-only. */
|
|
136
|
+
review_scope?: ReviewScopeAttestation | null;
|
|
107
137
|
}
|
|
@@ -332,7 +332,7 @@ endif
|
|
|
332
332
|
|
|
333
333
|
quiet_cmd_regen_makefile = ACTION Regenerating $@
|
|
334
334
|
cmd_regen_makefile = cd $(srcdir); /opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0" "-Dnode_gyp_dir=/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/hendryyeh/Workspace/CodeVibe/codevibe-claude-plugin/node_modules/fs-ext" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/hendryyeh/Workspace/CodeVibe/codevibe-claude-plugin/node_modules/fs-ext/build/config.gypi -I/opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/hendryyeh/Library/Caches/node-gyp/24.4.0/include/node/common.gypi "--toplevel-dir=." binding.gyp
|
|
335
|
-
Makefile: $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)
|
|
335
|
+
Makefile: $(srcdir)/../../../../../../../opt/homebrew/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/../../../../../Library/Caches/node-gyp/24.4.0/include/node/common.gypi $(srcdir)/binding.gyp
|
|
336
336
|
$(call do_cmd,regen_makefile)
|
|
337
337
|
|
|
338
338
|
# "all" is a concatenation of the "all" targets from all the included
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantiya/codevibe-claude-plugin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
4
4
|
"description": "Control Claude Code from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"codevibe": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"node": ">=22.0.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@quantiya/codevibe-core": "2.0.
|
|
50
|
+
"@quantiya/codevibe-core": "2.0.14",
|
|
51
51
|
"@quantiya/quorum-core": "^1.0.1",
|
|
52
52
|
"dotenv": "^16.6.1",
|
|
53
53
|
"express": "^5.1.0",
|