@kontextmind/kxm 0.7.23 → 0.7.25

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);
18479
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);
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");
@@ -19266,6 +19397,16 @@ var ATTEMPT_EDGES = {
19266
19397
  executing: /* @__PURE__ */ new Set(["settling"]),
19267
19398
  settling: /* @__PURE__ */ new Set(["terminal"])
19268
19399
  };
19400
+ function effectiveRunDurationBudget(planLimits, projectLimits) {
19401
+ const workflow = planLimits?.maxRunDurationMs;
19402
+ const project = projectLimits?.maxRunDurationMs;
19403
+ if (workflow === void 0 && project === void 0) return void 0;
19404
+ if (workflow !== void 0 && project !== void 0) {
19405
+ return { budgetMs: Math.min(workflow, project), source: "both" };
19406
+ }
19407
+ if (workflow !== void 0) return { budgetMs: workflow, source: "workflow" };
19408
+ return { budgetMs: project, source: "project" };
19409
+ }
19269
19410
  function emptyPanel() {
19270
19411
  return { order: [], assignments: /* @__PURE__ */ Object.create(null) };
19271
19412
  }
@@ -19497,7 +19638,10 @@ function foldVnextRunState(run, plan, events, options = {}) {
19497
19638
  foldRunStatus(state, plan, event);
19498
19639
  break;
19499
19640
  case "run.cancel_requested":
19500
- foldCancelRequested(state, event);
19641
+ foldCancelRequested(state, event, plan, options);
19642
+ break;
19643
+ case "run.drive_opened":
19644
+ foldDriveOpened(state, event);
19501
19645
  break;
19502
19646
  case "step.entered":
19503
19647
  foldStepEntered(state, plan, event);
@@ -19623,6 +19767,9 @@ function foldRunStatus(state, plan, event) {
19623
19767
  if ((status === "running" || status === "cancelling") && !plan) {
19624
19768
  throw runtimeError("run_plan_missing", state.runId, `status ${status} requires a pinned run plan`);
19625
19769
  }
19770
+ if (status === "running" && state.runningSince === void 0) {
19771
+ state.runningSince = event.occurredAt;
19772
+ }
19626
19773
  if (TERMINAL_RUN.has(status)) {
19627
19774
  assertTerminalRunStatus(state, plan, status, event);
19628
19775
  if (typeof event.payload.reason === "string") state.terminalReason = event.payload.reason;
@@ -19710,10 +19857,47 @@ function isProvenFailure(state, plan) {
19710
19857
  const used = state.stepAttempts[stepId] ?? 0;
19711
19858
  return Boolean(step && used >= step.maxAttempts);
19712
19859
  }
19713
- function foldCancelRequested(state, event) {
19860
+ function foldDriveOpened(state, event) {
19861
+ if (state.status !== "running" && state.status !== "blocked_uncertain") {
19862
+ throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running or blocked_uncertain");
19863
+ }
19864
+ const driveId = stringPayload(event, "driveId");
19865
+ const mode = stringPayload(event, "mode");
19866
+ if (mode !== "simulated" && mode !== "live") {
19867
+ throw runtimeError("run_events_illegal", state.runId, "run.drive_opened mode must be simulated or live");
19868
+ }
19869
+ state.drive = { driveId, mode, openedSequence: event.sequence };
19870
+ }
19871
+ function foldCancelRequested(state, event, plan, options) {
19714
19872
  if (state.cancelRequested || TERMINAL_RUN.has(state.status)) {
19715
19873
  throw runtimeError("run_events_illegal", state.runId, "duplicate run.cancel_requested is not legal");
19716
19874
  }
19875
+ if (event.payload.reason === "budget_run_duration") {
19876
+ const budget = event.payload.budget;
19877
+ if (!budget || typeof budget !== "object" || Array.isArray(budget)) {
19878
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration requires a budget payload");
19879
+ }
19880
+ const body = budget;
19881
+ const budgetMs = body.budgetMs;
19882
+ const elapsedMs = body.elapsedMs;
19883
+ const source = body.source;
19884
+ if (typeof budgetMs !== "number" || !Number.isInteger(budgetMs) || budgetMs < 0) {
19885
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration budgetMs is invalid");
19886
+ }
19887
+ if (typeof elapsedMs !== "number" || !Number.isInteger(elapsedMs) || elapsedMs < 0) {
19888
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration elapsedMs is invalid");
19889
+ }
19890
+ if (source !== "workflow" && source !== "project" && source !== "both") {
19891
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration source is invalid");
19892
+ }
19893
+ const expected = effectiveRunDurationBudget(plan?.limits, options.projectLimits);
19894
+ if (!expected || expected.budgetMs !== budgetMs || expected.source !== source) {
19895
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration budgetMs does not match the plan");
19896
+ }
19897
+ if (elapsedMs < budgetMs) {
19898
+ throw runtimeError("run_events_illegal", state.runId, "budget_run_duration elapsedMs is below budgetMs");
19899
+ }
19900
+ }
19717
19901
  state.cancelRequested = true;
19718
19902
  if (event.commandId) state.cancelCommandId = event.commandId;
19719
19903
  }
@@ -20358,7 +20542,9 @@ function freezeState(state) {
20358
20542
  transitionsUsed: state.transitionsUsed,
20359
20543
  cancelRequested: state.cancelRequested,
20360
20544
  ...state.terminalReason !== void 0 ? { terminalReason: state.terminalReason } : {},
20361
- ...state.terminalReason !== void 0 && state.status === "failed" ? { failureReason: state.terminalReason } : {}
20545
+ ...state.terminalReason !== void 0 && state.status === "failed" ? { failureReason: state.terminalReason } : {},
20546
+ ...state.drive !== void 0 ? { drive: Object.freeze({ ...state.drive }) } : {},
20547
+ ...state.runningSince !== void 0 ? { runningSince: state.runningSince } : {}
20362
20548
  };
20363
20549
  return Object.freeze(frozen);
20364
20550
  }
@@ -22256,7 +22442,8 @@ function foldStoredVnextRun(context, run) {
22256
22442
  const step = envelope.plan.steps[stepId];
22257
22443
  if (!step || step.kind !== "gate") return void 0;
22258
22444
  return envelope.gates.definitions[step.gate]?.kind;
22259
- }
22445
+ },
22446
+ projectLimits: envelope.projectLimits
22260
22447
  } : {});
