@kontextmind/kxm 0.7.22 → 0.7.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/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +55 -13
- package/plugins/kxm/dist/mcp-server.js +104 -32
- package/plugins/kxm/dist/runtime.js +307 -7
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +300 -6
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/hub.ts +2 -1
- package/plugins/kxm/src/cli/vnext.ts +46 -3
- package/plugins/kxm/src/cli.ts +3 -13
- package/plugins/kxm/src/database.ts +3 -1
- package/plugins/kxm/src/hub-env.ts +15 -0
- package/plugins/kxm/src/mcp-server.ts +5 -7
- package/plugins/kxm/src/vnext-config.ts +31 -0
- package/plugins/kxm/src/vnext-engine-fold.ts +24 -0
- package/plugins/kxm/src/vnext-engine.ts +172 -2
- package/plugins/kxm/src/vnext-runtime-owner.ts +1 -0
- package/plugins/kxm/src/vnext-runtime-store.ts +151 -2
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +23 -2
- package/schemas/vnext/common.schema.json +1 -0
- package/schemas/vnext/drive-receipt.schema.json +79 -0
- package/schemas/vnext/run-event.schema.json +10 -0
|
@@ -16431,6 +16431,7 @@ var VnextSchemaRegistry = class {
|
|
|
16431
16431
|
migrationReceiptValidator;
|
|
16432
16432
|
permissionDiffValidator;
|
|
16433
16433
|
runEventValidator;
|
|
16434
|
+
driveReceiptValidator;
|
|
16434
16435
|
constructor(schemasDir = DEFAULT_SCHEMA_DIR) {
|
|
16435
16436
|
this.schemasDir = resolve(schemasDir);
|
|
16436
16437
|
this.ajv = new import__.Ajv2020({ allErrors: true, strict: true, strictRequired: false });
|
|
@@ -16447,6 +16448,7 @@ var VnextSchemaRegistry = class {
|
|
|
16447
16448
|
const migrationReceiptFile = "migration-receipt.schema.json";
|
|
16448
16449
|
const permissionDiffFile = "permission-diff.schema.json";
|
|
16449
16450
|
const runEventFile = "run-event.schema.json";
|
|
16451
|
+
const driveReceiptFile = "drive-receipt.schema.json";
|
|
16450
16452
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, localBindingsFile)));
|
|
16451
16453
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, templateProvenanceFile)));
|
|
16452
16454
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, initOperationFile)));
|
|
@@ -16455,6 +16457,7 @@ var VnextSchemaRegistry = class {
|
|
|
16455
16457
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, migrationReceiptFile)));
|
|
16456
16458
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, permissionDiffFile)));
|
|
16457
16459
|
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, runEventFile)));
|
|
16460
|
+
this.ajv.addSchema(readJsonObject(join2(this.schemasDir, driveReceiptFile)));
|
|
16458
16461
|
for (const [kind, definition] of Object.entries(RESOURCE_SCHEMA)) {
|
|
16459
16462
|
const validator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${definition.file}`);
|
|
16460
16463
|
if (!validator) throw new Error(`schema did not compile: ${definition.file}`);
|
|
@@ -16468,6 +16471,7 @@ var VnextSchemaRegistry = class {
|
|
|
16468
16471
|
const migrationReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${migrationReceiptFile}`);
|
|
16469
16472
|
const permissionDiffValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${permissionDiffFile}`);
|
|
16470
16473
|
const runEventValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${runEventFile}`);
|
|
16474
|
+
const driveReceiptValidator = this.ajv.getSchema(`https://schemas.kxm.dev/vnext/${driveReceiptFile}`);
|
|
16471
16475
|
if (!localBindingsValidator) throw new Error(`schema did not compile: ${localBindingsFile}`);
|
|
16472
16476
|
if (!templateProvenanceValidator) throw new Error(`schema did not compile: ${templateProvenanceFile}`);
|
|
16473
16477
|
if (!initOperationValidator) throw new Error(`schema did not compile: ${initOperationFile}`);
|
|
@@ -16476,6 +16480,7 @@ var VnextSchemaRegistry = class {
|
|
|
16476
16480
|
if (!migrationReceiptValidator) throw new Error(`schema did not compile: ${migrationReceiptFile}`);
|
|
16477
16481
|
if (!permissionDiffValidator) throw new Error(`schema did not compile: ${permissionDiffFile}`);
|
|
16478
16482
|
if (!runEventValidator) throw new Error(`schema did not compile: ${runEventFile}`);
|
|
16483
|
+
if (!driveReceiptValidator) throw new Error(`schema did not compile: ${driveReceiptFile}`);
|
|
16479
16484
|
this.localBindingsValidator = localBindingsValidator;
|
|
16480
16485
|
this.templateProvenanceValidator = templateProvenanceValidator;
|
|
16481
16486
|
this.initOperationValidator = initOperationValidator;
|
|
@@ -16484,6 +16489,7 @@ var VnextSchemaRegistry = class {
|
|
|
16484
16489
|
this.migrationReceiptValidator = migrationReceiptValidator;
|
|
16485
16490
|
this.permissionDiffValidator = permissionDiffValidator;
|
|
16486
16491
|
this.runEventValidator = runEventValidator;
|
|
16492
|
+
this.driveReceiptValidator = driveReceiptValidator;
|
|
16487
16493
|
}
|
|
16488
16494
|
validate(kind, value, file) {
|
|
16489
16495
|
const definition = RESOURCE_SCHEMA[kind];
|
|
@@ -16516,6 +16522,9 @@ var VnextSchemaRegistry = class {
|
|
|
16516
16522
|
validatePermissionDiff(value, file) {
|
|
16517
16523
|
return this.validateAuxiliary(value, file, "kxm.permission-diff.v1", this.permissionDiffValidator);
|
|
16518
16524
|
}
|
|
16525
|
+
validateDriveReceipt(value, file) {
|
|
16526
|
+
return this.validateAuxiliary(value, file, "kxm.drive-receipt.v1", this.driveReceiptValidator);
|
|
16527
|
+
}
|
|
16519
16528
|
validateAuxiliary(value, file, identity, validator) {
|
|
16520
16529
|
if (value.schema !== identity) {
|
|
16521
16530
|
return [issue2("schema", "schema_identity_mismatch", file, `expected ${identity}, received ${String(value.schema)}`)];
|
|
@@ -16536,6 +16545,25 @@ function validateRunEvent(value, file) {
|
|
|
16536
16545
|
)]);
|
|
16537
16546
|
}
|
|
16538
16547
|
}
|
|
16548
|
+
function validateDriveReceipt(value, file) {
|
|
16549
|
+
const registry = cachedRunEventRegistry ??= new VnextSchemaRegistry();
|
|
16550
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || value.schema !== "kxm.drive-receipt.v1") {
|
|
16551
|
+
throw new VnextConfigError([issue2(
|
|
16552
|
+
"schema",
|
|
16553
|
+
"drive_receipt_invalid",
|
|
16554
|
+
file,
|
|
16555
|
+
"expected kxm.drive-receipt.v1"
|
|
16556
|
+
)]);
|
|
16557
|
+
}
|
|
16558
|
+
if (!registry.driveReceiptValidator(value)) {
|
|
16559
|
+
throw new VnextConfigError([issue2(
|
|
16560
|
+
"schema",
|
|
16561
|
+
"drive_receipt_invalid",
|
|
16562
|
+
file,
|
|
16563
|
+
registry.ajv.errorsText(registry.driveReceiptValidator.errors, { separator: "; " })
|
|
16564
|
+
)]);
|
|
16565
|
+
}
|
|
16566
|
+
}
|
|
16539
16567
|
function schemaIssue(file, error) {
|
|
16540
16568
|
const location = error.instancePath || "/";
|
|
16541
16569
|
const suffix = error.params && "additionalProperty" in error.params ? ` (${String(error.params.additionalProperty)})` : "";
|
|
@@ -17923,7 +17951,7 @@ function discoverProjectStores(projectRoot, options = {}) {
|
|
|
17923
17951
|
stores.push({
|
|
17924
17952
|
storeId: `events:${key}`,
|
|
17925
17953
|
sourcePath: join4(eventsDir, entry.name),
|
|
17926
|
-
maxSupportedVersion:
|
|
17954
|
+
maxSupportedVersion: 4
|
|
17927
17955
|
});
|
|
17928
17956
|
}
|
|
17929
17957
|
}
|
|
@@ -18013,6 +18041,8 @@ function restoreBackup(manifestPathOrDir, options = {}) {
|
|
|
18013
18041
|
let maxSupported = 3;
|
|
18014
18042
|
if (store.storeId === "registry" || store.storeId === "binding-store") {
|
|
18015
18043
|
maxSupported = 1;
|
|
18044
|
+
} else if (store.storeId.startsWith("events:")) {
|
|
18045
|
+
maxSupported = 4;
|
|
18016
18046
|
}
|
|
18017
18047
|
let targetPath = store.sourcePath;
|
|
18018
18048
|
if (options.projectRoot && manifest.projectRoot && targetPath.startsWith(manifest.projectRoot)) {
|
|
@@ -18255,7 +18285,36 @@ var VnextRuntimeRegistry = class {
|
|
|
18255
18285
|
};
|
|
18256
18286
|
var VNEXT_RUN_EVENT_SCHEMA = "kxm.run-event.v1";
|
|
18257
18287
|
var VNEXT_ABSENT_MEMORY_REVISION = "ctxrev_absent";
|
|
18258
|
-
|
|
18288
|
+
function hashVnextDriveLog(events) {
|
|
18289
|
+
const body = events.map((event) => `${event.eventId}:${event.sequence}`).join("\n");
|
|
18290
|
+
return `sha256:${createHash4("sha256").update(body, "utf8").digest("hex")}`;
|
|
18291
|
+
}
|
|
18292
|
+
function verifyVnextDriveReceipt(receipt, events, foldedStatus, binding) {
|
|
18293
|
+
const reasons = [];
|
|
18294
|
+
if (receipt.runId !== binding.runId) {
|
|
18295
|
+
reasons.push(`runId ${receipt.runId} != binding ${binding.runId}`);
|
|
18296
|
+
}
|
|
18297
|
+
if (receipt.driveId !== binding.driveId) {
|
|
18298
|
+
reasons.push(`driveId ${receipt.driveId} != binding ${binding.driveId}`);
|
|
18299
|
+
}
|
|
18300
|
+
const last = events[events.length - 1];
|
|
18301
|
+
const currentLast = last?.sequence ?? 0;
|
|
18302
|
+
if (receipt.lastSequence !== currentLast) {
|
|
18303
|
+
reasons.push(`lastSequence ${receipt.lastSequence} != log ${currentLast}`);
|
|
18304
|
+
}
|
|
18305
|
+
const prefix = events.filter((event) => event.sequence >= 1 && event.sequence <= receipt.lastSequence);
|
|
18306
|
+
if (hashVnextDriveLog(prefix) !== receipt.logHash) {
|
|
18307
|
+
reasons.push("logHash mismatch");
|
|
18308
|
+
}
|
|
18309
|
+
if (receipt.settlement.status !== foldedStatus) {
|
|
18310
|
+
reasons.push(`settlement.status ${receipt.settlement.status} != folded ${foldedStatus}`);
|
|
18311
|
+
}
|
|
18312
|
+
if (reasons.length === 0) return { verified: true };
|
|
18313
|
+
return { verified: false, divergence: reasons.join("; ") };
|
|
18314
|
+
}
|
|
18315
|
+
var VNEXT_EVENT_STORE_SCHEMA_VERSION = 4;
|
|
18316
|
+
var VNEXT_DRIVE_RECEIPT_SCHEMA = "kxm.drive-receipt.v1";
|
|
18317
|
+
var DRIVE_RECEIPT_MAX_BYTES = 8 * 1024;
|
|
18259
18318
|
var EVENT_STORE_TABLES = {
|
|
18260
18319
|
runs: ["run_id", "project_id", "home_runtime_id", "workflow_id", "prompt_sha256", "status", "config_revision", "memory_revision", "executor_policy_revision", "tool_policy_revision", "created_at", "updated_at"],
|
|
18261
18320
|
events: ["project_id", "run_id", "sequence", "event_id", "event_type", "command_id", "occurred_at", "recorded_at", "monotonic_ns", "config_revision", "memory_revision", "executor_policy_revision", "tool_policy_revision", "payload", "schema", "home_runtime_id"],
|
|
@@ -18334,7 +18393,8 @@ var EVENT_STORE_TABLES = {
|
|
|
18334
18393
|
"outcome",
|
|
18335
18394
|
"settled_event_id",
|
|
18336
18395
|
"content_hash"
|
|
18337
|
-
]
|
|
18396
|
+
],
|
|
18397
|
+
drive_receipts: ["drive_id", "run_id", "project_id", "opened_sequence", "last_sequence", "closed_at", "schema", "receipt"]
|
|
18338
18398
|
};
|
|
18339
18399
|
var EVENT_STORE_SCHEMA = `
|
|
18340
18400
|
CREATE TABLE runs (
|
|
@@ -18476,7 +18536,40 @@ CREATE TABLE gate_evidence (
|
|
|
18476
18536
|
) STRICT;
|
|
18477
18537
|
CREATE UNIQUE INDEX gate_evidence_key ON gate_evidence(run_id, step_id, step_attempt, evidence_key) WHERE evidence_key IS NOT NULL;
|
|
18478
18538
|
CREATE INDEX gate_evidence_run ON gate_evidence(run_id);
|
|
18539
|
+
CREATE TABLE drive_receipts (
|
|
18540
|
+
drive_id TEXT PRIMARY KEY,
|
|
18541
|
+
run_id TEXT NOT NULL,
|
|
18542
|
+
project_id TEXT NOT NULL,
|
|
18543
|
+
opened_sequence INTEGER NOT NULL,
|
|
18544
|
+
last_sequence INTEGER NOT NULL,
|
|
18545
|
+
closed_at TEXT NOT NULL,
|
|
18546
|
+
schema TEXT NOT NULL,
|
|
18547
|
+
receipt TEXT NOT NULL
|
|
18548
|
+
) STRICT;
|
|
18549
|
+
CREATE INDEX drive_receipts_run ON drive_receipts(run_id);
|
|
18550
|
+
`;
|
|
18551
|
+
var DRIVE_RECEIPTS_DDL = `
|
|
18552
|
+
CREATE TABLE IF NOT EXISTS drive_receipts (
|
|
18553
|
+
drive_id TEXT PRIMARY KEY,
|
|
18554
|
+
run_id TEXT NOT NULL,
|
|
18555
|
+
project_id TEXT NOT NULL,
|
|
18556
|
+
opened_sequence INTEGER NOT NULL,
|
|
18557
|
+
last_sequence INTEGER NOT NULL,
|
|
18558
|
+
closed_at TEXT NOT NULL,
|
|
18559
|
+
schema TEXT NOT NULL,
|
|
18560
|
+
receipt TEXT NOT NULL
|
|
18561
|
+
) STRICT;
|
|
18562
|
+
CREATE INDEX IF NOT EXISTS drive_receipts_run ON drive_receipts(run_id);
|
|
18479
18563
|
`;
|
|
18564
|
+
var EVENT_STORE_MIGRATIONS = [
|
|
18565
|
+
{
|
|
18566
|
+
fromVersion: 3,
|
|
18567
|
+
toVersion: 4,
|
|
18568
|
+
migrate(database) {
|
|
18569
|
+
database.exec(DRIVE_RECEIPTS_DDL);
|
|
18570
|
+
}
|
|
18571
|
+
}
|
|
18572
|
+
];
|
|
18480
18573
|
var VnextRunEventStore = class {
|
|
18481
18574
|
path;
|
|
18482
18575
|
database;
|
|
@@ -18485,7 +18578,8 @@ var VnextRunEventStore = class {
|
|
|
18485
18578
|
this.database = openDatabase(this.path, "run event store", {
|
|
18486
18579
|
schema: EVENT_STORE_SCHEMA,
|
|
18487
18580
|
version: VNEXT_EVENT_STORE_SCHEMA_VERSION,
|
|
18488
|
-
tables: EVENT_STORE_TABLES
|
|
18581
|
+
tables: EVENT_STORE_TABLES,
|
|
18582
|
+
migrations: EVENT_STORE_MIGRATIONS
|
|
18489
18583
|
});
|
|
18490
18584
|
}
|
|
18491
18585
|
close() {
|
|
@@ -18642,6 +18736,38 @@ var VnextRunEventStore = class {
|
|
|
18642
18736
|
ON CONFLICT(run_id) DO UPDATE SET last_sequence = excluded.last_sequence, state = excluded.state
|
|
18643
18737
|
`).run(row.runId, row.lastSequence, row.state);
|
|
18644
18738
|
}
|
|
18739
|
+
insertDriveReceipt(receipt) {
|
|
18740
|
+
validateDriveReceipt(receipt, "drive-receipt");
|
|
18741
|
+
const canonical = vnextCanonicalJson(receipt);
|
|
18742
|
+
if (Buffer.byteLength(canonical, "utf8") > DRIVE_RECEIPT_MAX_BYTES) {
|
|
18743
|
+
throw runtimeError("drive_receipt_invalid", receipt.driveId, `drive receipt exceeds ${DRIVE_RECEIPT_MAX_BYTES} bytes`);
|
|
18744
|
+
}
|
|
18745
|
+
const result = this.database.prepare(`
|
|
18746
|
+
INSERT INTO drive_receipts (drive_id, run_id, project_id, opened_sequence, last_sequence, closed_at, schema, receipt)
|
|
18747
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
18748
|
+
ON CONFLICT(drive_id) DO NOTHING
|
|
18749
|
+
`).run(
|
|
18750
|
+
receipt.driveId,
|
|
18751
|
+
receipt.runId,
|
|
18752
|
+
receipt.projectId,
|
|
18753
|
+
receipt.openedSequence,
|
|
18754
|
+
receipt.lastSequence,
|
|
18755
|
+
receipt.closedAt,
|
|
18756
|
+
receipt.schema,
|
|
18757
|
+
canonical
|
|
18758
|
+
);
|
|
18759
|
+
return { inserted: Number(result.changes) === 1 };
|
|
18760
|
+
}
|
|
18761
|
+
driveReceipt(driveId) {
|
|
18762
|
+
const row = this.database.prepare("SELECT receipt FROM drive_receipts WHERE drive_id = ?").get(driveId);
|
|
18763
|
+
return row ? parseDriveReceipt(row.receipt) : void 0;
|
|
18764
|
+
}
|
|
18765
|
+
driveReceiptsForRun(runId, limit = 20) {
|
|
18766
|
+
const rows = this.database.prepare(`
|
|
18767
|
+
SELECT receipt FROM drive_receipts WHERE run_id = ? ORDER BY closed_at DESC, drive_id DESC LIMIT ?
|
|
18768
|
+
`).all(runId, limit);
|
|
18769
|
+
return rows.map((row) => parseDriveReceipt(row.receipt));
|
|
18770
|
+
}
|
|
18645
18771
|
insertCapability(row) {
|
|
18646
18772
|
this.database.prepare(`
|
|
18647
18773
|
INSERT INTO attempt_capabilities (attempt_id, run_id, assignment_id, step_id, step_attempt, producer_id, capability_hash, state)
|
|
@@ -18876,6 +19002,11 @@ var VnextRunEventStore = class {
|
|
|
18876
19002
|
}
|
|
18877
19003
|
}
|
|
18878
19004
|
};
|
|
19005
|
+
function parseDriveReceipt(raw) {
|
|
19006
|
+
const parsed = JSON.parse(raw);
|
|
19007
|
+
validateDriveReceipt(parsed, "drive-receipt");
|
|
19008
|
+
return parsed;
|
|
19009
|
+
}
|
|
18879
19010
|
function runFromRow(row) {
|
|
18880
19011
|
if (typeof row.memory_revision !== "string" || row.memory_revision.length === 0) {
|
|
18881
19012
|
throw runtimeError("runtime_schema_shape_invalid", row.run_id, "memory_revision is required");
|
|
@@ -19499,6 +19630,9 @@ function foldVnextRunState(run, plan, events, options = {}) {
|
|
|
19499
19630
|
case "run.cancel_requested":
|
|
19500
19631
|
foldCancelRequested(state, event);
|
|
19501
19632
|
break;
|
|
19633
|
+
case "run.drive_opened":
|
|
19634
|
+
foldDriveOpened(state, event);
|
|
19635
|
+
break;
|
|
19502
19636
|
case "step.entered":
|
|
19503
19637
|
foldStepEntered(state, plan, event);
|
|
19504
19638
|
break;
|
|
@@ -19710,6 +19844,17 @@ function isProvenFailure(state, plan) {
|
|
|
19710
19844
|
const used = state.stepAttempts[stepId] ?? 0;
|
|
19711
19845
|
return Boolean(step && used >= step.maxAttempts);
|
|
19712
19846
|
}
|
|
19847
|
+
function foldDriveOpened(state, event) {
|
|
19848
|
+
if (state.status !== "running" && state.status !== "blocked_uncertain") {
|
|
19849
|
+
throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running or blocked_uncertain");
|
|
19850
|
+
}
|
|
19851
|
+
const driveId = stringPayload(event, "driveId");
|
|
19852
|
+
const mode = stringPayload(event, "mode");
|
|
19853
|
+
if (mode !== "simulated" && mode !== "live") {
|
|
19854
|
+
throw runtimeError("run_events_illegal", state.runId, "run.drive_opened mode must be simulated or live");
|
|
19855
|
+
}
|
|
19856
|
+
state.drive = { driveId, mode, openedSequence: event.sequence };
|
|
19857
|
+
}
|
|
19713
19858
|
function foldCancelRequested(state, event) {
|
|
19714
19859
|
if (state.cancelRequested || TERMINAL_RUN.has(state.status)) {
|
|
19715
19860
|
throw runtimeError("run_events_illegal", state.runId, "duplicate run.cancel_requested is not legal");
|
|
@@ -20358,7 +20503,8 @@ function freezeState(state) {
|
|
|
20358
20503
|
transitionsUsed: state.transitionsUsed,
|
|
20359
20504
|
cancelRequested: state.cancelRequested,
|
|
20360
20505
|
...state.terminalReason !== void 0 ? { terminalReason: state.terminalReason } : {},
|
|
20361
|
-
...state.terminalReason !== void 0 && state.status === "failed" ? { failureReason: state.terminalReason } : {}
|
|
20506
|
+
...state.terminalReason !== void 0 && state.status === "failed" ? { failureReason: state.terminalReason } : {},
|
|
20507
|
+
...state.drive !== void 0 ? { drive: Object.freeze({ ...state.drive }) } : {}
|
|
20362
20508
|
};
|
|
20363
20509
|
return Object.freeze(frozen);
|
|
20364
20510
|
}
|
|
@@ -24323,6 +24469,110 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
|
|
|
24323
24469
|
function newDriveId(runId, token, runtimeId, monotonicNs) {
|
|
24324
24470
|
return `drv_${createHash11("sha256").update(`${runId}\0${token}\0${runtimeId}\0${monotonicNs}`, "utf8").digest("hex").slice(0, 24)}`;
|
|
24325
24471
|
}
|
|
24472
|
+
function driveErrorSummary(error) {
|
|
24473
|
+
const raw = error instanceof VnextConfigError ? error.issues[0]?.code : void 0;
|
|
24474
|
+
const className = raw && /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/.test(raw) ? raw : "drive-failure";
|
|
24475
|
+
return { class: className, component: "vnext-engine", retryable: false };
|
|
24476
|
+
}
|
|
24477
|
+
function receiptHandoff(handoff) {
|
|
24478
|
+
return {
|
|
24479
|
+
reason: handoff.reason,
|
|
24480
|
+
detail: handoff.detail,
|
|
24481
|
+
...handoff.field !== void 0 ? { field: handoff.field } : {},
|
|
24482
|
+
...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {}
|
|
24483
|
+
};
|
|
24484
|
+
}
|
|
24485
|
+
function appendDriveOpened(context, runId, driveId, mode) {
|
|
24486
|
+
return context.eventStore.transaction(() => {
|
|
24487
|
+
const run = requireRun(context, runId);
|
|
24488
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24489
|
+
const sequence = context.eventStore.nextSequence(runId);
|
|
24490
|
+
const event = {
|
|
24491
|
+
...vnextEventBase(context, run, now, vnextMonotonicNs()),
|
|
24492
|
+
eventId: newVnextEventId(),
|
|
24493
|
+
eventType: "run.drive_opened",
|
|
24494
|
+
sequence,
|
|
24495
|
+
payload: { driveId, mode }
|
|
24496
|
+
};
|
|
24497
|
+
context.eventStore.appendEvent(event);
|
|
24498
|
+
const next = foldStoredVnextRun(context, run);
|
|
24499
|
+
persistVnextRunState(context, runId, next, sequence);
|
|
24500
|
+
return { sequence, occurredAt: now };
|
|
24501
|
+
});
|
|
24502
|
+
}
|
|
24503
|
+
function recordDriveReceipt(context, session, closeInfo) {
|
|
24504
|
+
if (isVnextRuntimeContextClosed(context)) return;
|
|
24505
|
+
try {
|
|
24506
|
+
const run = context.eventStore.run(session.runId);
|
|
24507
|
+
if (!run) return;
|
|
24508
|
+
const state = foldStoredVnextRun(context, run);
|
|
24509
|
+
const events = context.eventStore.events(session.runId, 0, 1e6);
|
|
24510
|
+
if (events.length === 0) return;
|
|
24511
|
+
const opened = state.drive;
|
|
24512
|
+
const openedEvent = opened ? events.find((event) => event.sequence === opened.openedSequence && event.eventType === "run.drive_opened") : events.find((event) => event.eventType === "run.drive_opened" && event.payload.driveId === session.driveId);
|
|
24513
|
+
const last = events[events.length - 1];
|
|
24514
|
+
const openedSequence = opened?.openedSequence ?? openedEvent?.sequence;
|
|
24515
|
+
if (openedSequence === void 0) return;
|
|
24516
|
+
const receipt = {
|
|
24517
|
+
schema: VNEXT_DRIVE_RECEIPT_SCHEMA,
|
|
24518
|
+
driveId: session.driveId,
|
|
24519
|
+
runId: session.runId,
|
|
24520
|
+
projectId: run.projectId,
|
|
24521
|
+
homeRuntimeId: session.homeRuntimeId,
|
|
24522
|
+
mode: session.mode,
|
|
24523
|
+
openedAt: openedEvent?.occurredAt ?? session.openedAt,
|
|
24524
|
+
openedSequence,
|
|
24525
|
+
closedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24526
|
+
lastSequence: last.sequence,
|
|
24527
|
+
logHash: hashVnextDriveLog(events.filter((event) => event.sequence >= 1 && event.sequence <= last.sequence)),
|
|
24528
|
+
settlement: {
|
|
24529
|
+
kind: closeInfo.kind,
|
|
24530
|
+
status: state.status,
|
|
24531
|
+
reason: closeInfo.reason ?? state.terminalReason ?? "",
|
|
24532
|
+
...closeInfo.kind === "handoff" && closeInfo.handoff ? { handoff: receiptHandoff(closeInfo.handoff) } : {},
|
|
24533
|
+
...closeInfo.error !== void 0 ? { error: closeInfo.error } : {}
|
|
24534
|
+
},
|
|
24535
|
+
budget: null,
|
|
24536
|
+
producer: { id: closeInfo.producerId, closed: closeInfo.producerClosed }
|
|
24537
|
+
};
|
|
24538
|
+
context.eventStore.insertDriveReceipt(receipt);
|
|
24539
|
+
} catch {
|
|
24540
|
+
}
|
|
24541
|
+
}
|
|
24542
|
+
function vnextDrivePollProjection(context, runId, state) {
|
|
24543
|
+
if (!state.drive) return void 0;
|
|
24544
|
+
const events = context.eventStore.events(runId, 0, 1e6);
|
|
24545
|
+
const openedEvent = events.find((event) => event.sequence === state.drive.openedSequence);
|
|
24546
|
+
let receipt = null;
|
|
24547
|
+
let unreadable = false;
|
|
24548
|
+
try {
|
|
24549
|
+
receipt = context.eventStore.driveReceipt(state.drive.driveId) ?? null;
|
|
24550
|
+
} catch {
|
|
24551
|
+
unreadable = true;
|
|
24552
|
+
}
|
|
24553
|
+
const projection = {
|
|
24554
|
+
driveId: state.drive.driveId,
|
|
24555
|
+
mode: state.drive.mode,
|
|
24556
|
+
openedAt: openedEvent?.occurredAt ?? "",
|
|
24557
|
+
receipt: unreadable ? null : receipt,
|
|
24558
|
+
verified: false
|
|
24559
|
+
};
|
|
24560
|
+
if (unreadable) {
|
|
24561
|
+
projection.divergence = "receipt unreadable";
|
|
24562
|
+
return projection;
|
|
24563
|
+
}
|
|
24564
|
+
if (!receipt) {
|
|
24565
|
+
projection.divergence = "no receipt";
|
|
24566
|
+
return projection;
|
|
24567
|
+
}
|
|
24568
|
+
const checked = verifyVnextDriveReceipt(receipt, events, state.status, {
|
|
24569
|
+
runId,
|
|
24570
|
+
driveId: state.drive.driveId
|
|
24571
|
+
});
|
|
24572
|
+
projection.verified = checked.verified;
|
|
24573
|
+
if (checked.divergence !== void 0) projection.divergence = checked.divergence;
|
|
24574
|
+
return projection;
|
|
24575
|
+
}
|
|
24326
24576
|
function inflightAttemptId(state) {
|
|
24327
24577
|
const leftover = unreconciledPanelAttemptId(state);
|
|
24328
24578
|
if (leftover) return leftover;
|
|
@@ -24470,13 +24720,15 @@ var VnextRunScheduler = class _VnextRunScheduler {
|
|
|
24470
24720
|
throw error;
|
|
24471
24721
|
}
|
|
24472
24722
|
const driveId = newDriveId(runId, token, this.context.homeRuntimeId, vnextMonotonicNs());
|
|
24723
|
+
const openedMeta = appendDriveOpened(this.context, runId, driveId, options.mode);
|
|
24473
24724
|
const session = {
|
|
24474
24725
|
driveId,
|
|
24475
24726
|
runId,
|
|
24476
24727
|
token,
|
|
24477
24728
|
homeRuntimeId: this.context.homeRuntimeId,
|
|
24478
24729
|
mode: options.mode,
|
|
24479
|
-
openedAt:
|
|
24730
|
+
openedAt: openedMeta.occurredAt,
|
|
24731
|
+
producerId: producer.id,
|
|
24480
24732
|
controller: new AbortController(),
|
|
24481
24733
|
settled
|
|
24482
24734
|
};
|
|
@@ -24485,10 +24737,30 @@ var VnextRunScheduler = class _VnextRunScheduler {
|
|
|
24485
24737
|
resolveOpen({ driveId, settled });
|
|
24486
24738
|
try {
|
|
24487
24739
|
const result = await driveAdmitted(this.context, runId, producer, token, driveOptions);
|
|
24740
|
+
const kind = result.handoff ? "handoff" : isTerminalRunStatus(result.state.status) ? "terminal" : "unsettled";
|
|
24741
|
+
recordDriveReceipt(this.context, session, {
|
|
24742
|
+
kind,
|
|
24743
|
+
...result.state.terminalReason !== void 0 ? { reason: result.state.terminalReason } : result.handoff ? { reason: result.handoff.reason } : {},
|
|
24744
|
+
...result.handoff ? { handoff: result.handoff } : {},
|
|
24745
|
+
producerId: producer.id,
|
|
24746
|
+
producerClosed: false
|
|
24747
|
+
});
|
|
24488
24748
|
pending.resolve(result);
|
|
24489
24749
|
return result;
|
|
24490
24750
|
} catch (error) {
|
|
24491
24751
|
recordBareDriveFailure(this.context, runId);
|
|
24752
|
+
let foldedStatus;
|
|
24753
|
+
try {
|
|
24754
|
+
foldedStatus = foldStoredVnextRun(this.context, requireRun(this.context, runId)).status;
|
|
24755
|
+
} catch {
|
|
24756
|
+
foldedStatus = void 0;
|
|
24757
|
+
}
|
|
24758
|
+
recordDriveReceipt(this.context, session, {
|
|
24759
|
+
kind: foldedStatus !== void 0 && isTerminalRunStatus(foldedStatus) ? "terminal" : "unsettled",
|
|
24760
|
+
error: driveErrorSummary(error),
|
|
24761
|
+
producerId: producer.id,
|
|
24762
|
+
producerClosed: false
|
|
24763
|
+
});
|
|
24492
24764
|
pending.reject(error);
|
|
24493
24765
|
throw error;
|
|
24494
24766
|
}
|
|
@@ -26732,6 +27004,19 @@ async function waitForDriveSessions(settled, graceMs) {
|
|
|
26732
27004
|
if (timeout !== void 0) clearTimeout(timeout);
|
|
26733
27005
|
}
|
|
26734
27006
|
}
|
|
27007
|
+
async function driveSessionStillPending(settled) {
|
|
27008
|
+
let pending = true;
|
|
27009
|
+
void settled.then(
|
|
27010
|
+
() => {
|
|
27011
|
+
pending = false;
|
|
27012
|
+
},
|
|
27013
|
+
() => {
|
|
27014
|
+
pending = false;
|
|
27015
|
+
}
|
|
27016
|
+
);
|
|
27017
|
+
await Promise.resolve();
|
|
27018
|
+
return pending;
|
|
27019
|
+
}
|
|
26735
27020
|
async function startVnextRuntimeSupervisor(options = {}) {
|
|
26736
27021
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
26737
27022
|
const paths = vnextRuntimePaths(options.stateRoot !== void 0 ? { stateRoot: options.stateRoot } : {});
|
|
@@ -26835,7 +27120,9 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
26835
27120
|
const bundle = loadVnextProject(projectRoot, {});
|
|
26836
27121
|
if (request.method === "GET" && !sub) {
|
|
26837
27122
|
const projected = rebuildVnextRunProjection(context, runId);
|
|
26838
|
-
|
|
27123
|
+
const folded = foldStoredVnextRun(context, projected);
|
|
27124
|
+
const drive = vnextDrivePollProjection(context, runId, folded);
|
|
27125
|
+
sendJson(response, 200, { ok: true, run: projected, ...drive !== void 0 ? { drive } : {} });
|
|
26839
27126
|
return;
|
|
26840
27127
|
}
|
|
26841
27128
|
if (request.method === "POST" && sub === "drive") {
|
|
@@ -27052,6 +27339,15 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
27052
27339
|
}
|
|
27053
27340
|
}
|
|
27054
27341
|
await waitForDriveSessions(openSessions.map(({ session }) => session.settled), runtimeStopGraceMs());
|
|
27342
|
+
for (const { context, session } of openSessions) {
|
|
27343
|
+
if (!await driveSessionStillPending(session.settled)) continue;
|
|
27344
|
+
recordDriveReceipt(context, session, {
|
|
27345
|
+
kind: "unsettled",
|
|
27346
|
+
reason: "runtime_shutdown_grace_expired",
|
|
27347
|
+
producerId: session.producerId,
|
|
27348
|
+
producerClosed: false
|
|
27349
|
+
});
|
|
27350
|
+
}
|
|
27055
27351
|
for (const context of contexts.values()) closeVnextRuntimeContext(context);
|
|
27056
27352
|
contexts.clear();
|
|
27057
27353
|
const closed = new Promise((resolveStop) => server.close(() => resolveStop()));
|
|
@@ -29382,6 +29678,7 @@ export {
|
|
|
29382
29678
|
DEFAULT_RUNTIME_STOP_GRACE_MS,
|
|
29383
29679
|
DEFAULT_SOCKET_DIR,
|
|
29384
29680
|
DEFAULT_SUBAGENT_MODELS,
|
|
29681
|
+
DRIVE_RECEIPT_MAX_BYTES,
|
|
29385
29682
|
IMPROVEMENT_REPORT_SCHEMA,
|
|
29386
29683
|
IMPROVEMENT_REPORT_V1_SCHEMA,
|
|
29387
29684
|
LOG_LEVEL_PRIORITY,
|
|
@@ -29398,6 +29695,7 @@ export {
|
|
|
29398
29695
|
SubagentManager,
|
|
29399
29696
|
VIEWPORT_PRESETS,
|
|
29400
29697
|
VNEXT_ABSENT_MEMORY_REVISION,
|
|
29698
|
+
VNEXT_DRIVE_RECEIPT_SCHEMA,
|
|
29401
29699
|
VNEXT_EVENT_STORE_SCHEMA_VERSION,
|
|
29402
29700
|
VNEXT_REGISTRY_SCHEMA_VERSION,
|
|
29403
29701
|
VNEXT_RUN_EVENT_SCHEMA,
|
|
@@ -29452,6 +29750,7 @@ export {
|
|
|
29452
29750
|
groupRoutingRecords,
|
|
29453
29751
|
harnessCommandCandidates,
|
|
29454
29752
|
harnessSpawnUsesShell,
|
|
29753
|
+
hashVnextDriveLog,
|
|
29455
29754
|
hashVnextSupervisorToken,
|
|
29456
29755
|
hashVnextTokenProof,
|
|
29457
29756
|
isKnownHarnessId,
|
|
@@ -29511,6 +29810,7 @@ export {
|
|
|
29511
29810
|
userTables,
|
|
29512
29811
|
validateHarnessModelPair,
|
|
29513
29812
|
verifyExpectedTables,
|
|
29813
|
+
verifyVnextDriveReceipt,
|
|
29514
29814
|
vnextDeclaredExecutorIds,
|
|
29515
29815
|
vnextDeclaredRepositoryIds,
|
|
29516
29816
|
vnextEventBase,
|