@kontextmind/kxm 0.7.24 → 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.
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.24",
14
+ "version": "0.7.25",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.24",
3
+ "version": "0.7.25",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "kxm",
4
4
  "displayName": "KXM",
5
- "version": "0.7.24",
5
+ "version": "0.7.25",
6
6
  "description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
7
7
  "author": {
8
8
  "name": "KontextMind",
@@ -33642,6 +33642,9 @@ ${RUN_ENGINE_NOTICE}`);
33642
33642
  return 1;
33643
33643
  }
33644
33644
  }
33645
+ function formatCancelledStatus(reason) {
33646
+ return reason.length > 0 ? `cancelled (${reason})` : "cancelled";
33647
+ }
33645
33648
  function formatDriveStatusLine(runStatus, drive) {
33646
33649
  if (!drive || typeof drive.driveId !== "string" || drive.driveId.length === 0) return void 0;
33647
33650
  const receipt = drive.receipt ?? null;
@@ -33659,11 +33662,20 @@ function formatDriveStatusLine(runStatus, drive) {
33659
33662
  if (kind === "handoff") {
33660
33663
  return drive.verified === true ? `drive ${drive.driveId}: handoff (receipt verified)` : `drive ${drive.driveId}: handoff`;
33661
33664
  }
33665
+ if (receipt.settlement?.status === "cancelled") {
33666
+ const label = formatCancelledStatus(reason);
33667
+ return drive.verified === true ? `drive ${drive.driveId}: ${label} (receipt verified)` : `drive ${drive.driveId}: ${label}`;
33668
+ }
33662
33669
  if (drive.verified === true) {
33663
33670
  return `drive ${drive.driveId}: completed (receipt verified)`;
33664
33671
  }
33665
33672
  return `drive ${drive.driveId}: completed`;
33666
33673
  }
33674
+ function formatRunStatusLine(run, drive) {
33675
+ const reason = typeof drive?.receipt?.settlement?.reason === "string" ? drive.receipt.settlement.reason : "";
33676
+ const statusLabel = run.status === "cancelled" ? formatCancelledStatus(reason) : run.status;
33677
+ return `run ${run.runId}: ${statusLabel} (workflow ${run.workflowId}, updated ${run.updatedAt})`;
33678
+ }
33667
33679
  async function cmdVnextRunStatus(runtime, runId) {
33668
33680
  try {
33669
33681
  const projectRoot = discoverVnextProjectRoot(runtime.cwd);
@@ -33680,7 +33692,7 @@ async function cmdVnextRunStatus(runtime, runId) {
33680
33692
  runtime.io,
33681
33693
  runtime.json,
33682
33694
  { ok: true, command: "runs status", run, ...drive !== void 0 ? { drive } : {} },
33683
- `run ${run.runId}: ${run.status} (workflow ${run.workflowId}, updated ${run.updatedAt})${driveLine ? `
33695
+ `${formatRunStatusLine(run, drive)}${driveLine ? `
33684
33696
  ${driveLine}` : ""}`
33685
33697
  );
33686
33698
  return 0;
@@ -17121,7 +17121,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17121
17121
  }
17122
17122
 
17123
17123
  // plugins/kxm/src/mcp-server.ts
17124
- var VERSION = "0.7.24";
17124
+ var VERSION = "0.7.25";
17125
17125
  var inbox = /* @__PURE__ */ new Map();
17126
17126
  var notifiedInbox = /* @__PURE__ */ new Set();
17127
17127
  var meshClient;
@@ -19397,6 +19397,16 @@ var ATTEMPT_EDGES = {
19397
19397
  executing: /* @__PURE__ */ new Set(["settling"]),
19398
19398
  settling: /* @__PURE__ */ new Set(["terminal"])
19399
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
+ }
19400
19410
  function emptyPanel() {
19401
19411
  return { order: [], assignments: /* @__PURE__ */ Object.create(null) };
19402
19412
  }
@@ -19628,7 +19638,7 @@ function foldVnextRunState(run, plan, events, options = {}) {
19628
19638
  foldRunStatus(state, plan, event);
19629
19639
  break;
19630
19640
  case "run.cancel_requested":
19631
- foldCancelRequested(state, event);
19641
+ foldCancelRequested(state, event, plan, options);
19632
19642
  break;
19633
19643
  case "run.drive_opened":
19634
19644
  foldDriveOpened(state, event);
@@ -19757,6 +19767,9 @@ function foldRunStatus(state, plan, event) {
19757
19767
  if ((status === "running" || status === "cancelling") && !plan) {
19758
19768
  throw runtimeError("run_plan_missing", state.runId, `status ${status} requires a pinned run plan`);
19759
19769
  }
19770
+ if (status === "running" && state.runningSince === void 0) {
19771
+ state.runningSince = event.occurredAt;
19772
+ }
19760
19773
  if (TERMINAL_RUN.has(status)) {
19761
19774
  assertTerminalRunStatus(state, plan, status, event);
19762
19775
  if (typeof event.payload.reason === "string") state.terminalReason = event.payload.reason;
@@ -19855,10 +19868,36 @@ function foldDriveOpened(state, event) {
19855
19868
  }
19856
19869
  state.drive = { driveId, mode, openedSequence: event.sequence };
19857
19870
  }
19858
- function foldCancelRequested(state, event) {
19871
+ function foldCancelRequested(state, event, plan, options) {
19859
19872
  if (state.cancelRequested || TERMINAL_RUN.has(state.status)) {
19860
19873
  throw runtimeError("run_events_illegal", state.runId, "duplicate run.cancel_requested is not legal");
19861
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
+ }
19862
19901
  state.cancelRequested = true;
19863
19902
  if (event.commandId) state.cancelCommandId = event.commandId;
19864
19903
  }
@@ -20504,7 +20543,8 @@ function freezeState(state) {
20504
20543
  cancelRequested: state.cancelRequested,
20505
20544
  ...state.terminalReason !== void 0 ? { terminalReason: state.terminalReason } : {},
20506
20545
  ...state.terminalReason !== void 0 && state.status === "failed" ? { failureReason: state.terminalReason } : {},
20507
- ...state.drive !== void 0 ? { drive: Object.freeze({ ...state.drive }) } : {}
20546
+ ...state.drive !== void 0 ? { drive: Object.freeze({ ...state.drive }) } : {},
20547
+ ...state.runningSince !== void 0 ? { runningSince: state.runningSince } : {}
20508
20548
  };
20509
20549
  return Object.freeze(frozen);
20510
20550
  }
@@ -22402,7 +22442,8 @@ function foldStoredVnextRun(context, run) {
22402
22442
  const step = envelope.plan.steps[stepId];
22403
22443
  if (!step || step.kind !== "gate") return void 0;
22404
22444
  return envelope.gates.definitions[step.gate]?.kind;
22405
- }
22445
+ },
22446
+ projectLimits: envelope.projectLimits
22406
22447
  } : {});
22407
22448
  if (envelope) verifyVnextGateEvidence(context.eventStore, run, envelope, events, state);
22408
22449
  assertStoredProjection(context, run);
@@ -22512,10 +22553,17 @@ function cancelVnextRun(context, runId, options = {}) {
22512
22553
  };
22513
22554
  const cancelReason = options.reason ?? "operator_cancel";
22514
22555
  const activeAttempt = Boolean(folded.currentStep?.attemptId) || vnextFoldPanelAttemptIds(folded.currentStep).length > 0;
22515
- push("run.cancel_requested", {
22556
+ const cancelPayload = {
22516
22557
  actor: { kind: "runtime", id: context.homeRuntimeId },
22517
22558
  reason: cancelReason
22518
- });
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);
22519
22567
  let status = "cancelled";
22520
22568
  if (folded.status === "running" && activeAttempt) {
22521
22569
  status = "cancelling";
@@ -23892,7 +23940,7 @@ function recordGateNoStartInTransaction(context, run, envelope, stepId, observat
23892
23940
  const cancelled = observation.stopCause === "cancel";
23893
23941
  const now = (/* @__PURE__ */ new Date()).toISOString();
23894
23942
  const seq = sequencer(context, run, now);
23895
- if (cancelled) ensureOperatorCancel(seq, ids.state, run);
23943
+ const cancelReason = cancelled ? ensureOperatorCancel(seq, ids.state, run, context) : void 0;
23896
23944
  const observationId = newVnextObservationId();
23897
23945
  const observed = seq.push("effect.observed", {
23898
23946
  effect: { id: ids.effectId, policy: { class: ids.gateKind === "artifacts-exist" ? "read-only" : "unknown", sharedMutable: false } },
@@ -23924,7 +23972,7 @@ function recordGateNoStartInTransaction(context, run, envelope, stepId, observat
23924
23972
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
23925
23973
  seq.push("assignment.terminal", { assignmentId: ids.assignmentId, outcome: "cancelled", status: "terminal" });
23926
23974
  seq.push("step.status_changed", { stepId, status: "cancelled", previousStatus: "running" });
23927
- seq.push("run.status_changed", { status: "cancelled", reason: "operator_cancel", stepId });
23975
+ seq.push("run.status_changed", { status: "cancelled", reason: cancelReason ?? "operator_cancel", stepId });
23928
23976
  } else {
23929
23977
  seq.push("assignment.result_recorded", { assignmentId: ids.assignmentId, resultClass: "producer_rejected", status: "result_recorded" });
23930
23978
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
@@ -23978,7 +24026,7 @@ function recordGateCancelObservedInTransaction(context, run, envelope, stepId, o
23978
24026
  }
23979
24027
  const now = (/* @__PURE__ */ new Date()).toISOString();
23980
24028
  const seq = sequencer(context, run, now);
23981
- ensureOperatorCancel(seq, ids.state, run);
24029
+ const cancelReason = ensureOperatorCancel(seq, ids.state, run, context);
23982
24030
  if (ids.gateKind === "artifacts-exist") {
23983
24031
  seq.push("assignment.executing", { assignmentId: ids.assignmentId, stepId, stepAttempt: ids.stepAttempt, attemptId: ids.attemptId, status: "executing" });
23984
24032
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, assignmentId: ids.assignmentId, stepId, stepAttempt: ids.stepAttempt, status: "executing" });
@@ -24021,7 +24069,7 @@ function recordGateCancelObservedInTransaction(context, run, envelope, stepId, o
24021
24069
  seq.push("attempt.status_changed", { attemptId: ids.attemptId, status: "terminal" });
24022
24070
  seq.push("assignment.terminal", { assignmentId: ids.assignmentId, outcome: "cancelled", status: "terminal" });
24023
24071
  seq.push("step.status_changed", { stepId, status: "cancelled", previousStatus: "running" });
24024
- seq.push("run.status_changed", { status: "cancelled", reason: "operator_cancel", stepId });
24072
+ seq.push("run.status_changed", { status: "cancelled", reason: cancelReason, stepId });
24025
24073
  for (const event of seq.events) context.eventStore.appendEvent(event);
24026
24074
  context.eventStore.insertGateObservation(observationRow);
24027
24075
  context.eventStore.settleCapability(ids.attemptId, "settled");
@@ -24106,8 +24154,8 @@ function requireIntent(context, run, envelope, stepId) {
24106
24154
  state: folded
24107
24155
  };
24108
24156
  }
24109
- function ensureOperatorCancel(seq, state, run) {
24110
- if (state.status === "cancelling") return;
24157
+ function ensureOperatorCancel(seq, state, run, context) {
24158
+ if (state.status === "cancelling") return cancelReasonFromLog(context, run.runId);
24111
24159
  if (state.status !== "running") {
24112
24160
  throw runtimeError("run_events_illegal", run.runId, "cancelled gate proof requires a running or cancelling run");
24113
24161
  }
@@ -24116,6 +24164,17 @@ function ensureOperatorCancel(seq, state, run) {
24116
24164
  reason: "operator_cancel"
24117
24165
  });
24118
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";
24119
24178
  }
24120
24179
  function sequencer(context, run, now) {
24121
24180
  let sequence = context.eventStore.nextSequence(run.runId);
@@ -24454,6 +24513,8 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
24454
24513
  }
24455
24514
  let latest = { state: foldStoredVnextRun(context, requireRun(context, runId)) };
24456
24515
  while (latest.state.status === "running") {
24516
+ const overBudget = cancelRunDurationIfExceeded(context, runId);
24517
+ if (overBudget) return overBudget;
24457
24518
  const before = context.eventStore.runState(runId)?.lastSequence;
24458
24519
  latest = await stepLocked(context, runId, producer, token);
24459
24520
  if (latest.handoff) return latest;
@@ -24513,6 +24574,7 @@ function recordDriveReceipt(context, session, closeInfo) {
24513
24574
  const last = events[events.length - 1];
24514
24575
  const openedSequence = opened?.openedSequence ?? openedEvent?.sequence;
24515
24576
  if (openedSequence === void 0) return;
24577
+ const closedAt = (/* @__PURE__ */ new Date()).toISOString();
24516
24578
  const receipt = {
24517
24579
  schema: VNEXT_DRIVE_RECEIPT_SCHEMA,
24518
24580
  driveId: session.driveId,
@@ -24522,7 +24584,7 @@ function recordDriveReceipt(context, session, closeInfo) {
24522
24584
  mode: session.mode,
24523
24585
  openedAt: openedEvent?.occurredAt ?? session.openedAt,
24524
24586
  openedSequence,
24525
- closedAt: (/* @__PURE__ */ new Date()).toISOString(),
24587
+ closedAt,
24526
24588
  lastSequence: last.sequence,
24527
24589
  logHash: hashVnextDriveLog(events.filter((event) => event.sequence >= 1 && event.sequence <= last.sequence)),
24528
24590
  settlement: {
@@ -24532,7 +24594,7 @@ function recordDriveReceipt(context, session, closeInfo) {
24532
24594
  ...closeInfo.kind === "handoff" && closeInfo.handoff ? { handoff: receiptHandoff(closeInfo.handoff) } : {},
24533
24595
  ...closeInfo.error !== void 0 ? { error: closeInfo.error } : {}
24534
24596
  },
24535
- budget: null,
24597
+ budget: driveReceiptBudget(context, run.runId, state, events, closedAt),
24536
24598
  producer: { id: closeInfo.producerId, closed: closeInfo.producerClosed }
24537
24599
  };
24538
24600
  context.eventStore.insertDriveReceipt(receipt);
@@ -24721,6 +24783,8 @@ var VnextRunScheduler = class _VnextRunScheduler {
24721
24783
  }
24722
24784
  const driveId = newDriveId(runId, token, this.context.homeRuntimeId, vnextMonotonicNs());
24723
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);
24724
24788
  const session = {
24725
24789
  driveId,
24726
24790
  runId,
@@ -24730,7 +24794,8 @@ var VnextRunScheduler = class _VnextRunScheduler {
24730
24794
  openedAt: openedMeta.occurredAt,
24731
24795
  producerId: producer.id,
24732
24796
  controller: new AbortController(),
24733
- settled
24797
+ settled,
24798
+ ...deadlineAt !== void 0 ? { deadlineAt } : {}
24734
24799
  };
24735
24800
  attachVnextDriveSession(this.context.eventStore.path, runId, token, session);
24736
24801
  opened = true;
@@ -24809,11 +24874,13 @@ async function stepLocked(context, runId, producer, token) {
24809
24874
  throw runtimeError("run_events_illegal", prepared.run.runId, "prepared gate is not artifacts-exist");
24810
24875
  }
24811
24876
  registerVnextAttemptController(context.eventStore.path, runId, { attemptId: prepared.attemptId, controller: prepared.controller });
24877
+ const clearBudget = armRunDurationBudgetTimer(context, runId);
24812
24878
  try {
24813
24879
  const observation = evaluateArtifactsGate(context, definition);
24814
24880
  vnextGateDispatchSeams.afterEvaluate?.(prepared);
24815
24881
  return context.eventStore.transaction(() => settlePreparedGate(context, prepared, observation));
24816
24882
  } finally {
24883
+ clearBudget();
24817
24884
  unregisterVnextAttemptController(context.eventStore.path, runId, prepared.attemptId);
24818
24885
  }
24819
24886
  }
@@ -24844,6 +24911,7 @@ async function runPreparedCommandGate(context, prepared, definition, token) {
24844
24911
  });
24845
24912
  armVnextGateHold(storePath, prepared.run.runId, token, prepared.attemptId, () => observer.requestStop("cancel"));
24846
24913
  registerVnextAttemptController(storePath, prepared.run.runId, { attemptId: prepared.attemptId, controller: prepared.controller });
24914
+ const clearBudget = armRunDurationBudgetTimer(context, prepared.run.runId);
24847
24915
  const unhookClose = registerVnextRuntimeCloseHook(context, () => {
24848
24916
  try {
24849
24917
  markVnextGateHoldUnsettled(storePath, prepared.run.runId, token, prepared.attemptId);
@@ -24884,6 +24952,7 @@ async function runPreparedCommandGate(context, prepared, definition, token) {
24884
24952
  return commitCommandUncertainty(context, prepared, token, outcome.reason, outcome.observation);
24885
24953
  } finally {
24886
24954
  unhookClose();
24955
+ clearBudget();
24887
24956
  unregisterVnextAttemptController(storePath, prepared.run.runId, prepared.attemptId);
24888
24957
  }
24889
24958
  }
@@ -25509,8 +25578,10 @@ async function drivePanel(context, panel, producer) {
25509
25578
  const pending = /* @__PURE__ */ new Map();
25510
25579
  let stopBirths = false;
25511
25580
  let settlementFailed = false;
25581
+ const budgetClears = /* @__PURE__ */ new Map();
25512
25582
  const register = (member) => {
25513
25583
  registerVnextAttemptController(context.eventStore.path, runId, { attemptId: member.attemptId, controller: member.controller });
25584
+ budgetClears.set(member.attemptId, armRunDurationBudgetTimer(context, runId));
25514
25585
  owned.set(member.attemptId, member);
25515
25586
  };
25516
25587
  const abortOwned = () => {
@@ -25693,6 +25764,7 @@ async function drivePanel(context, panel, producer) {
25693
25764
  throw error;
25694
25765
  } finally {
25695
25766
  for (const attemptId of owned.keys()) {
25767
+ budgetClears.get(attemptId)?.();
25696
25768
  unregisterVnextAttemptController(context.eventStore.path, runId, attemptId);
25697
25769
  }
25698
25770
  }
@@ -25872,7 +25944,7 @@ function joinPanel(context, panel) {
25872
25944
  };
25873
25945
  const cancelRun = () => {
25874
25946
  push("step.status_changed", { stepId: panel.stepId, status: "cancelled", previousStatus: "running" });
25875
- push("run.status_changed", { status: "cancelled", reason: "operator_cancel" });
25947
+ push("run.status_changed", { status: "cancelled", reason: cancelReasonFromLog2(context, run.runId) });
25876
25948
  for (const event of events) context.eventStore.appendEvent(event);
25877
25949
  const next2 = foldStoredVnextRun(context, run);
25878
25950
  persistVnextRunState(context, run.runId, next2, events[events.length - 1].sequence);
@@ -25979,16 +26051,124 @@ function transitionBudgetFailure(plan, state, fromStepId, outcome) {
25979
26051
  }
25980
26052
  return void 0;
25981
26053
  }
25982
- function unsupportedLimit(envelope) {
25983
- if (envelope.plan.limits.maxRunDurationMs !== void 0) {
25984
- 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;
25985
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) {
25986
26169
  if (envelope.plan.limits.maxAgentTimeMs !== void 0) {
25987
26170
  return { reason: "limit_unsupported", field: "limits.maxAgentTimeMs", detail: "agent-time budget enforcement is not available in this slice" };
25988
26171
  }
25989
- if (envelope.projectLimits.maxRunDurationMs !== void 0) {
25990
- return { reason: "limit_unsupported", field: "project.limits.maxRunDurationMs", detail: "duration budget enforcement is not available in this slice" };
25991
- }
25992
26172
  if (envelope.projectLimits.maxAgentTimeMs !== void 0) {
25993
26173
  return { reason: "limit_unsupported", field: "project.limits.maxAgentTimeMs", detail: "agent-time budget enforcement is not available in this slice" };
25994
26174
  }
@@ -27165,7 +27345,7 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
27165
27345
  const scheduler = VnextRunScheduler.for(context, bundle);
27166
27346
  const opening = scheduler.openDriveSession(runId, {
27167
27347
  mode: body.mode,
27168
- allowLimits: true,
27348
+ allowLimits: false,
27169
27349
  liveMode: body.mode === "live",
27170
27350
  createProducer
27171
27351
  });