@quantiya/codevibe-claude-plugin 2.0.22 → 2.0.23
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/diagnostics/shape-only.d.ts +11 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +321 -282
- 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/cli.js +500 -104
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +8 -1
- 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/node_modules/fs-ext/build/Makefile +1 -1
- package/node_modules/fs-ext/build/Release/fs_ext.node +0 -0
- package/package.json +2 -2
|
@@ -20277,6 +20277,37 @@ async function bindWorkingDirectory(payload){
|
|
|
20277
20277
|
throw new Error('target cwd incarnation changed before launch');
|
|
20278
20278
|
}
|
|
20279
20279
|
}
|
|
20280
|
+
function holdLaunchPathAuthorities(payload){
|
|
20281
|
+
const authorities=payload.launchPathAuthorities;
|
|
20282
|
+
if(authorities===undefined)return [];
|
|
20283
|
+
if(!Array.isArray(authorities)||authorities.length>16)throw new Error('invalid launch path authorities');
|
|
20284
|
+
const held=[];
|
|
20285
|
+
try{
|
|
20286
|
+
for(const authority of authorities){
|
|
20287
|
+
if(!authority||authority.version!==1||
|
|
20288
|
+
typeof authority.canonicalPath!=='string'||!require('node:path').isAbsolute(authority.canonicalPath)||authority.canonicalPath.includes('\0')||
|
|
20289
|
+
typeof authority.dev!=='string'||typeof authority.ino!=='string'||
|
|
20290
|
+
typeof authority.birthtimeNs!=='string')throw new Error('invalid launch path authority');
|
|
20291
|
+
const flags=fs.constants.O_RDONLY|(fs.constants.O_DIRECTORY||0)|(fs.constants.O_NOFOLLOW||0);
|
|
20292
|
+
const fd=fs.openSync(authority.canonicalPath,flags);
|
|
20293
|
+
held.push(fd);
|
|
20294
|
+
const opened=fs.fstatSync(fd,{bigint:true});
|
|
20295
|
+
const live=fs.lstatSync(authority.canonicalPath,{bigint:true});
|
|
20296
|
+
const canonical=fs.realpathSync(authority.canonicalPath);
|
|
20297
|
+
if(!opened.isDirectory()||!live.isDirectory()||live.isSymbolicLink()||
|
|
20298
|
+
opened.dev.toString()!==authority.dev||opened.ino.toString()!==authority.ino||
|
|
20299
|
+
opened.birthtimeNs.toString()!==authority.birthtimeNs||
|
|
20300
|
+
live.dev.toString()!==authority.dev||live.ino.toString()!==authority.ino||
|
|
20301
|
+
live.birthtimeNs.toString()!==authority.birthtimeNs||canonical!==authority.canonicalPath){
|
|
20302
|
+
throw new Error('launch path authority changed before target spawn');
|
|
20303
|
+
}
|
|
20304
|
+
}
|
|
20305
|
+
return held;
|
|
20306
|
+
}catch(err){
|
|
20307
|
+
for(const fd of held){try{fs.closeSync(fd);}catch{}}
|
|
20308
|
+
throw err;
|
|
20309
|
+
}
|
|
20310
|
+
}
|
|
20280
20311
|
const hostPipe=fs.createReadStream(null,{fd:5,autoClose:false});
|
|
20281
20312
|
for(const event of ['end','close','error'])hostPipe.once(event,killOwnGroup);
|
|
20282
20313
|
for(const [signal] of [['SIGTERM'],['SIGINT'],['SIGHUP']])process.on(signal,killOwnGroup);
|
|
@@ -20285,9 +20316,17 @@ for(const [signal] of [['SIGTERM'],['SIGINT'],['SIGHUP']])process.on(signal,kill
|
|
|
20285
20316
|
const start=await readLine(4);
|
|
20286
20317
|
if(start!=='START')throw new Error('target start not authorized');
|
|
20287
20318
|
await bindWorkingDirectory(payload);
|
|
20319
|
+
// This is deliberately synchronous and immediately adjacent to cp.spawn:
|
|
20320
|
+
// keep exact directory descriptors open across native process creation so a
|
|
20321
|
+
// pathname replacement during durable-owner publication cannot be adopted.
|
|
20322
|
+
const launchPathFds=holdLaunchPathAuthorities(payload);
|
|
20288
20323
|
// No pathname cwd is passed here: the child inherits the wrapper's already-
|
|
20289
20324
|
// authenticated kernel cwd reference, so a later rename cannot redirect it.
|
|
20290
|
-
|
|
20325
|
+
try{
|
|
20326
|
+
target=cp.spawn(payload.command,payload.args,{env:payload.env,stdio:['inherit','inherit','inherit'],detached:false,windowsHide:true});
|
|
20327
|
+
}finally{
|
|
20328
|
+
for(const fd of launchPathFds){try{fs.closeSync(fd);}catch{}}
|
|
20329
|
+
}
|
|
20291
20330
|
target.once('error',err=>{send({type:'target-exit',code:127,error:String(err&&err.message||err)});});
|
|
20292
20331
|
target.once('exit',(code,signal)=>{send({type:'target-exit',code:Number.isInteger(code)?code:(signal?128:1)});});
|
|
20293
20332
|
// Remain the authenticated group/session leader until the outside host has
|
|
@@ -20387,6 +20426,7 @@ function spawnPosixOwnedProcess(command, args, options, seams = {}) {
|
|
|
20387
20426
|
args,
|
|
20388
20427
|
cwd: targetCwd,
|
|
20389
20428
|
cwdAuthority: seams.workingDirAuthority,
|
|
20429
|
+
launchPathAuthorities: seams.launchPathAuthorities,
|
|
20390
20430
|
env: options?.env ?? process.env,
|
|
20391
20431
|
...seams.cleanupTimeoutMs === void 0 ? {} : { cleanupTimeoutMs: seams.cleanupTimeoutMs }
|
|
20392
20432
|
}), "utf8");
|
|
@@ -26409,6 +26449,38 @@ var LocalGemmaPlannerAdapter = class {
|
|
|
26409
26449
|
// src/orchestration-shell/quorum-loop.ts
|
|
26410
26450
|
var import_node_fs24 = require("node:fs");
|
|
26411
26451
|
|
|
26452
|
+
// src/diagnostics/shape-only.ts
|
|
26453
|
+
function outputShapeOnly(raw) {
|
|
26454
|
+
if (typeof raw != "string" || raw.length === 0)
|
|
26455
|
+
return {
|
|
26456
|
+
bytes: 0,
|
|
26457
|
+
lines: 0,
|
|
26458
|
+
leadClass: "empty",
|
|
26459
|
+
fenceCount: 0,
|
|
26460
|
+
bulletLines: 0,
|
|
26461
|
+
blankLines: 0
|
|
26462
|
+
};
|
|
26463
|
+
let lines = raw.split(`
|
|
26464
|
+
`), trimmed = raw.trim(), leadClass;
|
|
26465
|
+
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", {
|
|
26466
|
+
bytes: Buffer.byteLength(raw, "utf8"),
|
|
26467
|
+
lines: lines.length,
|
|
26468
|
+
leadClass,
|
|
26469
|
+
fenceCount: (raw.match(/```/g) ?? []).length,
|
|
26470
|
+
bulletLines: lines.filter((line) => /^\s*[-*+]\s/.test(line)).length,
|
|
26471
|
+
blankLines: lines.filter((line) => line.trim().length === 0).length
|
|
26472
|
+
};
|
|
26473
|
+
}
|
|
26474
|
+
function errorShapeOnly(error) {
|
|
26475
|
+
let value = error, message = typeof value?.message == "string" ? value.message : "", causeCount = Array.isArray(value?.causes) ? value.causes.length : value?.cause !== void 0 ? 1 : 0;
|
|
26476
|
+
return {
|
|
26477
|
+
errorClass: error instanceof Error ? "error" : "non-error",
|
|
26478
|
+
messageBytes: Buffer.byteLength(message, "utf8"),
|
|
26479
|
+
hasCause: value?.cause !== void 0,
|
|
26480
|
+
causeCount
|
|
26481
|
+
};
|
|
26482
|
+
}
|
|
26483
|
+
|
|
26412
26484
|
// src/reduced-trust-notice.ts
|
|
26413
26485
|
var surfacedRationales = /* @__PURE__ */ new Set();
|
|
26414
26486
|
function noticeKey(sessionId, tier, reason) {
|
|
@@ -28104,7 +28176,8 @@ var ClassBConsumer = class {
|
|
|
28104
28176
|
};
|
|
28105
28177
|
|
|
28106
28178
|
// src/substrate-launch/apikey-bootstrap.ts
|
|
28107
|
-
var import_node_fs14 = require("node:fs"), os19 = __toESM(require("node:os")), path32 = __toESM(require("node:path"))
|
|
28179
|
+
var import_node_fs14 = require("node:fs"), os19 = __toESM(require("node:os")), path32 = __toESM(require("node:path"));
|
|
28180
|
+
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
28181
|
function helperScriptSource(tokenFileAbsPathInSandbox) {
|
|
28109
28182
|
return `#!/bin/sh
|
|
28110
28183
|
# CP-7 apiKeyHelper \u2014 emits the current broker token (NEVER the vendor key).
|
|
@@ -28145,12 +28218,16 @@ function isInsideOrEqual(child, parent) {
|
|
|
28145
28218
|
return rel.length > 0 && !rel.startsWith("..") && !path32.isAbsolute(rel);
|
|
28146
28219
|
}
|
|
28147
28220
|
var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
28148
|
-
constructor(hostDir, sandboxDir, configHostDir, configSandboxDir, tokenFileHostPath) {
|
|
28221
|
+
constructor(hostDir, sandboxDir, configHostDir, configSandboxDir, tokenFileHostPath, claudeScratchHostDir, claudeScratchSandboxDir, claudeScratchIdentity, beforeClaudeScratchCleanupCommit) {
|
|
28149
28222
|
this.hostDir = hostDir;
|
|
28150
28223
|
this.sandboxDir = sandboxDir;
|
|
28151
28224
|
this.configHostDir = configHostDir;
|
|
28152
28225
|
this.configSandboxDir = configSandboxDir;
|
|
28153
28226
|
this.tokenFileHostPath = tokenFileHostPath;
|
|
28227
|
+
this.claudeScratchHostDir = claudeScratchHostDir;
|
|
28228
|
+
this.claudeScratchSandboxDir = claudeScratchSandboxDir;
|
|
28229
|
+
this.claudeScratchIdentity = claudeScratchIdentity;
|
|
28230
|
+
this.beforeClaudeScratchCleanupCommit = beforeClaudeScratchCleanupCommit;
|
|
28154
28231
|
}
|
|
28155
28232
|
/**
|
|
28156
28233
|
* Materialize the bootstrap: create the host dir (0700), write the token file
|
|
@@ -28166,9 +28243,8 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28166
28243
|
);
|
|
28167
28244
|
await import_node_fs14.promises.chmod(rawConfigHostDir, 448).catch(() => {
|
|
28168
28245
|
});
|
|
28169
|
-
let hostDir = await import_node_fs14.promises.realpath(rawHostDir), configHostDir = await import_node_fs14.promises.realpath(rawConfigHostDir);
|
|
28246
|
+
let hostDir = await import_node_fs14.promises.realpath(rawHostDir), configHostDir = await import_node_fs14.promises.realpath(rawConfigHostDir), realWorkdir;
|
|
28170
28247
|
if (input.workdir !== void 0) {
|
|
28171
|
-
let realWorkdir;
|
|
28172
28248
|
try {
|
|
28173
28249
|
realWorkdir = await import_node_fs14.promises.realpath(input.workdir);
|
|
28174
28250
|
} catch {
|
|
@@ -28205,7 +28281,7 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28205
28281
|
"ApiKeyBootstrap.create: provide `sandboxConfigDir` or `configDirEqualsHostDir`"
|
|
28206
28282
|
);
|
|
28207
28283
|
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
|
-
|
|
28284
|
+
await import_node_fs14.promises.writeFile(tokenFileHostPath, input.initialToken, {
|
|
28209
28285
|
encoding: "utf8",
|
|
28210
28286
|
mode: 384
|
|
28211
28287
|
}), await import_node_fs14.promises.writeFile(
|
|
@@ -28220,12 +28296,107 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28220
28296
|
path32.join(configHostDir, CODEX_CONFIG_NAME),
|
|
28221
28297
|
codexConfig(input.sandboxBrokerUrl, helperInSandbox),
|
|
28222
28298
|
{ encoding: "utf8", mode: 384 }
|
|
28223
|
-
)
|
|
28299
|
+
);
|
|
28300
|
+
let claudeScratchHostDir = null, claudeScratchSandboxDir = null, claudeScratchIdentity = null;
|
|
28301
|
+
if (input.claudeScratchHostRoot !== void 0) {
|
|
28302
|
+
if (input.provider !== "anthropic" || !input.sandboxDirEqualsHostDir) {
|
|
28303
|
+
let primary = new Error(
|
|
28304
|
+
"ApiKeyBootstrap.create: a short Claude scratch root is valid only for the A5 anthropic path"
|
|
28305
|
+
), cleanupErrors = [];
|
|
28306
|
+
for (let directory of [hostDir, configHostDir])
|
|
28307
|
+
try {
|
|
28308
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28309
|
+
} catch (cleanupError) {
|
|
28310
|
+
cleanupErrors.push(cleanupError);
|
|
28311
|
+
}
|
|
28312
|
+
throw cleanupErrors.length > 0 ? Object.assign(
|
|
28313
|
+
new Error(
|
|
28314
|
+
"ApiKeyBootstrap.create: invalid scratch configuration and cleanup did not complete"
|
|
28315
|
+
),
|
|
28316
|
+
{ causes: [primary, ...cleanupErrors] }
|
|
28317
|
+
) : primary;
|
|
28318
|
+
}
|
|
28319
|
+
let rawScratchDir = null;
|
|
28320
|
+
try {
|
|
28321
|
+
let canonicalScratchRoot = await import_node_fs14.promises.realpath(
|
|
28322
|
+
input.claudeScratchHostRoot
|
|
28323
|
+
);
|
|
28324
|
+
rawScratchDir = await import_node_fs14.promises.mkdtemp(path32.join(canonicalScratchRoot, "cv"));
|
|
28325
|
+
let initial = await import_node_fs14.promises.lstat(rawScratchDir, { bigint: !0 });
|
|
28326
|
+
if (!initial.isDirectory() || initial.isSymbolicLink())
|
|
28327
|
+
throw new Error(
|
|
28328
|
+
"ApiKeyBootstrap.create: generated Claude scratch root is not a real directory"
|
|
28329
|
+
);
|
|
28330
|
+
await input.beforeClaudeScratchOpen?.(rawScratchDir);
|
|
28331
|
+
let scratchHandle = await import_node_fs14.promises.open(
|
|
28332
|
+
rawScratchDir,
|
|
28333
|
+
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)
|
|
28334
|
+
);
|
|
28335
|
+
try {
|
|
28336
|
+
let opened = await scratchHandle.stat({ bigint: !0 });
|
|
28337
|
+
if (!opened.isDirectory() || opened.dev !== initial.dev || opened.ino !== initial.ino || opened.birthtimeNs !== initial.birthtimeNs)
|
|
28338
|
+
throw new Error(
|
|
28339
|
+
"ApiKeyBootstrap.create: Claude scratch root changed while binding its directory handle"
|
|
28340
|
+
);
|
|
28341
|
+
await scratchHandle.chmod(448);
|
|
28342
|
+
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;
|
|
28343
|
+
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)
|
|
28344
|
+
throw new Error(
|
|
28345
|
+
"ApiKeyBootstrap.create: generated Claude scratch root failed its descriptor-bound private-directory identity check"
|
|
28346
|
+
);
|
|
28347
|
+
claudeScratchHostDir = canonical, claudeScratchSandboxDir = rawScratchDir, claudeScratchIdentity = {
|
|
28348
|
+
version: 1,
|
|
28349
|
+
canonicalPath: canonical,
|
|
28350
|
+
dev: sealed.dev.toString(),
|
|
28351
|
+
ino: sealed.ino.toString(),
|
|
28352
|
+
birthtimeNs: sealed.birthtimeNs.toString()
|
|
28353
|
+
};
|
|
28354
|
+
} finally {
|
|
28355
|
+
await scratchHandle.close();
|
|
28356
|
+
}
|
|
28357
|
+
if (Buffer.byteLength(rawScratchDir, "utf8") > 30)
|
|
28358
|
+
throw new Error(
|
|
28359
|
+
"ApiKeyBootstrap.create: generated Claude scratch path exceeds the 30-byte A5 safety bound"
|
|
28360
|
+
);
|
|
28361
|
+
if (realWorkdir !== void 0 && isInsideOrEqual(claudeScratchHostDir, realWorkdir))
|
|
28362
|
+
throw new Error(
|
|
28363
|
+
"ApiKeyBootstrap.create: Claude scratch root is inside the agent workdir (fail-closed)"
|
|
28364
|
+
);
|
|
28365
|
+
} catch (error) {
|
|
28366
|
+
let cleanupErrors = [];
|
|
28367
|
+
if (claudeScratchIdentity !== null)
|
|
28368
|
+
try {
|
|
28369
|
+
await anchoredRemoveTree(
|
|
28370
|
+
claudeScratchIdentity.canonicalPath,
|
|
28371
|
+
claudeScratchIdentity
|
|
28372
|
+
);
|
|
28373
|
+
} catch (cleanupError) {
|
|
28374
|
+
cleanupErrors.push(cleanupError);
|
|
28375
|
+
}
|
|
28376
|
+
for (let directory of [hostDir, configHostDir])
|
|
28377
|
+
try {
|
|
28378
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28379
|
+
} catch (cleanupError) {
|
|
28380
|
+
cleanupErrors.push(cleanupError);
|
|
28381
|
+
}
|
|
28382
|
+
throw cleanupErrors.length > 0 ? Object.assign(
|
|
28383
|
+
new Error(
|
|
28384
|
+
"ApiKeyBootstrap.create: initialization failed and cleanup did not complete"
|
|
28385
|
+
),
|
|
28386
|
+
{ causes: [error, ...cleanupErrors] }
|
|
28387
|
+
) : error;
|
|
28388
|
+
}
|
|
28389
|
+
}
|
|
28390
|
+
return new _ApiKeyBootstrap(
|
|
28224
28391
|
hostDir,
|
|
28225
28392
|
sandboxDir,
|
|
28226
28393
|
configHostDir,
|
|
28227
28394
|
sandboxConfigDir,
|
|
28228
|
-
tokenFileHostPath
|
|
28395
|
+
tokenFileHostPath,
|
|
28396
|
+
claudeScratchHostDir,
|
|
28397
|
+
claudeScratchSandboxDir,
|
|
28398
|
+
claudeScratchIdentity,
|
|
28399
|
+
input.beforeClaudeScratchCleanupCommit
|
|
28229
28400
|
);
|
|
28230
28401
|
}
|
|
28231
28402
|
/** The `SubstrateSpec.agentBootstrap` value for this bootstrap. */
|
|
@@ -28236,6 +28407,14 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28236
28407
|
get configSpec() {
|
|
28237
28408
|
return { hostDir: this.configHostDir, sandboxDir: this.configSandboxDir };
|
|
28238
28409
|
}
|
|
28410
|
+
/** The unique writable Claude scratch grant, absent on Docker/Codex paths. */
|
|
28411
|
+
get claudeScratchSpec() {
|
|
28412
|
+
return this.claudeScratchHostDir === null || this.claudeScratchSandboxDir === null || this.claudeScratchIdentity === null ? null : {
|
|
28413
|
+
hostDir: this.claudeScratchHostDir,
|
|
28414
|
+
sandboxDir: this.claudeScratchSandboxDir,
|
|
28415
|
+
authority: this.claudeScratchIdentity
|
|
28416
|
+
};
|
|
28417
|
+
}
|
|
28239
28418
|
/**
|
|
28240
28419
|
* REFRESH the broker token (rotation / on a broker 401). Atomically rewrites
|
|
28241
28420
|
* the token file (write a temp + rename) so the agent never reads a partial
|
|
@@ -28246,15 +28425,41 @@ var ApiKeyBootstrap = class _ApiKeyBootstrap {
|
|
|
28246
28425
|
let tmp = `${this.tokenFileHostPath}.tmp-${process.pid}-${Date.now()}`;
|
|
28247
28426
|
await import_node_fs14.promises.writeFile(tmp, token, { encoding: "utf8", mode: 384 }), await import_node_fs14.promises.rename(tmp, this.tokenFileHostPath);
|
|
28248
28427
|
}
|
|
28249
|
-
/**
|
|
28428
|
+
/**
|
|
28429
|
+
* Remove the bootstrap, config, and unique Claude scratch dirs. Scratch
|
|
28430
|
+
* cleanup is identity-bound: a replaced pathname is retained and reported,
|
|
28431
|
+
* never recursively removed as though it still belonged to this seat.
|
|
28432
|
+
*/
|
|
28250
28433
|
async destroy() {
|
|
28251
|
-
|
|
28252
|
-
|
|
28434
|
+
let cleanupErrors = [];
|
|
28435
|
+
if (this.claudeScratchHostDir !== null && this.claudeScratchIdentity !== null)
|
|
28436
|
+
try {
|
|
28437
|
+
await anchoredRemoveTree(
|
|
28438
|
+
this.claudeScratchIdentity.canonicalPath,
|
|
28439
|
+
this.claudeScratchIdentity,
|
|
28440
|
+
{
|
|
28441
|
+
...this.beforeClaudeScratchCleanupCommit ? {
|
|
28442
|
+
beforeCommit: () => this.beforeClaudeScratchCleanupCommit(
|
|
28443
|
+
this.claudeScratchHostDir
|
|
28444
|
+
)
|
|
28445
|
+
} : {}
|
|
28446
|
+
}
|
|
28447
|
+
);
|
|
28448
|
+
} catch (error) {
|
|
28449
|
+
cleanupErrors.push(error);
|
|
28253
28450
|
}
|
|
28254
|
-
|
|
28255
|
-
|
|
28451
|
+
for (let directory of [this.hostDir, this.configHostDir])
|
|
28452
|
+
try {
|
|
28453
|
+
await import_node_fs14.promises.rm(directory, { recursive: !0, force: !0 });
|
|
28454
|
+
} catch (error) {
|
|
28455
|
+
cleanupErrors.push(error);
|
|
28256
28456
|
}
|
|
28257
|
-
);
|
|
28457
|
+
if (cleanupErrors.length === 1) throw cleanupErrors[0];
|
|
28458
|
+
if (cleanupErrors.length > 1)
|
|
28459
|
+
throw Object.assign(
|
|
28460
|
+
new Error("ApiKeyBootstrap.destroy: cleanup did not complete"),
|
|
28461
|
+
{ causes: cleanupErrors }
|
|
28462
|
+
);
|
|
28258
28463
|
}
|
|
28259
28464
|
};
|
|
28260
28465
|
|
|
@@ -42776,10 +42981,7 @@ var LocalExecutorImpl = class {
|
|
|
42776
42981
|
}).catch(() => {
|
|
42777
42982
|
}), {
|
|
42778
42983
|
args: { ...addClaudeSubstrateAuthArgs(args, result.agentConfigDir), substrate: result.substrateHandle },
|
|
42779
|
-
onExit:
|
|
42780
|
-
await result.teardown().catch(() => {
|
|
42781
|
-
});
|
|
42782
|
-
},
|
|
42984
|
+
onExit: () => result.teardown(),
|
|
42783
42985
|
// Stage-2 r3 Codex HIGH — the ONLY return that proves a real confining
|
|
42784
42986
|
// boundary (`result.mode === 'substrate'`, not reduced_trust / no-engager /
|
|
42785
42987
|
// pre-TaskAuthorized). The danger-sandbox authority keys on THIS boolean,
|
|
@@ -42871,7 +43073,11 @@ var LocalExecutorImpl = class {
|
|
|
42871
43073
|
}
|
|
42872
43074
|
}
|
|
42873
43075
|
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,
|
|
43076
|
+
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 () => {
|
|
43077
|
+
onSubstrateExit && (substrateCleanupPromise || (substrateCleanupPromise = onSubstrateExit().catch((error) => {
|
|
43078
|
+
throw substrateCleanupError = error, error;
|
|
43079
|
+
})), await substrateCleanupPromise);
|
|
43080
|
+
}, full = {
|
|
42875
43081
|
...args,
|
|
42876
43082
|
agentKind: args.agentKind ?? this.adapter,
|
|
42877
43083
|
onProcessSpawned: async (info) => {
|
|
@@ -42885,35 +43091,51 @@ var LocalExecutorImpl = class {
|
|
|
42885
43091
|
});
|
|
42886
43092
|
},
|
|
42887
43093
|
onProcessExited: async (info) => {
|
|
42888
|
-
|
|
42889
|
-
|
|
42890
|
-
|
|
42891
|
-
|
|
42892
|
-
|
|
42893
|
-
|
|
42894
|
-
|
|
42895
|
-
|
|
43094
|
+
try {
|
|
43095
|
+
if (await args.onProcessExited?.(info), lifecycleAudit !== "none") {
|
|
43096
|
+
let ctx = lifecycleCtx;
|
|
43097
|
+
ctx !== null && await this.emitter.emitProcessExited(ctx, {
|
|
43098
|
+
pid: info.pid,
|
|
43099
|
+
exitCode: info.exitCode,
|
|
43100
|
+
failureClass: info.failureClass,
|
|
43101
|
+
occurredAt: info.exitedAt
|
|
43102
|
+
});
|
|
43103
|
+
}
|
|
43104
|
+
} catch {
|
|
42896
43105
|
}
|
|
42897
|
-
|
|
43106
|
+
await cleanupSubstrate().catch(() => {
|
|
42898
43107
|
});
|
|
42899
43108
|
}
|
|
42900
43109
|
};
|
|
42901
43110
|
try {
|
|
42902
|
-
|
|
43111
|
+
let handle = await spawnFn(full), done = handle.done.then((info) => {
|
|
43112
|
+
if (substrateCleanupError !== void 0)
|
|
43113
|
+
throw Object.assign(
|
|
43114
|
+
new Error("implementor substrate cleanup failed after process exit"),
|
|
43115
|
+
{ cause: substrateCleanupError }
|
|
43116
|
+
);
|
|
43117
|
+
return info;
|
|
43118
|
+
});
|
|
43119
|
+
return { ...handle, done };
|
|
42903
43120
|
} catch (err) {
|
|
42904
|
-
|
|
42905
|
-
})
|
|
43121
|
+
await cleanupSubstrate().catch(() => {
|
|
43122
|
+
});
|
|
43123
|
+
let primary = err;
|
|
43124
|
+
if (err instanceof AuthorityError) {
|
|
42906
43125
|
let safeArgv = redactAgyPrintArgv(args.argv), safeDetail = redactAgyPrintValuesFromText(err.refusal.detail, args.argv), safeError = new AuthorityError({
|
|
42907
43126
|
...err.refusal,
|
|
42908
43127
|
detail: safeDetail
|
|
42909
43128
|
});
|
|
42910
|
-
|
|
43129
|
+
await this.bridge.bridgeAuthorityRefusal(safeError, {
|
|
42911
43130
|
refusedMessageId: "spawn:" + role + ":" + Date.now(),
|
|
42912
43131
|
shellContent: `Refused spawn (${role}): ${safeDetail}`,
|
|
42913
43132
|
shellMetadata: { role, argv: safeArgv }
|
|
42914
|
-
}), safeError;
|
|
43133
|
+
}), primary = safeError;
|
|
42915
43134
|
}
|
|
42916
|
-
throw
|
|
43135
|
+
throw substrateCleanupError !== void 0 ? Object.assign(
|
|
43136
|
+
new Error("implementor spawn failed and substrate cleanup also failed"),
|
|
43137
|
+
{ causes: [primary, substrateCleanupError] }
|
|
43138
|
+
) : primary;
|
|
42917
43139
|
}
|
|
42918
43140
|
}
|
|
42919
43141
|
// --- Hook bridge surface ---------------------------------------------------
|
|
@@ -49035,10 +49257,11 @@ var ChildProcessCommandRunner = class {
|
|
|
49035
49257
|
signal: opts.signal,
|
|
49036
49258
|
...opts.env !== void 0 ? { env: opts.env } : {},
|
|
49037
49259
|
...opts.cwd !== void 0 ? { cwd: opts.cwd } : {}
|
|
49038
|
-
},
|
|
49039
|
-
workingDirAuthority: opts.cwdAuthority
|
|
49260
|
+
}, needsOwnedProcessHost = opts.cwdAuthority !== void 0 || (opts.launchPathAuthorities?.length ?? 0) > 0, proc = needsOwnedProcessHost ? spawnPosixOwnedProcess(argv[0], argv.slice(1), spawnOptions, {
|
|
49261
|
+
workingDirAuthority: opts.cwdAuthority,
|
|
49262
|
+
launchPathAuthorities: opts.launchPathAuthorities
|
|
49040
49263
|
}) : (0, import_node_child_process7.spawn)(argv[0], argv.slice(1), spawnOptions);
|
|
49041
|
-
return
|
|
49264
|
+
return needsOwnedProcessHost && Object.defineProperty(proc, "hostProcessTreeOwnership", {
|
|
49042
49265
|
value: "posix-host",
|
|
49043
49266
|
configurable: !1,
|
|
49044
49267
|
enumerable: !1,
|
|
@@ -49618,13 +49841,14 @@ async function resolveOnParentPath(cmd) {
|
|
|
49618
49841
|
return null;
|
|
49619
49842
|
}
|
|
49620
49843
|
var SandboxExecHandle = class {
|
|
49621
|
-
constructor(id, runner, profilePath, sanitizedEnv, workdir, workdirAuthority, auditDir = null) {
|
|
49844
|
+
constructor(id, runner, profilePath, sanitizedEnv, workdir, workdirAuthority, scratchAuthority, auditDir = null) {
|
|
49622
49845
|
this.id = id;
|
|
49623
49846
|
this.runner = runner;
|
|
49624
49847
|
this.profilePath = profilePath;
|
|
49625
49848
|
this.sanitizedEnv = sanitizedEnv;
|
|
49626
49849
|
this.workdir = workdir;
|
|
49627
49850
|
this.workdirAuthority = workdirAuthority;
|
|
49851
|
+
this.scratchAuthority = scratchAuthority;
|
|
49628
49852
|
this.auditDir = auditDir;
|
|
49629
49853
|
this.egressFidelity = "coarse";
|
|
49630
49854
|
this.tornDown = !1;
|
|
@@ -49660,13 +49884,18 @@ var SandboxExecHandle = class {
|
|
|
49660
49884
|
; exec-time agent-binary read allowance (argv0 resolution, 2026-07-03)
|
|
49661
49885
|
${allowLines}
|
|
49662
49886
|
`
|
|
49887
|
+
), this.scratchAuthority && await assertWorkspaceRootAuthority(
|
|
49888
|
+
this.scratchAuthority.canonicalPath,
|
|
49889
|
+
this.scratchAuthority,
|
|
49890
|
+
"sandbox-exec Claude scratch handoff"
|
|
49663
49891
|
);
|
|
49664
49892
|
let sbArgv = ["sandbox-exec", "-f", this.profilePath, resolvedArgv0, ...argv.slice(1)], proc = this.runner.spawnLong(sbArgv, {
|
|
49665
49893
|
stdinTty: opts.stdinTty,
|
|
49666
49894
|
signal: opts.signal,
|
|
49667
49895
|
env: this.sanitizedEnv,
|
|
49668
49896
|
cwd: this.workdir,
|
|
49669
|
-
...this.workdirAuthority ? { cwdAuthority: this.workdirAuthority } : {}
|
|
49897
|
+
...this.workdirAuthority ? { cwdAuthority: this.workdirAuthority } : {},
|
|
49898
|
+
...this.scratchAuthority ? { launchPathAuthorities: [this.scratchAuthority] } : {}
|
|
49670
49899
|
});
|
|
49671
49900
|
return this.proc = proc, proc;
|
|
49672
49901
|
}
|
|
@@ -49724,6 +49953,22 @@ ${allowLines}
|
|
|
49724
49953
|
}
|
|
49725
49954
|
extraWriteDirs.push(configDir);
|
|
49726
49955
|
}
|
|
49956
|
+
if (spec.agentScratch) {
|
|
49957
|
+
try {
|
|
49958
|
+
await assertWorkspaceRootAuthority(
|
|
49959
|
+
spec.agentScratch.hostDir,
|
|
49960
|
+
spec.agentScratch.authority,
|
|
49961
|
+
"sandbox-exec Claude scratch launch"
|
|
49962
|
+
);
|
|
49963
|
+
} catch (error) {
|
|
49964
|
+
throw new SubstrateLaunchError(
|
|
49965
|
+
"sandbox_exec",
|
|
49966
|
+
"Claude scratch grant target identity could not be verified (fail-closed)",
|
|
49967
|
+
error
|
|
49968
|
+
);
|
|
49969
|
+
}
|
|
49970
|
+
extraWriteDirs.push(spec.agentScratch.authority.canonicalPath);
|
|
49971
|
+
}
|
|
49727
49972
|
let resolvedAuditDir = null;
|
|
49728
49973
|
if (spec.auditDir) {
|
|
49729
49974
|
resolvedAuditDir = spec.auditDir;
|
|
@@ -49764,6 +50009,17 @@ ${allowLines}
|
|
|
49764
50009
|
throw await import_node_fs23.promises.rm(profilePath, { force: !0 }).catch(() => {
|
|
49765
50010
|
}), err;
|
|
49766
50011
|
}
|
|
50012
|
+
if (spec.agentScratch)
|
|
50013
|
+
try {
|
|
50014
|
+
await assertWorkspaceRootAuthority(
|
|
50015
|
+
spec.agentScratch.authority.canonicalPath,
|
|
50016
|
+
spec.agentScratch.authority,
|
|
50017
|
+
"sandbox-exec Claude scratch profile handoff"
|
|
50018
|
+
);
|
|
50019
|
+
} catch (err) {
|
|
50020
|
+
throw await import_node_fs23.promises.rm(profilePath, { force: !0 }).catch(() => {
|
|
50021
|
+
}), err;
|
|
50022
|
+
}
|
|
49767
50023
|
return new SandboxExecHandle(
|
|
49768
50024
|
id,
|
|
49769
50025
|
this.runner,
|
|
@@ -49771,6 +50027,7 @@ ${allowLines}
|
|
|
49771
50027
|
finalEnv,
|
|
49772
50028
|
canonicalWorkdir,
|
|
49773
50029
|
spec.workdirAuthority,
|
|
50030
|
+
spec.agentScratch?.authority,
|
|
49774
50031
|
resolvedAuditDir
|
|
49775
50032
|
);
|
|
49776
50033
|
}
|
|
@@ -50397,13 +50654,13 @@ function formatReviewerError(detail) {
|
|
|
50397
50654
|
case "timeout":
|
|
50398
50655
|
return `${detail.agent} reviewer timed out after ${detail.elapsed_ms}ms`;
|
|
50399
50656
|
case "spawn_failed":
|
|
50400
|
-
return `${detail.agent} reviewer spawn failed
|
|
50657
|
+
return `${detail.agent} reviewer spawn failed`;
|
|
50401
50658
|
case "parse_failure":
|
|
50402
50659
|
return `${detail.agent} reviewer output was unparseable`;
|
|
50403
50660
|
case "cancelled":
|
|
50404
50661
|
return "reviewer cancelled before completion";
|
|
50405
50662
|
case "internal_join_failure":
|
|
50406
|
-
return
|
|
50663
|
+
return "reviewer task internal join failure";
|
|
50407
50664
|
}
|
|
50408
50665
|
}
|
|
50409
50666
|
|
|
@@ -50945,22 +51202,25 @@ var CONTINUATION_EXPIRES_TTL_MS = 1440 * 60 * 1e3, ACTIVE_AGENT_KINDS = ["CLAUDE
|
|
|
50945
51202
|
function isActiveAgentKind2(agent) {
|
|
50946
51203
|
return agent === "CLAUDE" || agent === "CODEX" || agent === "ANTIGRAVITY";
|
|
50947
51204
|
}
|
|
50948
|
-
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, BACKGROUND_RECOVERY_ABORTED = /* @__PURE__ */ Symbol("background-recovery-aborted")
|
|
51205
|
+
var IMPLEMENTOR_TICK_MS = 1e4, TICK_SCAN_MAX_TRACKED = 5e3, TICK_SCAN_TIMEOUT_MS = 1e3, BACKGROUND_RECOVERY_ABORTED = /* @__PURE__ */ Symbol("background-recovery-aborted");
|
|
50949
51206
|
function describeReviewerErrorDetail(detail) {
|
|
50950
51207
|
switch (detail.kind) {
|
|
50951
51208
|
case "timeout":
|
|
50952
51209
|
return { agent: detail.agent, elapsedMs: detail.elapsed_ms };
|
|
50953
51210
|
case "spawn_failed":
|
|
50954
|
-
return {
|
|
51211
|
+
return {
|
|
51212
|
+
agent: detail.agent,
|
|
51213
|
+
reasonBytes: Buffer.byteLength(detail.reason ?? "", "utf8")
|
|
51214
|
+
};
|
|
50955
51215
|
case "parse_failure":
|
|
50956
51216
|
return {
|
|
50957
51217
|
agent: detail.agent,
|
|
50958
|
-
|
|
51218
|
+
rawOutputShape: outputShapeOnly(detail.raw_output)
|
|
50959
51219
|
};
|
|
50960
51220
|
case "cancelled":
|
|
50961
51221
|
return {};
|
|
50962
51222
|
case "internal_join_failure":
|
|
50963
|
-
return {
|
|
51223
|
+
return { reasonBytes: Buffer.byteLength(detail.reason ?? "", "utf8") };
|
|
50964
51224
|
}
|
|
50965
51225
|
}
|
|
50966
51226
|
var REVIEWER_AGENT_DISPLAY_NAME = {
|
|
@@ -53274,8 +53534,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53274
53534
|
taskId: args.taskId,
|
|
53275
53535
|
trackIndex: args.validateDiffScope.trackIndex,
|
|
53276
53536
|
exitCode: exit.exitCode,
|
|
53277
|
-
|
|
53278
|
-
|
|
53537
|
+
stderrShape: outputShapeOnly(handle.stderr()),
|
|
53538
|
+
stdoutShape: outputShapeOnly(handle.stdout())
|
|
53279
53539
|
}
|
|
53280
53540
|
), await this.reportTeamTrackFailure(
|
|
53281
53541
|
args.taskId,
|
|
@@ -53297,8 +53557,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53297
53557
|
// exits 0 is still attributable from the log.
|
|
53298
53558
|
exitCode: exit.exitCode,
|
|
53299
53559
|
runtimeMs: exit.runtimeMs,
|
|
53300
|
-
|
|
53301
|
-
|
|
53560
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
53561
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
53302
53562
|
});
|
|
53303
53563
|
try {
|
|
53304
53564
|
let bundle = createSnapshotTrackBundle({
|
|
@@ -53375,8 +53635,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53375
53635
|
exitCode: exit.exitCode,
|
|
53376
53636
|
runtimeMs: exit.runtimeMs,
|
|
53377
53637
|
...files.length === 0 ? {
|
|
53378
|
-
|
|
53379
|
-
|
|
53638
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
53639
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
53380
53640
|
} : {}
|
|
53381
53641
|
}), this.surfaceHalt(reason), await this.discardShadow(args.taskId);
|
|
53382
53642
|
}
|
|
@@ -53391,7 +53651,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
53391
53651
|
}
|
|
53392
53652
|
logger.warn("[QuorumLoop] implementor round failed", {
|
|
53393
53653
|
gateId,
|
|
53394
|
-
err
|
|
53654
|
+
...errorShapeOnly(err)
|
|
53395
53655
|
});
|
|
53396
53656
|
let reason = classifyImplementorRoundFailure(err);
|
|
53397
53657
|
this.surfaceHalt(`The task could not proceed \u2014 ${reason}.`);
|
|
@@ -54470,7 +54730,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54470
54730
|
if (promptText === null) {
|
|
54471
54731
|
logger.warn("[QuorumLoop] getReviewerPrompt exhausted \u2014 ESCALATE", {
|
|
54472
54732
|
key,
|
|
54473
|
-
|
|
54733
|
+
...errorShapeOnly(lastErr),
|
|
54474
54734
|
audit: "synthesized ESCALATE (#C1F-8): prompt_fetch_failed"
|
|
54475
54735
|
}), await this.submitVerdict(args, this.synthesizeEscalate(args, DESKTOP_DISPATCH_ESCALATE_REASONING), sessionKey);
|
|
54476
54736
|
return;
|
|
@@ -54505,13 +54765,13 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54505
54765
|
failureReason,
|
|
54506
54766
|
audit: "synthesized ESCALATE (#C1F-8): reviewer_substrate_engage_failed",
|
|
54507
54767
|
...describeReviewerErrorDetail(engageErr.detail),
|
|
54508
|
-
|
|
54768
|
+
...errorShapeOnly(engageErr)
|
|
54509
54769
|
}), await this.submitVerdict(args, this.synthesizeEscalate(args, cleanReasoning), sessionKey);
|
|
54510
54770
|
return;
|
|
54511
54771
|
}
|
|
54512
54772
|
throw engageErr;
|
|
54513
54773
|
}
|
|
54514
|
-
let verdict;
|
|
54774
|
+
let verdict, evaluationError;
|
|
54515
54775
|
try {
|
|
54516
54776
|
verdict = await this.evaluateSeatWithTimeout(spec, args.gateId, seatSubstrate.handle);
|
|
54517
54777
|
} catch (err) {
|
|
@@ -54539,7 +54799,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54539
54799
|
// Audit prefix kept in LOGS only (#C1F-8) — never on the wire.
|
|
54540
54800
|
audit: `synthesized ESCALATE (#C1F-8): reviewer_error:${err.detail.kind}`,
|
|
54541
54801
|
...describeReviewerErrorDetail(err.detail),
|
|
54542
|
-
|
|
54802
|
+
...errorShapeOnly(err),
|
|
54543
54803
|
// 2026-08-22 (dogfood) — TIMEOUT DIAGNOSTICS, local log only.
|
|
54544
54804
|
//
|
|
54545
54805
|
// A live 5-minute reviewer timeout on a ONE-FILE deletion diff was
|
|
@@ -54556,16 +54816,51 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54556
54816
|
...this.describeReviewShapeForDiagnostics(args.gateId)
|
|
54557
54817
|
}), verdict = this.synthesizeEscalate(args, cleanReasoning);
|
|
54558
54818
|
} else
|
|
54559
|
-
|
|
54560
|
-
}
|
|
54561
|
-
|
|
54819
|
+
evaluationError = err;
|
|
54820
|
+
}
|
|
54821
|
+
let cleanupError;
|
|
54822
|
+
try {
|
|
54823
|
+
await seatSubstrate.teardown();
|
|
54824
|
+
} catch (error) {
|
|
54825
|
+
cleanupError = error, logger.warn("[QuorumLoop] reviewer substrate cleanup failed \u2014 forcing ESCALATE", {
|
|
54826
|
+
key,
|
|
54827
|
+
seatId: args.seatId,
|
|
54828
|
+
role: args.role,
|
|
54829
|
+
agentKind: args.agentKind,
|
|
54830
|
+
...errorShapeOnly(error),
|
|
54831
|
+
audit: "synthesized ESCALATE: reviewer_substrate_cleanup_failed"
|
|
54562
54832
|
});
|
|
54563
54833
|
}
|
|
54834
|
+
if (evaluationError !== void 0) {
|
|
54835
|
+
let terminalError = cleanupError !== void 0 ? Object.assign(
|
|
54836
|
+
new Error("reviewer evaluation failed and substrate cleanup also failed"),
|
|
54837
|
+
{ causes: [evaluationError, cleanupError] }
|
|
54838
|
+
) : Object.assign(
|
|
54839
|
+
new Error("reviewer evaluation failed unexpectedly"),
|
|
54840
|
+
{ cause: evaluationError }
|
|
54841
|
+
);
|
|
54842
|
+
logger.warn("[QuorumLoop] unexpected reviewer evaluation failure \u2014 forcing ESCALATE", {
|
|
54843
|
+
key,
|
|
54844
|
+
seatId: args.seatId,
|
|
54845
|
+
role: args.role,
|
|
54846
|
+
agentKind: args.agentKind,
|
|
54847
|
+
...errorShapeOnly(terminalError),
|
|
54848
|
+
audit: "synthesized ESCALATE: reviewer_evaluation_failed"
|
|
54849
|
+
}), verdict = this.synthesizeEscalate(
|
|
54850
|
+
args,
|
|
54851
|
+
DESKTOP_DISPATCH_ESCALATE_REASONING
|
|
54852
|
+
);
|
|
54853
|
+
}
|
|
54854
|
+
if (cleanupError !== void 0 && (verdict = this.synthesizeEscalate(
|
|
54855
|
+
args,
|
|
54856
|
+
DESKTOP_DISPATCH_ESCALATE_REASONING
|
|
54857
|
+
)), verdict === void 0)
|
|
54858
|
+
throw new Error("reviewer completed without a verdict");
|
|
54564
54859
|
reviewScope !== null && (verdict = enforceReviewRoundScope(verdict, reviewScope)), await this.submitVerdict(args, verdict, sessionKey);
|
|
54565
54860
|
} catch (err) {
|
|
54566
54861
|
logger.warn("[QuorumLoop] spawnOneSeat failed \u2014 dropped", {
|
|
54567
54862
|
key,
|
|
54568
|
-
err
|
|
54863
|
+
...errorShapeOnly(err)
|
|
54569
54864
|
});
|
|
54570
54865
|
} finally {
|
|
54571
54866
|
this.runningSeats.delete(key);
|
|
@@ -54658,19 +54953,18 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54658
54953
|
if (e.name === REVIEWER_CREDENTIAL_MISSING)
|
|
54659
54954
|
try {
|
|
54660
54955
|
this.surfaceHalt(
|
|
54661
|
-
`Reviewer (${seatLabel(args.agentKind, args.seatId)}) cannot start sandboxed:
|
|
54956
|
+
`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
54957
|
);
|
|
54663
54958
|
} catch {
|
|
54664
54959
|
}
|
|
54665
54960
|
throw new ReviewerErrorClass({
|
|
54666
54961
|
kind: "spawn_failed",
|
|
54667
54962
|
agent: args.agentKind,
|
|
54668
|
-
reason:
|
|
54963
|
+
reason: "CP-7: reviewer substrate engage failed for a Trusted agent \u2014 refusing the unsandboxed (ambient-cred) fallback (fail-closed)",
|
|
54669
54964
|
failureReason: "spawn_failed"
|
|
54670
54965
|
});
|
|
54671
54966
|
}
|
|
54672
|
-
return result.mode === "reduced_trust" ? (this.surfaceReviewerReducedTrust(args, result.reducedTrustReason), await result.teardown()
|
|
54673
|
-
}), NO_TEARDOWN) : (result.reducedTrust && this.surfaceReviewerReducedTrust(
|
|
54967
|
+
return result.mode === "reduced_trust" ? (this.surfaceReviewerReducedTrust(args, result.reducedTrustReason), await result.teardown(), NO_TEARDOWN) : (result.reducedTrust && this.surfaceReviewerReducedTrust(
|
|
54674
54968
|
args,
|
|
54675
54969
|
result.reducedTrustReason ?? "coarse egress (A5 sandbox-exec) \u2014 reviewer is sandboxed but loopback-only."
|
|
54676
54970
|
), {
|
|
@@ -54712,7 +55006,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54712
55006
|
reason
|
|
54713
55007
|
), logger.warn("[QuorumLoop] reduced-trust badge surfaceHalt threw (badge is best-effort) \u2014 continuing", {
|
|
54714
55008
|
seatId: args.seatId,
|
|
54715
|
-
|
|
55009
|
+
...errorShapeOnly(e)
|
|
54716
55010
|
});
|
|
54717
55011
|
}
|
|
54718
55012
|
}
|
|
@@ -54767,13 +55061,20 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54767
55061
|
});
|
|
54768
55062
|
if (result.mode === "substrate")
|
|
54769
55063
|
return { mode: "substrate", handle: result.substrateHandle, teardown: () => result.teardown() };
|
|
54770
|
-
|
|
54771
|
-
|
|
55064
|
+
try {
|
|
55065
|
+
await result.teardown();
|
|
55066
|
+
} catch (cleanupError) {
|
|
55067
|
+
return logger.warn("[QuorumLoop] Wave B reduced-trust cleanup failed \u2014 refusing fallback", {
|
|
55068
|
+
taskId,
|
|
55069
|
+
agent,
|
|
55070
|
+
...errorShapeOnly(cleanupError)
|
|
55071
|
+
}), { mode: "none" };
|
|
55072
|
+
}
|
|
54772
55073
|
} catch (e) {
|
|
54773
55074
|
logger.warn("[QuorumLoop] Wave B substrate engage failed \u2014 falling through to trusted-container/none", {
|
|
54774
55075
|
taskId,
|
|
54775
55076
|
agent,
|
|
54776
|
-
|
|
55077
|
+
...errorShapeOnly(e)
|
|
54777
55078
|
});
|
|
54778
55079
|
}
|
|
54779
55080
|
return isTrustedContainerBoundary() ? { mode: "trusted_container", teardown: async () => {
|
|
@@ -54804,9 +55105,11 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54804
55105
|
...substrate !== void 0 ? { substrate } : {}
|
|
54805
55106
|
});
|
|
54806
55107
|
if (!outcome.exit_success)
|
|
54807
|
-
throw
|
|
54808
|
-
|
|
54809
|
-
|
|
55108
|
+
throw logger.warn("[QuorumLoop] class-2 resolver model call exited non-zero", {
|
|
55109
|
+
ownerTaskId: args.ownerTaskId,
|
|
55110
|
+
stdoutShape: outputShapeOnly(outcome.stdout),
|
|
55111
|
+
stderrShape: outputShapeOnly(outcome.stderr)
|
|
55112
|
+
}), new Error("class-2 resolver model call exited non-zero");
|
|
54810
55113
|
return outcome.stdout;
|
|
54811
55114
|
};
|
|
54812
55115
|
return {
|
|
@@ -54850,7 +55153,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54850
55153
|
return { establishable: !0, via: "ladder_tier" };
|
|
54851
55154
|
} catch (err) {
|
|
54852
55155
|
logger.warn("[QuorumLoop] A1d resolver probe: ladder select failed \u2014 treating as no tier", {
|
|
54853
|
-
err
|
|
55156
|
+
...errorShapeOnly(err)
|
|
54854
55157
|
});
|
|
54855
55158
|
}
|
|
54856
55159
|
return (this.deps.resolverProbeDeps?.trustedContainer ?? isTrustedContainerBoundary)() ? { establishable: !0, via: "trusted_container" } : { establishable: !1 };
|
|
@@ -54981,8 +55284,8 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
54981
55284
|
taskId: tid,
|
|
54982
55285
|
exitCode: exit.exitCode,
|
|
54983
55286
|
runtimeMs: exit.runtimeMs,
|
|
54984
|
-
|
|
54985
|
-
|
|
55287
|
+
stdoutShape: outputShapeOnly(handle.stdout()),
|
|
55288
|
+
stderrShape: outputShapeOnly(handle.stderr())
|
|
54986
55289
|
}), exit.failureClass !== null)
|
|
54987
55290
|
throw new Error(`agentic resolver implementor failed: ${exit.failureClass}`);
|
|
54988
55291
|
}
|
|
@@ -55045,6 +55348,7 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
55045
55348
|
});
|
|
55046
55349
|
continue;
|
|
55047
55350
|
}
|
|
55351
|
+
let candidateError;
|
|
55048
55352
|
try {
|
|
55049
55353
|
let substrate = confinement.mode === "substrate" ? confinement.handle : void 0, spec = {
|
|
55050
55354
|
seat_id: 0,
|
|
@@ -55067,14 +55371,27 @@ var QuorumLoop = class _QuorumLoop {
|
|
|
55067
55371
|
...pass ? {} : { reason: `final-tip Tier-2 verdict: ${verdict.verdict}` }
|
|
55068
55372
|
};
|
|
55069
55373
|
} catch (e) {
|
|
55070
|
-
lastFailure = `final-tip Tier-2 reviewer
|
|
55374
|
+
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
55375
|
ownerTaskId: args.ownerTaskId,
|
|
55072
55376
|
agent,
|
|
55073
|
-
|
|
55377
|
+
...errorShapeOnly(e)
|
|
55074
55378
|
});
|
|
55075
55379
|
} finally {
|
|
55076
|
-
|
|
55077
|
-
|
|
55380
|
+
try {
|
|
55381
|
+
await confinement.teardown();
|
|
55382
|
+
} catch (cleanupError) {
|
|
55383
|
+
throw logger.warn("[QuorumLoop] final-tip Tier-2 substrate cleanup failed \u2014 failing closed", {
|
|
55384
|
+
ownerTaskId: args.ownerTaskId,
|
|
55385
|
+
agent,
|
|
55386
|
+
...errorShapeOnly(cleanupError)
|
|
55387
|
+
}), candidateError !== void 0 ? Object.assign(
|
|
55388
|
+
new Error("final-tip Tier-2 evaluation failed and substrate cleanup also failed"),
|
|
55389
|
+
{ causes: [candidateError, cleanupError] }
|
|
55390
|
+
) : Object.assign(
|
|
55391
|
+
new Error("final-tip Tier-2 substrate cleanup failed"),
|
|
55392
|
+
{ cause: cleanupError }
|
|
55393
|
+
);
|
|
55394
|
+
}
|
|
55078
55395
|
}
|
|
55079
55396
|
}
|
|
55080
55397
|
return {
|
|
@@ -65193,7 +65510,7 @@ function buildSanitizedBaseEnv(input) {
|
|
|
65193
65510
|
let v = safeSource[key];
|
|
65194
65511
|
typeof v == "string" && v.length > 0 && (env[key] = v);
|
|
65195
65512
|
}
|
|
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;
|
|
65513
|
+
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
65514
|
}
|
|
65198
65515
|
var FORBIDDEN_KEY_PATTERNS = [
|
|
65199
65516
|
/^ANTHROPIC_API_KEY$/i,
|
|
@@ -65319,16 +65636,36 @@ async function engageSubstrate(input) {
|
|
|
65319
65636
|
try {
|
|
65320
65637
|
({ hostBrokerAddr } = await broker.start());
|
|
65321
65638
|
} catch (e) {
|
|
65322
|
-
|
|
65323
|
-
|
|
65324
|
-
|
|
65639
|
+
let primary = Object.assign(
|
|
65640
|
+
new Error("CP-7: broker failed to start \u2014 refusing to launch the implementor (fail-closed)"),
|
|
65641
|
+
{ cause: e }
|
|
65325
65642
|
);
|
|
65643
|
+
try {
|
|
65644
|
+
await broker.stop();
|
|
65645
|
+
} catch (cleanupError) {
|
|
65646
|
+
throw Object.assign(
|
|
65647
|
+
new Error("CP-7: broker start failed and cleanup also failed"),
|
|
65648
|
+
{ causes: [primary, cleanupError] }
|
|
65649
|
+
);
|
|
65650
|
+
}
|
|
65651
|
+
throw primary;
|
|
65326
65652
|
}
|
|
65327
65653
|
let initialTokenObj = broker.currentBrokerToken();
|
|
65328
|
-
if (!initialTokenObj)
|
|
65329
|
-
|
|
65330
|
-
|
|
65331
|
-
|
|
65654
|
+
if (!initialTokenObj) {
|
|
65655
|
+
let primary = new Error(
|
|
65656
|
+
"CP-7: broker minted no token \u2014 refusing to launch (fail-closed)"
|
|
65657
|
+
);
|
|
65658
|
+
try {
|
|
65659
|
+
await broker.stop();
|
|
65660
|
+
} catch (cleanupError) {
|
|
65661
|
+
throw Object.assign(
|
|
65662
|
+
new Error("CP-7: broker minted no token and cleanup also failed"),
|
|
65663
|
+
{ causes: [primary, cleanupError] }
|
|
65664
|
+
);
|
|
65665
|
+
}
|
|
65666
|
+
throw primary;
|
|
65667
|
+
}
|
|
65668
|
+
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
65669
|
try {
|
|
65333
65670
|
bootstrap = await ApiKeyBootstrap.create({
|
|
65334
65671
|
provider,
|
|
@@ -65339,6 +65676,7 @@ async function engageSubstrate(input) {
|
|
|
65339
65676
|
sandboxConfigDir: sandboxConfigMount ?? SANDBOX_AGENT_CONFIG_DIR
|
|
65340
65677
|
} : { sandboxDirEqualsHostDir: !0, configDirEqualsHostDir: !0 },
|
|
65341
65678
|
hostRoot: input.bootstrapHostRoot,
|
|
65679
|
+
...selection.tier === "sandbox_exec" && provider === "anthropic" ? { claudeScratchHostRoot: input.claudeScratchHostRoot ?? "/tmp" } : {},
|
|
65342
65680
|
// M-2 — fail closed if the bootstrap dir lands inside the agent's rw
|
|
65343
65681
|
// workdir mount (the token would leak through it).
|
|
65344
65682
|
workdir: input.workdir,
|
|
@@ -65350,11 +65688,12 @@ async function engageSubstrate(input) {
|
|
|
65350
65688
|
), agentConfigSpec = sandboxConfigMount !== null ? { hostDir: bootstrap.configHostDir, sandboxDir: sandboxConfigMount } : (
|
|
65351
65689
|
// A5: sandbox fs == host fs → config path equals the host dir.
|
|
65352
65690
|
{ hostDir: bootstrap.configHostDir, sandboxDir: bootstrap.configHostDir }
|
|
65353
|
-
), sanitizedBase = buildSanitizedBaseEnv({
|
|
65691
|
+
), agentScratchSpec = bootstrap.claudeScratchSpec, sanitizedBase = buildSanitizedBaseEnv({
|
|
65354
65692
|
provider,
|
|
65355
65693
|
sandboxBrokerUrl,
|
|
65356
65694
|
sandboxHome,
|
|
65357
65695
|
sandboxBootstrapDir: agentConfigSpec.sandboxDir,
|
|
65696
|
+
...agentScratchSpec !== null ? { claudeScratchDir: agentScratchSpec.sandboxDir } : {},
|
|
65358
65697
|
safeSource: input.localeSource
|
|
65359
65698
|
});
|
|
65360
65699
|
assertNoAmbientCreds(sanitizedBase);
|
|
@@ -65368,6 +65707,7 @@ async function engageSubstrate(input) {
|
|
|
65368
65707
|
sanitizedEnv: finalEnv,
|
|
65369
65708
|
agentBootstrap: agentBootstrapSpec,
|
|
65370
65709
|
agentConfig: agentConfigSpec,
|
|
65710
|
+
...agentScratchSpec !== null ? { agentScratch: agentScratchSpec } : {},
|
|
65371
65711
|
// CP-7 W3 — Stage-2 r1 HIGH. The resolved audit dir → A5 trailing deny.
|
|
65372
65712
|
// Undefined when a test injects its own in-memory sink (no real tree).
|
|
65373
65713
|
...resolvedAuditDir !== null ? { auditDir: resolvedAuditDir } : {}
|
|
@@ -65376,12 +65716,30 @@ async function engageSubstrate(input) {
|
|
|
65376
65716
|
`[CP-7] Substrate engaged (tier=${selection.tier}, egress=${handle.egressFidelity}) \u2014 agent is creditless, broker holds the key`,
|
|
65377
65717
|
{ taskId: input.taskId, agent: input.agentKind }
|
|
65378
65718
|
);
|
|
65379
|
-
let liveBootstrap = bootstrap, liveHandle = handle, liveBroker = broker, refreshTimer = null, teardown = async () => {
|
|
65380
|
-
refreshTimer && (clearInterval(refreshTimer), refreshTimer = null)
|
|
65381
|
-
|
|
65382
|
-
|
|
65383
|
-
|
|
65384
|
-
|
|
65719
|
+
let liveBootstrap = bootstrap, liveHandle = handle, liveBroker = broker, refreshTimer = null, teardownPromise, teardown = () => teardownPromise || (teardownPromise = (async () => {
|
|
65720
|
+
refreshTimer && (clearInterval(refreshTimer), refreshTimer = null);
|
|
65721
|
+
let failures = [];
|
|
65722
|
+
for (let cleanup of [
|
|
65723
|
+
() => liveHandle.teardown(),
|
|
65724
|
+
() => liveBroker.stop(),
|
|
65725
|
+
() => liveBootstrap.destroy()
|
|
65726
|
+
])
|
|
65727
|
+
try {
|
|
65728
|
+
await cleanup();
|
|
65729
|
+
} catch (error) {
|
|
65730
|
+
failures.push(error);
|
|
65731
|
+
}
|
|
65732
|
+
if (failures.length > 0)
|
|
65733
|
+
throw logger.warn("[CP-7] substrate cleanup failed \u2014 task cannot pass", {
|
|
65734
|
+
taskId: input.taskId,
|
|
65735
|
+
failureCount: failures.length,
|
|
65736
|
+
...errorShapeOnly(failures[0])
|
|
65737
|
+
}), failures.length === 1 ? failures[0] : Object.assign(new Error("CP-7 substrate cleanup failed"), {
|
|
65738
|
+
causes: failures
|
|
65739
|
+
});
|
|
65740
|
+
})(), teardownPromise);
|
|
65741
|
+
activeTeardown = teardown;
|
|
65742
|
+
let launchId = `launch-${input.taskId}-${Date.now()}`, denialReason = liveHandle.egressFidelity === "strict" ? "structural_deny_network_none" : "coarse_loopback_only", postureRes;
|
|
65385
65743
|
try {
|
|
65386
65744
|
postureRes = await auditSink.emit("egress_denied", {
|
|
65387
65745
|
destination: "*",
|
|
@@ -65390,13 +65748,16 @@ async function engageSubstrate(input) {
|
|
|
65390
65748
|
caller_event_id: launchId
|
|
65391
65749
|
});
|
|
65392
65750
|
} catch (e) {
|
|
65393
|
-
throw
|
|
65394
|
-
|
|
65751
|
+
throw Object.assign(
|
|
65752
|
+
new Error(
|
|
65753
|
+
"CP-7 W3: egress-posture audit emit failed \u2014 refusing to launch the creditless agent (audit-before-effect fail-closed)"
|
|
65754
|
+
),
|
|
65755
|
+
{ cause: e }
|
|
65395
65756
|
);
|
|
65396
65757
|
}
|
|
65397
65758
|
if (!("ack" in postureRes))
|
|
65398
|
-
throw
|
|
65399
|
-
|
|
65759
|
+
throw new Error(
|
|
65760
|
+
"CP-7 W3: egress-posture audit was rejected \u2014 refusing to launch the creditless agent (no durable egress posture \u2192 no agent)"
|
|
65400
65761
|
);
|
|
65401
65762
|
let refreshIntervalMs = input.tokenRefreshIntervalMs ?? 600 * 1e3, inFlightRefresh = null, doRefreshOnce = async () => {
|
|
65402
65763
|
if (!(typeof liveBroker.rotateBrokerToken == "function" && typeof liveBroker.commitBrokerTokenRotation == "function" && typeof liveBroker.rollbackBrokerTokenRotation == "function")) {
|
|
@@ -65409,10 +65770,23 @@ async function engageSubstrate(input) {
|
|
|
65409
65770
|
try {
|
|
65410
65771
|
await liveBootstrap.refresh(rotated.token.value), liveBroker.commitBrokerTokenRotation(rotated);
|
|
65411
65772
|
} catch (e) {
|
|
65412
|
-
|
|
65773
|
+
liveBroker.rollbackBrokerTokenRotation(rotated), logger.warn(
|
|
65413
65774
|
"[CP-7] broker-token refresh write FAILED \u2014 rolled back to the prior token and tearing down (fail-closed)",
|
|
65414
|
-
{ taskId: input.taskId,
|
|
65415
|
-
)
|
|
65775
|
+
{ taskId: input.taskId, ...errorShapeOnly(e) }
|
|
65776
|
+
);
|
|
65777
|
+
let refreshFailure = Object.assign(
|
|
65778
|
+
new Error("CP-7 broker-token refresh failed"),
|
|
65779
|
+
{ cause: e }
|
|
65780
|
+
);
|
|
65781
|
+
try {
|
|
65782
|
+
await teardown();
|
|
65783
|
+
} catch (cleanupError) {
|
|
65784
|
+
throw Object.assign(
|
|
65785
|
+
new Error("CP-7 broker-token refresh failed and cleanup also failed"),
|
|
65786
|
+
{ causes: [refreshFailure, cleanupError] }
|
|
65787
|
+
);
|
|
65788
|
+
}
|
|
65789
|
+
throw refreshFailure;
|
|
65416
65790
|
}
|
|
65417
65791
|
}, doRefresh = async () => {
|
|
65418
65792
|
let next = (inFlightRefresh ?? Promise.resolve()).catch(() => {
|
|
@@ -65439,10 +65813,32 @@ async function engageSubstrate(input) {
|
|
|
65439
65813
|
teardown
|
|
65440
65814
|
};
|
|
65441
65815
|
} catch (e) {
|
|
65442
|
-
|
|
65443
|
-
|
|
65444
|
-
|
|
65445
|
-
|
|
65816
|
+
let primary = e instanceof Error ? e : new Error("CP-7 substrate launch failed"), cleanupFailures = [];
|
|
65817
|
+
if (activeTeardown)
|
|
65818
|
+
try {
|
|
65819
|
+
await activeTeardown();
|
|
65820
|
+
} catch (cleanupError) {
|
|
65821
|
+
cleanupFailures.push(cleanupError);
|
|
65822
|
+
}
|
|
65823
|
+
else
|
|
65824
|
+
for (let cleanup of [
|
|
65825
|
+
...handle ? [() => handle.teardown()] : [],
|
|
65826
|
+
...bootstrap ? [() => bootstrap.destroy()] : [],
|
|
65827
|
+
() => broker.stop()
|
|
65828
|
+
])
|
|
65829
|
+
try {
|
|
65830
|
+
await cleanup();
|
|
65831
|
+
} catch (cleanupError) {
|
|
65832
|
+
cleanupFailures.push(cleanupError);
|
|
65833
|
+
}
|
|
65834
|
+
throw cleanupFailures.length > 0 ? (logger.warn("[CP-7] failed launch also failed cleanup", {
|
|
65835
|
+
taskId: input.taskId,
|
|
65836
|
+
failureCount: cleanupFailures.length,
|
|
65837
|
+
...errorShapeOnly(cleanupFailures[0])
|
|
65838
|
+
}), Object.assign(
|
|
65839
|
+
new Error("CP-7 substrate launch failed and cleanup also failed"),
|
|
65840
|
+
{ causes: [primary, ...cleanupFailures] }
|
|
65841
|
+
)) : primary;
|
|
65446
65842
|
}
|
|
65447
65843
|
}
|
|
65448
65844
|
var RESOLVER_AGENT_STATE_DIR_SEGMENTS = {
|