@kontextmind/kxm 0.7.23 → 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.
@@ -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: 3
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
- var VNEXT_EVENT_STORE_SCHEMA_VERSION = 3;
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: (/* @__PURE__ */ new Date()).toISOString(),
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
- sendJson(response, 200, { ok: true, run: projected });
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,