@quantiya/codevibe-codex-plugin 2.0.13 → 2.0.15
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/server.js +35 -32
- package/hooks/common.sh +21 -9
- package/libexec/companion-launcher +47 -14
- package/node_modules/@iarna/toml/CHANGELOG.md +278 -0
- package/node_modules/@quantiya/codevibe-core/dist/__tests__/gate-ux-regressions.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/index.js +240 -240
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/workspace-shadow.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/local-model/manager.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/audit-runner.d.ts +2 -3
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.d.ts +2 -2
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +158 -28
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +22 -3
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/task-progress.d.ts +3 -0
- package/node_modules/@quantiya/codevibe-core/dist/reduced-trust-notice.d.ts +44 -0
- package/node_modules/@quantiya/codevibe-core/dist/tool-activity/consolidator.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/tool-activity/ledger.d.ts +33 -13
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/node_modules/color-convert/CHANGELOG.md +54 -0
- package/node_modules/deep-extend/CHANGELOG.md +46 -0
- package/node_modules/es-toolkit/CHANGELOG.md +810 -0
- package/node_modules/es-toolkit/src/compat/_internal/Equals.d.ts +1 -0
- package/node_modules/es-toolkit/src/compat/_internal/IsWritable.d.ts +3 -0
- package/node_modules/es-toolkit/src/compat/_internal/MutableList.d.ts +4 -0
- package/node_modules/es-toolkit/src/compat/_internal/RejectReadonly.d.ts +4 -0
- package/node_modules/fs-ext/build/Makefile +2 -2
- package/node_modules/fs-ext/build/Release/fs_ext.node +0 -0
- package/node_modules/fs-ext/build/Release/obj.target/fs_ext/fs-ext.o +0 -0
- package/node_modules/fs-ext/build/config.gypi +1 -1
- package/node_modules/keytar/build/Release/keytar.node +0 -0
- package/node_modules/which/CHANGELOG.md +166 -0
- package/package.json +2 -2
|
@@ -223,6 +223,13 @@ export declare class WorkspaceShadow {
|
|
|
223
223
|
private constructor();
|
|
224
224
|
/** @internal — test introspection of the tracked set. */
|
|
225
225
|
get trackedSetForTests(): ReadonlySet<string>;
|
|
226
|
+
/**
|
|
227
|
+
* Number of paths this shadow tracks. 2026-08-22 — exposed for the reviewer
|
|
228
|
+
* timeout diagnostics: workspace SIZE is what separates "the diff was large"
|
|
229
|
+
* from "the workspace was large" when a reviewer blows its wall clock, and
|
|
230
|
+
* that distinction picks the fix. A count only; never the paths.
|
|
231
|
+
*/
|
|
232
|
+
get trackedCount(): number;
|
|
226
233
|
/** Exact user-root instance authenticated into reviewed team bundles. */
|
|
227
234
|
rootAuthorityForBundle(): WorkspaceRootAuthority;
|
|
228
235
|
/** Exact disposable-root incarnation required by every task-scoped consumer. */
|
|
@@ -4,7 +4,7 @@ import { type LocalModelState, type LocalModelStateStore } from './state';
|
|
|
4
4
|
import { type OllamaPullProgressListener } from './ollama';
|
|
5
5
|
import type { LocalGemmaPlannerRunner } from '../planner/local-gemma';
|
|
6
6
|
export type LocalModelCommand = 'install' | 'status' | 'remove' | 'enable' | 'warm' | 'health-check';
|
|
7
|
-
export type LocalModelEntitlementSource = 'backend' | '
|
|
7
|
+
export type LocalModelEntitlementSource = 'backend' | 'unauthenticated' | 'unavailable';
|
|
8
8
|
export interface LocalModelEntitlement {
|
|
9
9
|
tier: Tier | 'UNKNOWN';
|
|
10
10
|
source: LocalModelEntitlementSource;
|
|
@@ -17,9 +17,8 @@ export interface RunAuditBrowserDeps {
|
|
|
17
17
|
/** The session the task belongs to (the `queryAudit` 2-arg shape needs it). */
|
|
18
18
|
sessionId: string;
|
|
19
19
|
/**
|
|
20
|
-
* The effective tier
|
|
21
|
-
*
|
|
22
|
-
* the runner reads `getSubscriptionStatus().tier` from the backend.
|
|
20
|
+
* The effective tier from an already-authenticated caller. Production CLI
|
|
21
|
+
* omits this and lets the runner read `getSubscriptionStatus().tier`.
|
|
23
22
|
*/
|
|
24
23
|
tier?: Tier;
|
|
25
24
|
/** Test seam — defaults to `cryptoService.decryptContent`. */
|
|
@@ -84,8 +84,8 @@ export declare function resolveLaunchMode(args: Pick<ParsedCliArgs, 'agent'>, ti
|
|
|
84
84
|
* Authentication, encryption, and backend admission are hard prerequisites.
|
|
85
85
|
* Failures propagate to `main`, which exits before opening the shell.
|
|
86
86
|
*
|
|
87
|
-
* The tier is resolved here too (§3.C.19):
|
|
88
|
-
*
|
|
87
|
+
* The tier is resolved here too (§3.C.19): `getSubscriptionStatus` must
|
|
88
|
+
* succeed unless a test passes the explicit `deps.tier` seam.
|
|
89
89
|
*/
|
|
90
90
|
export declare function resumeOrCreateSession(appsyncClient: AppSyncClient, deps?: {
|
|
91
91
|
resolveSessionIdFn?: (client: AppSyncClient) => Promise<string | null>;
|
|
@@ -6832,6 +6832,8 @@ function formatTokens(n) {
|
|
|
6832
6832
|
}
|
|
6833
6833
|
function renderProgressLine(event) {
|
|
6834
6834
|
switch (event.phase) {
|
|
6835
|
+
case "preparing_workspace":
|
|
6836
|
+
return "Preparing an isolated workspace copy \u2014 this can take a while on a large folder";
|
|
6835
6837
|
case "shadow_created":
|
|
6836
6838
|
return "Workspace copy ready \u2014 starting implementor";
|
|
6837
6839
|
case "implementor_running": {
|
|
@@ -7063,6 +7065,10 @@ var REFRESH_ONLY_PHASES = /* @__PURE__ */ new Set([
|
|
|
7063
7065
|
"not_applied",
|
|
7064
7066
|
"progress_cleared"
|
|
7065
7067
|
]), IMPLEMENT_REVIEW_PHASES = /* @__PURE__ */ new Set([
|
|
7068
|
+
// 2026-08-22 (Stage-1 MED-6) — the preparing window belongs to the same
|
|
7069
|
+
// IMPLEMENT family as `shadow_created`; omitting it would silently DROP any
|
|
7070
|
+
// REFRESH-ONLY event that arrives while it is open.
|
|
7071
|
+
"preparing_workspace",
|
|
7066
7072
|
"shadow_created",
|
|
7067
7073
|
"implementor_running",
|
|
7068
7074
|
"diff_captured",
|
|
@@ -23120,7 +23126,31 @@ var LocalGemmaPlannerAdapter = class {
|
|
|
23120
23126
|
};
|
|
23121
23127
|
|
|
23122
23128
|
// src/orchestration-shell/quorum-loop.ts
|
|
23123
|
-
var import_node_fs19 = require("node:fs")
|
|
23129
|
+
var import_node_fs19 = require("node:fs");
|
|
23130
|
+
|
|
23131
|
+
// src/reduced-trust-notice.ts
|
|
23132
|
+
var surfacedRationales = /* @__PURE__ */ new Set();
|
|
23133
|
+
function noticeKey(sessionId, tier, reason) {
|
|
23134
|
+
return `${sessionId}\0${tier}\0${reason}`;
|
|
23135
|
+
}
|
|
23136
|
+
function shouldSurfaceFullReducedTrustRationale(sessionId, tier, reason) {
|
|
23137
|
+
let key = noticeKey(sessionId, tier, reason);
|
|
23138
|
+
if (surfacedRationales.has(key)) return !1;
|
|
23139
|
+
if (surfacedRationales.size >= 512) {
|
|
23140
|
+
let oldest = surfacedRationales.values().next();
|
|
23141
|
+
oldest.done || surfacedRationales.delete(oldest.value);
|
|
23142
|
+
}
|
|
23143
|
+
return surfacedRationales.add(key), !0;
|
|
23144
|
+
}
|
|
23145
|
+
function releaseReducedTrustRationaleClaim(sessionId, tier, reason) {
|
|
23146
|
+
surfacedRationales.delete(noticeKey(sessionId, tier, reason));
|
|
23147
|
+
}
|
|
23148
|
+
function collapsedReducedTrustLine(actor) {
|
|
23149
|
+
return `${actor} is running with reduced trust (same posture as above).`;
|
|
23150
|
+
}
|
|
23151
|
+
|
|
23152
|
+
// src/orchestration-shell/quorum-loop.ts
|
|
23153
|
+
var path54 = __toESM(require("node:path")), os29 = __toESM(require("node:os")), import_uuid8 = require("uuid"), import_ulid4 = require("ulid");
|
|
23124
23154
|
|
|
23125
23155
|
// src/local-executor/authority.ts
|
|
23126
23156
|
var import_node_fs6 = require("node:fs"), path26 = __toESM(require("node:path")), AuthorityError = class extends Error {
|
|
@@ -26483,6 +26513,15 @@ var WorkspaceShadow = class _WorkspaceShadow {
|
|
|
26483
26513
|
get trackedSetForTests() {
|
|
26484
26514
|
return this.trackedSet;
|
|
26485
26515
|
}
|
|
26516
|
+
/**
|
|
26517
|
+
* Number of paths this shadow tracks. 2026-08-22 — exposed for the reviewer
|
|
26518
|
+
* timeout diagnostics: workspace SIZE is what separates "the diff was large"
|
|
26519
|
+
* from "the workspace was large" when a reviewer blows its wall clock, and
|
|
26520
|
+
* that distinction picks the fix. A count only; never the paths.
|
|
26521
|
+
*/
|
|
26522
|
+
get trackedCount() {
|
|
26523
|
+
return this.trackedSet.size;
|
|
26524
|
+
}
|
|
26486
26525
|
/** Exact user-root instance authenticated into reviewed team bundles. */
|
|
26487
26526
|
rootAuthorityForBundle() {
|
|
26488
26527
|
return { ...this.workspaceRootAuthority };
|
|
@@ -39174,7 +39213,7 @@ var LocalExecutorImpl = class {
|
|
|
39174
39213
|
`[LocalExecutorImpl] \u26A0\uFE0F CP-7 REDUCED-TRUST (tier=${tier}) \u2014 the trusted-execution moat is ${tier === "none" ? "OFF" : "WEAKENED"} for this implementor session: ${reason}`,
|
|
39175
39214
|
{ sessionId: this.sessionId, agentKind, tier, reducedTrust: !0 }
|
|
39176
39215
|
);
|
|
39177
|
-
let content = `\u26A0\uFE0F Reduced-trust mode: ${reason} The implementor's ambient credentials may be reachable; the trusted-execution moat is ${tier === "none" ? "OFF" : "weakened"} for this session
|
|
39216
|
+
let content = tier === "none" || shouldSurfaceFullReducedTrustRationale(this.sessionId, tier, reason) ? `\u26A0\uFE0F Reduced-trust mode: ${reason} The implementor's ambient credentials may be reachable; the trusted-execution moat is ${tier === "none" ? "OFF" : "weakened"} for this session.` : collapsedReducedTrustLine("The implementor"), metadata = {
|
|
39178
39217
|
source: "cp7_reduced_trust",
|
|
39179
39218
|
reducedTrust: !0,
|
|
39180
39219
|
tier,
|
|
@@ -47115,7 +47154,7 @@ var CONTINUATION_EXPIRES_TTL_MS = 1440 * 60 * 1e3, ACTIVE_AGENT_KINDS = ["CLAUDE
|
|
|
47115
47154
|
function isActiveAgentKind2(agent) {
|
|
47116
47155
|
return agent === "CLAUDE" || agent === "CODEX" || agent === "ANTIGRAVITY";
|
|
47117
47156
|
}
|
|
47118
|
-
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, REVIEWER_ERROR_LOG_RAW_OUTPUT_CAP = 4e3;
|
|
47157
|
+
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, BACKGROUND_RECOVERY_ABORTED = /* @__PURE__ */ Symbol("background-recovery-aborted"), REVIEWER_ERROR_LOG_RAW_OUTPUT_CAP = 4e3;
|
|
47119
47158
|
function describeReviewerErrorDetail(detail) {
|
|
47120
47159
|
switch (detail.kind) {
|
|
47121
47160
|
case "timeout":
|
|
@@ -47898,6 +47937,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
47898
47937
|
* never call each other), so it cannot self-deadlock.
|
|
47899
47938
|
*/
|
|
47900
47939
|
this.shadowOpsByTask = /* @__PURE__ */ new Map();
|
|
47940
|
+
/** Abort only the read-only waits owned by non-draining startup recovery. */
|
|
47941
|
+
this.backgroundRecoveryAbortControllers = /* @__PURE__ */ new Set();
|
|
47901
47942
|
/** Once set, no new implementor workspace may be created for this session. */
|
|
47902
47943
|
this.shuttingDown = !1;
|
|
47903
47944
|
/**
|
|
@@ -48057,6 +48098,17 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
48057
48098
|
this.releaseRecoveryRelaunchPermit();
|
|
48058
48099
|
}
|
|
48059
48100
|
}
|
|
48101
|
+
awaitBackgroundRecoveryStep(work, signal) {
|
|
48102
|
+
return signal ? signal.aborted ? Promise.reject(BACKGROUND_RECOVERY_ABORTED) : new Promise((resolve18, reject) => {
|
|
48103
|
+
let settled = !1, finish = (complete) => {
|
|
48104
|
+
settled || (settled = !0, signal.removeEventListener("abort", onAbort), complete());
|
|
48105
|
+
}, onAbort = () => finish(() => reject(BACKGROUND_RECOVERY_ABORTED));
|
|
48106
|
+
signal.addEventListener("abort", onAbort, { once: !0 }), work.then(
|
|
48107
|
+
(value) => finish(() => resolve18(value)),
|
|
48108
|
+
(err) => finish(() => reject(err))
|
|
48109
|
+
);
|
|
48110
|
+
}) : work;
|
|
48111
|
+
}
|
|
48060
48112
|
/**
|
|
48061
48113
|
* Serialize one shadow lifecycle op for `taskId` behind any in-flight op for
|
|
48062
48114
|
* the same task. The op's result/rejection is returned to ITS caller; a
|
|
@@ -49047,6 +49099,10 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
49047
49099
|
roundActive = !1, tickTimer && (clearInterval(tickTimer), tickTimer = null);
|
|
49048
49100
|
}, roundBriefForSpawn = args.brief, copiedForSpawn = [];
|
|
49049
49101
|
try {
|
|
49102
|
+
this.emitProgressForTask(args.taskId, originEpoch, {
|
|
49103
|
+
phase: "preparing_workspace",
|
|
49104
|
+
round: args.roundNumber
|
|
49105
|
+
});
|
|
49050
49106
|
let shadow = await this.ensureShadow(args.taskId);
|
|
49051
49107
|
if (this.teamRunIsHalted(args.teamAuthority)) return;
|
|
49052
49108
|
let snapshotAuthority = shadow.snapshotAuthorityForDispatch();
|
|
@@ -50611,7 +50667,9 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50611
50667
|
role: args.role,
|
|
50612
50668
|
agentKind: args.agentKind,
|
|
50613
50669
|
guardMs: SEAT_EVALUATE_TIMEOUT_MS,
|
|
50614
|
-
audit: "synthesized ESCALATE (#C1F-8): reviewer_error:timeout (seat-guard)"
|
|
50670
|
+
audit: "synthesized ESCALATE (#C1F-8): reviewer_error:timeout (seat-guard)",
|
|
50671
|
+
// 2026-08-22 — same timeout diagnostics as the inner path (below).
|
|
50672
|
+
...this.describeReviewShapeForDiagnostics(args.gateId)
|
|
50615
50673
|
}), verdict = this.synthesizeEscalate(args, cleanReasoning);
|
|
50616
50674
|
} else if (err instanceof ReviewerErrorClass) {
|
|
50617
50675
|
let failureReason = failureReasonFromDetail(err.detail), cleanReasoning = failureReasonTemplate(args.agentKind, failureReason);
|
|
@@ -50625,7 +50683,21 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50625
50683
|
// Audit prefix kept in LOGS only (#C1F-8) — never on the wire.
|
|
50626
50684
|
audit: `synthesized ESCALATE (#C1F-8): reviewer_error:${err.detail.kind}`,
|
|
50627
50685
|
...describeReviewerErrorDetail(err.detail),
|
|
50628
|
-
message: err.message
|
|
50686
|
+
message: err.message,
|
|
50687
|
+
// 2026-08-22 (dogfood) — TIMEOUT DIAGNOSTICS, local log only.
|
|
50688
|
+
//
|
|
50689
|
+
// A live 5-minute reviewer timeout on a ONE-FILE deletion diff was
|
|
50690
|
+
// not root-causable from this record: it says the wall expired but
|
|
50691
|
+
// nothing about what the reviewer was up against. Without the
|
|
50692
|
+
// review's shape you cannot separate "the diff was genuinely large"
|
|
50693
|
+
// from "the reviewer wandered the workspace" from "the host was
|
|
50694
|
+
// saturated" — the three have different fixes, and guessing between
|
|
50695
|
+
// them is how a one-off gets mistaken for a systemic defect.
|
|
50696
|
+
//
|
|
50697
|
+
// Emitted for EVERY reviewer error (cheap, and a spawn_failed
|
|
50698
|
+
// benefits from the same shape context). All values are counts and
|
|
50699
|
+
// labels — no diff content, no agent output, nothing on the wire.
|
|
50700
|
+
...this.describeReviewShapeForDiagnostics(args.gateId)
|
|
50629
50701
|
}), verdict = this.synthesizeEscalate(args, cleanReasoning);
|
|
50630
50702
|
} else
|
|
50631
50703
|
throw err;
|
|
@@ -50767,17 +50839,58 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
50767
50839
|
agentKind: args.agentKind,
|
|
50768
50840
|
reason
|
|
50769
50841
|
});
|
|
50842
|
+
let claimedFullRationale = !1;
|
|
50770
50843
|
try {
|
|
50771
|
-
this.
|
|
50772
|
-
|
|
50844
|
+
let actor = `Reviewer (${seatLabel(args.agentKind, args.seatId)})`, sessionId = this.deps.session.sessionId;
|
|
50845
|
+
claimedFullRationale = shouldSurfaceFullReducedTrustRationale(
|
|
50846
|
+
sessionId,
|
|
50847
|
+
"reviewer",
|
|
50848
|
+
reason
|
|
50849
|
+
), this.surfaceHalt(
|
|
50850
|
+
claimedFullRationale ? `${actor} is running with reduced trust: ${reason}` : collapsedReducedTrustLine(actor)
|
|
50773
50851
|
);
|
|
50774
50852
|
} catch (e) {
|
|
50775
|
-
|
|
50853
|
+
claimedFullRationale && releaseReducedTrustRationaleClaim(
|
|
50854
|
+
this.deps.session.sessionId,
|
|
50855
|
+
"reviewer",
|
|
50856
|
+
reason
|
|
50857
|
+
), logger.warn("[QuorumLoop] reduced-trust badge surfaceHalt threw (badge is best-effort) \u2014 continuing", {
|
|
50776
50858
|
seatId: args.seatId,
|
|
50777
50859
|
err: e.message
|
|
50778
50860
|
});
|
|
50779
50861
|
}
|
|
50780
50862
|
}
|
|
50863
|
+
/**
|
|
50864
|
+
* Local-only shape summary of the review a failing seat was working on.
|
|
50865
|
+
*
|
|
50866
|
+
* 2026-08-22 (dogfood): a reviewer wall-clock expiry told us WHEN it gave up
|
|
50867
|
+
* and nothing about WHAT it faced, so a single load-induced timeout on a
|
|
50868
|
+
* one-file diff looked indistinguishable from a systemic defect. These counts
|
|
50869
|
+
* separate the three candidate causes (big diff / big workspace / saturated
|
|
50870
|
+
* host) on the next occurrence.
|
|
50871
|
+
*
|
|
50872
|
+
* Counts and labels ONLY — never diff content, paths, or agent output. This
|
|
50873
|
+
* feeds a `logger.warn` that stays on the desktop; nothing here reaches the
|
|
50874
|
+
* wire. Fail-soft: diagnostics must never throw inside an error handler.
|
|
50875
|
+
*/
|
|
50876
|
+
describeReviewShapeForDiagnostics(gateId) {
|
|
50877
|
+
try {
|
|
50878
|
+
let taskId = this.taskByGateId.get(gateId), reviewed = taskId ? this.reviewedSnapshotByTask.get(taskId) : void 0, shadow = taskId ? this.shadowForTask(taskId) : void 0;
|
|
50879
|
+
return {
|
|
50880
|
+
diagReviewFiles: reviewed?.length ?? null,
|
|
50881
|
+
// Stage-2 R1 LOW-3: `.length` counts UTF-16 code units, not bytes, so a
|
|
50882
|
+
// diff of multi-byte source under-reported against a byte-named field.
|
|
50883
|
+
// `Buffer.byteLength` is the idiom already used in this file (~:774).
|
|
50884
|
+
diagReviewBytes: reviewed?.reduce(
|
|
50885
|
+
(sum, f) => sum + (f.content ? Buffer.byteLength(f.content, "utf8") : 0),
|
|
50886
|
+
0
|
|
50887
|
+
) ?? null,
|
|
50888
|
+
diagWorkspaceTracked: shadow?.trackedCount ?? null
|
|
50889
|
+
};
|
|
50890
|
+
} catch {
|
|
50891
|
+
return { diagReviewFiles: null, diagUnavailable: !0 };
|
|
50892
|
+
}
|
|
50893
|
+
}
|
|
50781
50894
|
// ─── CP-14 Wave B — confined class-2 resolver + final-tip Tier-2 dispatch ────
|
|
50782
50895
|
/**
|
|
50783
50896
|
* Wave B §2.1 confinement TRI-STATE for a merge-gate model/reviewer invocation
|
|
@@ -51240,17 +51353,25 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
51240
51353
|
* while `pending` and un-expired), so the approved code is never lost; a
|
|
51241
51354
|
* re-delivered packet (or the next live edge) promotes it.
|
|
51242
51355
|
*/
|
|
51243
|
-
recoverShadows() {
|
|
51244
|
-
|
|
51356
|
+
recoverShadows(opts = {}) {
|
|
51357
|
+
if (opts.drainOnShutdown ?? !0)
|
|
51358
|
+
return this.startSessionWork((admission2) => this.recoverShadowsOwned(admission2));
|
|
51359
|
+
if (this.shuttingDown) return Promise.resolve();
|
|
51360
|
+
let admission = /* @__PURE__ */ Symbol("quorum-background-recovery"), controller = new AbortController();
|
|
51361
|
+
this.backgroundRecoveryAbortControllers.add(controller);
|
|
51362
|
+
let recovery = this.recoverShadowsOwned(admission, controller.signal), release = () => {
|
|
51363
|
+
this.backgroundRecoveryAbortControllers.delete(controller);
|
|
51364
|
+
};
|
|
51365
|
+
return recovery.then(release, release), recovery;
|
|
51245
51366
|
}
|
|
51246
|
-
async recoverShadowsOwned(admission) {
|
|
51367
|
+
async recoverShadowsOwned(admission, signal) {
|
|
51247
51368
|
if (this.admittedSessionWorkMayContinue(admission))
|
|
51248
51369
|
try {
|
|
51249
|
-
let env = this.deps.shadowEnv ?? {}, [recoverable, canonicalWorkingDir, currentOwner] = await Promise.all([
|
|
51370
|
+
let env = this.deps.shadowEnv ?? {}, [recoverable, canonicalWorkingDir, currentOwner] = await this.awaitBackgroundRecoveryStep(Promise.all([
|
|
51250
51371
|
(this.deps.shadowRecoveryOps?.listRecoverableShadows ?? listRecoverableShadows)(env),
|
|
51251
51372
|
(this.deps.shadowRecoveryOps?.captureWorkspaceRootAuthority ?? captureWorkspaceRootAuthority)(this.deps.workingDir).then((authority) => authority.canonicalPath),
|
|
51252
51373
|
currentProcessIdentity()
|
|
51253
|
-
]);
|
|
51374
|
+
]), signal);
|
|
51254
51375
|
if (!this.admittedSessionWorkMayContinue(admission)) return;
|
|
51255
51376
|
let now = Date.now(), ttlMs = env.ttlMs ?? DEFAULT_SHADOW_TTL_MS, keep = /* @__PURE__ */ new Set();
|
|
51256
51377
|
this.activeTaskId && keep.add(this.activeTaskId);
|
|
@@ -51273,9 +51394,15 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
51273
51394
|
try {
|
|
51274
51395
|
await this.runExclusiveShadowOp(recovered.taskId, async () => {
|
|
51275
51396
|
if (!this.admittedSessionWorkMayContinue(admission) || this.shadowsByTask.get(recovered.taskId)?.matchesRecoveredInstance(recovered)) return;
|
|
51276
|
-
if (!(recovered.ownerProcessIdentity.pid === currentOwner.pid && recovered.ownerProcessIdentity.incarnationId === currentOwner.incarnationId) && await
|
|
51397
|
+
if (!(recovered.ownerProcessIdentity.pid === currentOwner.pid && recovered.ownerProcessIdentity.incarnationId === currentOwner.incarnationId) && await this.awaitBackgroundRecoveryStep(
|
|
51398
|
+
isProcessIdentityAlive(recovered.ownerProcessIdentity),
|
|
51399
|
+
signal
|
|
51400
|
+
))
|
|
51277
51401
|
throw new Error("recoverable workspace belongs to another live process");
|
|
51278
|
-
let shadow = await
|
|
51402
|
+
let shadow = await this.awaitBackgroundRecoveryStep(
|
|
51403
|
+
(this.deps.shadowRecoveryOps?.reopenShadow ?? reopenShadow)(recovered, env),
|
|
51404
|
+
signal
|
|
51405
|
+
);
|
|
51279
51406
|
if (!this.admittedSessionWorkMayContinue(admission) || !shadow) return;
|
|
51280
51407
|
if (!shadow.matchesRecoveredInstance(recovered))
|
|
51281
51408
|
throw new Error("reopened recovery snapshot changed exact authority");
|
|
@@ -51294,6 +51421,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
51294
51421
|
));
|
|
51295
51422
|
});
|
|
51296
51423
|
} catch (err) {
|
|
51424
|
+
if (err === BACKGROUND_RECOVERY_ABORTED) return;
|
|
51297
51425
|
failures.push(this.rememberWorkspaceLifecycleFailure(
|
|
51298
51426
|
err,
|
|
51299
51427
|
`workspace ${recovered.taskId} recovery reconciliation failed`
|
|
@@ -51311,6 +51439,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
51311
51439
|
causes: failures
|
|
51312
51440
|
});
|
|
51313
51441
|
} catch (err) {
|
|
51442
|
+
if (err === BACKGROUND_RECOVERY_ABORTED || !this.admittedSessionWorkMayContinue(admission)) return;
|
|
51314
51443
|
let failure = this.rememberWorkspaceLifecycleFailure(
|
|
51315
51444
|
err,
|
|
51316
51445
|
"workspace recovery/GC sweep failed"
|
|
@@ -51446,7 +51575,10 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
51446
51575
|
}
|
|
51447
51576
|
async disposeWorkspaces(opts = {}) {
|
|
51448
51577
|
let strict = opts.strict ?? !0;
|
|
51449
|
-
this.shuttingDown = !0
|
|
51578
|
+
this.shuttingDown = !0;
|
|
51579
|
+
for (let controller of this.backgroundRecoveryAbortControllers)
|
|
51580
|
+
controller.abort();
|
|
51581
|
+
this.cancelRecoveryRelaunchWaiters(), this.pendingB1TaskGroupId = null, this.subscriptionReady = !1, this.bufferedTeamPackets.length = 0, this.pendingGateDispatches.length = 0;
|
|
51450
51582
|
let failures = [], pendingImplementors = [...this.pendingImplementorByGate.values()];
|
|
51451
51583
|
for (let pending of pendingImplementors)
|
|
51452
51584
|
try {
|
|
@@ -53997,7 +54129,7 @@ async function runOrchestrationShell(args) {
|
|
|
53997
54129
|
{ error: err.message }
|
|
53998
54130
|
);
|
|
53999
54131
|
}
|
|
54000
|
-
args.quorumLoop && args.quorumLoop.recoverShadows().catch((err) => {
|
|
54132
|
+
args.quorumLoop && args.quorumLoop.recoverShadows({ drainOnShutdown: !1 }).catch((err) => {
|
|
54001
54133
|
logger.warn("[orchestration-shell] startup workspace recovery failed", {
|
|
54002
54134
|
error: err.message
|
|
54003
54135
|
});
|
|
@@ -58973,6 +59105,7 @@ async function findPendingForIntent(intent, logger2) {
|
|
|
58973
59105
|
var DEFINITIVE_CREATE_REJECTIONS = /* @__PURE__ */ new Set([
|
|
58974
59106
|
"AccountDeletionInProgress",
|
|
58975
59107
|
"CreationRequestConflict",
|
|
59108
|
+
"InvalidSessionStatus",
|
|
58976
59109
|
"RateLimited",
|
|
58977
59110
|
"SessionIdReserved",
|
|
58978
59111
|
"SessionIdRetired",
|
|
@@ -58982,6 +59115,7 @@ var DEFINITIVE_CREATE_REJECTIONS = /* @__PURE__ */ new Set([
|
|
|
58982
59115
|
"UnauthorizedException"
|
|
58983
59116
|
]), DEFINITIVE_CREATE_REJECTION_CODES = /* @__PURE__ */ new Set([
|
|
58984
59117
|
"RATE_LIMITED",
|
|
59118
|
+
"INVALID_SESSION_STATUS",
|
|
58985
59119
|
"SESSION_ID_RESERVED",
|
|
58986
59120
|
"SESSION_LIMIT_EXCEEDED",
|
|
58987
59121
|
"UNAUTHORIZED"
|
|
@@ -62742,9 +62876,6 @@ async function resumeOrCreateSession2(appsyncClient, deps) {
|
|
|
62742
62876
|
}
|
|
62743
62877
|
}
|
|
62744
62878
|
async function resolveCliTier(appsyncClient) {
|
|
62745
|
-
let envTier = process.env.CODEVIBE_TIER;
|
|
62746
|
-
if (envTier === "FREE" || envTier === "PRO" || envTier === "MAX")
|
|
62747
|
-
return envTier;
|
|
62748
62879
|
try {
|
|
62749
62880
|
return (await appsyncClient.getSubscriptionStatus()).tier;
|
|
62750
62881
|
} catch (err) {
|
|
@@ -63031,15 +63162,17 @@ async function runAuditCli(parsed, deps) {
|
|
|
63031
63162
|
`Usage: codevibe audit show <task-id> [--json] [--session <session-id>]
|
|
63032
63163
|
`
|
|
63033
63164
|
), 2;
|
|
63034
|
-
let appsyncClient = deps?.appsyncClient ?? new AppSyncClient();
|
|
63165
|
+
let appsyncClient = deps?.appsyncClient ?? new AppSyncClient(), authenticated;
|
|
63035
63166
|
try {
|
|
63036
|
-
await appsyncClient.authenticateWithStoredTokens();
|
|
63167
|
+
authenticated = await appsyncClient.authenticateWithStoredTokens();
|
|
63037
63168
|
} catch (e) {
|
|
63038
63169
|
return err(
|
|
63039
63170
|
`Not signed in \u2014 run \`codevibe login\` first (${e?.message ?? "auth unavailable"}).
|
|
63040
63171
|
`
|
|
63041
63172
|
), 2;
|
|
63042
63173
|
}
|
|
63174
|
+
if (!authenticated)
|
|
63175
|
+
return err("Not signed in \u2014 run `codevibe login` first.\n"), 2;
|
|
63043
63176
|
let sessionId = parsed.sessionId ?? null;
|
|
63044
63177
|
if (!sessionId) {
|
|
63045
63178
|
let resolveSessionId = deps?.resolveSessionIdFn ?? resolveActiveSessionId;
|
|
@@ -63059,10 +63192,7 @@ async function runAuditCli(parsed, deps) {
|
|
|
63059
63192
|
let result = await runAuditBrowser({
|
|
63060
63193
|
appsyncClient,
|
|
63061
63194
|
taskId: parsed.taskId,
|
|
63062
|
-
sessionId
|
|
63063
|
-
// Honor CODEVIBE_TIER for the Max gate (same override the rest of the CLI
|
|
63064
|
-
// uses); when FREE/PRO/unset the runner falls back to getSubscriptionStatus.
|
|
63065
|
-
tier: process.env.CODEVIBE_TIER === "MAX" || process.env.CODEVIBE_TIER === "PRO" || process.env.CODEVIBE_TIER === "FREE" ? process.env.CODEVIBE_TIER : void 0
|
|
63195
|
+
sessionId
|
|
63066
63196
|
});
|
|
63067
63197
|
return parsed.json ? (out(`${JSON.stringify(result, null, 2)}
|
|
63068
63198
|
`), 0) : (out(`${renderAuditResultText(result)}
|
|
@@ -63127,9 +63257,9 @@ Run codevibe --help for usage.
|
|
|
63127
63257
|
error: err?.message
|
|
63128
63258
|
});
|
|
63129
63259
|
});
|
|
63130
|
-
let localModelState = await readLocalModelState(),
|
|
63260
|
+
let localModelState = await readLocalModelState(), localModelEntitlement = {
|
|
63131
63261
|
tier,
|
|
63132
|
-
source:
|
|
63262
|
+
source: "backend"
|
|
63133
63263
|
}, localModelBoot = resolveLocalModelBoot({
|
|
63134
63264
|
requestedMode: mode,
|
|
63135
63265
|
entitlement: localModelEntitlement,
|
|
@@ -369,8 +369,8 @@ export interface QuorumLoopDeps {
|
|
|
369
369
|
*/
|
|
370
370
|
detectedAgents?: string[];
|
|
371
371
|
/**
|
|
372
|
-
* #585 auto-continuation (Max) — the resolved subscription tier
|
|
373
|
-
*
|
|
372
|
+
* #585 auto-continuation (Max) — the resolved authenticated subscription tier
|
|
373
|
+
* threaded from CLI startup/resume.
|
|
374
374
|
* MAX → a quota-exhausted continuation handoff AUTO-ACCEPTS on the strongest
|
|
375
375
|
* available agent (no prompt). Pro/Free/unresolved/absent → the existing
|
|
376
376
|
* `continuation_offer_handoff` prompt (fail-closed). Auto-continuation only
|
|
@@ -1095,8 +1095,11 @@ export declare class QuorumLoop {
|
|
|
1095
1095
|
* never call each other), so it cannot self-deadlock.
|
|
1096
1096
|
*/
|
|
1097
1097
|
private readonly shadowOpsByTask;
|
|
1098
|
+
/** Abort only the read-only waits owned by non-draining startup recovery. */
|
|
1099
|
+
private readonly backgroundRecoveryAbortControllers;
|
|
1098
1100
|
/** Once set, no new implementor workspace may be created for this session. */
|
|
1099
1101
|
private shuttingDown;
|
|
1102
|
+
private awaitBackgroundRecoveryStep;
|
|
1100
1103
|
/**
|
|
1101
1104
|
* Serialize one shadow lifecycle op for `taskId` behind any in-flight op for
|
|
1102
1105
|
* the same task. The op's result/rejection is returned to ITS caller; a
|
|
@@ -1818,6 +1821,20 @@ export declare class QuorumLoop {
|
|
|
1818
1821
|
* RUNS (it always runs; the badge only informs the user).
|
|
1819
1822
|
*/
|
|
1820
1823
|
private surfaceReviewerReducedTrust;
|
|
1824
|
+
/**
|
|
1825
|
+
* Local-only shape summary of the review a failing seat was working on.
|
|
1826
|
+
*
|
|
1827
|
+
* 2026-08-22 (dogfood): a reviewer wall-clock expiry told us WHEN it gave up
|
|
1828
|
+
* and nothing about WHAT it faced, so a single load-induced timeout on a
|
|
1829
|
+
* one-file diff looked indistinguishable from a systemic defect. These counts
|
|
1830
|
+
* separate the three candidate causes (big diff / big workspace / saturated
|
|
1831
|
+
* host) on the next occurrence.
|
|
1832
|
+
*
|
|
1833
|
+
* Counts and labels ONLY — never diff content, paths, or agent output. This
|
|
1834
|
+
* feeds a `logger.warn` that stays on the desktop; nothing here reaches the
|
|
1835
|
+
* wire. Fail-soft: diagnostics must never throw inside an error handler.
|
|
1836
|
+
*/
|
|
1837
|
+
private describeReviewShapeForDiagnostics;
|
|
1821
1838
|
/**
|
|
1822
1839
|
* Wave B §2.1 confinement TRI-STATE for a merge-gate model/reviewer invocation
|
|
1823
1840
|
* (LOCK #C14-MOAT). Path A: the CP-7 substrate/broker (not opted out + a Trusted
|
|
@@ -1985,7 +2002,9 @@ export declare class QuorumLoop {
|
|
|
1985
2002
|
* while `pending` and un-expired), so the approved code is never lost; a
|
|
1986
2003
|
* re-delivered packet (or the next live edge) promotes it.
|
|
1987
2004
|
*/
|
|
1988
|
-
recoverShadows(
|
|
2005
|
+
recoverShadows(opts?: {
|
|
2006
|
+
drainOnShutdown?: boolean;
|
|
2007
|
+
}): Promise<void>;
|
|
1989
2008
|
private recoverShadowsOwned;
|
|
1990
2009
|
/**
|
|
1991
2010
|
* Session-exit ownership boundary. Stop future creates, wait behind every
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session de-duplication for the CP-7 reduced-trust rationale.
|
|
3
|
+
*
|
|
4
|
+
* WHY (2026-08-22, dogfood): the reduced-trust rationale is ~600 characters and
|
|
5
|
+
* was surfaced in FULL once per agent — implementor, reviewer seat 0, reviewer
|
|
6
|
+
* seat 1 — so a single one-file task printed roughly 1.8 KB of identical
|
|
7
|
+
* boilerplate that buried the actual progress milestones. In the live transcript
|
|
8
|
+
* the banner outweighed every `●` line combined.
|
|
9
|
+
*
|
|
10
|
+
* The rationale is genuinely important the FIRST time: it tells the operator the
|
|
11
|
+
* trusted-execution moat is weakened for this session and why. It carries no new
|
|
12
|
+
* information on the second and third repetition within the same session, where
|
|
13
|
+
* the tier and reason are identical.
|
|
14
|
+
*
|
|
15
|
+
* So: surface the full rationale ONCE per (session, tier, reason), and collapse
|
|
16
|
+
* every later occurrence to a one-line reminder that still names the actor. The
|
|
17
|
+
* WARN log is unaffected — the durable forensic record keeps every occurrence in
|
|
18
|
+
* full; only the user-facing surface is de-duplicated.
|
|
19
|
+
*
|
|
20
|
+
* Keyed on (sessionId, tier, reason) rather than sessionId alone so a session
|
|
21
|
+
* that DEGRADES (e.g. `sandbox_exec` → `none`, or a different reason) surfaces
|
|
22
|
+
* the new rationale in full rather than silently collapsing a more severe
|
|
23
|
+
* posture into a one-liner.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* True the FIRST time this exact (session, tier, reason) rationale is surfaced;
|
|
27
|
+
* false for every later call. Call once per user-facing surfacing decision.
|
|
28
|
+
*/
|
|
29
|
+
export declare function shouldSurfaceFullReducedTrustRationale(sessionId: string, tier: string, reason: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Undo a claim (Stage-1 LOW-15). The caller test-and-sets BEFORE surfacing, so
|
|
32
|
+
* a surfacing that then THROWS would otherwise burn the "first" slot: every
|
|
33
|
+
* later actor collapses to "(same posture as above)" pointing at a rationale
|
|
34
|
+
* the operator never saw. Callers that surface fallibly must release on failure.
|
|
35
|
+
*/
|
|
36
|
+
export declare function releaseReducedTrustRationaleClaim(sessionId: string, tier: string, reason: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* The collapsed one-line form for a repeat occurrence. Names the actor so the
|
|
39
|
+
* operator can still see WHICH agent is reduced-trust, and points at the full
|
|
40
|
+
* rationale already in scrollback.
|
|
41
|
+
*/
|
|
42
|
+
export declare function collapsedReducedTrustLine(actor: string): string;
|
|
43
|
+
/** Test-only reset — the Set is module-global and would leak across cases. */
|
|
44
|
+
export declare function __resetReducedTrustNoticesForTest(): void;
|
|
@@ -48,6 +48,13 @@ export interface ToolActivityTransport {
|
|
|
48
48
|
* undecryptable generation forever (a liveness/G2 failure on key rotation).
|
|
49
49
|
*/
|
|
50
50
|
export declare function isSessionKeyStaleError(err: unknown): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* True only when the backend has proved that this session generation can never
|
|
53
|
+
* accept another event. These errors settle the durable window terminally;
|
|
54
|
+
* key rotation, contention, throttling, networking, and unknown failures remain
|
|
55
|
+
* retryable so recoverable tool activity is never discarded.
|
|
56
|
+
*/
|
|
57
|
+
export declare function isTerminalSessionError(err: unknown): boolean;
|
|
51
58
|
export interface ToolActivityConsolidatorOptions {
|
|
52
59
|
agent: string;
|
|
53
60
|
/** The backend session id bound into each window's envelope (X2a routing). */
|