22261
22448
  if (envelope) verifyVnextGateEvidence(context.eventStore, run, envelope, events, state);
22262
22449
  assertStoredProjection(context, run);
@@ -22366,10 +22553,17 @@ function cancelVnextRun(context, runId, options = {}) {
22366
22553
  };
22367
22554
  const cancelReason = options.reason ?? "operator_cancel";
22368
22555
  const activeAttempt = Boolean(folded.currentStep?.attemptId) || vnextFoldPanelAttemptIds(folded.currentStep).length > 0;
22369
- push("run.cancel_requested", {
22556
+ const cancelPayload = {
22370
22557
  actor: { kind: "runtime", id: context.homeRuntimeId },
22371
22558
  reason: cancelReason
22372
- });
22559
+ };
22560
+ if (cancelReason === "budget_run_duration") {
22561
+ if (!options.budget) {
22562
+ throw runtimeError("run_events_illegal", runId, "budget_run_duration requires a budget payload");
22563
+ }
22564
+ cancelPayload.budget = options.budget;
22565
+ }
22566
+ push("run.cancel_requested", cancelPayload);
22373
22567
  let status = "cancelled";
22374
22568
  if (folded.status === "running" && activeAttempt) {
22375
22569
  status = "cancelling";
@@ -23746,7 +23940,7 @@ function recordGateNoStartInTransaction(context, run, envelope, stepId, observat
23746
23940
  const cancelled = observation.stopCause === "cancel";
23747
23941
  const now = (/* @__PURE__ */ new Date()).toISOString();
23748
23942
  const seq = sequencer(context, run, now);
23749
- if (cancelled) ensureOperatorCancel(seq, ids.state, run);
23943
+ const cancelReason = cancelled ? ensureOperatorCancel(seq, ids.state, run, context) : void 0;
23750
23944
  const observationId = newVnextObservationId();
23751
23945
  const observed = seq.push("effect.observed", {
23752
23946
  effect: { id: ids.effectId, policy: { class: ids.gateKind === "artifacts-exist" ? "read-only" : "unknown", sharedMutable: false } },
@@ -23778,7 +23972,7 @@ function recordGateNoStartInTransaction(context, run, envelope, stepId, observat
23778
23972
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
23779
23973
  seq.push("assignment.terminal", { assignmentId: ids.assignmentId, outcome: "cancelled", status: "terminal" });
23780
23974
  seq.push("step.status_changed", { stepId, status: "cancelled", previousStatus: "running" });
23781
- seq.push("run.status_changed", { status: "cancelled", reason: "operator_cancel", stepId });
23975
+ seq.push("run.status_changed", { status: "cancelled", reason: cancelReason ?? "operator_cancel", stepId });
23782
23976
  } else {
23783
23977
  seq.push("assignment.result_recorded", { assignmentId: ids.assignmentId, resultClass: "producer_rejected", status: "result_recorded" });
23784
23978
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
@@ -23832,7 +24026,7 @@ function recordGateCancelObservedInTransaction(context, run, envelope, stepId, o
23832
24026
  }
23833
24027
  const now = (/* @__PURE__ */ new Date()).toISOString();
23834
24028
  const seq = sequencer(context, run, now);
23835
- ensureOperatorCancel(seq, ids.state, run);
24029
+ const cancelReason = ensureOperatorCancel(seq, ids.state, run, context);
23836
24030
  if (ids.gateKind === "artifacts-exist") {
23837
24031
  seq.push("assignment.executing", { assignmentId: ids.assignmentId, stepId, stepAttempt: ids.stepAttempt, attemptId: ids.attemptId, status: "executing" });
23838
24032
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, assignmentId: ids.assignmentId, stepId, stepAttempt: ids.stepAttempt, status: "executing" });
@@ -23875,7 +24069,7 @@ function recordGateCancelObservedInTransaction(context, run, envelope, stepId, o
23875
24069
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
23876
24070
  seq.push("assignment.terminal", { assignmentId: ids.assignmentId, outcome: "cancelled", status: "terminal" });
23877
24071
  seq.push("step.status_changed", { stepId, status: "cancelled", previousStatus: "running" });
23878
- seq.push("run.status_changed", { status: "cancelled", reason: "operator_cancel", stepId });
24072
+ seq.push("run.status_changed", { status: "cancelled", reason: cancelReason, stepId });
23879
24073
  for (const event of seq.events) context.eventStore.appendEvent(event);
23880
24074
  context.eventStore.insertGateObservation(observationRow);
23881
24075
  context.eventStore.settleCapability(ids.attemptId, "settled");
@@ -23960,8 +24154,8 @@ function requireIntent(context, run, envelope, stepId) {
23960
24154
  state: folded
23961
24155
  };
23962
24156
  }
23963
- function ensureOperatorCancel(seq, state, run) {
23964
- if (state.status === "cancelling") return;
24157
+ function ensureOperatorCancel(seq, state, run, context) {
24158
+ if (state.status === "cancelling") return cancelReasonFromLog(context, run.runId);
23965
24159
  if (state.status !== "running") {
23966
24160
  throw runtimeError("run_events_illegal", run.runId, "cancelled gate proof requires a running or cancelling run");
23967
24161
  }
@@ -23970,6 +24164,17 @@ function ensureOperatorCancel(seq, state, run) {
23970
24164
  reason: "operator_cancel"
23971
24165
  });
23972
24166
  seq.push("run.status_changed", { status: "cancelling", reason: "operator_cancel" });
24167
+ return "operator_cancel";
24168
+ }
24169
+ function cancelReasonFromLog(context, runId) {
24170
+ const events = context.eventStore.events(runId, 0, 1e6);
24171
+ for (let index = events.length - 1; index >= 0; index -= 1) {
24172
+ const event = events[index];
24173
+ if (event.eventType === "run.cancel_requested" && typeof event.payload.reason === "string") {
24174
+ return event.payload.reason;
24175
+ }
24176
+ }
24177
+ return "operator_cancel";
23973
24178
  }
23974
24179
  function sequencer(context, run, now) {
23975
24180
  let sequence = context.eventStore.nextSequence(run.runId);
@@ -24308,6 +24513,8 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
24308
24513
  }
24309
24514
  let latest = { state: foldStoredVnextRun(context, requireRun(context, runId)) };
24310
24515
  while (latest.state.status === "running") {
24516
+ const overBudget = cancelRunDurationIfExceeded(context, runId);
24517
+ if (overBudget) return overBudget;
24311
24518
  const before = context.eventStore.runState(runId)?.lastSequence;
24312
24519
  latest = await stepLocked(context, runId, producer, token);
24313
24520
  if (latest.handoff) return latest;
@@ -24323,6 +24530,111 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
24323
24530
  function newDriveId(runId, token, runtimeId, monotonicNs) {
24324
24531
  return `drv_${createHash11("sha256").update(`${runId}\0${token}\0${runtimeId}\0${monotonicNs}`, "utf8").digest("hex").slice(0, 24)}`;
24325
24532
  }
24533
+ function driveErrorSummary(error) {
24534
+ const raw = error instanceof VnextConfigError ? error.issues[0]?.code : void 0;
24535
+ const className = raw && /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/.test(raw) ? raw : "drive-failure";
24536
+ return { class: className, component: "vnext-engine", retryable: false };
24537
+ }
24538
+ function receiptHandoff(handoff) {
24539
+ return {
24540
+ reason: handoff.reason,
24541
+ detail: handoff.detail,
24542
+ ...handoff.field !== void 0 ? { field: handoff.field } : {},
24543
+ ...handoff.stepId !== void 0 ? { stepId: handoff.stepId } : {}
24544
+ };
24545
+ }
24546
+ function appendDriveOpened(context, runId, driveId, mode) {
24547
+ return context.eventStore.transaction(() => {
24548
+ const run = requireRun(context, runId);
24549
+ const now = (/* @__PURE__ */ new Date()).toISOString();
24550
+ const sequence = context.eventStore.nextSequence(runId);
24551
+ const event = {
24552
+ ...vnextEventBase(context, run, now, vnextMonotonicNs()),
24553
+ eventId: newVnextEventId(),
24554
+ eventType: "run.drive_opened",
24555
+ sequence,
24556
+ payload: { driveId, mode }
24557
+ };
24558
+ context.eventStore.appendEvent(event);
24559
+ const next = foldStoredVnextRun(context, run);
24560
+ persistVnextRunState(context, runId, next, sequence);
24561
+ return { sequence, occurredAt: now };
24562
+ });
24563
+ }
24564
+ function recordDriveReceipt(context, session, closeInfo) {
24565
+ if (isVnextRuntimeContextClosed(context)) return;
24566
+ try {
24567
+ const run = context.eventStore.run(session.runId);
24568
+ if (!run) return;
24569
+ const state = foldStoredVnextRun(context, run);
24570
+ const events = context.eventStore.events(session.runId, 0, 1e6);
24571
+ if (events.length === 0) return;
24572
+ const opened = state.drive;
24573
+ 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);
24574
+ const last = events[events.length - 1];
24575
+ const openedSequence = opened?.openedSequence ?? openedEvent?.sequence;
24576
+ if (openedSequence === void 0) return;
24577
+ const closedAt = (/* @__PURE__ */ new Date()).toISOString();
24578
+ const receipt = {
24579
+ schema: VNEXT_DRIVE_RECEIPT_SCHEMA,
24580
+ driveId: session.driveId,
24581
+ runId: session.runId,
24582
+ projectId: run.projectId,
24583
+ homeRuntimeId: session.homeRuntimeId,
24584
+ mode: session.mode,
24585
+ openedAt: openedEvent?.occurredAt ?? session.openedAt,
24586
+ openedSequence,
24587
+ closedAt,
24588
+ lastSequence: last.sequence,
24589
+ logHash: hashVnextDriveLog(events.filter((event) => event.sequence >= 1 && event.sequence <= last.sequence)),
24590
+ settlement: {
24591
+ kind: closeInfo.kind,
24592
+ status: state.status,
24593
+ reason: closeInfo.reason ?? state.terminalReason ?? "",
24594
+ ...closeInfo.kind === "handoff" && closeInfo.handoff ? { handoff: receiptHandoff(closeInfo.handoff) } : {},
24595
+ ...closeInfo.error !== void 0 ? { error: closeInfo.error } : {}
24596
+ },
24597
+ budget: driveReceiptBudget(context, run.runId, state, events, closedAt),
24598
+ producer: { id: closeInfo.producerId, closed: closeInfo.producerClosed }
24599
+ };
24600
+ context.eventStore.insertDriveReceipt(receipt);
24601
+ } catch {
24602
+ }
24603
+ }
24604
+ function vnextDrivePollProjection(context, runId, state) {
24605
+ if (!state.drive) return void 0;
24606
+ const events = context.eventStore.events(runId, 0, 1e6);
24607
+ const openedEvent = events.find((event) => event.sequence === state.drive.openedSequence);
24608
+ let receipt = null;
24609
+ let unreadable = false;
24610
+ try {
24611
+ receipt = context.eventStore.driveReceipt(state.drive.driveId) ?? null;
24612
+ } catch {
24613
+ unreadable = true;
24614
+ }
24615
+ const projection = {
24616
+ driveId: state.drive.driveId,
24617
+ mode: state.drive.mode,
24618
+ openedAt: openedEvent?.occurredAt ?? "",
24619
+ receipt: unreadable ? null : receipt,
24620
+ verified: false
24621
+ };
24622
+ if (unreadable) {
24623
+ projection.divergence = "receipt unreadable";
24624
+ return projection;
24625
+ }
24626
+ if (!receipt) {
24627
+ projection.divergence = "no receipt";
24628
+ return projection;
24629
+ }
24630
+ const checked = verifyVnextDriveReceipt(receipt, events, state.status, {
24631
+ runId,
24632
+ driveId: state.drive.driveId
24633
+ });
24634
+ projection.verified = checked.verified;
24635
+ if (checked.divergence !== void 0) projection.divergence = checked.divergence;
24636
+ return projection;
24637
+ }
24326
24638
  function inflightAttemptId(state) {
24327
24639
  const leftover = unreconciledPanelAttemptId(state);
24328
24640
  if (leftover) return leftover;
@@ -24470,25 +24782,50 @@ var VnextRunScheduler = class _VnextRunScheduler {
24470
24782
  throw error;
24471
24783
  }
24472
24784
  const driveId = newDriveId(runId, token, this.context.homeRuntimeId, vnextMonotonicNs());
24785
+ const openedMeta = appendDriveOpened(this.context, runId, driveId, options.mode);
24786
+ const startedState = foldStoredVnextRun(this.context, requireRun(this.context, runId));
24787
+ const deadlineAt = driveDeadlineAt(this.context, runId, startedState);
24473
24788
  const session = {
24474
24789
  driveId,
24475
24790
  runId,
24476
24791
  token,
24477
24792
  homeRuntimeId: this.context.homeRuntimeId,
24478
24793
  mode: options.mode,
24479
- openedAt: (/* @__PURE__ */ new Date()).toISOString(),
24794
+ openedAt: openedMeta.occurredAt,
24795
+ producerId: producer.id,
24480
24796
  controller: new AbortController(),
24481
- settled
24797
+ settled,
24798
+ ...deadlineAt !== void 0 ? { deadlineAt } : {}
24482
24799
  };
24483
24800
  attachVnextDriveSession(this.context.eventStore.path, runId, token, session);
24484
24801
  opened = true;
24485
24802
  resolveOpen({ driveId, settled });
24486
24803
  try {
24487
24804
  const result = await driveAdmitted(this.context, runId, producer, token, driveOptions);
24805
+ const kind = result.handoff ? "handoff" : isTerminalRunStatus(result.state.status) ? "terminal" : "unsettled";
24806
+ recordDriveReceipt(this.context, session, {
24807
+ kind,
24808
+ ...result.state.terminalReason !== void 0 ? { reason: result.state.terminalReason } : result.handoff ? { reason: result.handoff.reason } : {},
24809
+ ...result.handoff ? { handoff: result.handoff } : {},
24810
+ producerId: producer.id,
24811
+ producerClosed: false
24812
+ });
24488
24813
  pending.resolve(result);
24489
24814
  return result;
24490
24815
  } catch (error) {
24491
24816
  recordBareDriveFailure(this.context, runId);
24817
+ let foldedStatus;
24818
+ try {
24819
+ foldedStatus = foldStoredVnextRun(this.context, requireRun(this.context, runId)).status;
24820
+ } catch {
24821
+ foldedStatus = void 0;
24822
+ }
24823
+ recordDriveReceipt(this.context, session, {
24824
+ kind: foldedStatus !== void 0 && isTerminalRunStatus(foldedStatus) ? "terminal" : "unsettled",
24825
+ error: driveErrorSummary(error),
24826
+ producerId: producer.id,
24827
+ producerClosed: false
24828
+ });
24492
24829
  pending.reject(error);
24493
24830
  throw error;
24494
24831
  }
@@ -24537,11 +24874,13 @@ async function stepLocked(context, runId, producer, token) {
24537
24874
  throw runtimeError("run_events_illegal", prepared.run.runId, "prepared gate is not artifacts-exist");
24538
24875
  }
24539
24876
  registerVnextAttemptController(context.eventStore.path, runId, { attemptId: prepared.attemptId, controller: prepared.controller });
24877
+ const clearBudget = armRunDurationBudgetTimer(context, runId);
24540
24878
  try {
24541
24879
  const observation = evaluateArtifactsGate(context, definition);
24542
24880
  vnextGateDispatchSeams.afterEvaluate?.(prepared);
24543
24881
  return context.eventStore.transaction(() => settlePreparedGate(context, prepared, observation));
24544
24882
  } finally {
24883
+ clearBudget();
24545
24884
  unregisterVnextAttemptController(context.eventStore.path, runId, prepared.attemptId);
24546
24885
  }
24547
24886
  }
@@ -24572,6 +24911,7 @@ async function runPreparedCommandGate(context, prepared, definition, token) {
24572
24911
  });
24573
24912
  armVnextGateHold(storePath, prepared.run.runId, token, prepared.attemptId, () => observer.requestStop("cancel"));
24574
24913
  registerVnextAttemptController(storePath, prepared.run.runId, { attemptId: prepared.attemptId, controller: prepared.controller });
24914
+ const clearBudget = armRunDurationBudgetTimer(context, prepared.run.runId);
24575
24915
  const unhookClose = registerVnextRuntimeCloseHook(context, () => {
24576
24916
  try {
24577
24917
  markVnextGateHoldUnsettled(storePath, prepared.run.runId, token, prepared.attemptId);
@@ -24612,6 +24952,7 @@ async function runPreparedCommandGate(context, prepared, definition, token) {
24612
24952
  return commitCommandUncertainty(context, prepared, token, outcome.reason, outcome.observation);
24613
24953
  } finally {
24614
24954
  unhookClose();
24955
+ clearBudget();
24615
24956
  unregisterVnextAttemptController(storePath, prepared.run.runId, prepared.attemptId);
24616
24957
  }
24617
24958
  }
@@ -25237,8 +25578,10 @@ async function drivePanel(context, panel, producer) {
25237
25578
  const pending = /* @__PURE__ */ new Map();
25238
25579
  let stopBirths = false;
25239
25580
  let settlementFailed = false;
25581
+ const budgetClears = /* @__PURE__ */ new Map();
25240
25582
  const register = (member) => {
25241
25583
  registerVnextAttemptController(context.eventStore.path, runId, { attemptId: member.attemptId, controller: member.controller });
25584
+ budgetClears.set(member.attemptId, armRunDurationBudgetTimer(context, runId));
25242
25585
  owned.set(member.attemptId, member);
25243
25586
  };
25244
25587
  const abortOwned = () => {
@@ -25421,6 +25764,7 @@ async function drivePanel(context, panel, producer) {
25421
25764
  throw error;
25422
25765
  } finally {
25423
25766
  for (const attemptId of owned.keys()) {
25767
+ budgetClears.get(attemptId)?.();
25424
25768
  unregisterVnextAttemptController(context.eventStore.path, runId, attemptId);
25425
25769
  }
25426
25770
  }
@@ -25600,7 +25944,7 @@ function joinPanel(context, panel) {
25600
25944
  };
25601
25945
  const cancelRun = () => {
25602
25946
  push("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
25603
- push("run.status_changed", { status: "cancelled", reason: "operator_cancel" });
25947
+ push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
25604
25948
  for (const event of events) context.eventStore.appendEvent(event);
25605
25949
  const next2 = foldStoredVnextRun(context, run);
25606
25950
  persistVnextRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -25707,16 +26051,124 @@ function transitionBudgetFailure(plan, state, fromStepId, outcome) {
25707
26051
  }
25708
26052
  return void 0;
25709
26053
  }
25710
- function unsupportedLimit(envelope) {
25711
- if (envelope.plan.limits.maxRunDurationMs !== void 0) {
25712
- return { reason: "limit_unsupported", field: "limits.maxRunDurationMs", detail: "duration budget enforcement is not available in this slice" };
26054
+ var MAX_TIMER_DELAY_MS = 2147483647;
26055
+ function elapsedMsBetween(fromIso, toIso) {
26056
+ const from = Date.parse(fromIso);
26057
+ const to = Date.parse(toIso);
26058
+ if (!Number.isFinite(from) || !Number.isFinite(to)) return 0;
26059
+ return Math.max(0, Math.trunc(to - from));
26060
+ }
26061
+ function declaredRunDurationBudget(context, runId) {
26062
+ const run = context.eventStore.run(runId);
26063
+ if (!run) return void 0;
26064
+ try {
26065
+ const envelope = loadVnextRunPlanEnvelope(context.eventStore, run);
26066
+ return effectiveRunDurationBudget(envelope.plan.limits, envelope.projectLimits);
26067
+ } catch {
26068
+ return void 0;
25713
26069
  }
26070
+ }
26071
+ function runDurationOverrunPayload(context, runId, nowIso2 = (/* @__PURE__ */ new Date()).toISOString()) {
26072
+ const declared = declaredRunDurationBudget(context, runId);
26073
+ if (!declared) return void 0;
26074
+ const run = context.eventStore.run(runId);
26075
+ if (!run) return void 0;
26076
+ const state = foldStoredVnextRun(context, run);
26077
+ if (!state.runningSince) return void 0;
26078
+ if (isTerminalRunStatus(state.status) || state.status === "cancelling") return void 0;
26079
+ const elapsedMs = elapsedMsBetween(state.runningSince, nowIso2);
26080
+ if (elapsedMs < declared.budgetMs) return void 0;
26081
+ return { budgetMs: declared.budgetMs, elapsedMs, source: declared.source };
26082
+ }
26083
+ function cancelRunDurationIfExceeded(context, runId) {
26084
+ if (isVnextRuntimeContextClosed(context)) return void 0;
26085
+ const payload = runDurationOverrunPayload(context, runId);
26086
+ if (!payload) return void 0;
26087
+ cancelVnextRun(context, runId, { reason: "budget_run_duration", budget: payload });
26088
+ return { state: foldStoredVnextRun(context, requireRun(context, runId)) };
26089
+ }
26090
+ function driveDeadlineAt(context, runId, state) {
26091
+ const declared = declaredRunDurationBudget(context, runId);
26092
+ if (!declared || !state.runningSince) return void 0;
26093
+ const start = Date.parse(state.runningSince);
26094
+ if (!Number.isFinite(start)) return void 0;
26095
+ return new Date(start + declared.budgetMs).toISOString();
26096
+ }
26097
+ function driveReceiptBudget(context, runId, state, events, closedAt) {
26098
+ const declared = declaredRunDurationBudget(context, runId);
26099
+ if (!declared) return null;
26100
+ const elapsedMs = state.runningSince ? elapsedMsBetween(state.runningSince, closedAt) : 0;
26101
+ const overrun = events.some((event) => event.eventType === "run.cancel_requested" && event.payload.reason === "budget_run_duration");
26102
+ return {
26103
+ budgetMs: declared.budgetMs,
26104
+ source: declared.source,
26105
+ elapsedMs,
26106
+ overrun
26107
+ };
26108
+ }
26109
+ function cancelReasonFromLog2(context, runId) {
26110
+ const events = context.eventStore.events(runId, 0, 1e6);
26111
+ for (let index = events.length - 1; index >= 0; index -= 1) {
26112
+ const event = events[index];
26113
+ if (event.eventType === "run.cancel_requested" && typeof event.payload.reason === "string") {
26114
+ return event.payload.reason;
26115
+ }
26116
+ }
26117
+ return "operator_cancel";
26118
+ }
26119
+ function armRunDurationBudgetTimer(context, runId) {
26120
+ const declared = declaredRunDurationBudget(context, runId);
26121
+ if (!declared) return () => void 0;
26122
+ const run = context.eventStore.run(runId);
26123
+ if (!run) return () => void 0;
26124
+ const state = foldStoredVnextRun(context, run);
26125
+ if (!state.runningSince) return () => void 0;
26126
+ const startMs = Date.parse(state.runningSince);
26127
+ if (!Number.isFinite(startMs)) return () => void 0;
26128
+ const deadlineMs = startMs + declared.budgetMs;
26129
+ let timer;
26130
+ let cleared = false;
26131
+ const fire = () => {
26132
+ timer = void 0;
26133
+ if (cleared || isVnextRuntimeContextClosed(context)) return;
26134
+ const nowIso2 = (/* @__PURE__ */ new Date()).toISOString();
26135
+ const elapsedMs = elapsedMsBetween(state.runningSince, nowIso2);
26136
+ if (elapsedMs < declared.budgetMs) {
26137
+ arm(declared.budgetMs - elapsedMs);
26138
+ return;
26139
+ }
26140
+ try {
26141
+ cancelVnextRun(context, runId, {
26142
+ reason: "budget_run_duration",
26143
+ budget: { budgetMs: declared.budgetMs, elapsedMs, source: declared.source }
26144
+ });
26145
+ } catch {
26146
+ }
26147
+ };
26148
+ const arm = (remaining) => {
26149
+ if (cleared) return;
26150
+ const delay = Math.min(Math.max(0, remaining), MAX_TIMER_DELAY_MS);
26151
+ timer = setTimeout(fire, delay);
26152
+ timer.unref();
26153
+ };
26154
+ const unhook = registerVnextRuntimeCloseHook(context, () => {
26155
+ cleared = true;
26156
+ if (timer !== void 0) clearTimeout(timer);
26157
+ timer = void 0;
26158
+ });
26159
+ arm(deadlineMs - Date.now());
26160
+ return () => {
26161
+ if (cleared) return;
26162
+ cleared = true;
26163
+ if (timer !== void 0) clearTimeout(timer);
26164
+ timer = void 0;
26165
+ unhook();
26166
+ };
26167
+ }
26168
+ function unsupportedLimit(envelope) {
25714
26169
  if (envelope.plan.limits.maxAgentTimeMs !== void 0) {
25715
26170
  return { reason: "limit_unsupported", field: "limits.maxAgentTimeMs", detail: "agent-time budget enforcement is not available in this slice" };
25716
26171
  }
25717
- if (envelope.projectLimits.maxRunDurationMs !== void 0) {
25718
- return { reason: "limit_unsupported", field: "project.limits.maxRunDurationMs", detail: "duration budget enforcement is not available in this slice" };
25719
- }
25720
26172
  if (envelope.projectLimits.maxAgentTimeMs !== void 0) {
25721
26173
  return { reason: "limit_unsupported", field: "project.limits.maxAgentTimeMs", detail: "agent-time budget enforcement is not available in this slice" };
25722
26174
  }
@@ -26732,6 +27184,19 @@ async function waitForDriveSessions(settled, graceMs) {
26732
27184
  if (timeout !== void 0) clearTimeout(timeout);
26733
27185
  }
26734
27186
  }
27187
+ async function driveSessionStillPending(settled) {
27188
+ let pending = true;
27189
+ void settled.then(
27190
+ () => {
27191
+ pending = false;
27192
+ },
27193
+ () => {
27194
+ pending = false;
27195
+ }
27196
+ );
27197
+ await Promise.resolve();
27198
+ return pending;
27199
+ }
26735
27200
  async function startVnextRuntimeSupervisor(options = {}) {
26736
27201
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
26737
27202
  const paths = vnextRuntimePaths(options.stateRoot !== void 0 ? { stateRoot: options.stateRoot } : {});
@@ -26835,7 +27300,9 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26835
27300
  const bundle = loadVnextProject(projectRoot, {});
26836
27301
  if (request.method === "GET" && !sub) {
26837
27302
  const projected = rebuildVnextRunProjection(context, runId);
26838
- sendJson(response, 200, { ok: true, run: projected });
27303
+ const folded = foldStoredVnextRun(context, projected);
27304
+ const drive = vnextDrivePollProjection(context, runId, folded);
27305
+ sendJson(response, 200, { ok: true, run: projected, ...drive !== void 0 ? { drive } : {} });
26839
27306
  return;
26840
27307
  }
26841
27308
  if (request.method === "POST" && sub === "drive") {
@@ -26878,7 +27345,7 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26878
27345
  const scheduler = VnextRunScheduler.for(context, bundle);
26879
27346
  const opening = scheduler.openDriveSession(runId, {
26880
27347
  mode: body.mode,
26881
- allowLimits: true,
27348
+ allowLimits: false,
26882
27349
  liveMode: body.mode === "live",
26883
27350
  createProducer
26884
27351
  });
@@ -27052,6 +27519,15 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
27052
27519
  }
27053
27520
  }
27054
27521
  await waitForDriveSessions(openSessions.map(({ session }) => session.settled), runtimeStopGraceMs());
27522
+ for (const { context, session } of openSessions) {
27523
+ if (!await driveSessionStillPending(session.settled)) continue;
27524
+ recordDriveReceipt(context, session, {
27525
+ kind: "unsettled",
27526
+ reason: "runtime_shutdown_grace_expired",
27527
+ producerId: session.producerId,
27528
+ producerClosed: false
27529
+ });
27530
+ }
27055
27531
  for (const context of contexts.values()) closeVnextRuntimeContext(context);
27056
27532
  contexts.clear();
27057
27533
  const closed = new Promise((resolveStop) => server.close(() => resolveStop()));
@@ -29382,6 +29858,7 @@ export {
29382
29858
  DEFAULT_RUNTIME_STOP_GRACE_MS,
29383
29859
  DEFAULT_SOCKET_DIR,
29384
29860
  DEFAULT_SUBAGENT_MODELS,
29861
+ DRIVE_RECEIPT_MAX_BYTES,
29385
29862
  IMPROVEMENT_REPORT_SCHEMA,
29386
29863
  IMPROVEMENT_REPORT_V1_SCHEMA,
29387
29864
  LOG_LEVEL_PRIORITY,
@@ -29398,6 +29875,7 @@ export {
29398
29875
  SubagentManager,
29399
29876
  VIEWPORT_PRESETS,
29400
29877
  VNEXT_ABSENT_MEMORY_REVISION,
29878
+ VNEXT_DRIVE_RECEIPT_SCHEMA,
29401
29879
  VNEXT_EVENT_STORE_SCHEMA_VERSION,
29402
29880
  VNEXT_REGISTRY_SCHEMA_VERSION,
29403
29881
  VNEXT_RUN_EVENT_SCHEMA,
@@ -29452,6 +29930,7 @@ export {
29452
29930
  groupRoutingRecords,
29453
29931
  harnessCommandCandidates,
29454
29932
  harnessSpawnUsesShell,
29933
+ hashVnextDriveLog,
29455
29934
  hashVnextSupervisorToken,
29456
29935
  hashVnextTokenProof,
29457
29936
  isKnownHarnessId,
@@ -29511,6 +29990,7 @@ export {
29511
29990
  userTables,
29512
29991
  validateHarnessModelPair,
29513
29992
  verifyExpectedTables,
29993
+ verifyVnextDriveReceipt,
29514
29994
  vnextDeclaredExecutorIds,
29515
29995
  vnextDeclaredRepositoryIds,
29516
29996
  vnextEventBase,