@quantiya/codevibe-claude-plugin 2.0.22 → 2.0.24
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/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +25 -0
- package/node_modules/@quantiya/codevibe-core/dist/appsync/index.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/config/config.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/diagnostics/shape-only.d.ts +11 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +329 -290
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/process-tree.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/o5-diagnostics.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/quorum-loop-outcome-recency.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +888 -225
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +12 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/types.d.ts +24 -0
- package/node_modules/@quantiya/codevibe-core/dist/ordinal-presentation.d.ts +4 -0
- package/node_modules/@quantiya/codevibe-core/dist/ordinal-presentation.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/provider.d.ts +7 -7
- package/node_modules/@quantiya/codevibe-core/dist/substrate/command-runner.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/substrate/sandbox-exec.d.ts +3 -2
- package/node_modules/@quantiya/codevibe-core/dist/substrate/types.d.ts +20 -0
- package/node_modules/@quantiya/codevibe-core/dist/substrate-launch/apikey-bootstrap.d.ts +32 -1
- package/node_modules/@quantiya/codevibe-core/dist/substrate-launch/engage-substrate.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/substrate-launch/sanitized-env.d.ts +6 -0
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
- package/node_modules/fs-ext/build/Makefile +0 -347
- package/node_modules/fs-ext/build/Release/.deps/Release/fs_ext.node.d +0 -1
- package/node_modules/fs-ext/build/Release/.deps/Release/obj.target/fs_ext/fs-ext.o.d +0 -165
- 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/binding.Makefile +0 -6
- package/node_modules/fs-ext/build/config.gypi +0 -503
- package/node_modules/fs-ext/build/fs_ext.target.mk +0 -183
- package/node_modules/fs-ext/build/gyp-mac-tool +0 -768
- package/node_modules/keytar/build/Release/keytar.node +0 -0
|
@@ -1042,6 +1042,7 @@ __export(cli_exports, {
|
|
|
1042
1042
|
CliEntitlementError: () => CliEntitlementError,
|
|
1043
1043
|
CliUsageError: () => CliUsageError,
|
|
1044
1044
|
LocalModelPlannerUnavailableAdapter: () => LocalModelPlannerUnavailableAdapter,
|
|
1045
|
+
ORCHESTRATION_ORPHAN_SWEEP_STALE_THRESHOLD_MS: () => ORCHESTRATION_ORPHAN_SWEEP_STALE_THRESHOLD_MS,
|
|
1045
1046
|
OrchestrationSessionBootstrapError: () => OrchestrationSessionBootstrapError,
|
|
1046
1047
|
PlannerUnavailableError: () => PlannerUnavailableError,
|
|
1047
1048
|
bridgeAuthorityErrorToShellRefusal: () => bridgeAuthorityErrorToShellRefusal,
|
|
@@ -1067,7 +1068,8 @@ __export(cli_exports, {
|
|
|
1067
1068
|
resumeOrCreateSession: () => resumeOrCreateSession2,
|
|
1068
1069
|
runAuditCli: () => runAuditCli,
|
|
1069
1070
|
runModelCli: () => runModelCli,
|
|
1070
|
-
runWithAdmittedSessionOwnership: () => runWithAdmittedSessionOwnership
|
|
1071
|
+
runWithAdmittedSessionOwnership: () => runWithAdmittedSessionOwnership,
|
|
1072
|
+
triggerStartupOrphanSweep: () => triggerStartupOrphanSweep
|
|
1071
1073
|
});
|
|
1072
1074
|
module.exports = __toCommonJS(cli_exports);
|
|
1073
1075
|
var import_node_crypto19 = require("node:crypto");
|
|
@@ -1173,9 +1175,9 @@ var import_os = __toESM(require("os")), import_path = __toESM(require("path")),
|
|
|
1173
1175
|
}
|
|
1174
1176
|
}
|
|
1175
1177
|
}, currentConfig = null, configInitialized = !1;
|
|
1176
|
-
function getEnvironment() {
|
|
1177
|
-
let
|
|
1178
|
-
return
|
|
1178
|
+
function getEnvironment(env = process.env) {
|
|
1179
|
+
let target = env.ENVIRONMENT;
|
|
1180
|
+
return target === "development" || target === "production" || target === "experiment" ? target : "production";
|
|
1179
1181
|
}
|
|
1180
1182
|
function loadConfig(environment) {
|
|
1181
1183
|
let env = environment || getEnvironment();
|
|
@@ -4467,6 +4469,18 @@ var RECONNECT_CONFIG = {
|
|
|
4467
4469
|
function shouldDeliverSubscribedEvent(event, receiveDesktopEvents) {
|
|
4468
4470
|
return !!(event.source === "MOBILE" /* MOBILE */ || receiveDesktopEvents && event.source === "DESKTOP" /* DESKTOP */);
|
|
4469
4471
|
}
|
|
4472
|
+
var DEFAULT_HEARTBEAT_INTERVAL_MS = 12e4, MIN_HEARTBEAT_INTERVAL_MS = 1e3, MAX_HEARTBEAT_INTERVAL_MS = 3e5;
|
|
4473
|
+
function isRecognizedNonProductionEnvironment(env = process.env) {
|
|
4474
|
+
let canonicalEnv = getEnvironment(env);
|
|
4475
|
+
return canonicalEnv === "development" || canonicalEnv === "experiment";
|
|
4476
|
+
}
|
|
4477
|
+
function resolveHeartbeatIntervalMs(override, env = process.env) {
|
|
4478
|
+
let candidate;
|
|
4479
|
+
if (override !== void 0 ? candidate = override : isRecognizedNonProductionEnvironment(env) && env.CODEVIBE_HEARTBEAT_INTERVAL_MS !== void 0 && (candidate = env.CODEVIBE_HEARTBEAT_INTERVAL_MS), candidate == null || candidate === "")
|
|
4480
|
+
return DEFAULT_HEARTBEAT_INTERVAL_MS;
|
|
4481
|
+
let num = typeof candidate == "number" ? candidate : Number(candidate);
|
|
4482
|
+
return !Number.isFinite(num) || !Number.isInteger(num) || num < MIN_HEARTBEAT_INTERVAL_MS || num > MAX_HEARTBEAT_INTERVAL_MS ? DEFAULT_HEARTBEAT_INTERVAL_MS : num;
|
|
4483
|
+
}
|
|
4470
4484
|
var AppSyncClient = class _AppSyncClient {
|
|
4471
4485
|
constructor() {
|
|
4472
4486
|
this.authenticated = !1;
|
|
@@ -7212,14 +7226,14 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
7212
7226
|
* Start periodic heartbeat for a session.
|
|
7213
7227
|
* Updates lastHeartbeatAt on the session every intervalMs (default 2 minutes).
|
|
7214
7228
|
*/
|
|
7215
|
-
startHeartbeat(sessionId, intervalMs
|
|
7216
|
-
let existingConfirmation = this.heartbeatInitialPulses.get(sessionId);
|
|
7229
|
+
startHeartbeat(sessionId, intervalMs) {
|
|
7230
|
+
let effectiveIntervalMs = resolveHeartbeatIntervalMs(intervalMs), existingConfirmation = this.heartbeatInitialPulses.get(sessionId);
|
|
7217
7231
|
if (existingConfirmation) return existingConfirmation;
|
|
7218
|
-
let confirmation = this.startHeartbeatOutcome(sessionId,
|
|
7232
|
+
let confirmation = this.startHeartbeatOutcome(sessionId, effectiveIntervalMs).then((value) => (value === "retired" && this.notifyRetiredSession(sessionId), value === "confirmed"));
|
|
7219
7233
|
return this.heartbeatInitialPulses.set(sessionId, confirmation), confirmation;
|
|
7220
7234
|
}
|
|
7221
|
-
startHeartbeatOutcome(sessionId, intervalMs
|
|
7222
|
-
let existingToken = this.heartbeatTokens.get(sessionId), existingTimer = this.heartbeatTimers.get(sessionId);
|
|
7235
|
+
startHeartbeatOutcome(sessionId, intervalMs) {
|
|
7236
|
+
let effectiveIntervalMs = resolveHeartbeatIntervalMs(intervalMs), existingToken = this.heartbeatTokens.get(sessionId), existingTimer = this.heartbeatTimers.get(sessionId);
|
|
7223
7237
|
if (existingToken && existingTimer) {
|
|
7224
7238
|
let existingOutcome = this.heartbeatInitialOutcomes.get(sessionId);
|
|
7225
7239
|
if (existingOutcome) return existingOutcome;
|
|
@@ -7244,8 +7258,8 @@ var AppSyncClient = class _AppSyncClient {
|
|
|
7244
7258
|
).then((outcome) => {
|
|
7245
7259
|
outcome === "retired" && this.notifyRetiredSession(sessionId);
|
|
7246
7260
|
});
|
|
7247
|
-
},
|
|
7248
|
-
return this.heartbeatTimers.set(sessionId, timer), logger.info("[AppSyncClient] Heartbeat started", { sessionId, intervalMs }), initialHeartbeat;
|
|
7261
|
+
}, effectiveIntervalMs);
|
|
7262
|
+
return this.heartbeatTimers.set(sessionId, timer), logger.info("[AppSyncClient] Heartbeat started", { sessionId, intervalMs: effectiveIntervalMs }), initialHeartbeat;
|
|
7249
7263
|
}
|
|
7250
7264
|
/**
|
|
7251
7265
|
* Stop heartbeat for a session.
|
|
@@ -7945,6 +7959,14 @@ function sanitizeForTerminal(input) {
|
|
|
7945
7959
|
return out;
|
|
7946
7960
|
}
|
|
7947
7961
|
|
|
7962
|
+
// src/ordinal-presentation.ts
|
|
7963
|
+
function displayOrdinal(index) {
|
|
7964
|
+
return Number.isSafeInteger(index) && index >= 0 ? String(index + 1) : "?";
|
|
7965
|
+
}
|
|
7966
|
+
function displaySeatNumber(seatId) {
|
|
7967
|
+
return /^(0|[1-9][0-9]*)$/.test(seatId) ? displayOrdinal(Number(seatId)) : seatId;
|
|
7968
|
+
}
|
|
7969
|
+
|
|
7948
7970
|
// src/reviewer/token-usage.ts
|
|
7949
7971
|
function finiteToken(n) {
|
|
7950
7972
|
return tokenFieldAvailable(n) ? n : 0;
|
|
@@ -8123,7 +8145,7 @@ function renderProgressLine(event) {
|
|
|
8123
8145
|
return "Workspace copy ready \u2014 starting implementor";
|
|
8124
8146
|
case "implementor_running": {
|
|
8125
8147
|
let files = typeof event.filesChanged == "number" ? `, ${event.filesChanged} ${event.filesChanged === 1 ? "file" : "files"} changed` : "";
|
|
8126
|
-
return `Implementor working in shadow \u2014 round ${event.round}${files}`;
|
|
8148
|
+
return `Implementor working in shadow \u2014 round ${displayOrdinal(event.round)}${files}`;
|
|
8127
8149
|
}
|
|
8128
8150
|
case "diff_captured": {
|
|
8129
8151
|
let parts = [];
|
|
@@ -8132,7 +8154,7 @@ function renderProgressLine(event) {
|
|
|
8132
8154
|
return `Diff captured: ${event.files} ${event.files === 1 ? "file" : "files"}${breakdown}`;
|
|
8133
8155
|
}
|
|
8134
8156
|
case "submitting_diff":
|
|
8135
|
-
return `Submitting changes for review \u2014 round ${event.round}`;
|
|
8157
|
+
return `Submitting changes for review \u2014 round ${displayOrdinal(event.round)}`;
|
|
8136
8158
|
case "reviewers_dispatched":
|
|
8137
8159
|
return `Reviewers dispatched \u2014 ${event.seats} ${event.seats === 1 ? "seat" : "seats"}`;
|
|
8138
8160
|
case "seat_update":
|
|
@@ -8141,10 +8163,10 @@ function renderProgressLine(event) {
|
|
|
8141
8163
|
return `Verdicts ${event.received}/${event.expected} received`;
|
|
8142
8164
|
case "revise_round": {
|
|
8143
8165
|
let summary = event.feedbackSummary ? ` \u2014 ${event.feedbackSummary}` : "";
|
|
8144
|
-
return `Revise round ${event.round} \u2014 re-running implementor${summary}`;
|
|
8166
|
+
return `Revise round ${displayOrdinal(event.round)} \u2014 re-running implementor${summary}`;
|
|
8145
8167
|
}
|
|
8146
8168
|
case "round_failed":
|
|
8147
|
-
return `Implementor round ${event.round} failed \u2014 ${event.reason}`;
|
|
8169
|
+
return `Implementor round ${displayOrdinal(event.round)} failed \u2014 ${event.reason}`;
|
|
8148
8170
|
case "continuation_offered":
|
|
8149
8171
|
return `Implementor halted (${event.reason}) \u2014 choose a continuation agent`;
|
|
8150
8172
|
case "declared_tests_skipped":
|
|
@@ -8279,19 +8301,20 @@ function reducer(state, action) {
|
|
|
8279
8301
|
return reduceGateSummaryLoaded(state, action.gateId, action.panelModel);
|
|
8280
8302
|
// ─── CP-12 W3 team-track arms (per PHASE-CP-12-DESIGN.md §3.5) ──────────
|
|
8281
8303
|
case "TEAM_STARTED":
|
|
8282
|
-
return reduceTeamStarted(state, action.taskGroupId);
|
|
8304
|
+
return reduceTeamStarted(state, action.taskGroupId, action.startedAt);
|
|
8283
8305
|
case "TEAM_TRACK_ASSIGNED":
|
|
8284
8306
|
return reduceTeamTrackAssigned(
|
|
8285
8307
|
state,
|
|
8286
8308
|
action.trackIndex,
|
|
8287
8309
|
action.state,
|
|
8288
8310
|
action.taskId,
|
|
8289
|
-
action.agent
|
|
8311
|
+
action.agent,
|
|
8312
|
+
action.startedAt
|
|
8290
8313
|
);
|
|
8291
8314
|
case "TEAM_MERGE_GATE":
|
|
8292
8315
|
return reduceTeamMergeGate(state, action.status, action.startedAt, action.endedAt);
|
|
8293
8316
|
case "TEAM_HALTED":
|
|
8294
|
-
return reduceTeamHalted(state, action.haltReason);
|
|
8317
|
+
return reduceTeamHalted(state, action.haltReason, action.completedAt);
|
|
8295
8318
|
case "TEAM_TRACK_TERMINAL":
|
|
8296
8319
|
return reduceTeamTrackTerminal(state, action.trackIndex, action.state);
|
|
8297
8320
|
case "TEAM_TRACK_REVISING":
|
|
@@ -8299,7 +8322,7 @@ function reducer(state, action) {
|
|
|
8299
8322
|
case "TEAM_TRACK_AWAITING_DECISION":
|
|
8300
8323
|
return reduceTeamTrackTerminal(state, action.trackIndex, "AwaitingDecision");
|
|
8301
8324
|
case "TEAM_GROUP_RESOLVED":
|
|
8302
|
-
return reduceTeamGroupResolved(state, action.outcome);
|
|
8325
|
+
return reduceTeamGroupResolved(state, action.outcome, action.completedAt);
|
|
8303
8326
|
case "TASK_PROGRESS":
|
|
8304
8327
|
return reduceTaskProgress(
|
|
8305
8328
|
reduceReviewerStatusLine(
|
|
@@ -8410,19 +8433,26 @@ function reduceSessionTaskTerminal(state, event) {
|
|
|
8410
8433
|
if (terminal === null) return state;
|
|
8411
8434
|
let taskId = "taskId" in event ? event.taskId : void 0;
|
|
8412
8435
|
if (!taskId) return state;
|
|
8413
|
-
let runningTasks = new Map(state.runningTasks), evictedRunningTask = runningTasks.delete(taskId), existing = state.sessionTasks.get(taskId), sessionTasks = new Map(state.sessionTasks);
|
|
8436
|
+
let runningTasks = new Map(state.runningTasks), evictedRunningTask = runningTasks.delete(taskId), existing = state.sessionTasks.get(taskId), sessionTasks = new Map(state.sessionTasks), nextSeq = (state.terminalSequence ?? 0) + 1;
|
|
8414
8437
|
if (existing) {
|
|
8415
8438
|
if (existing.origin !== "single" || existing.status !== "running")
|
|
8416
8439
|
return evictedRunningTask ? { ...state, runningTasks } : state;
|
|
8417
|
-
sessionTasks.set(taskId, {
|
|
8440
|
+
sessionTasks.set(taskId, {
|
|
8441
|
+
...existing,
|
|
8442
|
+
status: terminal,
|
|
8443
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8444
|
+
terminalSeq: nextSeq
|
|
8445
|
+
});
|
|
8418
8446
|
} else
|
|
8419
8447
|
sessionTasks.set(taskId, {
|
|
8420
8448
|
taskId,
|
|
8421
8449
|
origin: "single",
|
|
8422
8450
|
status: terminal,
|
|
8423
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8451
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8452
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8453
|
+
terminalSeq: nextSeq
|
|
8424
8454
|
});
|
|
8425
|
-
return { ...state, runningTasks, sessionTasks };
|
|
8455
|
+
return { ...state, runningTasks, sessionTasks, terminalSequence: nextSeq };
|
|
8426
8456
|
}
|
|
8427
8457
|
var REVIEWER_STATUS_PHASES = /* @__PURE__ */ new Set([
|
|
8428
8458
|
"reviewers_dispatched",
|
|
@@ -8727,14 +8757,21 @@ function reduceClarificationAnswered(state, answer) {
|
|
|
8727
8757
|
function reduceTaskLifecycle(state, task) {
|
|
8728
8758
|
let existing = state.sessionTasks.get(task.taskId), existingIsTerminal = existing?.origin === "single" && (existing.status === "completed" || existing.status === "cancelled" || existing.status === "failed"), incomingIsTerminal = task.status === "completed" || task.status === "cancelled" || task.status === "failed", next = new Map(state.runningTasks);
|
|
8729
8759
|
incomingIsTerminal || existingIsTerminal && !incomingIsTerminal ? next.delete(task.taskId) : next.set(task.taskId, task);
|
|
8730
|
-
let history = new Map(state.sessionTasks);
|
|
8760
|
+
let history = new Map(state.sessionTasks), nextSeq = incomingIsTerminal ? existing?.terminalSeq ?? (state.terminalSequence ?? 0) + 1 : existing?.terminalSeq, terminalSequence = incomingIsTerminal && !existing?.terminalSeq ? nextSeq : state.terminalSequence;
|
|
8731
8761
|
return history.set(task.taskId, {
|
|
8732
8762
|
taskId: task.taskId,
|
|
8733
8763
|
agentKind: task.agentKind,
|
|
8734
8764
|
origin: "single",
|
|
8735
8765
|
status: existingIsTerminal && !incomingIsTerminal ? existing.status : task.status,
|
|
8736
|
-
startedAt: task.startedAt
|
|
8737
|
-
|
|
8766
|
+
startedAt: task.startedAt,
|
|
8767
|
+
completedAt: incomingIsTerminal ? task.completedAt ?? existing?.completedAt ?? task.startedAt : existing?.completedAt,
|
|
8768
|
+
...nextSeq !== void 0 ? { terminalSeq: nextSeq } : {}
|
|
8769
|
+
}), {
|
|
8770
|
+
...state,
|
|
8771
|
+
runningTasks: next,
|
|
8772
|
+
sessionTasks: history,
|
|
8773
|
+
...terminalSequence !== void 0 ? { terminalSequence } : {}
|
|
8774
|
+
};
|
|
8738
8775
|
}
|
|
8739
8776
|
function findUnfinalizedGatePromptIndex(state, taskId) {
|
|
8740
8777
|
for (let i = 0; i < state.conversation.length; i++) {
|
|
@@ -9059,28 +9096,38 @@ function reduceGateSummaryLoaded(state, gateId, panelModel) {
|
|
|
9059
9096
|
], attached = { ...state, conversation: nextConversation };
|
|
9060
9097
|
return isFirstLoad && panelModel.rounds.length > 0 ? appendConversation(attached, makeGateSummaryPanel(panelModel)) : attached;
|
|
9061
9098
|
}
|
|
9062
|
-
function reduceTeamStarted(state, taskGroupId) {
|
|
9099
|
+
function reduceTeamStarted(state, taskGroupId, startedAt) {
|
|
9063
9100
|
if (state.team) {
|
|
9064
9101
|
if (state.team.taskGroupId === taskGroupId)
|
|
9065
9102
|
return state;
|
|
9066
9103
|
if (state.team.taskGroupId === "")
|
|
9067
|
-
return {
|
|
9104
|
+
return {
|
|
9105
|
+
...state,
|
|
9106
|
+
team: {
|
|
9107
|
+
...state.team,
|
|
9108
|
+
taskGroupId,
|
|
9109
|
+
startedAt: state.team.startedAt ?? startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
9110
|
+
}
|
|
9111
|
+
};
|
|
9068
9112
|
}
|
|
9069
|
-
|
|
9113
|
+
let team = {
|
|
9070
9114
|
taskGroupId,
|
|
9071
9115
|
tracks: /* @__PURE__ */ new Map(),
|
|
9072
9116
|
mergeGate: "none",
|
|
9073
9117
|
haltReason: null,
|
|
9074
|
-
groupResolved: !1
|
|
9075
|
-
|
|
9118
|
+
groupResolved: !1,
|
|
9119
|
+
startedAt: startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
9120
|
+
};
|
|
9121
|
+
return { ...state, team };
|
|
9076
9122
|
}
|
|
9077
|
-
function reduceTeamTrackAssigned(state, trackIndex, trackState, taskId, agent) {
|
|
9123
|
+
function reduceTeamTrackAssigned(state, trackIndex, trackState, taskId, agent, startedAt) {
|
|
9078
9124
|
let base = state.team ?? {
|
|
9079
9125
|
taskGroupId: "",
|
|
9080
9126
|
tracks: /* @__PURE__ */ new Map(),
|
|
9081
9127
|
mergeGate: "none",
|
|
9082
9128
|
haltReason: null,
|
|
9083
|
-
groupResolved: !1
|
|
9129
|
+
groupResolved: !1,
|
|
9130
|
+
startedAt: startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
9084
9131
|
}, tracks = new Map(base.tracks), prior = tracks.get(trackIndex), merged = {
|
|
9085
9132
|
state: trackState,
|
|
9086
9133
|
// Preserve a prior taskId/agent when the new event omits them.
|
|
@@ -9091,12 +9138,16 @@ function reduceTeamTrackAssigned(state, trackIndex, trackState, taskId, agent) {
|
|
|
9091
9138
|
let sessionTasks = state.sessionTasks;
|
|
9092
9139
|
if (merged.taskId) {
|
|
9093
9140
|
let existing = state.sessionTasks.get(merged.taskId);
|
|
9094
|
-
sessionTasks = new Map(state.sessionTasks)
|
|
9141
|
+
sessionTasks = new Map(state.sessionTasks);
|
|
9142
|
+
let isTerminal = trackState === "Passed" || trackState === "Failed";
|
|
9143
|
+
sessionTasks.set(merged.taskId, {
|
|
9095
9144
|
taskId: merged.taskId,
|
|
9096
9145
|
agentKind: merged.agent ?? existing?.agentKind,
|
|
9097
9146
|
origin: "team",
|
|
9098
9147
|
status: trackState,
|
|
9099
|
-
startedAt: existing?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
9148
|
+
startedAt: existing?.startedAt ?? startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
9149
|
+
completedAt: isTerminal ? existing?.completedAt : void 0,
|
|
9150
|
+
...isTerminal && existing?.terminalSeq !== void 0 ? { terminalSeq: existing.terminalSeq } : {}
|
|
9100
9151
|
});
|
|
9101
9152
|
}
|
|
9102
9153
|
return { ...state, team: { ...base, tracks }, sessionTasks };
|
|
@@ -9132,12 +9183,19 @@ function reduceTeamMergeGate(state, status, startedAt, endedAt) {
|
|
|
9132
9183
|
let elapsed = team.mergeGateElapsedMs ?? mergeGateElapsed(team.mergeGateStartedAt, endedAt);
|
|
9133
9184
|
return { ...state, team: { ...team, mergeGate: status, mergeGateElapsedMs: elapsed } };
|
|
9134
9185
|
}
|
|
9135
|
-
function reduceTeamHalted(state, haltReason) {
|
|
9186
|
+
function reduceTeamHalted(state, haltReason, completedAt) {
|
|
9136
9187
|
if (!state.team) return state;
|
|
9137
|
-
let t = state.team, frozen = t.mergeGateStartedAt != null && t.mergeGateElapsedMs == null ? mergeGateElapsed(t.mergeGateStartedAt, (/* @__PURE__ */ new Date()).toISOString()) : t.mergeGateElapsedMs;
|
|
9188
|
+
let t = state.team, frozen = t.mergeGateStartedAt != null && t.mergeGateElapsedMs == null ? mergeGateElapsed(t.mergeGateStartedAt, (/* @__PURE__ */ new Date()).toISOString()) : t.mergeGateElapsedMs, nextSeq = (state.terminalSequence ?? 0) + 1;
|
|
9138
9189
|
return {
|
|
9139
9190
|
...state,
|
|
9140
|
-
team: {
|
|
9191
|
+
team: {
|
|
9192
|
+
...t,
|
|
9193
|
+
haltReason,
|
|
9194
|
+
mergeGateElapsedMs: frozen,
|
|
9195
|
+
completedAt: completedAt ?? t.completedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
9196
|
+
terminalSeq: nextSeq
|
|
9197
|
+
},
|
|
9198
|
+
terminalSequence: nextSeq,
|
|
9141
9199
|
lastReviewerProgress: null
|
|
9142
9200
|
};
|
|
9143
9201
|
}
|
|
@@ -9147,15 +9205,37 @@ function reduceTeamTrackTerminal(state, trackIndex, trackState) {
|
|
|
9147
9205
|
if (!prior || prior.state === trackState) return state;
|
|
9148
9206
|
let tracks = new Map(state.team.tracks);
|
|
9149
9207
|
tracks.set(trackIndex, { ...prior, state: trackState });
|
|
9150
|
-
let sessionTasks = state.sessionTasks, record = prior.taskId ? state.sessionTasks.get(prior.taskId) : void 0;
|
|
9151
|
-
|
|
9208
|
+
let sessionTasks = state.sessionTasks, record = prior.taskId ? state.sessionTasks.get(prior.taskId) : void 0, terminalSequence = state.terminalSequence;
|
|
9209
|
+
if (prior.taskId && record) {
|
|
9210
|
+
let isTerminal = trackState === "Passed" || trackState === "Failed", nextSeq = isTerminal ? record.terminalSeq ?? (state.terminalSequence ?? 0) + 1 : void 0;
|
|
9211
|
+
isTerminal && !record.terminalSeq && (terminalSequence = nextSeq), sessionTasks = new Map(state.sessionTasks), sessionTasks.set(prior.taskId, {
|
|
9212
|
+
...record,
|
|
9213
|
+
status: trackState,
|
|
9214
|
+
completedAt: isTerminal ? record.completedAt ?? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
9215
|
+
...isTerminal && nextSeq !== void 0 ? { terminalSeq: nextSeq } : {}
|
|
9216
|
+
});
|
|
9217
|
+
}
|
|
9218
|
+
return {
|
|
9219
|
+
...state,
|
|
9220
|
+
team: { ...state.team, tracks },
|
|
9221
|
+
sessionTasks,
|
|
9222
|
+
...terminalSequence !== void 0 ? { terminalSequence } : {}
|
|
9223
|
+
};
|
|
9152
9224
|
}
|
|
9153
|
-
function reduceTeamGroupResolved(state, outcome) {
|
|
9225
|
+
function reduceTeamGroupResolved(state, outcome, completedAt) {
|
|
9154
9226
|
if (!state.team || state.team.groupResolved && state.team.outcome === outcome) return state;
|
|
9155
|
-
let t = state.team, frozen = t.mergeGateStartedAt != null && t.mergeGateElapsedMs == null ? mergeGateElapsed(t.mergeGateStartedAt, (/* @__PURE__ */ new Date()).toISOString()) : t.mergeGateElapsedMs;
|
|
9227
|
+
let t = state.team, frozen = t.mergeGateStartedAt != null && t.mergeGateElapsedMs == null ? mergeGateElapsed(t.mergeGateStartedAt, (/* @__PURE__ */ new Date()).toISOString()) : t.mergeGateElapsedMs, nextSeq = (state.terminalSequence ?? 0) + 1;
|
|
9156
9228
|
return {
|
|
9157
9229
|
...state,
|
|
9158
|
-
team: {
|
|
9230
|
+
team: {
|
|
9231
|
+
...t,
|
|
9232
|
+
groupResolved: !0,
|
|
9233
|
+
outcome,
|
|
9234
|
+
mergeGateElapsedMs: frozen,
|
|
9235
|
+
completedAt: completedAt ?? t.completedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
9236
|
+
terminalSeq: nextSeq
|
|
9237
|
+
},
|
|
9238
|
+
terminalSequence: nextSeq,
|
|
9159
9239
|
lastReviewerProgress: null
|
|
9160
9240
|
};
|
|
9161
9241
|
}
|
|
@@ -9441,7 +9521,7 @@ function ReviewerQuorumStatusNode(props) {
|
|
|
9441
9521
|
React5.createElement(
|
|
9442
9522
|
Text,
|
|
9443
9523
|
null,
|
|
9444
|
-
`${seat.seatId} ${seat.reviewerKind.padEnd(7)} `
|
|
9524
|
+
`${displaySeatNumber(seat.seatId)} ${seat.reviewerKind.padEnd(7)} `
|
|
9445
9525
|
),
|
|
9446
9526
|
React5.createElement(Text, { color: STATUS_COLOR[seat.status] }, STATUS_GLYPH[seat.status]),
|
|
9447
9527
|
React5.createElement(Text, null, ` ${seat.status}`)
|
|
@@ -9819,7 +9899,7 @@ function buildPerSeatTruncationHint(findingsTruncated, truncatedFindingCount) {
|
|
|
9819
9899
|
return truncatedFindingCount > 0 ? `(${truncatedFindingCount} more \u2014 ${PER_SEAT_AUDIT_BROWSER_HINT})` : findingsTruncated ? `(more \u2014 ${PER_SEAT_AUDIT_BROWSER_HINT})` : null;
|
|
9820
9900
|
}
|
|
9821
9901
|
function buildGateDetailsPanelModel(envelope) {
|
|
9822
|
-
let headline = envelope.summary ?? null, reason = formatHaltReason(envelope.reason), reasonLabel = reason?.label ?? null, reasonExplanation = reason?.explanation ?? null, roundLabel = `Round ${envelope.currentRound}`, timeline = (envelope.timeline ?? []).map((t) => ({
|
|
9902
|
+
let headline = envelope.summary ?? null, reason = formatHaltReason(envelope.reason), reasonLabel = reason?.label ?? null, reasonExplanation = reason?.explanation ?? null, roundLabel = `Round ${displayOrdinal(envelope.currentRound)}`, timeline = (envelope.timeline ?? []).map((t) => ({
|
|
9823
9903
|
kind: t.kind,
|
|
9824
9904
|
at: t.at
|
|
9825
9905
|
})), elapsedSeconds = computeElapsedSeconds(envelope.timeline), history = envelope.roundHistory ?? [], cascade = history.length > 1 ? history.map((h) => ({
|
|
@@ -9837,7 +9917,7 @@ function buildGateDetailsPanelModel(envelope) {
|
|
|
9837
9917
|
seatId: seat.seatId,
|
|
9838
9918
|
role: seat.role,
|
|
9839
9919
|
reviewerAgent: seat.reviewerAgent,
|
|
9840
|
-
header: `Reviewer ${seat.seatId} (${seat.role}, ${seat.reviewerAgent}): ${formatDecision(
|
|
9920
|
+
header: `Reviewer ${displayOrdinal(seat.seatId)} (${seat.role}, ${seat.reviewerAgent}): ${formatDecision(
|
|
9841
9921
|
seat.decision
|
|
9842
9922
|
)}`,
|
|
9843
9923
|
findings: seat.findings,
|
|
@@ -9933,7 +10013,7 @@ function buildReviewSummaryPanelModel(summary) {
|
|
|
9933
10013
|
seatId,
|
|
9934
10014
|
role,
|
|
9935
10015
|
agent,
|
|
9936
|
-
header: `Reviewer ${seatId} (${role}, ${agent}): ${formatDecision(decision)}`,
|
|
10016
|
+
header: `Reviewer ${displayOrdinal(seatId)} (${role}, ${agent}): ${formatDecision(decision)}`,
|
|
9937
10017
|
decisionLabel: formatDecision(decision),
|
|
9938
10018
|
reasoning,
|
|
9939
10019
|
suggestedChanges
|
|
@@ -9941,7 +10021,7 @@ function buildReviewSummaryPanelModel(summary) {
|
|
|
9941
10021
|
}
|
|
9942
10022
|
rounds.push({
|
|
9943
10023
|
round,
|
|
9944
|
-
roundLabel: `Round ${round}`,
|
|
10024
|
+
roundLabel: `Round ${displayOrdinal(round)}`,
|
|
9945
10025
|
proposal,
|
|
9946
10026
|
reviewers,
|
|
9947
10027
|
outcome,
|
|
@@ -10216,7 +10296,7 @@ function GateContextPanel(props) {
|
|
|
10216
10296
|
React10.createElement(
|
|
10217
10297
|
Text,
|
|
10218
10298
|
{ dimColor: !0 },
|
|
10219
|
-
`Round ${c.round}: ${c.reasonLabel}`
|
|
10299
|
+
`Round ${displayOrdinal(c.round)}: ${c.reasonLabel}`
|
|
10220
10300
|
)
|
|
10221
10301
|
)
|
|
10222
10302
|
);
|
|
@@ -10423,7 +10503,7 @@ function renderReviewSummarySection(reviewSummary) {
|
|
|
10423
10503
|
)
|
|
10424
10504
|
);
|
|
10425
10505
|
for (let [index, usage] of terminal.tokenUsage.invocations.entries()) {
|
|
10426
|
-
let locator = usage.role === "reviewer" ? `r${usage.round
|
|
10506
|
+
let locator = usage.role === "reviewer" ? `r${usage.round == null ? "?" : displayOrdinal(usage.round)} seat ${usage.seatId == null ? "?" : displayOrdinal(usage.seatId)}` : usage.round !== null ? `r${displayOrdinal(usage.round)}` : usage.role, usageBreakdown = [
|
|
10427
10507
|
usage.inputTokens !== null ? `${usage.inputTokens.toLocaleString()} input` : null,
|
|
10428
10508
|
usage.outputTokens !== null ? `${usage.outputTokens.toLocaleString()} output` : null,
|
|
10429
10509
|
usage.cachedInputTokens !== null ? `cached ${usage.cachedInputTokens.toLocaleString()}` : null
|
|
@@ -17859,7 +17939,7 @@ function renderEntryAsLine(entry) {
|
|
|
17859
17939
|
case "subagent-event":
|
|
17860
17940
|
return ` \u23BF [${entry.role}] ${entry.event.kind === "NOTIFICATION" && "payload" in entry.event && typeof entry.event.payload.message == "string" ? entry.event.payload.message : entry.event.kind}`;
|
|
17861
17941
|
case "reviewer-status-node": {
|
|
17862
|
-
let seatLines = entry.seats.map((s) => `${s.seatId} ${s.reviewerKind} ${s.status}`).join(", ");
|
|
17942
|
+
let seatLines = entry.seats.map((s) => `${displaySeatNumber(s.seatId)} ${s.reviewerKind} ${s.status}`).join(", ");
|
|
17863
17943
|
return `[quorum ${entry.quorumStatus}] ${seatLines}`;
|
|
17864
17944
|
}
|
|
17865
17945
|
case "gate-status-node":
|
|
@@ -20277,6 +20357,37 @@ async function bindWorkingDirectory(payload){
|
|
|
20277
20357
|
throw new Error('target cwd incarnation changed before launch');
|
|
20278
20358
|
}
|
|
20279
20359
|
}
|
|
20360
|
+
function holdLaunchPathAuthorities(payload){
|
|
20361
|
+
const authorities=payload.launchPathAuthorities;
|
|
20362
|
+
if(authorities===undefined)return [];
|
|
20363
|
+
if(!Array.isArray(authorities)||authorities.length>16)throw new Error('invalid launch path authorities');
|
|
20364
|
+
const held=[];
|
|
20365
|
+
try{
|
|
20366
|
+
for(const authority of authorities){
|
|
20367
|
+
if(!authority||authority.version!==1||
|
|
20368
|
+
typeof authority.canonicalPath!=='string'||!require('node:path').isAbsolute(authority.canonicalPath)||authority.canonicalPath.includes('\0')||
|
|
20369
|
+
typeof authority.dev!=='string'||typeof authority.ino!=='string'||
|
|
20370
|
+
typeof authority.birthtimeNs!=='string')throw new Error('invalid launch path authority');
|
|
20371
|
+
const flags=fs.constants.O_RDONLY|(fs.constants.O_DIRECTORY||0)|(fs.constants.O_NOFOLLOW||0);
|
|
20372
|
+
const fd=fs.openSync(authority.canonicalPath,flags);
|
|
20373
|
+
held.push(fd);
|
|
20374
|
+
const opened=fs.fstatSync(fd,{bigint:true});
|
|
20375
|
+
const live=fs.lstatSync(authority.canonicalPath,{bigint:true});
|
|
20376
|
+
const canonical=fs.realpathSync(authority.canonicalPath);
|
|
20377
|
+
if(!opened.isDirectory()||!live.isDirectory()||live.isSymbolicLink()||
|
|
20378
|
+
opened.dev.toString()!==authority.dev||opened.ino.toString()!==authority.ino||
|
|
20379
|
+
opened.birthtimeNs.toString()!==authority.birthtimeNs||
|
|
20380
|
+
live.dev.toString()!==authority.dev||live.ino.toString()!==authority.ino||
|
|
20381
|
+
live.birthtimeNs.toString()!==authority.birthtimeNs||canonical!==authority.canonicalPath){
|
|
20382
|
+
throw new Error('launch path authority changed before target spawn');
|
|
20383
|
+
}
|
|
20384
|
+
}
|
|
20385
|
+
return held;
|
|
20386
|
+
}catch(err){
|
|
20387
|
+
for(const fd of held){try{fs.closeSync(fd);}catch{}}
|
|
20388
|
+
throw err;
|
|
20389
|
+
}
|
|
20390
|
+
}
|
|
20280
20391
|
const hostPipe=fs.createReadStream(null,{fd:5,autoClose:false});
|
|
20281
20392
|
for(const event of ['end','close','error'])hostPipe.once(event,killOwnGroup);
|
|
20282
20393
|
for(const [signal] of [['SIGTERM'],['SIGINT'],['SIGHUP']])process.on(signal,killOwnGroup);
|
|
@@ -20285,9 +20396,17 @@ for(const [signal] of [['SIGTERM'],['SIGINT'],['SIGHUP']])process.on(signal,kill
|
|
|
20285
20396
|
const start=await readLine(4);
|
|
20286
20397
|
if(start!=='START')throw new Error('target start not authorized');
|
|
20287
20398
|
await bindWorkingDirectory(payload);
|
|
20399
|
+
// This is deliberately synchronous and immediately adjacent to cp.spawn:
|
|
20400
|
+
// keep exact directory descriptors open across native process creation so a
|
|
20401
|
+
// pathname replacement during durable-owner publication cannot be adopted.
|
|
20402
|
+
const launchPathFds=holdLaunchPathAuthorities(payload);
|
|
20288
20403
|
// No pathname cwd is passed here: the child inherits the wrapper's already-
|
|
20289
20404
|
// authenticated kernel cwd reference, so a later rename cannot redirect it.
|
|
20290
|
-
|
|
20405
|
+
try{
|
|
20406
|
+
target=cp.spawn(payload.command,payload.args,{env:payload.env,stdio:['inherit','inherit','inherit'],detached:false,windowsHide:true});
|
|
20407
|
+
}finally{
|
|
20408
|
+
for(const fd of launchPathFds){try{fs.closeSync(fd);}catch{}}
|
|
20409
|
+
}
|
|
20291
20410
|
target.once('error',err=>{send({type:'target-exit',code:127,error:String(err&&err.message||err)});});
|
|
20292
20411
|
target.once('exit',(code,signal)=>{send({type:'target-exit',code:Number.isInteger(code)?code:(signal?128:1)});});
|
|
20293
20412
|
// Remain the authenticated group/session leader until the outside host has
|
|
@@ -20387,6 +20506,7 @@ function spawnPosixOwnedProcess(command, args, options, seams = {}) {
|
|
|
20387
20506
|
args,
|
|
20388
20507
|
cwd: targetCwd,
|
|
20389
20508
|
cwdAuthority: seams.workingDirAuthority,
|
|
20509
|
+
launchPathAuthorities: seams.launchPathAuthorities,
|
|
20390
20510
|
env: options?.env ?? process.env,
|
|
20391
20511
|
...seams.cleanupTimeoutMs === void 0 ? {} : { cleanupTimeoutMs: seams.cleanupTimeoutMs }
|
|
20392
20512
|
}), "utf8");
|
|
@@ -24639,7 +24759,7 @@ function buildReviewerVerdictModel(payload) {
|
|
|
24639
24759
|
let decisionRaw = asString(verdict.verdict);
|
|
24640
24760
|
if (decisionRaw === null) return null;
|
|
24641
24761
|
let decisionLabel = decisionCopy[decisionRaw] ?? decisionRaw, parts = [], seatId = payload.seat_id ?? payload.seatId, role = asString(payload.role), agent = asString(payload.reviewer_agent) ?? asString(payload.reviewerAgent);
|
|
24642
|
-
typeof seatId == "number" && parts.push(`Seat ${seatId}`), role && parts.push(role), agent && parts.push(agent);
|
|
24762
|
+
typeof seatId == "number" && parts.push(`Seat ${displayOrdinal(seatId)}`), role && parts.push(role), agent && parts.push(agent);
|
|
24643
24763
|
let provenance = parts.length > 0 ? parts.join(" \xB7 ") : null, reasoning = asString(verdict.reasoning), sugRaw = verdict.suggested_changes ?? verdict.suggestedChanges, suggestedChanges = Array.isArray(sugRaw) ? sugRaw.filter((s) => typeof s == "string") : [];
|
|
24644
24764
|
return { decisionLabel, provenance, reasoning, suggestedChanges };
|
|
24645
24765
|
}
|
|
@@ -26409,6 +26529,38 @@ var LocalGemmaPlannerAdapter = class {
|
|
|
26409
26529
|
// src/orchestration-shell/quorum-loop.ts
|
|
26410
26530
|
var import_node_fs24 = require("node:fs");
|
|
26411
26531
|
|
|
26532
|
+
// src/diagnostics/shape-only.ts
|
|
26533
|
+
function outputShapeOnly(raw) {
|
|
26534
|
+
if (typeof raw != "string" || raw.length === 0)
|
|
26535
|
+
return {
|
|
26536
|
+
bytes: 0,
|
|
26537
|
+
lines: 0,
|
|
26538
|
+
leadClass: "empty",
|
|
26539
|
+
fenceCount: 0,
|
|
26540
|
+
bulletLines: 0,
|
|
26541
|
+
blankLines: 0
|
|
26542
|
+
};
|
|
26543
|
+
let lines = raw.split(`
|
|
26544
|
+
`), trimmed = raw.trim(), leadClass;
|
|
26545
|
+
return trimmed.length === 0 ? leadClass = "empty" : trimmed.startsWith("{") || trimmed.startsWith("[") ? leadClass = "json-open" : trimmed.startsWith("```") ? leadClass = "fence" : /^#{1,6}\s/.test(trimmed) ? leadClass = "heading" : /^[-*+]\s/.test(trimmed) ? leadClass = "bullet" : /^\d+[.)]\s/.test(trimmed) ? leadClass = "ordinal" : /^[A-Za-z]/.test(trimmed) ? leadClass = "prose" : leadClass = "other", {
|
|
26546
|
+
bytes: Buffer.byteLength(raw, "utf8"),
|
|
26547
|
+
lines: lines.length,
|
|
26548
|
+
leadClass,
|
|
26549
|
+
fenceCount: (raw.match(/```/g) ?? []).length,
|
|
26550
|
+
bulletLines: lines.filter((line) => /^\s*[-*+]\s/.test(line)).length,
|
|
26551
|
+
blankLines: lines.filter((line) => line.trim().length === 0).length
|
|
26552
|
+
};
|
|
26553
|
+
}
|
|
26554
|
+
function errorShapeOnly(error) {
|
|
26555
|
+
let value = error, message = typeof value?.message == "string" ? value.message : "", causeCount = Array.isArray(value?.causes) ? value.causes.length : value?.cause !== void 0 ? 1 : 0;
|
|
26556
|
+
return {
|
|
26557
|
+
errorClass: error instanceof Error ? "error" : "non-error",
|
|
26558
|
+
messageBytes: Buffer.byteLength(message, "utf8"),
|
|
26559
|
+
hasCause: value?.cause !== void 0,
|
|
26560
|
+
causeCount
|
|
26561
|
+
};
|
|
26562
|
+
}
|
|
26563
|
+
|
|
26412
26564
|
// src/reduced-trust-notice.ts
|
|
26413
26565
|
var surfacedRationales = /* @__PURE__ */ new Set();
|
|
26414
26566
|
function noticeKey(sessionId, tier, reason) {
|
|
@@ -28104,7 +28256,8 @@ var ClassBConsumer = class {
|
|
|
28104
28256
|
};
|
|
28105
28257
|
|
|
28106
28258
|
// src/substrate-launch/apikey-bootstrap.ts
|
|
28107
|
-
var import_node_fs14 = require("node:fs"), os19 = __toESM(require("node:os")), path32 = __toESM(require("node:path"))
|
|
28259
|
+
var import_node_fs14 = require("node:fs"), os19 = __toESM(require("node:os")), path32 = __toESM(require("node:path"));
|
|
28260
|
+
var HELPER_SCRIPT_NAME = "broker-apikey-helper.sh", TOKEN_FILE_NAME = "broker-token", CLAUDE_SETTINGS_NAME = "settings.json", CODEX_CONFIG_NAME = "config.toml", SANDBOX_BOOTSTRAP_DIR = "/codevibe/agent", SANDBOX_AGENT_CONFIG_DIR = "/codevibe/agent-config", CODEX_PROVIDER_ID = "codevibe_broker";
|
|
28108
28261
|
function helperScriptSource(tokenFileAbsPathInSandbox) {
|
|
28109
28262
|
return `#!/bin/sh
|
|
28110
28263
|
# CP-7 apiKeyHelper \u2014 emits the current broker token (NEVER the vendor key).
|
|
@@ -28145,12 +28298,16 @@ function isInsideOrEqual(child, parent) {
|
|
|
28145
28298
|
return rel.length > 0 && !rel.startsWith("..") && !path32.isAbsolute(rel);
|
|
28146
28299
|
}
|
|
28147
28300
|
var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
28148
|
-
constructor(hostDir, sandboxDir, configHostDir, configSandboxDir, tokenFileHostPath) {
|
|
28301
|
+
constructor(hostDir, sandboxDir, configHostDir, configSandboxDir, tokenFileHostPath, claudeScratchHostDir, claudeScratchSandboxDir, claudeScratchIdentity, beforeClaudeScratchCleanupCommit) {
|
|
28149
28302
|
this.hostDir = hostDir;
|
|
28150
28303
|
this.sandboxDir = sandboxDir;
|
|
28151
28304
|
this.configHostDir = configHostDir;
|
|
28152
28305
|
this.configSandboxDir = configSandboxDir;
|
|
28153
28306
|
this.tokenFileHostPath = tokenFileHostPath;
|
|
28307
|
+
this.claudeScratchHostDir = claudeScratchHostDir;
|
|
28308
|
+
this.claudeScratchSandboxDir = claudeScratchSandboxDir;
|
|
28309
|
+
this.claudeScratchIdentity = claudeScratchIdentity;
|
|
28310
|
+
this.beforeClaudeScratchCleanupCommit = beforeClaudeScratchCleanupCommit;
|
|
28154
28311
|
}
|
|
28155
28312
|
/**
|
|
28156
28313
|
* Materialize the bootstrap: create the host dir (0700), write the token file
|
|
@@ -28166,9 +28323,8 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28166
28323
|
);
|
|
28167
28324
|
await import_node_fs14.promises.chmod(rawConfigHostDir, 448).catch(() => {
|
|
28168
28325
|
});
|
|
28169
|
-
let hostDir = await import_node_fs14.promises.realpath(rawHostDir), configHostDir = await import_node_fs14.promises.realpath(rawConfigHostDir);
|
|
28326
|
+
let hostDir = await import_node_fs14.promises.realpath(rawHostDir), configHostDir = await import_node_fs14.promises.realpath(rawConfigHostDir), realWorkdir;
|
|
28170
28327
|
if (input.workdir !== void 0) {
|
|
28171
|
-
let realWorkdir;
|
|
28172
28328
|
try {
|
|
28173
28329
|
realWorkdir = await import_node_fs14.promises.realpath(input.workdir);
|
|
28174
28330
|
} catch {
|
|
@@ -28205,7 +28361,7 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28205
28361
|
"ApiKeyBootstrap.create: provide `sandboxConfigDir` or `configDirEqualsHostDir`"
|
|
28206
28362
|
);
|
|
28207
28363
|
let tokenInSandbox = path32.posix.join(sandboxDir, TOKEN_FILE_NAME), helperInSandbox = path32.posix.join(sandboxDir, HELPER_SCRIPT_NAME), tokenFileHostPath = path32.join(hostDir, TOKEN_FILE_NAME);
|
|
28208
|
-
|
|
28364
|
+
await import_node_fs14.promises.writeFile(tokenFileHostPath, input.initialToken, {
|
|
28209
28365
|
encoding: "utf8",
|
|
28210
28366
|
mode: 384
|
|
28211
28367
|
}), await import_node_fs14.promises.writeFile(
|
|
@@ -28220,12 +28376,107 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28220
28376
|
path32.join(configHostDir, CODEX_CONFIG_NAME),
|
|
28221
28377
|
codexConfig(input.sandboxBrokerUrl, helperInSandbox),
|
|
28222
28378
|
{ encoding: "utf8", mode: 384 }
|
|
28223
|
-
)
|
|
28379
|
+
);
|
|
28380
|
+
let claudeScratchHostDir = null, claudeScratchSandboxDir = null, claudeScratchIdentity = null;
|
|
28381
|
+
if (input.claudeScratchHostRoot !== void 0) {
|
|
28382
|
+
if (input.provider !== "anthropic" || !input.sandboxDirEqualsHostDir) {
|
|
28383
|
+
let primary = new Error(
|
|
28384
|
+
"ApiKeyBootstrap.create: a short Claude scratch root is valid only for the A5 anthropic path"
|
|
28385
|
+
), cleanupErrors = [];
|
|
28386
|
+
for (let directory of [hostDir, configHostDir])
|
|
28387
|
+
try {
|
|
28388
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28389
|
+
} catch (cleanupError) {
|
|
28390
|
+
cleanupErrors.push(cleanupError);
|
|
28391
|
+
}
|
|
28392
|
+
throw cleanupErrors.length > 0 ? Object.assign(
|
|
28393
|
+
new Error(
|
|
28394
|
+
"ApiKeyBootstrap.create: invalid scratch configuration and cleanup did not complete"
|
|
28395
|
+
),
|
|
28396
|
+
{ causes: [primary, ...cleanupErrors] }
|
|
28397
|
+
) : primary;
|
|
28398
|
+
}
|
|
28399
|
+
let rawScratchDir = null;
|
|
28400
|
+
try {
|
|
28401
|
+
let canonicalScratchRoot = await import_node_fs14.promises.realpath(
|
|
28402
|
+
input.claudeScratchHostRoot
|
|
28403
|
+
);
|
|
28404
|
+
rawScratchDir = await import_node_fs14.promises.mkdtemp(path32.join(canonicalScratchRoot, "cv"));
|
|
28405
|
+
let initial = await import_node_fs14.promises.lstat(rawScratchDir, { bigint: !0 });
|
|
28406
|
+
if (!initial.isDirectory() || initial.isSymbolicLink())
|
|
28407
|
+
throw new Error(
|
|
28408
|
+
"ApiKeyBootstrap.create: generated Claude scratch root is not a real directory"
|
|
28409
|
+
);
|
|
28410
|
+
await input.beforeClaudeScratchOpen?.(rawScratchDir);
|
|
28411
|
+
let scratchHandle = await import_node_fs14.promises.open(
|
|
28412
|
+
rawScratchDir,
|
|
28413
|
+
import_node_fs14.constants.O_RDONLY | import_node_fs14.constants.O_NOFOLLOW | (typeof import_node_fs14.constants.O_DIRECTORY == "number" ? import_node_fs14.constants.O_DIRECTORY : 0)
|
|
28414
|
+
);
|
|
28415
|
+
try {
|
|
28416
|
+
let opened = await scratchHandle.stat({ bigint: !0 });
|
|
28417
|
+
if (!opened.isDirectory() || opened.dev !== initial.dev || opened.ino !== initial.ino || opened.birthtimeNs !== initial.birthtimeNs)
|
|
28418
|
+
throw new Error(
|
|
28419
|
+
"ApiKeyBootstrap.create: Claude scratch root changed while binding its directory handle"
|
|
28420
|
+
);
|
|
28421
|
+
await scratchHandle.chmod(448);
|
|
28422
|
+
let sealed = await scratchHandle.stat({ bigint: !0 }), live = await import_node_fs14.promises.lstat(rawScratchDir, { bigint: !0 }), canonical = rawScratchDir, currentUid = process.getuid?.(), mode = sealed.mode & 0o777n;
|
|
28423
|
+
if (!sealed.isDirectory() || !live.isDirectory() || live.isSymbolicLink() || live.dev !== sealed.dev || live.ino !== sealed.ino || live.birthtimeNs !== sealed.birthtimeNs || currentUid === void 0 || sealed.uid !== BigInt(currentUid) || mode !== 0o700n)
|
|
28424
|
+
throw new Error(
|
|
28425
|
+
"ApiKeyBootstrap.create: generated Claude scratch root failed its descriptor-bound private-directory identity check"
|
|
28426
|
+
);
|
|
28427
|
+
claudeScratchHostDir = canonical, claudeScratchSandboxDir = rawScratchDir, claudeScratchIdentity = {
|
|
28428
|
+
version: 1,
|
|
28429
|
+
canonicalPath: canonical,
|
|
28430
|
+
dev: sealed.dev.toString(),
|
|
28431
|
+
ino: sealed.ino.toString(),
|
|
28432
|
+
birthtimeNs: sealed.birthtimeNs.toString()
|
|
28433
|
+
};
|
|
28434
|
+
} finally {
|
|
28435
|
+
await scratchHandle.close();
|
|
28436
|
+
}
|
|
28437
|
+
if (Buffer.byteLength(rawScratchDir, "utf8") > 30)
|
|
28438
|
+
throw new Error(
|
|
28439
|
+
"ApiKeyBootstrap.create: generated Claude scratch path exceeds the 30-byte A5 safety bound"
|
|
28440
|
+
);
|
|
28441
|
+
if (realWorkdir !== void 0 && isInsideOrEqual(claudeScratchHostDir, realWorkdir))
|
|
28442
|
+
throw new Error(
|
|
28443
|
+
"ApiKeyBootstrap.create: Claude scratch root is inside the agent workdir (fail-closed)"
|
|
28444
|
+
);
|
|
28445
|
+
} catch (error) {
|
|
28446
|
+
let cleanupErrors = [];
|
|
28447
|
+
if (claudeScratchIdentity !== null)
|
|
28448
|
+
try {
|
|
28449
|
+
await anchoredRemoveTree(
|
|
28450
|
+
claudeScratchIdentity.canonicalPath,
|
|
28451
|
+
claudeScratchIdentity
|
|
28452
|
+
);
|
|
28453
|
+
} catch (cleanupError) {
|
|
28454
|
+
cleanupErrors.push(cleanupError);
|
|
28455
|
+
}
|
|
28456
|
+
for (let directory of [hostDir, configHostDir])
|
|
28457
|
+
try {
|
|
28458
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28459
|
+
} catch (cleanupError) {
|
|
28460
|
+
cleanupErrors.push(cleanupError);
|
|
28461
|
+
}
|
|
28462
|
+
throw cleanupErrors.length > 0 ? Object.assign(
|
|
28463
|
+
new Error(
|
|
28464
|
+
"ApiKeyBootstrap.create: initialization failed and cleanup did not complete"
|
|
28465
|
+
),
|
|
28466
|
+
{ causes: [error, ...cleanupErrors] }
|
|
28467
|
+
) : error;
|
|
28468
|
+
}
|
|
28469
|
+
}
|
|
28470
|
+
return new _ApiKeyBootstrap(
|
|
28224
28471
|
hostDir,
|
|
28225
28472
|
sandboxDir,
|
|
28226
28473
|
configHostDir,
|
|
28227
28474
|
sandboxConfigDir,
|
|
28228
|
-
tokenFileHostPath
|
|
28475
|
+
tokenFileHostPath,
|
|
28476
|
+
claudeScratchHostDir,
|
|
28477
|
+
claudeScratchSandboxDir,
|
|
28478
|
+
claudeScratchIdentity,
|
|
28479
|
+
input.beforeClaudeScratchCleanupCommit
|
|
28229
28480
|
);
|
|
28230
28481
|
}
|
|
28231
28482
|
/** The `SubstrateSpec.agentBootstrap` value for this bootstrap. */
|
|
@@ -28236,6 +28487,14 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28236
28487
|
get configSpec() {
|
|
28237
28488
|
return { hostDir: this.configHostDir, sandboxDir: this.configSandboxDir };
|
|
28238
28489
|
}
|
|
28490
|
+
/** The unique writable Claude scratch grant, absent on Docker/Codex paths. */
|
|
28491
|
+
get claudeScratchSpec() {
|
|
28492
|
+
return this.claudeScratchHostDir === null || this.claudeScratchSandboxDir === null || this.claudeScratchIdentity === null ? null : {
|
|
28493
|
+
hostDir: this.claudeScratchHostDir,
|
|
28494
|
+
sandboxDir: this.claudeScratchSandboxDir,
|
|
28495
|
+
authority: this.claudeScratchIdentity
|
|
28496
|
+
};
|
|
28497
|
+
}
|
|
28239
28498
|
/**
|
|
28240
28499
|
* REFRESH the broker token (rotation / on a broker 401). Atomically rewrites
|
|
28241
28500
|
* the token file (write a temp + rename) so the agent never reads a partial
|
|
@@ -28246,15 +28505,41 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28246
28505
|
let tmp = `${this.tokenFileHostPath}.tmp-${process.pid}-${Date.now()}`;
|
|
28247
28506
|
await import_node_fs14.promises.writeFile(tmp, token, { encoding: "utf8", mode: 384 }), await import_node_fs14.promises.rename(tmp, this.tokenFileHostPath);
|
|
28248
28507
|
}
|
|
28249
|
-
/**
|
|
28508
|
+
/**
|
|
28509
|
+
* Remove the bootstrap, config, and unique Claude scratch dirs. Scratch
|
|
28510
|
+
* cleanup is identity-bound: a replaced pathname is retained and reported,
|
|
28511
|
+
* never recursively removed as though it still belonged to this seat.
|
|
28512
|
+
*/
|
|
28250
28513
|
async destroy() {
|
|
28251
|
-
|
|
28252
|
-
|
|
28514
|
+
let cleanupErrors = [];
|
|
28515
|
+
if (this.claudeScratchHostDir !== null && this.claudeScratchIdentity !== null)
|
|
28516
|
+
try {
|
|
28517
|
+
await anchoredRemoveTree(
|
|
28518
|
+
this.claudeScratchIdentity.canonicalPath,
|
|
28519
|
+
this.claudeScratchIdentity,
|
|
28520
|
+
{
|
|
28521
|
+
...this.beforeClaudeScratchCleanupCommit ? {
|
|
28522
|
+
beforeCommit: () => this.beforeClaudeScratchCleanupCommit(
|
|
28523
|
+
this.claudeScratchHostDir
|
|
28524
|
+
)
|
|
28525
|
+
} : {}
|
|
28526
|
+
}
|
|
28527
|
+
);
|
|
28528
|
+
} catch (error) {
|
|
28529
|
+
cleanupErrors.push(error);
|
|
28253
28530
|
}
|
|
28254
|
-
|
|
28255
|
-
|
|
28531
|
+
for (let directory of [this.hostDir, this.configHostDir])
|
|
28532
|
+
try {
|
|
28533
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28534
|
+
} catch (error) {
|
|
28535
|
+
cleanupErrors.push(error);
|
|
28256
28536
|
}
|
|
28257
|
-
);
|
|
28537
|
+
if (cleanupErrors.length === 1) throw cleanupErrors[0];
|
|
28538
|
+
if (cleanupErrors.length > 1)
|
|
28539
|
+
throw Object.assign(
|
|
28540
|
+
new Error("ApiKeyBootstrap.destroy: cleanup did not complete"),
|
|
28541
|
+
{ causes: cleanupErrors }
|
|
28542
|
+
);
|
|
28258
28543
|
}
|
|
28259
28544
|
};
|
|
28260
28545
|
|
|
@@ -42776,10 +43061,7 @@ var LocalExecutorImpl = class {
|
|
|
42776
43061
|
}).catch(() => {
|
|
42777
43062
|
}), {
|
|
42778
43063
|
args: { ...addClaudeSubstrateAuthArgs(args, result.agentConfigDir), substrate: result.substrateHandle },
|
|
42779
|
-
onExit:
|
|
42780
|
-
await result.teardown().catch(() => {
|
|
42781
|
-
});
|
|
42782
|
-
},
|
|
43064
|
+
onExit: () => result.teardown(),
|
|
42783
43065
|
// Stage-2 r3 Codex HIGH — the ONLY return that proves a real confining
|
|
42784
43066
|
// boundary (`result.mode === 'substrate'`, not reduced_trust / no-engager /
|
|
42785
43067
|
// pre-TaskAuthorized). The danger-sandbox authority keys on THIS boolean,
|
|
@@ -42871,7 +43153,11 @@ var LocalExecutorImpl = class {
|
|
|
42871
43153
|
}
|
|
42872
43154
|
}
|
|
42873
43155
|
async spawnWithLifecycle(args, spawnFn, onSubstrateExit) {
|
|
42874
|
-
let role = args.role, lifecycleAudit = args.lifecycleAudit ?? "active_task", lifecycleTaskId = args.taskId ?? this.taskId, lifecycleCtx = lifecycleTaskId ? { taskId: lifecycleTaskId, ...this.baseCtx } : null,
|
|
43156
|
+
let role = args.role, lifecycleAudit = args.lifecycleAudit ?? "active_task", lifecycleTaskId = args.taskId ?? this.taskId, lifecycleCtx = lifecycleTaskId ? { taskId: lifecycleTaskId, ...this.baseCtx } : null, substrateCleanupError, substrateCleanupPromise, cleanupSubstrate = async () => {
|
|
43157
|
+
onSubstrateExit && (substrateCleanupPromise || (substrateCleanupPromise = onSubstrateExit().catch((error) => {
|
|
43158
|
+
throw substrateCleanupError = error, error;
|
|
43159
|
+
})), await substrateCleanupPromise);
|
|
43160
|
+
}, full = {
|
|
42875
43161
|
...args,
|
|
42876
43162
|
agentKind: args.agentKind ?? this.adapter,
|
|
42877
43163
|
onProcessSpawned: async (info) => {
|
|
@@ -42885,35 +43171,51 @@ var LocalExecutorImpl = class {
|
|
|
42885
43171
|
});
|
|
42886
43172
|
},
|
|
42887
43173
|
onProcessExited: async (info) => {
|
|
42888
|
-
|
|
42889
|
-
|
|
42890
|
-
|
|
42891
|
-
|
|
42892
|
-
|
|
42893
|
-
|
|
42894
|
-
|
|
42895
|
-
|
|
43174
|
+
try {
|
|
43175
|
+
if (await args.onProcessExited?.(info), lifecycleAudit !== "none") {
|
|
43176
|
+
let ctx = lifecycleCtx;
|
|
43177
|
+
ctx !== null && await this.emitter.emitProcessExited(ctx, {
|
|
43178
|
+
pid: info.pid,
|
|
43179
|
+
exitCode: info.exitCode,
|
|
43180
|
+
failureClass: info.failureClass,
|
|
43181
|
+
occurredAt: info.exitedAt
|
|
43182
|
+
});
|
|
43183
|
+
}
|
|
43184
|
+
} catch {
|
|
42896
43185
|
}
|
|
42897
|
-
|
|
43186
|
+
await cleanupSubstrate().catch(() => {
|
|
42898
43187
|
});
|
|
42899
43188
|
}
|
|
42900
43189
|
};
|
|
42901
43190
|
try {
|
|
42902
|
-
|
|
43191
|
+
let handle = await spawnFn(full), done = handle.done.then((info) => {
|
|
43192
|
+
if (substrateCleanupError !== void 0)
|
|
43193
|
+
throw Object.assign(
|
|
43194
|
+
new Error("implementor substrate cleanup failed after process exit"),
|
|
43195
|
+
{ cause: substrateCleanupError }
|
|
43196
|
+
);
|
|
43197
|
+
return info;
|
|
43198
|
+
});
|
|
43199
|
+
return { ...handle, done };
|
|
42903
43200
|
} catch (err) {
|
|
42904
|
-
|
|
42905
|
-
})
|
|
43201
|
+
await cleanupSubstrate().catch(() => {
|
|
43202
|
+
});
|
|
43203
|
+
let primary = err;
|
|
43204
|
+
if (err instanceof AuthorityError) {
|
|
42906
43205
|
let safeArgv = redactAgyPrintArgv(args.argv), safeDetail = redactAgyPrintValuesFromText(err.refusal.detail, args.argv), safeError = new AuthorityError({
|
|
42907
43206
|
...err.refusal,
|
|
42908
43207
|
detail: safeDetail
|
|
42909
43208
|
});
|
|
42910
|
-
|
|
43209
|
+
await this.bridge.bridgeAuthorityRefusal(safeError, {
|
|
42911
43210
|
refusedMessageId: "spawn:" + role + ":" + Date.now(),
|
|
42912
43211
|
shellContent: `Refused spawn (${role}): ${safeDetail}`,
|
|
42913
43212
|
shellMetadata: { role, argv: safeArgv }
|
|
42914
|
-
}), safeError;
|
|
43213
|
+
}), primary = safeError;
|
|
42915
43214
|
}
|
|
42916
|
-
throw
|
|
43215
|
+
throw substrateCleanupError !== void 0 ? Object.assign(
|
|
43216
|
+
new Error("implementor spawn failed and substrate cleanup also failed"),
|
|
43217
|
+
{ causes: [primary, substrateCleanupError] }
|
|
43218
|
+
) : primary;
|
|
42917
43219
|
}
|
|
42918
43220
|
}
|
|
42919
43221
|
// --- Hook bridge surface ---------------------------------------------------
|
|
@@ -44051,7 +44353,8 @@ var LocalExecutorImpl = class {
|
|
|
44051
44353
|
metadata: {
|
|
44052
44354
|
source: "team_group_resolved",
|
|
44053
44355
|
task_group_id: taskGroupId,
|
|
44054
|
-
outcome
|
|
44356
|
+
outcome,
|
|
44357
|
+
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
44055
44358
|
}
|
|
44056
44359
|
}),
|
|
44057
44360
|
"team_group_resolved"
|
|
@@ -49035,10 +49338,11 @@ var ChildProcessCommandRunner = class {
|
|
|
49035
49338
|
signal: opts.signal,
|
|
49036
49339
|
...opts.env !== void 0 ? { env: opts.env } : {},
|
|
49037
49340
|
...opts.cwd !== void 0 ? { cwd: opts.cwd } : {}
|
|
49038
|
-
},
|
|
49039
|
-
workingDirAuthority: opts.cwdAuthority
|
|
49341
|
+
}, needsOwnedProcessHost = opts.cwdAuthority !== void 0 || (opts.launchPathAuthorities?.length ?? 0) > 0, proc = needsOwnedProcessHost ? spawnPosixOwnedProcess(argv[0], argv.slice(1), spawnOptions, {
|
|
49342
|
+
workingDirAuthority: opts.cwdAuthority,
|
|
49343
|
+
launchPathAuthorities: opts.launchPathAuthorities
|
|
49040
49344
|
}) : (0, import_node_child_process7.spawn)(argv[0], argv.slice(1), spawnOptions);
|
|
49041
|
-
return
|
|
49345
|
+
return needsOwnedProcessHost && Object.defineProperty(proc, "hostProcessTreeOwnership", {
|
|
49042
49346
|
value: "posix-host",
|
|
49043
49347
|
configurable: !1,
|
|
49044
49348
|
enumerable: !1,
|
|
@@ -49618,13 +49922,14 @@ async function resolveOnParentPath(cmd) {
|
|
|
49618
49922
|
return null;
|
|
49619
49923
|
}
|
|
49620
49924
|
var SandboxExecHandle = class {
|
|
49621
|
-
constructor(id, runner, profilePath, sanitizedEnv, workdir, workdirAuthority, auditDir = null) {
|
|
49925
|
+
constructor(id, runner, profilePath, sanitizedEnv, workdir, workdirAuthority, scratchAuthority, auditDir = null) {
|
|
49622
49926
|
this.id = id;
|
|
49623
49927
|
this.runner = runner;
|
|
49624
49928
|
this.profilePath = profilePath;
|
|
49625
49929
|
this.sanitizedEnv = sanitizedEnv;
|
|
49626
49930
|
this.workdir = workdir;
|
|
49627
49931
|
this.workdirAuthority = workdirAuthority;
|
|
49932
|
+
this.scratchAuthority = scratchAuthority;
|
|
49628
49933
|
this.auditDir = auditDir;
|
|
49629
49934
|
this.egressFidelity = "coarse";
|
|
49630
49935
|
this.tornDown = !1;
|
|
@@ -49660,13 +49965,18 @@ var SandboxExecHandle = class {
|
|
|
49660
49965
|
; exec-time agent-binary read allowance (argv0 resolution, 2026-07-03)
|
|
49661
49966
|
${allowLines}
|
|
49662
49967
|
`
|
|
49968
|
+
), this.scratchAuthority && await assertWorkspaceRootAuthority(
|
|
49969
|
+
this.scratchAuthority.canonicalPath,
|
|
49970
|
+
this.scratchAuthority,
|
|
49971
|
+
"sandbox-exec Claude scratch handoff"
|
|
49663
49972
|
);
|
|
49664
49973
|
let sbArgv = ["sandbox-exec", "-f", this.profilePath, resolvedArgv0, ...argv.slice(1)], proc = this.runner.spawnLong(sbArgv, {
|
|
49665
49974
|
stdinTty: opts.stdinTty,
|
|
49666
49975
|
signal: opts.signal,
|
|
49667
49976
|
env: this.sanitizedEnv,
|
|
49668
49977
|
cwd: this.workdir,
|
|
49669
|
-
...this.workdirAuthority ? { cwdAuthority: this.workdirAuthority } : {}
|
|
49978
|
+
...this.workdirAuthority ? { cwdAuthority: this.workdirAuthority } : {},
|
|
49979
|
+
...this.scratchAuthority ? { launchPathAuthorities: [this.scratchAuthority] } : {}
|
|
49670
49980
|
});
|
|
49671
49981
|
return this.proc = proc, proc;
|
|
49672
49982
|
}
|
|
@@ -49724,6 +50034,22 @@ ${allowLines}
|
|
|
49724
50034
|
}
|
|
49725
50035
|
extraWriteDirs.push(configDir);
|
|
49726
50036
|
}
|
|
50037
|
+
if (spec.agentScratch) {
|
|
50038
|
+
try {
|
|
50039
|
+
await assertWorkspaceRootAuthority(
|
|
50040
|
+
spec.agentScratch.hostDir,
|
|
50041
|
+
spec.agentScratch.authority,
|
|
50042
|
+
"sandbox-exec Claude scratch launch"
|
|
50043
|
+
);
|
|
50044
|
+
} catch (error) {
|
|
50045
|
+
throw new SubstrateLaunchError(
|
|
50046
|
+
"sandbox_exec",
|
|
50047
|
+
"Claude scratch grant target identity could not be verified (fail-closed)",
|
|
50048
|
+
error
|
|
50049
|
+
);
|
|
50050
|
+
}
|
|
50051
|
+
extraWriteDirs.push(spec.agentScratch.authority.canonicalPath);
|
|
50052
|
+
}
|
|
49727
50053
|
let resolvedAuditDir = null;
|
|
49728
50054
|
if (spec.auditDir) {
|
|
49729
50055
|
resolvedAuditDir = spec.auditDir;
|
|
@@ -49764,6 +50090,17 @@ ${allowLines}
|
|
|
49764
50090
|
throw await import_node_fs23.promises.rm(profilePath, { force: !0 }).catch(() => {
|
|
49765
50091
|
}), err;
|
|
49766
50092
|
}
|
|
50093
|
+
if (spec.agentScratch)
|
|
50094
|
+
try {
|
|
50095
|
+
await assertWorkspaceRootAuthority(
|
|
50096
|
+
spec.agentScratch.authority.canonicalPath,
|
|
50097
|
+
spec.agentScratch.authority,
|
|
50098
|
+
"sandbox-exec Claude scratch profile handoff"
|
|
50099
|
+
);
|
|
50100
|
+
} catch (err) {
|
|
50101
|
+
throw await import_node_fs23.promises.rm(profilePath, { force: !0 }).catch(() => {
|
|
50102
|
+
}), err;
|
|
50103
|
+
}
|
|
49767
50104
|
return new SandboxExecHandle(
|
|
49768
50105
|
id,
|
|
49769
50106
|
this.runner,
|
|
@@ -49771,6 +50108,7 @@ ${allowLines}
|
|
|
49771
50108
|
finalEnv,
|
|
49772
50109
|
canonicalWorkdir,
|
|
49773
50110
|
spec.workdirAuthority,
|
|
50111
|
+
spec.agentScratch?.authority,
|
|
49774
50112
|
resolvedAuditDir
|
|
49775
50113
|
);
|
|
49776
50114
|
}
|
|
@@ -50397,13 +50735,13 @@ function formatReviewerError(detail) {
|
|
|
50397
50735
|
case "timeout":
|
|
50398
50736
|
return `${detail.agent} reviewer timed out after ${detail.elapsed_ms}ms`;
|
|
50399
50737
|
case "spawn_failed":
|
|
50400
|
-
return `${detail.agent} reviewer spawn failed
|
|
50738
|
+
return `${detail.agent} reviewer spawn failed`;
|
|
50401
50739
|
case "parse_failure":
|
|
50402
50740
|
return `${detail.agent} reviewer output was unparseable`;
|
|
50403
50741
|
case "cancelled":
|
|
50404
50742
|
return "reviewer cancelled before completion";
|
|
50405
50743
|
case "internal_join_failure":
|
|
50406
|
-
return
|
|
50744
|
+
return "reviewer task internal join failure";
|
|
50407
50745
|
}
|
|
50408
50746
|
}
|
|
50409
50747
|
|
|
@@ -50945,22 +51283,25 @@ var CONTINUATION_EXPIRES_TTL_MS = 1440 * 60 * 1e3, ACTIVE_AGENT_KINDS = ["CLAUDE
|
|
|
50945
51283
|
function isActiveAgentKind2(agent) {
|
|
50946
51284
|
return agent === "CLAUDE" || agent === "CODEX" || agent === "ANTIGRAVITY";
|
|
50947
51285
|
}
|
|
50948
|
-
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, BACKGROUND_RECOVERY_ABORTED = /* @__PURE__ */ Symbol("background-recovery-aborted")
|
|
51286
|
+
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, BACKGROUND_RECOVERY_ABORTED = /* @__PURE__ */ Symbol("background-recovery-aborted");
|
|
50949
51287
|
function describeReviewerErrorDetail(detail) {
|
|
50950
51288
|
switch (detail.kind) {
|
|
50951
51289
|
case "timeout":
|
|
50952
51290
|
return { agent: detail.agent, elapsedMs: detail.elapsed_ms };
|
|
50953
51291
|
case "spawn_failed":
|
|
50954
|
-
return {
|
|
51292
|
+
return {
|
|
51293
|
+
agent: detail.agent,
|
|
51294
|
+
reasonBytes: Buffer.byteLength(detail.reason ?? "", "utf8")
|
|
51295
|
+
};
|
|
50955
51296
|
case "parse_failure":
|
|
50956
51297
|
return {
|
|
50957
51298
|
agent: detail.agent,
|
|
50958
|
-
|
|
51299
|
+
rawOutputShape: outputShapeOnly(detail.raw_output)
|
|
50959
51300
|
};
|
|
50960
51301
|
case "cancelled":
|
|
50961
51302
|
return {};
|
|
50962
51303
|
case "internal_join_failure":
|
|
50963
|
-
return {
|
|
51304
|
+
return { reasonBytes: Buffer.byteLength(detail.reason ?? "", "utf8") };
|
|
50964
51305
|
}
|
|
50965
51306
|
}
|
|
50966
51307
|
var REVIEWER_AGENT_DISPLAY_NAME = {
|
|
@@ -52248,7 +52589,16 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
52248
52589
|
* first promote/discard.
|
|
52249
52590
|
*/
|
|
52250
52591
|
getLastWorkspaceOutcome() {
|
|
52251
|
-
return this.lastWorkspaceOutcome === null ? null : this.lastWorkspaceOutcome.kind === "promoted" ? {
|
|
52592
|
+
return this.lastWorkspaceOutcome === null ? null : this.lastWorkspaceOutcome.kind === "promoted" ? {
|
|
52593
|
+
kind: "promoted",
|
|
52594
|
+
files: [...this.lastWorkspaceOutcome.files],
|
|
52595
|
+
taskId: this.lastWorkspaceOutcome.taskId,
|
|
52596
|
+
completedAt: this.lastWorkspaceOutcome.completedAt
|
|
52597
|
+
} : {
|
|
52598
|
+
kind: "discarded",
|
|
52599
|
+
taskId: this.lastWorkspaceOutcome.taskId,
|
|
52600
|
+
completedAt: this.lastWorkspaceOutcome.completedAt
|
|
52601
|
+
};
|
|
52252
52602
|
}
|
|
52253
52603
|
/**
|
|
52254
52604
|
* Session-owned Class-B ingress. The subscription calls this wrapper instead
|
|
@@ -53274,8 +53624,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53274
53624
|
taskId: args.taskId,
|
|
53275
53625
|
trackIndex: args.validateDiffScope.trackIndex,
|
|
53276
53626
|
exitCode: exit.exitCode,
|
|
53277
|
-
|
|
53278
|
-
|
|
53627
|
+
stderrShape: outputShapeOnly(handle.stderr()),
|
|
53628
|
+
stdoutShape: outputShapeOnly(handle.stdout())
|
|
53279
53629
|
}
|
|
53280
53630
|
), await this.reportTeamTrackFailure(
|
|
53281
53631
|
args.taskId,
|
|
@@ -53297,8 +53647,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53297
53647
|
// exits 0 is still attributable from the log.
|
|
53298
53648
|
exitCode: exit.exitCode,
|
|
53299
53649
|
runtimeMs: exit.runtimeMs,
|
|
53300
|
-
|
|
53301
|
-
|
|
53650
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
53651
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
53302
53652
|
});
|
|
53303
53653
|
try {
|
|
53304
53654
|
let bundle = createSnapshotTrackBundle({
|
|
@@ -53375,8 +53725,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53375
53725
|
exitCode: exit.exitCode,
|
|
53376
53726
|
runtimeMs: exit.runtimeMs,
|
|
53377
53727
|
...files.length === 0 ? {
|
|
53378
|
-
|
|
53379
|
-
|
|
53728
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
53729
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
53380
53730
|
} : {}
|
|
53381
53731
|
}), this.surfaceHalt(reason), await this.discardShadow(args.taskId);
|
|
53382
53732
|
}
|
|
@@ -53391,7 +53741,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53391
53741
|
}
|
|
53392
53742
|
logger.warn("[QuorumLoop] implementor round failed", {
|
|
53393
53743
|
gateId,
|
|
53394
|
-
err
|
|
53744
|
+
...errorShapeOnly(err)
|
|
53395
53745
|
});
|
|
53396
53746
|
let reason = classifyImplementorRoundFailure(err);
|
|
53397
53747
|
this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`);
|
|
@@ -53879,7 +54229,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53879
54229
|
err: err.message
|
|
53880
54230
|
});
|
|
53881
54231
|
} finally {
|
|
53882
|
-
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && terminalDiscard && this.terminallyRetiredWorkspaceTasks.add(taskId),
|
|
54232
|
+
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && terminalDiscard && this.terminallyRetiredWorkspaceTasks.add(taskId), terminalDiscard && opts?.taskContinues !== !0 && (this.lastWorkspaceOutcome = {
|
|
54233
|
+
kind: "discarded",
|
|
54234
|
+
taskId,
|
|
54235
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54236
|
+
}), this.emitProgress(
|
|
53883
54237
|
{
|
|
53884
54238
|
phase: "discarded",
|
|
53885
54239
|
...terminalDiscard && opts?.taskContinues !== !0 ? { taskId } : {}
|
|
@@ -53988,7 +54342,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53988
54342
|
err: discardErr.message
|
|
53989
54343
|
});
|
|
53990
54344
|
}
|
|
53991
|
-
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.lastWorkspaceOutcome = {
|
|
54345
|
+
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.lastWorkspaceOutcome = {
|
|
54346
|
+
kind: "discarded",
|
|
54347
|
+
taskId,
|
|
54348
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54349
|
+
}, this.emitProgress({ phase: "discarded", taskId }, originEpoch), discarded && terminalOutcomeReserved && await this.workspaceOutcomeSink.completeTask(taskId, "apply_failed");
|
|
53992
54350
|
return;
|
|
53993
54351
|
}
|
|
53994
54352
|
if (this.teamRunIsHalted(teamAuthority)) return;
|
|
@@ -54022,7 +54380,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54022
54380
|
err: discardErr.message
|
|
54023
54381
|
});
|
|
54024
54382
|
}
|
|
54025
|
-
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.reviewedSnapshotByTask.delete(taskId), this.lastWorkspaceOutcome = {
|
|
54383
|
+
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.reviewedSnapshotByTask.delete(taskId), this.lastWorkspaceOutcome = {
|
|
54384
|
+
kind: "discarded",
|
|
54385
|
+
taskId,
|
|
54386
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54387
|
+
}, this.emitProgress({ phase: "discarded", taskId }, originEpoch), discarded && terminalOutcomeReserved && await this.workspaceOutcomeSink.completeTask(taskId, "apply_failed");
|
|
54026
54388
|
return;
|
|
54027
54389
|
}
|
|
54028
54390
|
this.reviewedSnapshotByTask.set(taskId, reviewedSnapshot);
|
|
@@ -54052,7 +54414,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54052
54414
|
err: discardErr.message
|
|
54053
54415
|
});
|
|
54054
54416
|
}
|
|
54055
|
-
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.lastWorkspaceOutcome = {
|
|
54417
|
+
discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.lastWorkspaceOutcome = {
|
|
54418
|
+
kind: "discarded",
|
|
54419
|
+
taskId,
|
|
54420
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54421
|
+
}, this.emitProgress({ phase: "discarded", taskId }, originEpoch), discarded && terminalOutcomeReserved && await this.workspaceOutcomeSink.completeTask(taskId, "apply_failed");
|
|
54056
54422
|
return;
|
|
54057
54423
|
}
|
|
54058
54424
|
}
|
|
@@ -54207,7 +54573,12 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54207
54573
|
}), logger.info("[QuorumLoop] shadow promoted to real tree", {
|
|
54208
54574
|
taskId,
|
|
54209
54575
|
promoted: appliedPaths.length
|
|
54210
|
-
}), this.lastWorkspaceOutcome = {
|
|
54576
|
+
}), this.lastWorkspaceOutcome = {
|
|
54577
|
+
kind: "promoted",
|
|
54578
|
+
files: [...appliedPaths],
|
|
54579
|
+
taskId,
|
|
54580
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54581
|
+
}, appendContextItem(this.deps.session.sessionId, {
|
|
54211
54582
|
kind: "verdict",
|
|
54212
54583
|
author: { role: "engine" },
|
|
54213
54584
|
sensitivity: "user",
|
|
@@ -54470,7 +54841,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54470
54841
|
if (promptText === null) {
|
|
54471
54842
|
logger.warn("[QuorumLoop] getReviewerPrompt exhausted \u2014 ESCALATE", {
|
|
54472
54843
|
key,
|
|
54473
|
-
|
|
54844
|
+
...errorShapeOnly(lastErr),
|
|
54474
54845
|
audit: "synthesized ESCALATE (#C1F-8): prompt_fetch_failed"
|
|
54475
54846
|
}), await this.submitVerdict(args, this.synthesizeEscalate(args, DESKTOP_DISPATCH_ESCALATE_REASONING), sessionKey);
|
|
54476
54847
|
return;
|
|
@@ -54505,13 +54876,13 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54505
54876
|
failureReason,
|
|
54506
54877
|
audit: "synthesized ESCALATE (#C1F-8): reviewer_substrate_engage_failed",
|
|
54507
54878
|
...describeReviewerErrorDetail(engageErr.detail),
|
|
54508
|
-
|
|
54879
|
+
...errorShapeOnly(engageErr)
|
|
54509
54880
|
}), await this.submitVerdict(args, this.synthesizeEscalate(args, cleanReasoning), sessionKey);
|
|
54510
54881
|
return;
|
|
54511
54882
|
}
|
|
54512
54883
|
throw engageErr;
|
|
54513
54884
|
}
|
|
54514
|
-
let verdict;
|
|
54885
|
+
let verdict, evaluationError;
|
|
54515
54886
|
try {
|
|
54516
54887
|
verdict = await this.evaluateSeatWithTimeout(spec, args.gateId, seatSubstrate.handle);
|
|
54517
54888
|
} catch (err) {
|
|
@@ -54539,7 +54910,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54539
54910
|
// Audit prefix kept in LOGS only (#C1F-8) — never on the wire.
|
|
54540
54911
|
audit: `synthesized ESCALATE (#C1F-8): reviewer_error:${err.detail.kind}`,
|
|
54541
54912
|
...describeReviewerErrorDetail(err.detail),
|
|
54542
|
-
|
|
54913
|
+
...errorShapeOnly(err),
|
|
54543
54914
|
// 2026-08-22 (dogfood) — TIMEOUT DIAGNOSTICS, local log only.
|
|
54544
54915
|
//
|
|
54545
54916
|
// A live 5-minute reviewer timeout on a ONE-FILE deletion diff was
|
|
@@ -54556,16 +54927,51 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54556
54927
|
...this.describeReviewShapeForDiagnostics(args.gateId)
|
|
54557
54928
|
}), verdict = this.synthesizeEscalate(args, cleanReasoning);
|
|
54558
54929
|
} else
|
|
54559
|
-
|
|
54560
|
-
}
|
|
54561
|
-
|
|
54930
|
+
evaluationError = err;
|
|
54931
|
+
}
|
|
54932
|
+
let cleanupError;
|
|
54933
|
+
try {
|
|
54934
|
+
await seatSubstrate.teardown();
|
|
54935
|
+
} catch (error) {
|
|
54936
|
+
cleanupError = error, logger.warn("[QuorumLoop] reviewer substrate cleanup failed \u2014 forcing ESCALATE", {
|
|
54937
|
+
key,
|
|
54938
|
+
seatId: args.seatId,
|
|
54939
|
+
role: args.role,
|
|
54940
|
+
agentKind: args.agentKind,
|
|
54941
|
+
...errorShapeOnly(error),
|
|
54942
|
+
audit: "synthesized ESCALATE: reviewer_substrate_cleanup_failed"
|
|
54562
54943
|
});
|
|
54563
54944
|
}
|
|
54945
|
+
if (evaluationError !== void 0) {
|
|
54946
|
+
let terminalError = cleanupError !== void 0 ? Object.assign(
|
|
54947
|
+
new Error("reviewer evaluation failed and substrate cleanup also failed"),
|
|
54948
|
+
{ causes: [evaluationError, cleanupError] }
|
|
54949
|
+
) : Object.assign(
|
|
54950
|
+
new Error("reviewer evaluation failed unexpectedly"),
|
|
54951
|
+
{ cause: evaluationError }
|
|
54952
|
+
);
|
|
54953
|
+
logger.warn("[QuorumLoop] unexpected reviewer evaluation failure \u2014 forcing ESCALATE", {
|
|
54954
|
+
key,
|
|
54955
|
+
seatId: args.seatId,
|
|
54956
|
+
role: args.role,
|
|
54957
|
+
agentKind: args.agentKind,
|
|
54958
|
+
...errorShapeOnly(terminalError),
|
|
54959
|
+
audit: "synthesized ESCALATE: reviewer_evaluation_failed"
|
|
54960
|
+
}), verdict = this.synthesizeEscalate(
|
|
54961
|
+
args,
|
|
54962
|
+
DESKTOP_DISPATCH_ESCALATE_REASONING
|
|
54963
|
+
);
|
|
54964
|
+
}
|
|
54965
|
+
if (cleanupError !== void 0 && (verdict = this.synthesizeEscalate(
|
|
54966
|
+
args,
|
|
54967
|
+
DESKTOP_DISPATCH_ESCALATE_REASONING
|
|
54968
|
+
)), verdict === void 0)
|
|
54969
|
+
throw new Error("reviewer completed without a verdict");
|
|
54564
54970
|
reviewScope !== null && (verdict = enforceReviewRoundScope(verdict, reviewScope)), await this.submitVerdict(args, verdict, sessionKey);
|
|
54565
54971
|
} catch (err) {
|
|
54566
54972
|
logger.warn("[QuorumLoop] spawnOneSeat failed \u2014 dropped", {
|
|
54567
54973
|
key,
|
|
54568
|
-
err
|
|
54974
|
+
...errorShapeOnly(err)
|
|
54569
54975
|
});
|
|
54570
54976
|
} finally {
|
|
54571
54977
|
this.runningSeats.delete(key);
|
|
@@ -54658,19 +55064,18 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54658
55064
|
if (e.name === REVIEWER_CREDENTIAL_MISSING)
|
|
54659
55065
|
try {
|
|
54660
55066
|
this.surfaceHalt(
|
|
54661
|
-
`Reviewer (${seatLabel(args.agentKind, args.seatId)}) cannot start sandboxed:
|
|
55067
|
+
`Reviewer (${seatLabel(args.agentKind, args.seatId)}) cannot start sandboxed: the required provider credential is unavailable. Run \`codevibe vendor-key setup\`` + (args.agentKind === "codex" ? " (or `codevibe vendor-key import-codex` for a ChatGPT subscription)" : "") + ", or set CODEVIBE_SANDBOX_REVIEWERS=0 to opt out of reviewer sandboxing."
|
|
54662
55068
|
);
|
|
54663
55069
|
} catch {
|
|
54664
55070
|
}
|
|
54665
55071
|
throw new ReviewerErrorClass({
|
|
54666
55072
|
kind: "spawn_failed",
|
|
54667
55073
|
agent: args.agentKind,
|
|
54668
|
-
reason:
|
|
55074
|
+
reason: "CP-7: reviewer substrate engage failed for a Trusted agent \u2014 refusing the unsandboxed (ambient-cred) fallback (fail-closed)",
|
|
54669
55075
|
failureReason: "spawn_failed"
|
|
54670
55076
|
});
|
|
54671
55077
|
}
|
|
54672
|
-
return result.mode === "reduced_trust" ? (this.surfaceReviewerReducedTrust(args, result.reducedTrustReason), await result.teardown()
|
|
54673
|
-
}), NO_TEARDOWN) : (result.reducedTrust && this.surfaceReviewerReducedTrust(
|
|
55078
|
+
return result.mode === "reduced_trust" ? (this.surfaceReviewerReducedTrust(args, result.reducedTrustReason), await result.teardown(), NO_TEARDOWN) : (result.reducedTrust && this.surfaceReviewerReducedTrust(
|
|
54674
55079
|
args,
|
|
54675
55080
|
result.reducedTrustReason ?? "coarse egress (A5 sandbox-exec) \u2014 reviewer is sandboxed but loopback-only."
|
|
54676
55081
|
), {
|
|
@@ -54712,7 +55117,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54712
55117
|
reason
|
|
54713
55118
|
), logger.warn("[QuorumLoop] reduced-trust badge surfaceHalt threw (badge is best-effort) \u2014 continuing", {
|
|
54714
55119
|
seatId: args.seatId,
|
|
54715
|
-
|
|
55120
|
+
...errorShapeOnly(e)
|
|
54716
55121
|
});
|
|
54717
55122
|
}
|
|
54718
55123
|
}
|
|
@@ -54767,13 +55172,20 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54767
55172
|
});
|
|
54768
55173
|
if (result.mode === "substrate")
|
|
54769
55174
|
return { mode: "substrate", handle: result.substrateHandle, teardown: () => result.teardown() };
|
|
54770
|
-
|
|
54771
|
-
|
|
55175
|
+
try {
|
|
55176
|
+
await result.teardown();
|
|
55177
|
+
} catch (cleanupError) {
|
|
55178
|
+
return logger.warn("[QuorumLoop] Wave B reduced-trust cleanup failed \u2014 refusing fallback", {
|
|
55179
|
+
taskId,
|
|
55180
|
+
agent,
|
|
55181
|
+
...errorShapeOnly(cleanupError)
|
|
55182
|
+
}), { mode: "none" };
|
|
55183
|
+
}
|
|
54772
55184
|
} catch (e) {
|
|
54773
55185
|
logger.warn("[QuorumLoop] Wave B substrate engage failed \u2014 falling through to trusted-container/none", {
|
|
54774
55186
|
taskId,
|
|
54775
55187
|
agent,
|
|
54776
|
-
|
|
55188
|
+
...errorShapeOnly(e)
|
|
54777
55189
|
});
|
|
54778
55190
|
}
|
|
54779
55191
|
return isTrustedContainerBoundary() ? { mode: "trusted_container", teardown: async () => {
|
|
@@ -54804,9 +55216,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54804
55216
|
...substrate !== void 0 ? { substrate } : {}
|
|
54805
55217
|
});
|
|
54806
55218
|
if (!outcome.exit_success)
|
|
54807
|
-
throw
|
|
54808
|
-
|
|
54809
|
-
|
|
55219
|
+
throw logger.warn("[QuorumLoop] class-2 resolver model call exited non-zero", {
|
|
55220
|
+
ownerTaskId: args.ownerTaskId,
|
|
55221
|
+
stdoutShape: outputShapeOnly(outcome.stdout),
|
|
55222
|
+
stderrShape: outputShapeOnly(outcome.stderr)
|
|
55223
|
+
}), new Error("class-2 resolver model call exited non-zero");
|
|
54810
55224
|
return outcome.stdout;
|
|
54811
55225
|
};
|
|
54812
55226
|
return {
|
|
@@ -54850,7 +55264,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54850
55264
|
return { establishable: !0, via: "ladder_tier" };
|
|
54851
55265
|
} catch (err) {
|
|
54852
55266
|
logger.warn("[QuorumLoop] A1d resolver probe: ladder select failed \u2014 treating as no tier", {
|
|
54853
|
-
err
|
|
55267
|
+
...errorShapeOnly(err)
|
|
54854
55268
|
});
|
|
54855
55269
|
}
|
|
54856
55270
|
return (this.deps.resolverProbeDeps?.trustedContainer ?? isTrustedContainerBoundary)() ? { establishable: !0, via: "trusted_container" } : { establishable: !1 };
|
|
@@ -54981,8 +55395,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54981
55395
|
taskId: tid,
|
|
54982
55396
|
exitCode: exit.exitCode,
|
|
54983
55397
|
runtimeMs: exit.runtimeMs,
|
|
54984
|
-
|
|
54985
|
-
|
|
55398
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
55399
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
54986
55400
|
}), exit.failureClass !== null)
|
|
54987
55401
|
throw new Error(`agentic resolver implementor failed: ${exit.failureClass}`);
|
|
54988
55402
|
}
|
|
@@ -55045,6 +55459,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
55045
55459
|
});
|
|
55046
55460
|
continue;
|
|
55047
55461
|
}
|
|
55462
|
+
let candidateError;
|
|
55048
55463
|
try {
|
|
55049
55464
|
let substrate = confinement.mode === "substrate" ? confinement.handle : void 0, spec = {
|
|
55050
55465
|
seat_id: 0,
|
|
@@ -55067,14 +55482,27 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
55067
55482
|
...pass ? {} : { reason: `final-tip Tier-2 verdict: ${verdict.verdict}` }
|
|
55068
55483
|
};
|
|
55069
55484
|
} catch (e) {
|
|
55070
|
-
lastFailure = `final-tip Tier-2 reviewer
|
|
55485
|
+
candidateError = e, lastFailure = `final-tip Tier-2 reviewer ${agent} failed to produce a verdict`, logger.warn("[QuorumLoop] final-tip Tier-2 candidate failed \u2014 trying next", {
|
|
55071
55486
|
ownerTaskId: args.ownerTaskId,
|
|
55072
55487
|
agent,
|
|
55073
|
-
|
|
55488
|
+
...errorShapeOnly(e)
|
|
55074
55489
|
});
|
|
55075
55490
|
} finally {
|
|
55076
|
-
|
|
55077
|
-
|
|
55491
|
+
try {
|
|
55492
|
+
await confinement.teardown();
|
|
55493
|
+
} catch (cleanupError) {
|
|
55494
|
+
throw logger.warn("[QuorumLoop] final-tip Tier-2 substrate cleanup failed \u2014 failing closed", {
|
|
55495
|
+
ownerTaskId: args.ownerTaskId,
|
|
55496
|
+
agent,
|
|
55497
|
+
...errorShapeOnly(cleanupError)
|
|
55498
|
+
}), candidateError !== void 0 ? Object.assign(
|
|
55499
|
+
new Error("final-tip Tier-2 evaluation failed and substrate cleanup also failed"),
|
|
55500
|
+
{ causes: [candidateError, cleanupError] }
|
|
55501
|
+
) : Object.assign(
|
|
55502
|
+
new Error("final-tip Tier-2 substrate cleanup failed"),
|
|
55503
|
+
{ cause: cleanupError }
|
|
55504
|
+
);
|
|
55505
|
+
}
|
|
55078
55506
|
}
|
|
55079
55507
|
}
|
|
55080
55508
|
return {
|
|
@@ -56825,7 +57253,7 @@ function seatKey(gateId, seatId) {
|
|
|
56825
57253
|
return `${gateId}::${seatId}`;
|
|
56826
57254
|
}
|
|
56827
57255
|
function seatLabel(agentKind, seatId) {
|
|
56828
|
-
return `${REVIEWER_AGENT_DISPLAY_NAME[agentKind] ?? agentKind} (seat ${seatId})`;
|
|
57256
|
+
return `${REVIEWER_AGENT_DISPLAY_NAME[agentKind] ?? agentKind} (seat ${displayOrdinal(seatId)})`;
|
|
56829
57257
|
}
|
|
56830
57258
|
function diffCapturedProgress(round, files) {
|
|
56831
57259
|
let created = 0, modified = 0, deleted = 0;
|
|
@@ -57793,7 +58221,7 @@ async function runOrchestrationShell(args) {
|
|
|
57793
58221
|
});
|
|
57794
58222
|
}
|
|
57795
58223
|
workspaceTerminalCoordinator && await workspaceTerminalCoordinator.replayPending(), processMarkers();
|
|
57796
|
-
let unsubscribeEvents = null, pendingDurableResolutions = /* @__PURE__ */ new Map(), durableDecisionEffectDispatcher = null, dispatchDurableDecisionEffect = async (resolution) => {
|
|
58224
|
+
let inkUnmount = null, nonTtyAbort = null, explicitExit = null, sessionRetiredExitRequested = !1, triggerSessionRetiredTeardown = null, unsubscribeEvents = null, pendingDurableResolutions = /* @__PURE__ */ new Map(), durableDecisionEffectDispatcher = null, dispatchDurableDecisionEffect = async (resolution) => {
|
|
57797
58225
|
if (!durableDecisionEffectDispatcher) {
|
|
57798
58226
|
pendingDurableResolutions.set(resolution.eventId, resolution);
|
|
57799
58227
|
return;
|
|
@@ -57929,6 +58357,16 @@ async function runOrchestrationShell(args) {
|
|
|
57929
58357
|
text: "Gate history recovery is unavailable. Existing gate actions remain fail-closed until recovery succeeds."
|
|
57930
58358
|
})) : rejectInitialSubscription(error);
|
|
57931
58359
|
});
|
|
58360
|
+
},
|
|
58361
|
+
onSessionRetired: () => {
|
|
58362
|
+
logger.warn(
|
|
58363
|
+
"[orchestration-shell] Session permanently retired on backend; triggering fail-closed teardown",
|
|
58364
|
+
{ sessionId: args.session.sessionId }
|
|
58365
|
+
), store.dispatch({
|
|
58366
|
+
type: "SHELL_ADVISORY",
|
|
58367
|
+
source: "shell",
|
|
58368
|
+
text: "Hosted session has been retired. Exiting orchestration shell."
|
|
58369
|
+
}), triggerSessionRetiredTeardown ? triggerSessionRetiredTeardown() : sessionRetiredExitRequested = !0;
|
|
57932
58370
|
}
|
|
57933
58371
|
}
|
|
57934
58372
|
);
|
|
@@ -58171,7 +58609,7 @@ async function runOrchestrationShell(args) {
|
|
|
58171
58609
|
if (admitted.length === 0) return;
|
|
58172
58610
|
await Promise.allSettled(admitted);
|
|
58173
58611
|
}
|
|
58174
|
-
}, NORMAL_SHUTDOWN_TIMEOUT_MS = 1e4, SIGNAL_SHUTDOWN_TIMEOUT_MS = 3e3, SESSION_RETIRE_TIMEOUT_MS2 = 3e3, hostedSessionIngressFenced = !1, hostedSessionIngressFenceFailures = [], hostedSessionIngressFenceDrain = Promise.resolve(), shutdownFailure = (message, reason) => Object.assign(
|
|
58612
|
+
}, NORMAL_SHUTDOWN_TIMEOUT_MS = 1e4, SIGNAL_SHUTDOWN_TIMEOUT_MS = 3e3, SESSION_RETIRE_TIMEOUT_MS2 = 3e3, hostedSessionIngressFenced = !1, hostedRetirementMutationStarted = !1, lastDitchRetirementPromise = null, hostedSessionIngressFenceFailures = [], hostedSessionIngressFenceDrain = Promise.resolve(), shutdownFailure = (message, reason) => Object.assign(
|
|
58175
58613
|
new Error(
|
|
58176
58614
|
`${message}: ${reason instanceof Error ? reason.message : String(reason)}`
|
|
58177
58615
|
),
|
|
@@ -58242,7 +58680,7 @@ async function runOrchestrationShell(args) {
|
|
|
58242
58680
|
shutdownFailure("session heartbeat stop failed", reason)
|
|
58243
58681
|
);
|
|
58244
58682
|
}
|
|
58245
|
-
},
|
|
58683
|
+
}, retireHostedSession = async () => {
|
|
58246
58684
|
await hostedSessionIngressFenceDrain;
|
|
58247
58685
|
let failures = [...hostedSessionIngressFenceFailures];
|
|
58248
58686
|
try {
|
|
@@ -58279,11 +58717,11 @@ async function runOrchestrationShell(args) {
|
|
|
58279
58717
|
new Error("final ContextItems publication did not converge"),
|
|
58280
58718
|
{ causes: failures }
|
|
58281
58719
|
);
|
|
58282
|
-
}, workspaceResourceRetirement = null, plannerTeardown = createBoundedSharedShutdownOperation({
|
|
58720
|
+
}, workspaceResourceRetirement = null, teardownDeadlineExpired = !1, plannerTeardown = createBoundedSharedShutdownOperation({
|
|
58283
58721
|
normalTimeoutMs: NORMAL_SHUTDOWN_TIMEOUT_MS,
|
|
58284
58722
|
signalTimeoutMs: SIGNAL_SHUTDOWN_TIMEOUT_MS,
|
|
58285
58723
|
onTimeout: (deadlineClass, timeoutMs) => {
|
|
58286
|
-
logger.warn("[orchestration-shell] planner teardown timed out", {
|
|
58724
|
+
teardownDeadlineExpired = !0, logger.warn("[orchestration-shell] planner teardown timed out", {
|
|
58287
58725
|
deadlineClass,
|
|
58288
58726
|
timeoutMs
|
|
58289
58727
|
});
|
|
@@ -58350,47 +58788,75 @@ async function runOrchestrationShell(args) {
|
|
|
58350
58788
|
});
|
|
58351
58789
|
}
|
|
58352
58790
|
}), runPlannerTeardown = async (deadlineClass = "normal") => {
|
|
58353
|
-
let boundedCompletion = plannerTeardown.wait(deadlineClass);
|
|
58354
|
-
if (deadlineClass === "signal") return boundedCompletion;
|
|
58355
|
-
let requiredRetirement = workspaceResourceRetirement;
|
|
58791
|
+
let boundedCompletion = plannerTeardown.wait(deadlineClass), requiredRetirement = workspaceResourceRetirement;
|
|
58356
58792
|
if (!requiredRetirement)
|
|
58357
58793
|
throw new Error("workspace retirement boundary was not published");
|
|
58358
58794
|
let [boundedResult] = await Promise.allSettled([boundedCompletion]);
|
|
58359
|
-
if (boundedResult.status === "rejected" && boundedResult.reason?.teardownDeadlineExpired === !0 && // The leak scenario is a hung EARLIER phase starving `retireHostedSession`
|
|
58795
|
+
if ((teardownDeadlineExpired || boundedResult.status === "rejected" && boundedResult.reason?.teardownDeadlineExpired === !0) && // The leak scenario is a hung EARLIER phase starving `retireHostedSession`
|
|
58360
58796
|
// before it could issue its mutation. If the ordered mutation already
|
|
58361
58797
|
// started (in flight when the deadline expired, or settled with the
|
|
58362
58798
|
// deadline expiring on a parallel phase such as the planner flush), the
|
|
58363
58799
|
// last-ditch duplicate is redundant — skip it.
|
|
58364
|
-
!hostedRetirementMutationStarted)
|
|
58365
|
-
|
|
58366
|
-
|
|
58367
|
-
|
|
58368
|
-
|
|
58369
|
-
|
|
58370
|
-
|
|
58371
|
-
|
|
58372
|
-
|
|
58373
|
-
|
|
58374
|
-
|
|
58375
|
-
|
|
58376
|
-
|
|
58377
|
-
|
|
58378
|
-
|
|
58379
|
-
|
|
58380
|
-
|
|
58381
|
-
|
|
58382
|
-
|
|
58383
|
-
|
|
58384
|
-
|
|
58385
|
-
|
|
58386
|
-
|
|
58387
|
-
|
|
58800
|
+
!hostedRetirementMutationStarted)
|
|
58801
|
+
if (lastDitchRetirementPromise)
|
|
58802
|
+
await lastDitchRetirementPromise;
|
|
58803
|
+
else {
|
|
58804
|
+
let timer;
|
|
58805
|
+
lastDitchRetirementPromise = (async () => {
|
|
58806
|
+
try {
|
|
58807
|
+
await Promise.race([
|
|
58808
|
+
args.appsyncClient.updateSession({
|
|
58809
|
+
sessionId: args.session.sessionId,
|
|
58810
|
+
status: "INACTIVE" /* INACTIVE */
|
|
58811
|
+
}).then(() => {
|
|
58812
|
+
logger.warn(
|
|
58813
|
+
"[orchestration-shell] last-ditch session retirement landed after teardown timeout",
|
|
58814
|
+
{ sessionId: args.session.sessionId }
|
|
58815
|
+
);
|
|
58816
|
+
}).catch((reason) => {
|
|
58817
|
+
logger.warn("[orchestration-shell] last-ditch session retirement failed", {
|
|
58818
|
+
sessionId: args.session.sessionId,
|
|
58819
|
+
errorName: reason?.name ?? "Error"
|
|
58820
|
+
});
|
|
58821
|
+
}),
|
|
58822
|
+
new Promise((resolve21) => {
|
|
58823
|
+
timer = setTimeout(resolve21, SESSION_RETIRE_TIMEOUT_MS2), timer.unref?.();
|
|
58824
|
+
})
|
|
58825
|
+
]);
|
|
58826
|
+
} finally {
|
|
58827
|
+
timer && clearTimeout(timer);
|
|
58828
|
+
}
|
|
58829
|
+
})(), await lastDitchRetirementPromise;
|
|
58388
58830
|
}
|
|
58389
|
-
|
|
58390
|
-
|
|
58831
|
+
let [retirementResult] = await Promise.allSettled(
|
|
58832
|
+
deadlineClass === "signal" && teardownDeadlineExpired ? [] : [requiredRetirement]
|
|
58833
|
+
);
|
|
58391
58834
|
if (boundedResult.status === "rejected") throw boundedResult.reason;
|
|
58392
|
-
if (retirementResult.status === "rejected") throw retirementResult.reason;
|
|
58393
|
-
}
|
|
58835
|
+
if (retirementResult && retirementResult.status === "rejected") throw retirementResult.reason;
|
|
58836
|
+
};
|
|
58837
|
+
triggerSessionRetiredTeardown = () => {
|
|
58838
|
+
if (sessionRetiredExitRequested = !0, nonTtyAbort)
|
|
58839
|
+
try {
|
|
58840
|
+
nonTtyAbort.abort();
|
|
58841
|
+
} catch {
|
|
58842
|
+
}
|
|
58843
|
+
if (explicitExit)
|
|
58844
|
+
try {
|
|
58845
|
+
explicitExit.start();
|
|
58846
|
+
} catch {
|
|
58847
|
+
}
|
|
58848
|
+
else if (inkUnmount)
|
|
58849
|
+
try {
|
|
58850
|
+
inkUnmount(), inkUnmount = null;
|
|
58851
|
+
} catch {
|
|
58852
|
+
}
|
|
58853
|
+
runPlannerTeardown("normal").catch((err) => {
|
|
58854
|
+
logger.warn("[orchestration-shell] session-retired teardown failed", {
|
|
58855
|
+
error: err instanceof Error ? err.message : String(err)
|
|
58856
|
+
});
|
|
58857
|
+
});
|
|
58858
|
+
}, sessionRetiredExitRequested && triggerSessionRetiredTeardown();
|
|
58859
|
+
let signalShutdownStarted = !1, signalShutdownCompletion = null, signalsRegistered = /* @__PURE__ */ new Set(), onSignal = (sig) => {
|
|
58394
58860
|
signalShutdownCompletion || (signalShutdownStarted = !0, disableBracketedPaste(), signalShutdownCompletion = Promise.allSettled([runPlannerTeardown("signal")]).then(() => {
|
|
58395
58861
|
}).finally(() => {
|
|
58396
58862
|
logger.info(`[orchestration-shell] caught ${sig}, teardown complete`);
|
|
@@ -58409,7 +58875,7 @@ async function runOrchestrationShell(args) {
|
|
|
58409
58875
|
try {
|
|
58410
58876
|
process.kill(process.pid, sig);
|
|
58411
58877
|
} catch {
|
|
58412
|
-
let code = sig === "SIGTERM" ? 143 : 130;
|
|
58878
|
+
let code = sig === "SIGTERM" ? 143 : sig === "SIGHUP" ? 129 : 130;
|
|
58413
58879
|
process.exit(code);
|
|
58414
58880
|
}
|
|
58415
58881
|
}));
|
|
@@ -58621,14 +59087,19 @@ async function runOrchestrationShell(args) {
|
|
|
58621
59087
|
// land in the active conversation. ABSENT on a non-team session.
|
|
58622
59088
|
...args.groupDecisionDeps ? { groupDecision: { ...args.groupDecisionDeps, store } } : {}
|
|
58623
59089
|
};
|
|
58624
|
-
mobileGateDecisionDeps = gateDecisionDeps, process.
|
|
59090
|
+
mobileGateDecisionDeps = gateDecisionDeps, process.on("SIGINT", onSignal), signalsRegistered.add("SIGINT"), process.on("SIGTERM", onSignal), signalsRegistered.add("SIGTERM"), process.on("SIGHUP", onSignal), signalsRegistered.add("SIGHUP");
|
|
58625
59091
|
try {
|
|
58626
59092
|
if (signalShutdownCompletion) {
|
|
58627
59093
|
await signalShutdownCompletion;
|
|
58628
59094
|
return;
|
|
58629
59095
|
}
|
|
59096
|
+
if (sessionRetiredExitRequested)
|
|
59097
|
+
return;
|
|
58630
59098
|
if (args.acceptSessionLifecycleOwnership?.(), !isInteractiveTty()) {
|
|
58631
|
-
nonTtyAbort = new AbortController()
|
|
59099
|
+
if (nonTtyAbort = new AbortController(), sessionRetiredExitRequested) {
|
|
59100
|
+
nonTtyAbort = null;
|
|
59101
|
+
return;
|
|
59102
|
+
}
|
|
58632
59103
|
try {
|
|
58633
59104
|
await runLineLogFallback({
|
|
58634
59105
|
store,
|
|
@@ -58656,6 +59127,8 @@ async function runOrchestrationShell(args) {
|
|
|
58656
59127
|
await signalShutdownCompletion;
|
|
58657
59128
|
return;
|
|
58658
59129
|
}
|
|
59130
|
+
if (sessionRetiredExitRequested)
|
|
59131
|
+
return;
|
|
58659
59132
|
let { ink } = getInkRuntime(), { waitUntilExit, unmount } = ink.render(
|
|
58660
59133
|
React20.createElement(OrchestrationApp, {
|
|
58661
59134
|
store,
|
|
@@ -58706,19 +59179,21 @@ async function runOrchestrationShell(args) {
|
|
|
58706
59179
|
{ stdout: process.stdout }
|
|
58707
59180
|
);
|
|
58708
59181
|
inkUnmount = unmount;
|
|
58709
|
-
let
|
|
59182
|
+
let ttyExplicitExit = createExplicitTtyExitCoordinator({
|
|
58710
59183
|
runTeardown: runPlannerTeardown,
|
|
58711
59184
|
unmount: () => {
|
|
58712
59185
|
inkUnmount && (inkUnmount(), inkUnmount = null);
|
|
58713
59186
|
}
|
|
58714
|
-
})
|
|
59187
|
+
});
|
|
59188
|
+
explicitExit = ttyExplicitExit, sessionRetiredExitRequested && ttyExplicitExit.start();
|
|
59189
|
+
let unsubscribe = store.subscribe((state) => {
|
|
58715
59190
|
let last = state.conversation[state.conversation.length - 1];
|
|
58716
|
-
last && last.kind === "slash-output" && isExitCommand(last.command) &&
|
|
59191
|
+
last && last.kind === "slash-output" && isExitCommand(last.command) && ttyExplicitExit.start();
|
|
58717
59192
|
});
|
|
58718
59193
|
try {
|
|
58719
|
-
await Promise.race([waitUntilExit(),
|
|
59194
|
+
await Promise.race([waitUntilExit(), ttyExplicitExit.completion]);
|
|
58720
59195
|
} finally {
|
|
58721
|
-
unsubscribe(), inkUnmount = null;
|
|
59196
|
+
unsubscribe(), inkUnmount = null, explicitExit = null;
|
|
58722
59197
|
}
|
|
58723
59198
|
} finally {
|
|
58724
59199
|
try {
|
|
@@ -59275,8 +59750,8 @@ function routeTeamShellEventToStore(store, evt) {
|
|
|
59275
59750
|
return;
|
|
59276
59751
|
}
|
|
59277
59752
|
if (source === "task_group_halted") {
|
|
59278
|
-
let haltReason = typeof md.haltReason == "string" ? md.haltReason : "halted";
|
|
59279
|
-
store.dispatch({ type: "TEAM_HALTED", haltReason });
|
|
59753
|
+
let haltReason = typeof md.haltReason == "string" ? md.haltReason : "halted", completedAt = typeof md.completed_at == "string" ? md.completed_at : typeof md.completedAt == "string" ? md.completedAt : void 0;
|
|
59754
|
+
store.dispatch({ type: "TEAM_HALTED", haltReason, ...completedAt ? { completedAt } : {} });
|
|
59280
59755
|
let team = store.getState().team;
|
|
59281
59756
|
if (team)
|
|
59282
59757
|
for (let [trackIndex, t] of team.tracks)
|
|
@@ -59322,8 +59797,12 @@ function routeTeamShellEventToStore(store, evt) {
|
|
|
59322
59797
|
if (!team || team.groupResolved) return;
|
|
59323
59798
|
let trackStates = [...team.tracks.values()].map((t) => t.state), allTerminal = trackStates.length > 0 && trackStates.every((s) => s === "Passed" || s === "Failed"), anyFailed = trackStates.some((s) => s === "Failed");
|
|
59324
59799
|
if (!allTerminal || !anyFailed) return;
|
|
59325
|
-
let failedTrackIndices = [...team.tracks.entries()].filter(([, t]) => t.state === "Failed").map(([idx]) => idx).sort((a, b) => a - b), failedLabel = failedTrackIndices.length === 1 ? `track ${displayTrackNumber(failedTrackIndices[0])}` : `tracks ${failedTrackIndices.map(displayTrackNumber).join(", ")}
|
|
59326
|
-
store.dispatch({
|
|
59800
|
+
let failedTrackIndices = [...team.tracks.entries()].filter(([, t]) => t.state === "Failed").map(([idx]) => idx).sort((a, b) => a - b), failedLabel = failedTrackIndices.length === 1 ? `track ${displayTrackNumber(failedTrackIndices[0])}` : `tracks ${failedTrackIndices.map(displayTrackNumber).join(", ")}`, localHaltCompletedAt = typeof md.completed_at == "string" ? md.completed_at : typeof md.completedAt == "string" ? md.completedAt : void 0;
|
|
59801
|
+
store.dispatch({
|
|
59802
|
+
type: "TEAM_GROUP_RESOLVED",
|
|
59803
|
+
outcome: `team_halted:${reason}`,
|
|
59804
|
+
...localHaltCompletedAt ? { completedAt: localHaltCompletedAt } : {}
|
|
59805
|
+
}), store.dispatch({
|
|
59327
59806
|
type: "SHELL_ADVISORY",
|
|
59328
59807
|
source: "shell",
|
|
59329
59808
|
text: `Agent Teams: Team halted \u2014 ${failedLabel} failed (${reason}). Passing tracks were not applied to your files; CodeVibe will clean up their disposable task resources automatically.`
|
|
@@ -59333,8 +59812,12 @@ function routeTeamShellEventToStore(store, evt) {
|
|
|
59333
59812
|
if (source === "team_group_resolved") {
|
|
59334
59813
|
let outcome = md.outcome;
|
|
59335
59814
|
if (typeof outcome != "string" || outcome.length === 0) return;
|
|
59336
|
-
let priorTeam = store.getState().team, alreadyResolvedSame = priorTeam?.groupResolved === !0 && priorTeam.outcome === outcome;
|
|
59337
|
-
if (store.dispatch({
|
|
59815
|
+
let completedAt = typeof md.completed_at == "string" ? md.completed_at : typeof md.completedAt == "string" ? md.completedAt : void 0, priorTeam = store.getState().team, alreadyResolvedSame = priorTeam?.groupResolved === !0 && priorTeam.outcome === outcome;
|
|
59816
|
+
if (store.dispatch({
|
|
59817
|
+
type: "TEAM_GROUP_RESOLVED",
|
|
59818
|
+
outcome,
|
|
59819
|
+
...completedAt ? { completedAt } : {}
|
|
59820
|
+
}), alreadyResolvedSame) return;
|
|
59338
59821
|
let text2 = outcome === "complete" ? "Agent Teams: Team complete" : `Agent Teams: Team halted \u2014 ${outcome}`;
|
|
59339
59822
|
store.dispatch({ type: "SHELL_ADVISORY", source: "shell", text: text2 });
|
|
59340
59823
|
return;
|
|
@@ -62517,6 +63000,11 @@ var GATE_PROMPT_KIND_LABEL = {
|
|
|
62517
63000
|
orchestration_escalated_gate: "escalated review gate",
|
|
62518
63001
|
continuation_offer_handoff: "continuation handoff offer"
|
|
62519
63002
|
};
|
|
63003
|
+
function parseIsoTimestamp(iso) {
|
|
63004
|
+
if (!iso) return 0;
|
|
63005
|
+
let t = Date.parse(iso);
|
|
63006
|
+
return Number.isFinite(t) ? t : 0;
|
|
63007
|
+
}
|
|
62520
63008
|
function buildStatusSummary(state, quorumLoop) {
|
|
62521
63009
|
let lines = [];
|
|
62522
63010
|
if (state.team) {
|
|
@@ -62548,7 +63036,80 @@ function buildStatusSummary(state, quorumLoop) {
|
|
|
62548
63036
|
`Awaiting your decision: ${label} for task ${entry.envelope.taskId} \u2014 reply with an option number (1-${entry.envelope.options.length})${queued}.`
|
|
62549
63037
|
);
|
|
62550
63038
|
}
|
|
62551
|
-
let
|
|
63039
|
+
let rawOutcome = quorumLoop?.getLastWorkspaceOutcome() ?? null, outcome = null;
|
|
63040
|
+
if (rawOutcome !== null && !teamActive)
|
|
63041
|
+
if (rawOutcome.taskId) {
|
|
63042
|
+
let refTask = state.sessionTasks.get(rawOutcome.taskId);
|
|
63043
|
+
if (refTask && refTask.origin === "single")
|
|
63044
|
+
if (!state.team)
|
|
63045
|
+
outcome = rawOutcome;
|
|
63046
|
+
else {
|
|
63047
|
+
let singleTaskTime = Math.max(
|
|
63048
|
+
parseIsoTimestamp(rawOutcome.completedAt),
|
|
63049
|
+
parseIsoTimestamp(refTask.completedAt),
|
|
63050
|
+
parseIsoTimestamp(refTask.startedAt)
|
|
63051
|
+
), teamTasks = [...state.sessionTasks.values()].filter(
|
|
63052
|
+
(t) => t.origin === "team"
|
|
63053
|
+
), maxTeamTrackTime = teamTasks.length > 0 ? Math.max(
|
|
63054
|
+
...teamTasks.map(
|
|
63055
|
+
(tt) => Math.max(
|
|
63056
|
+
parseIsoTimestamp(tt.completedAt),
|
|
63057
|
+
parseIsoTimestamp(tt.startedAt)
|
|
63058
|
+
)
|
|
63059
|
+
)
|
|
63060
|
+
) : 0, teamStartedTime = parseIsoTimestamp(state.team.startedAt), teamCompletedTime = parseIsoTimestamp(state.team.completedAt), latestTeamTime = Math.max(
|
|
63061
|
+
teamStartedTime,
|
|
63062
|
+
teamCompletedTime,
|
|
63063
|
+
maxTeamTrackTime
|
|
63064
|
+
), teamRanAfter;
|
|
63065
|
+
if (latestTeamTime !== singleTaskTime)
|
|
63066
|
+
teamRanAfter = latestTeamTime > singleTaskTime || teamTasks.length === 0 && teamStartedTime === 0 && teamCompletedTime === 0;
|
|
63067
|
+
else {
|
|
63068
|
+
let teamSeq = Math.max(
|
|
63069
|
+
state.team.terminalSeq ?? 0,
|
|
63070
|
+
...teamTasks.map((tt) => tt.terminalSeq ?? 0)
|
|
63071
|
+
), singleSeq = refTask.terminalSeq ?? 0;
|
|
63072
|
+
teamSeq > 0 && singleSeq > 0 ? teamRanAfter = teamSeq > singleSeq : teamRanAfter = teamTasks.length === 0 && teamStartedTime === 0 && teamCompletedTime === 0;
|
|
63073
|
+
}
|
|
63074
|
+
teamRanAfter || (outcome = rawOutcome);
|
|
63075
|
+
}
|
|
63076
|
+
} else if (!state.team)
|
|
63077
|
+
outcome = rawOutcome;
|
|
63078
|
+
else {
|
|
63079
|
+
let singleTasks = [...state.sessionTasks.values()].filter(
|
|
63080
|
+
(t) => t.origin === "single"
|
|
63081
|
+
);
|
|
63082
|
+
if (singleTasks.length > 0) {
|
|
63083
|
+
let latestSingle = singleTasks.reduce((latest, curr) => {
|
|
63084
|
+
let currTime = Math.max(
|
|
63085
|
+
parseIsoTimestamp(curr.completedAt),
|
|
63086
|
+
parseIsoTimestamp(curr.startedAt)
|
|
63087
|
+
), latestTime = Math.max(
|
|
63088
|
+
parseIsoTimestamp(latest.completedAt),
|
|
63089
|
+
parseIsoTimestamp(latest.startedAt)
|
|
63090
|
+
);
|
|
63091
|
+
return currTime > latestTime ? curr : latest;
|
|
63092
|
+
}), singleTaskTime = Math.max(
|
|
63093
|
+
parseIsoTimestamp(rawOutcome.completedAt),
|
|
63094
|
+
parseIsoTimestamp(latestSingle.completedAt),
|
|
63095
|
+
parseIsoTimestamp(latestSingle.startedAt)
|
|
63096
|
+
), teamTasks = [...state.sessionTasks.values()].filter(
|
|
63097
|
+
(t) => t.origin === "team"
|
|
63098
|
+
), maxTeamTrackTime = teamTasks.length > 0 ? Math.max(
|
|
63099
|
+
...teamTasks.map(
|
|
63100
|
+
(tt) => Math.max(
|
|
63101
|
+
parseIsoTimestamp(tt.completedAt),
|
|
63102
|
+
parseIsoTimestamp(tt.startedAt)
|
|
63103
|
+
)
|
|
63104
|
+
)
|
|
63105
|
+
) : 0, teamStartedTime = parseIsoTimestamp(state.team.startedAt), teamCompletedTime = parseIsoTimestamp(state.team.completedAt);
|
|
63106
|
+
Math.max(
|
|
63107
|
+
teamStartedTime,
|
|
63108
|
+
teamCompletedTime,
|
|
63109
|
+
maxTeamTrackTime
|
|
63110
|
+
) > singleTaskTime || teamTasks.length === 0 && teamStartedTime === 0 && teamCompletedTime === 0 || (outcome = rawOutcome);
|
|
63111
|
+
}
|
|
63112
|
+
}
|
|
62552
63113
|
if (outcome && outcome.kind === "promoted") {
|
|
62553
63114
|
let n = outcome.files.length;
|
|
62554
63115
|
n > 0 ? lines.push(
|
|
@@ -65193,7 +65754,7 @@ function buildSanitizedBaseEnv(input) {
|
|
|
65193
65754
|
let v = safeSource[key];
|
|
65194
65755
|
typeof v == "string" && v.length > 0 && (env[key] = v);
|
|
65195
65756
|
}
|
|
65196
|
-
return input.provider === "anthropic" ? env.ANTHROPIC_BASE_URL = input.sandboxBrokerUrl : env.OPENAI_BASE_URL = `${input.sandboxBrokerUrl.replace(/\/+$/, "")}/v1`, input.provider === "anthropic" ? (env.CLAUDE_CONFIG_DIR = input.sandboxBootstrapDir, env.CLAUDE_CODE_TMPDIR = input.sandboxBootstrapDir) : env.CODEX_HOME = input.sandboxBootstrapDir, env;
|
|
65757
|
+
return input.provider === "anthropic" ? env.ANTHROPIC_BASE_URL = input.sandboxBrokerUrl : env.OPENAI_BASE_URL = `${input.sandboxBrokerUrl.replace(/\/+$/, "")}/v1`, input.provider === "anthropic" ? (env.CLAUDE_CONFIG_DIR = input.sandboxBootstrapDir, env.CLAUDE_CODE_TMPDIR = input.claudeScratchDir ?? input.sandboxBootstrapDir) : env.CODEX_HOME = input.sandboxBootstrapDir, env;
|
|
65197
65758
|
}
|
|
65198
65759
|
var FORBIDDEN_KEY_PATTERNS = [
|
|
65199
65760
|
/^ANTHROPIC_API_KEY$/i,
|
|
@@ -65319,16 +65880,36 @@ async function engageSubstrate(input) {
|
|
|
65319
65880
|
try {
|
|
65320
65881
|
({ hostBrokerAddr } = await broker.start());
|
|
65321
65882
|
} catch (e) {
|
|
65322
|
-
|
|
65323
|
-
|
|
65324
|
-
|
|
65883
|
+
let primary = Object.assign(
|
|
65884
|
+
new Error("CP-7: broker failed to start \u2014 refusing to launch the implementor (fail-closed)"),
|
|
65885
|
+
{ cause: e }
|
|
65325
65886
|
);
|
|
65887
|
+
try {
|
|
65888
|
+
await broker.stop();
|
|
65889
|
+
} catch (cleanupError) {
|
|
65890
|
+
throw Object.assign(
|
|
65891
|
+
new Error("CP-7: broker start failed and cleanup also failed"),
|
|
65892
|
+
{ causes: [primary, cleanupError] }
|
|
65893
|
+
);
|
|
65894
|
+
}
|
|
65895
|
+
throw primary;
|
|
65326
65896
|
}
|
|
65327
65897
|
let initialTokenObj = broker.currentBrokerToken();
|
|
65328
|
-
if (!initialTokenObj)
|
|
65329
|
-
|
|
65330
|
-
|
|
65331
|
-
|
|
65898
|
+
if (!initialTokenObj) {
|
|
65899
|
+
let primary = new Error(
|
|
65900
|
+
"CP-7: broker minted no token \u2014 refusing to launch (fail-closed)"
|
|
65901
|
+
);
|
|
65902
|
+
try {
|
|
65903
|
+
await broker.stop();
|
|
65904
|
+
} catch (cleanupError) {
|
|
65905
|
+
throw Object.assign(
|
|
65906
|
+
new Error("CP-7: broker minted no token and cleanup also failed"),
|
|
65907
|
+
{ causes: [primary, cleanupError] }
|
|
65908
|
+
);
|
|
65909
|
+
}
|
|
65910
|
+
throw primary;
|
|
65911
|
+
}
|
|
65912
|
+
let initialToken = initialTokenObj.value, sandboxBrokerUrl = selection.tier === "docker" ? `http://127.0.0.1:${RELAY_PORT}` : `http://${hostBrokerAddr}`, sandboxHome = selection.tier === "docker" ? CONTAINER_WORKDIR : input.workdir, sandboxBootstrapMount = selection.tier === "docker" ? SANDBOX_BOOTSTRAP_DIR : null, sandboxConfigMount = selection.tier === "docker" ? SANDBOX_AGENT_CONFIG_DIR : null, bootstrap, handle, activeTeardown;
|
|
65332
65913
|
try {
|
|
65333
65914
|
bootstrap = await ApiKeyBootstrap.create({
|
|
65334
65915
|
provider,
|
|
@@ -65339,6 +65920,7 @@ async function engageSubstrate(input) {
|
|
|
65339
65920
|
sandboxConfigDir: sandboxConfigMount ?? SANDBOX_AGENT_CONFIG_DIR
|
|
65340
65921
|
} : { sandboxDirEqualsHostDir: !0, configDirEqualsHostDir: !0 },
|
|
65341
65922
|
hostRoot: input.bootstrapHostRoot,
|
|
65923
|
+
...selection.tier === "sandbox_exec" && provider === "anthropic" ? { claudeScratchHostRoot: input.claudeScratchHostRoot ?? "/tmp" } : {},
|
|
65342
65924
|
// M-2 — fail closed if the bootstrap dir lands inside the agent's rw
|
|
65343
65925
|
// workdir mount (the token would leak through it).
|
|
65344
65926
|
workdir: input.workdir,
|
|
@@ -65350,11 +65932,12 @@ async function engageSubstrate(input) {
|
|
|
65350
65932
|
), agentConfigSpec = sandboxConfigMount !== null ? { hostDir: bootstrap.configHostDir, sandboxDir: sandboxConfigMount } : (
|
|
65351
65933
|
// A5: sandbox fs == host fs → config path equals the host dir.
|
|
65352
65934
|
{ hostDir: bootstrap.configHostDir, sandboxDir: bootstrap.configHostDir }
|
|
65353
|
-
), sanitizedBase = buildSanitizedBaseEnv({
|
|
65935
|
+
), agentScratchSpec = bootstrap.claudeScratchSpec, sanitizedBase = buildSanitizedBaseEnv({
|
|
65354
65936
|
provider,
|
|
65355
65937
|
sandboxBrokerUrl,
|
|
65356
65938
|
sandboxHome,
|
|
65357
65939
|
sandboxBootstrapDir: agentConfigSpec.sandboxDir,
|
|
65940
|
+
...agentScratchSpec !== null ? { claudeScratchDir: agentScratchSpec.sandboxDir } : {},
|
|
65358
65941
|
safeSource: input.localeSource
|
|
65359
65942
|
});
|
|
65360
65943
|
assertNoAmbientCreds(sanitizedBase);
|
|
@@ -65368,6 +65951,7 @@ async function engageSubstrate(input) {
|
|
|
65368
65951
|
sanitizedEnv: finalEnv,
|
|
65369
65952
|
agentBootstrap: agentBootstrapSpec,
|
|
65370
65953
|
agentConfig: agentConfigSpec,
|
|
65954
|
+
...agentScratchSpec !== null ? { agentScratch: agentScratchSpec } : {},
|
|
65371
65955
|
// CP-7 W3 — Stage-2 r1 HIGH. The resolved audit dir → A5 trailing deny.
|
|
65372
65956
|
// Undefined when a test injects its own in-memory sink (no real tree).
|
|
65373
65957
|
...resolvedAuditDir !== null ? { auditDir: resolvedAuditDir } : {}
|
|
@@ -65376,12 +65960,30 @@ async function engageSubstrate(input) {
|
|
|
65376
65960
|
`[CP-7] Substrate engaged (tier=${selection.tier}, egress=${handle.egressFidelity}) \u2014 agent is creditless, broker holds the key`,
|
|
65377
65961
|
{ taskId: input.taskId, agent: input.agentKind }
|
|
65378
65962
|
);
|
|
65379
|
-
let liveBootstrap = bootstrap, liveHandle = handle, liveBroker = broker, refreshTimer = null, teardown = async () => {
|
|
65380
|
-
refreshTimer && (clearInterval(refreshTimer), refreshTimer = null)
|
|
65381
|
-
|
|
65382
|
-
|
|
65383
|
-
|
|
65384
|
-
|
|
65963
|
+
let liveBootstrap = bootstrap, liveHandle = handle, liveBroker = broker, refreshTimer = null, teardownPromise, teardown = () => teardownPromise || (teardownPromise = (async () => {
|
|
65964
|
+
refreshTimer && (clearInterval(refreshTimer), refreshTimer = null);
|
|
65965
|
+
let failures = [];
|
|
65966
|
+
for (let cleanup of [
|
|
65967
|
+
() => liveHandle.teardown(),
|
|
65968
|
+
() => liveBroker.stop(),
|
|
65969
|
+
() => liveBootstrap.destroy()
|
|
65970
|
+
])
|
|
65971
|
+
try {
|
|
65972
|
+
await cleanup();
|
|
65973
|
+
} catch (error) {
|
|
65974
|
+
failures.push(error);
|
|
65975
|
+
}
|
|
65976
|
+
if (failures.length > 0)
|
|
65977
|
+
throw logger.warn("[CP-7] substrate cleanup failed \u2014 task cannot pass", {
|
|
65978
|
+
taskId: input.taskId,
|
|
65979
|
+
failureCount: failures.length,
|
|
65980
|
+
...errorShapeOnly(failures[0])
|
|
65981
|
+
}), failures.length === 1 ? failures[0] : Object.assign(new Error("CP-7 substrate cleanup failed"), {
|
|
65982
|
+
causes: failures
|
|
65983
|
+
});
|
|
65984
|
+
})(), teardownPromise);
|
|
65985
|
+
activeTeardown = teardown;
|
|
65986
|
+
let launchId = `launch-${input.taskId}-${Date.now()}`, denialReason = liveHandle.egressFidelity === "strict" ? "structural_deny_network_none" : "coarse_loopback_only", postureRes;
|
|
65385
65987
|
try {
|
|
65386
65988
|
postureRes = await auditSink.emit("egress_denied", {
|
|
65387
65989
|
destination: "*",
|
|
@@ -65390,13 +65992,16 @@ async function engageSubstrate(input) {
|
|
|
65390
65992
|
caller_event_id: launchId
|
|
65391
65993
|
});
|
|
65392
65994
|
} catch (e) {
|
|
65393
|
-
throw
|
|
65394
|
-
|
|
65995
|
+
throw Object.assign(
|
|
65996
|
+
new Error(
|
|
65997
|
+
"CP-7 W3: egress-posture audit emit failed \u2014 refusing to launch the creditless agent (audit-before-effect fail-closed)"
|
|
65998
|
+
),
|
|
65999
|
+
{ cause: e }
|
|
65395
66000
|
);
|
|
65396
66001
|
}
|
|
65397
66002
|
if (!("ack" in postureRes))
|
|
65398
|
-
throw
|
|
65399
|
-
|
|
66003
|
+
throw new Error(
|
|
66004
|
+
"CP-7 W3: egress-posture audit was rejected \u2014 refusing to launch the creditless agent (no durable egress posture \u2192 no agent)"
|
|
65400
66005
|
);
|
|
65401
66006
|
let refreshIntervalMs = input.tokenRefreshIntervalMs ?? 600 * 1e3, inFlightRefresh = null, doRefreshOnce = async () => {
|
|
65402
66007
|
if (!(typeof liveBroker.rotateBrokerToken == "function" && typeof liveBroker.commitBrokerTokenRotation == "function" && typeof liveBroker.rollbackBrokerTokenRotation == "function")) {
|
|
@@ -65409,10 +66014,23 @@ async function engageSubstrate(input) {
|
|
|
65409
66014
|
try {
|
|
65410
66015
|
await liveBootstrap.refresh(rotated.token.value), liveBroker.commitBrokerTokenRotation(rotated);
|
|
65411
66016
|
} catch (e) {
|
|
65412
|
-
|
|
66017
|
+
liveBroker.rollbackBrokerTokenRotation(rotated), logger.warn(
|
|
65413
66018
|
"[CP-7] broker-token refresh write FAILED \u2014 rolled back to the prior token and tearing down (fail-closed)",
|
|
65414
|
-
{ taskId: input.taskId,
|
|
65415
|
-
)
|
|
66019
|
+
{ taskId: input.taskId, ...errorShapeOnly(e) }
|
|
66020
|
+
);
|
|
66021
|
+
let refreshFailure = Object.assign(
|
|
66022
|
+
new Error("CP-7 broker-token refresh failed"),
|
|
66023
|
+
{ cause: e }
|
|
66024
|
+
);
|
|
66025
|
+
try {
|
|
66026
|
+
await teardown();
|
|
66027
|
+
} catch (cleanupError) {
|
|
66028
|
+
throw Object.assign(
|
|
66029
|
+
new Error("CP-7 broker-token refresh failed and cleanup also failed"),
|
|
66030
|
+
{ causes: [refreshFailure, cleanupError] }
|
|
66031
|
+
);
|
|
66032
|
+
}
|
|
66033
|
+
throw refreshFailure;
|
|
65416
66034
|
}
|
|
65417
66035
|
}, doRefresh = async () => {
|
|
65418
66036
|
let next = (inFlightRefresh ?? Promise.resolve()).catch(() => {
|
|
@@ -65439,10 +66057,32 @@ async function engageSubstrate(input) {
|
|
|
65439
66057
|
teardown
|
|
65440
66058
|
};
|
|
65441
66059
|
} catch (e) {
|
|
65442
|
-
|
|
65443
|
-
|
|
65444
|
-
|
|
65445
|
-
|
|
66060
|
+
let primary = e instanceof Error ? e : new Error("CP-7 substrate launch failed"), cleanupFailures = [];
|
|
66061
|
+
if (activeTeardown)
|
|
66062
|
+
try {
|
|
66063
|
+
await activeTeardown();
|
|
66064
|
+
} catch (cleanupError) {
|
|
66065
|
+
cleanupFailures.push(cleanupError);
|
|
66066
|
+
}
|
|
66067
|
+
else
|
|
66068
|
+
for (let cleanup of [
|
|
66069
|
+
...handle ? [() => handle.teardown()] : [],
|
|
66070
|
+
...bootstrap ? [() => bootstrap.destroy()] : [],
|
|
66071
|
+
() => broker.stop()
|
|
66072
|
+
])
|
|
66073
|
+
try {
|
|
66074
|
+
await cleanup();
|
|
66075
|
+
} catch (cleanupError) {
|
|
66076
|
+
cleanupFailures.push(cleanupError);
|
|
66077
|
+
}
|
|
66078
|
+
throw cleanupFailures.length > 0 ? (logger.warn("[CP-7] failed launch also failed cleanup", {
|
|
66079
|
+
taskId: input.taskId,
|
|
66080
|
+
failureCount: cleanupFailures.length,
|
|
66081
|
+
...errorShapeOnly(cleanupFailures[0])
|
|
66082
|
+
}), Object.assign(
|
|
66083
|
+
new Error("CP-7 substrate launch failed and cleanup also failed"),
|
|
66084
|
+
{ causes: [primary, ...cleanupFailures] }
|
|
66085
|
+
)) : primary;
|
|
65446
66086
|
}
|
|
65447
66087
|
}
|
|
65448
66088
|
var RESOLVER_AGENT_STATE_DIR_SEGMENTS = {
|
|
@@ -67223,13 +67863,14 @@ function createAdmittedSessionOwnershipController(appsyncClient) {
|
|
|
67223
67863
|
appsyncClient,
|
|
67224
67864
|
admittedSession.sessionId
|
|
67225
67865
|
), retirement) : Promise.resolve(), removeTemporarySignalHandlers = () => {
|
|
67226
|
-
process.removeListener("SIGINT", onSigint), process.removeListener("SIGTERM", onSigterm);
|
|
67866
|
+
process.removeListener("SIGINT", onSigint), process.removeListener("SIGTERM", onSigterm), process.removeListener("SIGHUP", onSighup);
|
|
67227
67867
|
}, handleSignal = (signal) => {
|
|
67228
|
-
signalReceived || ownershipAccepted || closed || (signalReceived = !0,
|
|
67868
|
+
signalReceived || ownershipAccepted || closed || (signalReceived = !0, retireOnce().finally(() => {
|
|
67869
|
+
removeTemporarySignalHandlers();
|
|
67229
67870
|
try {
|
|
67230
67871
|
process.kill(process.pid, signal);
|
|
67231
67872
|
} catch {
|
|
67232
|
-
process.exit(signal === "SIGTERM" ? 143 : 130);
|
|
67873
|
+
process.exit(signal === "SIGTERM" ? 143 : signal === "SIGHUP" ? 129 : 130);
|
|
67233
67874
|
}
|
|
67234
67875
|
}));
|
|
67235
67876
|
};
|
|
@@ -67239,7 +67880,10 @@ function createAdmittedSessionOwnershipController(appsyncClient) {
|
|
|
67239
67880
|
function onSigterm() {
|
|
67240
67881
|
handleSignal("SIGTERM");
|
|
67241
67882
|
}
|
|
67242
|
-
|
|
67883
|
+
function onSighup() {
|
|
67884
|
+
handleSignal("SIGHUP");
|
|
67885
|
+
}
|
|
67886
|
+
process.on("SIGINT", onSigint), process.on("SIGTERM", onSigterm), process.on("SIGHUP", onSighup);
|
|
67243
67887
|
let close = async () => {
|
|
67244
67888
|
if (closed) return retirement ?? Promise.resolve();
|
|
67245
67889
|
closed = !0, removeTemporarySignalHandlers(), ownershipAccepted || await retireOnce();
|
|
@@ -67270,6 +67914,20 @@ async function runWithAdmittedSessionOwnership(args) {
|
|
|
67270
67914
|
let ownership = createAdmittedSessionOwnershipController(args.appsyncClient);
|
|
67271
67915
|
return ownership.onAdmitted(args.session), ownership.run(args.launch);
|
|
67272
67916
|
}
|
|
67917
|
+
var ORCHESTRATION_ORPHAN_SWEEP_STALE_THRESHOLD_MS = 600 * 1e3;
|
|
67918
|
+
async function triggerStartupOrphanSweep(appsyncClient, currentSessionId, staleThresholdMs = ORCHESTRATION_ORPHAN_SWEEP_STALE_THRESHOLD_MS) {
|
|
67919
|
+
try {
|
|
67920
|
+
return await appsyncClient.sweepOrphanSessions({
|
|
67921
|
+
agentType: "CODEVIBE" /* CODEVIBE */,
|
|
67922
|
+
staleThresholdMs,
|
|
67923
|
+
excludeSessionIds: [currentSessionId]
|
|
67924
|
+
});
|
|
67925
|
+
} catch (err) {
|
|
67926
|
+
return logger.warn("[cli] startup orphan sweep failed (non-fatal)", {
|
|
67927
|
+
error: err?.message
|
|
67928
|
+
}), 0;
|
|
67929
|
+
}
|
|
67930
|
+
}
|
|
67273
67931
|
async function runCompanion(args) {
|
|
67274
67932
|
let { runCompanionMode: runCompanionMode2 } = (init_companion_mode(), __toCommonJS(companion_mode_exports));
|
|
67275
67933
|
return runCompanionMode2({
|
|
@@ -67601,7 +68259,7 @@ ${err.message}
|
|
|
67601
68259
|
`), 1;
|
|
67602
68260
|
}
|
|
67603
68261
|
let session = resolved.session;
|
|
67604
|
-
return admissionOwnership.run(async (acceptSessionLifecycleOwnership) => {
|
|
68262
|
+
return triggerStartupOrphanSweep(appsyncClient, session.sessionId), admissionOwnership.run(async (acceptSessionLifecycleOwnership) => {
|
|
67605
68263
|
let emitter = createShellEventEmitter(appsyncClient, session), localPlanner = await buildLocalGemmaPlannerAdapter({
|
|
67606
68264
|
state: localModelState
|
|
67607
68265
|
});
|
|
@@ -68033,11 +68691,14 @@ function mapTeamSourceToTypedEvent(sessionId, md) {
|
|
|
68033
68691
|
}
|
|
68034
68692
|
case "team_group_resolved": {
|
|
68035
68693
|
let outcome = teamMetaStr(md, "outcome");
|
|
68036
|
-
|
|
68694
|
+
if (!outcome) return null;
|
|
68695
|
+
let completedAt = typeof md.completed_at == "string" ? md.completed_at : typeof md.completedAt == "string" ? md.completedAt : void 0, metadata = {
|
|
68037
68696
|
team_event: "group_resolved",
|
|
68038
68697
|
task_group_id: taskGroupId,
|
|
68039
|
-
outcome
|
|
68040
|
-
|
|
68698
|
+
outcome,
|
|
68699
|
+
...completedAt ? { completed_at: completedAt } : {}
|
|
68700
|
+
};
|
|
68701
|
+
return { sessionId, type: "TEAM_GROUP_RESOLVED", source: "DESKTOP", isEncrypted: !0, metadata };
|
|
68041
68702
|
}
|
|
68042
68703
|
// NB TEAM_DECOMPOSED is emitted DIRECTLY at the launch layer
|
|
68043
68704
|
// (launchTeamFromWorkItems, index.ts) which has no `leEmitShellEvent`, so it
|
|
@@ -68644,6 +69305,7 @@ require.main === module && main(process.argv.slice(2)).then(
|
|
|
68644
69305
|
CliEntitlementError,
|
|
68645
69306
|
CliUsageError,
|
|
68646
69307
|
LocalModelPlannerUnavailableAdapter,
|
|
69308
|
+
ORCHESTRATION_ORPHAN_SWEEP_STALE_THRESHOLD_MS,
|
|
68647
69309
|
OrchestrationSessionBootstrapError,
|
|
68648
69310
|
PlannerUnavailableError,
|
|
68649
69311
|
bridgeAuthorityErrorToShellRefusal,
|
|
@@ -68669,5 +69331,6 @@ require.main === module && main(process.argv.slice(2)).then(
|
|
|
68669
69331
|
resumeOrCreateSession,
|
|
68670
69332
|
runAuditCli,
|
|
68671
69333
|
runModelCli,
|
|
68672
|
-
runWithAdmittedSessionOwnership
|
|
69334
|
+
runWithAdmittedSessionOwnership,
|
|
69335
|
+
triggerStartupOrphanSweep
|
|
68673
69336
|
});
|