@oxagen/cli 2.1.5-69 → 2.1.5-76

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.
Files changed (2) hide show
  1. package/oxagen.mjs +213 -72
  2. package/package.json +1 -1
package/oxagen.mjs CHANGED
@@ -9627,7 +9627,7 @@ var init_settings_writer = __esm({
9627
9627
  "Stop"
9628
9628
  ];
9629
9629
  STEER_WAIT_FLAG = "--await-steer";
9630
- STEER_WAIT_TIMEOUT_S = 86400;
9630
+ STEER_WAIT_TIMEOUT_S = 1814400;
9631
9631
  COMMAND_HOOK_TIMEOUTS_S = {
9632
9632
  SessionStart: 10,
9633
9633
  UserPromptSubmit: 10,
@@ -26672,7 +26672,7 @@ import { readFileSync as readFileSync10 } from "node:fs";
26672
26672
  import { dirname as dirname9, resolve as resolve3 } from "node:path";
26673
26673
  import { fileURLToPath } from "node:url";
26674
26674
  function readVersion() {
26675
- if (true) return "2.1.5-69";
26675
+ if (true) return "2.1.5-76";
26676
26676
  try {
26677
26677
  const here = dirname9(fileURLToPath(import.meta.url));
26678
26678
  const pkg = JSON.parse(
@@ -28225,6 +28225,73 @@ function readTailLine(path2, size = statSync5(path2).size, window2 = SCAN_CHUNK_
28225
28225
  closeSync5(fd2);
28226
28226
  }
28227
28227
  }
28228
+ function* readLinesBackward(path2, size = statSync5(path2).size, window2 = SCAN_CHUNK_BYTES) {
28229
+ if (size === 0) return;
28230
+ const fd2 = openSync5(path2, "r");
28231
+ try {
28232
+ let buffer = Buffer.alloc(0);
28233
+ let start = size;
28234
+ let chunk2 = Math.max(1, window2);
28235
+ const largest = Math.max(chunk2, SCAN_CHUNK_BYTES);
28236
+ let cut = false;
28237
+ const readEarlier = (end2) => {
28238
+ if (start === 0) return false;
28239
+ const from = Math.max(0, start - chunk2);
28240
+ const length = start - from;
28241
+ const earlier = Buffer.allocUnsafe(length);
28242
+ let filled = 0;
28243
+ while (filled < length) {
28244
+ const read2 = readSync2(
28245
+ fd2,
28246
+ earlier,
28247
+ filled,
28248
+ length - filled,
28249
+ from + filled
28250
+ );
28251
+ if (read2 <= 0) break;
28252
+ filled += read2;
28253
+ }
28254
+ if (filled < length) {
28255
+ cut = true;
28256
+ return false;
28257
+ }
28258
+ buffer = Buffer.concat([earlier, buffer.subarray(0, end2 - start)]);
28259
+ start = from;
28260
+ chunk2 = Math.min(chunk2 * 2, largest);
28261
+ return true;
28262
+ };
28263
+ let end = size;
28264
+ while (end > 0) {
28265
+ if (end - 1 < start && !readEarlier(end)) return;
28266
+ let terminated = false;
28267
+ let lineEnd = end;
28268
+ if (buffer[end - 1 - start] === 10) {
28269
+ terminated = true;
28270
+ lineEnd = end - 1;
28271
+ }
28272
+ if (lineEnd === 0) return;
28273
+ let offset = 0;
28274
+ for (; ; ) {
28275
+ const at2 = lineEnd > start ? buffer.lastIndexOf(10, lineEnd - start - 1) : -1;
28276
+ if (at2 !== -1) {
28277
+ offset = start + at2 + 1;
28278
+ break;
28279
+ }
28280
+ if (!readEarlier(end)) break;
28281
+ }
28282
+ if (cut) return;
28283
+ yield {
28284
+ text: buffer.subarray(offset - start, lineEnd - start).toString("utf8"),
28285
+ offset,
28286
+ end: terminated ? lineEnd + 1 : lineEnd,
28287
+ terminated
28288
+ };
28289
+ end = offset;
28290
+ }
28291
+ } finally {
28292
+ closeSync5(fd2);
28293
+ }
28294
+ }
28228
28295
  function* readLinesFrom(path2, from = 0, chunkBytes = SCAN_CHUNK_BYTES) {
28229
28296
  const fd2 = openSync5(path2, "r");
28230
28297
  try {
@@ -29831,11 +29898,11 @@ ${lines.join("\n")}
29831
29898
  *eventsBackward(sessionUuid2) {
29832
29899
  const path2 = this.fileFor(sessionUuid2);
29833
29900
  if (!existsSync12(path2)) return;
29834
- let end = statSync6(path2).size;
29835
- while (end > 0) {
29836
- const line = readTailLine(path2, end, EVENT_TAIL_WINDOW);
29837
- if (line === void 0) return;
29838
- end = line.offset;
29901
+ for (const line of readLinesBackward(
29902
+ path2,
29903
+ statSync6(path2).size,
29904
+ EVENT_TAIL_WINDOW
29905
+ )) {
29839
29906
  if (line.text.trim().length === 0) continue;
29840
29907
  let event;
29841
29908
  try {
@@ -29977,6 +30044,17 @@ ${lines.join("\n")}
29977
30044
  firstUnshippedAt(sessionUuid2, through) {
29978
30045
  const known = this.firstUnshipped.get(sessionUuid2);
29979
30046
  if (known?.through === through) return known.ts;
30047
+ const waiting = this.lastSeqOf(sessionUuid2) - through;
30048
+ if (!this.resume.has(sessionUuid2) && waiting > 0 && waiting <= through) {
30049
+ let first;
30050
+ for (const event of this.eventsBackward(sessionUuid2)) {
30051
+ if (event.seq <= through) break;
30052
+ first = event;
30053
+ }
30054
+ if (first === void 0) return void 0;
30055
+ this.firstUnshipped.set(sessionUuid2, { through, ts: first.ts });
30056
+ return first.ts;
30057
+ }
29980
30058
  for (const first of this.eventsAfterShipped(
29981
30059
  sessionUuid2,
29982
30060
  EVENT_TAIL_WINDOW
@@ -48245,10 +48323,13 @@ var init_hook_handler = __esm({
48245
48323
  });
48246
48324
 
48247
48325
  // ../../packages/tacho/src/collector/steer-waiters.ts
48326
+ function answerBlocksAgent(response) {
48327
+ return response["decision"] === "block" || response["continue"] === false;
48328
+ }
48248
48329
  function owesText(session) {
48249
48330
  return session.control.messages.length > 0 || session.control.resumeOwed !== void 0;
48250
48331
  }
48251
- var STEER_WAIT_HOLD_MS, STEER_WAIT_BUSY_KEPT, STEER_WAIT_RELEASING_EVENTS, SteerWaiters;
48332
+ var STEER_WAIT_HOLD_MS, STEER_WAIT_BUSY_KEPT, STEER_WAIT_RELEASING_EVENTS, STEER_WAIT_RELEASED_AFTER_ANSWER, SteerWaiters;
48252
48333
  var init_steer_waiters = __esm({
48253
48334
  "../../packages/tacho/src/collector/steer-waiters.ts"() {
48254
48335
  "use strict";
@@ -48261,6 +48342,9 @@ var init_steer_waiters = __esm({
48261
48342
  "PostToolUseFailure",
48262
48343
  "SessionEnd"
48263
48344
  ]);
48345
+ STEER_WAIT_RELEASED_AFTER_ANSWER = /* @__PURE__ */ new Set([
48346
+ "UserPromptSubmit"
48347
+ ]);
48264
48348
  SteerWaiters = class {
48265
48349
  constructor(deps) {
48266
48350
  this.deps = deps;
@@ -48279,12 +48363,17 @@ var init_steer_waiters = __esm({
48279
48363
  * Hold one waiter request for the session `key` names. `signal` aborts
48280
48364
  * when the waiter's connection closes. `startedAt` is when the waiter
48281
48365
  * started; one whose session was busy since is told to stop.
48366
+ *
48367
+ * A stale request is refused before it touches the waiter that holds the
48368
+ * key. An old waiter can be told `wait`, and ask again after a prompt and
48369
+ * a later `Stop` installed a newer one. Settling the newer one first ended
48370
+ * both, and left the idle agent with no waiter until the next `Stop`.
48282
48371
  */
48283
48372
  wait(key, signal, startedAt) {
48284
- this.waiting.get(key)?.settle({ done: true });
48285
48373
  const busy = this.busyAt.get(key);
48286
48374
  if (startedAt !== void 0 && busy !== void 0 && busy >= startedAt)
48287
48375
  return Promise.resolve({ done: true });
48376
+ this.waiting.get(key)?.settle({ done: true });
48288
48377
  const session = this.deps.find(key);
48289
48378
  if (session !== void 0 && (session.sealed || session.pendingTerminal === true))
48290
48379
  return Promise.resolve({ done: true });
@@ -57697,6 +57786,20 @@ function reconcileRestoredCursor(state, wal, log) {
57697
57786
  for (const child of Object.values(state.children))
57698
57787
  reconcileRestoredCursor(child.state, wal, log);
57699
57788
  }
57789
+ function startupClock(log, clock2 = () => performance.now()) {
57790
+ const began = clock2();
57791
+ let since = began;
57792
+ return {
57793
+ phase: (name) => {
57794
+ const at2 = clock2();
57795
+ log(`startup phase ${name} took ${Math.round(at2 - since)}ms`);
57796
+ since = at2;
57797
+ },
57798
+ ready: () => {
57799
+ log(`startup took ${Math.round(clock2() - began)}ms to ready`);
57800
+ }
57801
+ };
57802
+ }
57700
57803
  async function startDaemon(options) {
57701
57804
  const loaded = options.host ?? readHostFile(options.paths.hostFile);
57702
57805
  if (loaded === void 0) {
@@ -57712,6 +57815,7 @@ async function startDaemon(options) {
57712
57815
  `);
57713
57816
  });
57714
57817
  const server = createCollectorServer(() => ready, log);
57818
+ const clock2 = startupClock(log);
57715
57819
  let port;
57716
57820
  try {
57717
57821
  if (options.listen ?? true) {
@@ -57721,20 +57825,22 @@ async function startDaemon(options) {
57721
57825
  port: options.port ?? loaded.port
57722
57826
  })).port;
57723
57827
  }
57828
+ clock2.phase("listeners");
57724
57829
  return await initializeDaemon(
57725
57830
  { ...options, host: loaded, log },
57726
57831
  server,
57727
57832
  port,
57728
57833
  (api) => {
57729
57834
  ready = api;
57730
- }
57835
+ },
57836
+ clock2
57731
57837
  );
57732
57838
  } catch (error) {
57733
57839
  await server.close();
57734
57840
  throw error;
57735
57841
  }
57736
57842
  }
57737
- async function initializeDaemon(options, server, port, ready) {
57843
+ async function initializeDaemon(options, server, port, ready, clock2) {
57738
57844
  const paths = withRecordedHarnessFiles(options.paths, options.host);
57739
57845
  const harnessHomes = recordedHarnessHomes(options.host);
57740
57846
  const now = options.now ?? (() => Date.now());
@@ -57866,6 +57972,7 @@ async function initializeDaemon(options, server, port, ready) {
57866
57972
  },
57867
57973
  (movedTo) => logSetAside("WAL cursor", movedTo)
57868
57974
  );
57975
+ clock2.phase("setup");
57869
57976
  for (const session of wal.sessions()) {
57870
57977
  const outcome = wal.repairTail(session);
57871
57978
  if (outcome !== "ok")
@@ -57874,6 +57981,7 @@ async function initializeDaemon(options, server, port, ready) {
57874
57981
  const orphanBodies = wal.repairOrphanBodies();
57875
57982
  if (orphanBodies > 0)
57876
57983
  log(`WAL removed ${orphanBodies} body lines a crash left with no event`);
57984
+ clock2.phase("WAL repair");
57877
57985
  context.chainTail = (sessionUuid2) => {
57878
57986
  const head2 = wal.lastEvent(sessionUuid2);
57879
57987
  return head2 === void 0 ? void 0 : { ...cursorAfter(head2), stopped: head2.kind === "agent_stop" };
@@ -57893,9 +58001,14 @@ async function initializeDaemon(options, server, port, ready) {
57893
58001
  (movedTo) => logSetAside("daemon sealed state", movedTo)
57894
58002
  )
57895
58003
  );
58004
+ let reconcileMs = 0;
58005
+ const reconcile = (state) => {
58006
+ const at2 = performance.now();
58007
+ reconcileRestoredCursor(state, wal, log);
58008
+ reconcileMs += performance.now() - at2;
58009
+ };
57896
58010
  if (sealedState !== void 0) {
57897
- for (const session of sealedState.sessions)
57898
- reconcileRestoredCursor(session.recorder, wal, log);
58011
+ for (const session of sealedState.sessions) reconcile(session.recorder);
57899
58012
  registry2.restore(
57900
58013
  { schema: "tacho.daemon-state.v1", sessions: sealedState.sessions },
57901
58014
  { sealedFile: true }
@@ -57908,8 +58021,7 @@ async function initializeDaemon(options, server, port, ready) {
57908
58021
  )
57909
58022
  );
57910
58023
  if (persisted !== void 0) {
57911
- for (const session of persisted.sessions)
57912
- reconcileRestoredCursor(session.recorder, wal, log);
58024
+ for (const session of persisted.sessions) reconcile(session.recorder);
57913
58025
  registry2.restore(persisted);
57914
58026
  }
57915
58027
  const journaledHookIds = restoreHookIdJournal(
@@ -57917,6 +58029,8 @@ async function initializeDaemon(options, server, port, ready) {
57917
58029
  registry2,
57918
58030
  (uuid) => wal.lastEvent(uuid)?.seq
57919
58031
  );
58032
+ log(`startup phase cursor reconcile took ${Math.round(reconcileMs)}ms`);
58033
+ clock2.phase("state restore");
57920
58034
  const bootId = `tachod-${ulid(now())}`;
57921
58035
  const hostRecord = registry2.ensure(bootId, { pid: process.pid }).record;
57922
58036
  const hostRecorder = hostRecord.recorder;
@@ -59175,9 +59289,15 @@ async function initializeDaemon(options, server, port, ready) {
59175
59289
  }) : void 0;
59176
59290
  void drained?.catch(() => void 0);
59177
59291
  const answer = await queues.session(harnessSessionId, async () => {
59178
- if (options2.refuseWhenStopping && stopped2) throw new Error(STOPPING);
59179
- if (drained !== void 0) await drained;
59180
- return handleHookInner(envelope2, "session");
59292
+ let inner;
59293
+ try {
59294
+ if (options2.refuseWhenStopping && stopped2) throw new Error(STOPPING);
59295
+ if (drained !== void 0) await drained;
59296
+ inner = await handleHookInner(envelope2, "session");
59297
+ return inner;
59298
+ } finally {
59299
+ options2.answered?.(inner?.response);
59300
+ }
59181
59301
  });
59182
59302
  if (answer.durable !== void 0) await answer.durable;
59183
59303
  return answer.response;
@@ -60132,18 +60252,24 @@ async function initializeDaemon(options, server, port, ready) {
60132
60252
  quarantineChanged();
60133
60253
  return Promise.reject(readable.error);
60134
60254
  }
60135
- if (envelope2.replay === void 0 && readable.data.agent_id === void 0 && STEER_WAIT_RELEASING_EVENTS.has(readable.data.hook_event_name))
60136
- steerWaiters.release(
60137
- sessionMapKey(readable.data.session_id, {
60138
- harness: envelope2.harness,
60139
- customAgent: envelope2.agent
60140
- }),
60141
- now()
60142
- );
60255
+ const waiterKey = envelope2.replay === void 0 && readable.data.agent_id === void 0 && STEER_WAIT_RELEASING_EVENTS.has(readable.data.hook_event_name) ? sessionMapKey(readable.data.session_id, {
60256
+ harness: envelope2.harness,
60257
+ customAgent: envelope2.agent
60258
+ }) : void 0;
60259
+ const arrivedAt = waiterKey !== void 0 ? now() : 0;
60260
+ const releasesAfterAnswer = waiterKey !== void 0 && STEER_WAIT_RELEASED_AFTER_ANSWER.has(readable.data.hook_event_name);
60261
+ if (waiterKey !== void 0 && !releasesAfterAnswer)
60262
+ steerWaiters.release(waiterKey, arrivedAt);
60143
60263
  const timed = envelope2.answer_by === void 0 && envelope2.answer_within_ms !== void 0 ? { ...envelope2, answer_by: now() + envelope2.answer_within_ms } : envelope2;
60144
60264
  return answerHook(timed, readable.data.session_id, {
60145
60265
  drainSpoolFirst: true,
60146
- refuseWhenStopping: true
60266
+ refuseWhenStopping: true,
60267
+ ...waiterKey !== void 0 && releasesAfterAnswer ? {
60268
+ answered: (response) => {
60269
+ if (response === void 0 || !answerBlocksAgent(response))
60270
+ steerWaiters.release(waiterKey, arrivedAt);
60271
+ }
60272
+ } : {}
60147
60273
  });
60148
60274
  },
60149
60275
  // Each session the post names takes the post's records on its own queue,
@@ -60300,6 +60426,7 @@ async function initializeDaemon(options, server, port, ready) {
60300
60426
  return exportSession(events, format);
60301
60427
  }
60302
60428
  };
60429
+ clock2.phase("services");
60303
60430
  if (!hostRecorder.hasStarted) {
60304
60431
  record([
60305
60432
  hostRecorder.sealCollectorEvent("agent_start", {
@@ -60335,6 +60462,7 @@ async function initializeDaemon(options, server, port, ready) {
60335
60462
  );
60336
60463
  }
60337
60464
  }
60465
+ clock2.phase("restart gaps");
60338
60466
  try {
60339
60467
  const day = utcDay(now());
60340
60468
  startupDaySpend = { day, micros: walDaySpendMicros(day) };
@@ -60343,7 +60471,9 @@ async function initializeDaemon(options, server, port, ready) {
60343
60471
  `day spend not read from the WAL at startup: ${error instanceof Error ? error.message : String(error)}`
60344
60472
  );
60345
60473
  }
60474
+ clock2.phase("day spend");
60346
60475
  ready(api);
60476
+ clock2.ready();
60347
60477
  servingSince = now();
60348
60478
  if (options.listen ?? true) {
60349
60479
  const unixSocket = (options.platform ?? process.platform) !== "win32";
@@ -63246,7 +63376,7 @@ var init_package = __esm({
63246
63376
  "package.json"() {
63247
63377
  package_default = {
63248
63378
  name: "@oxagen/cli",
63249
- version: "2.1.5-69",
63379
+ version: "2.1.5-76",
63250
63380
  description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
63251
63381
  type: "module",
63252
63382
  main: "./dist/index.js",
@@ -78652,7 +78782,7 @@ var init_json_wire = __esm({
78652
78782
 
78653
78783
  // ../../packages/run-evidence/src/contextgraph.ts
78654
78784
  function defineReadonly(target2, key, value) {
78655
- Object.defineProperty(target2, key, {
78785
+ intrinsicObjectDefineProperty(target2, key, {
78656
78786
  configurable: false,
78657
78787
  enumerable: true,
78658
78788
  value,
@@ -78660,13 +78790,13 @@ function defineReadonly(target2, key, value) {
78660
78790
  });
78661
78791
  }
78662
78792
  function createIndexedSnapshot(length) {
78663
- const snapshot = /* @__PURE__ */ Object.create(null);
78793
+ const snapshot = intrinsicObjectCreate(null);
78664
78794
  defineReadonly(snapshot, "length", length);
78665
78795
  return snapshot;
78666
78796
  }
78667
78797
  function captureDescriptor(descriptor) {
78668
- const isData = Object.hasOwn(descriptor, "value");
78669
- const snapshot = /* @__PURE__ */ Object.create(null);
78798
+ const isData = intrinsicObjectHasOwn(descriptor, "value");
78799
+ const snapshot = intrinsicObjectCreate(null);
78670
78800
  defineReadonly(snapshot, "configurable", descriptor.configurable === true);
78671
78801
  defineReadonly(snapshot, "enumerable", descriptor.enumerable === true);
78672
78802
  defineReadonly(snapshot, "isData", isData);
@@ -78678,29 +78808,29 @@ function captureDescriptor(descriptor) {
78678
78808
  defineReadonly(snapshot, "value", isData ? descriptor.value : void 0);
78679
78809
  defineReadonly(snapshot, "get", isData ? void 0 : descriptor.get);
78680
78810
  defineReadonly(snapshot, "set", isData ? void 0 : descriptor.set);
78681
- return Object.freeze(snapshot);
78811
+ return intrinsicObjectFreeze(snapshot);
78682
78812
  }
78683
78813
  function capturePrototype(label2, target2) {
78684
- const keys = Reflect.ownKeys(target2);
78814
+ const keys = intrinsicReflectOwnKeys(target2);
78685
78815
  const entries2 = createIndexedSnapshot(keys.length);
78686
78816
  for (let index = 0; index < keys.length; index += 1) {
78687
78817
  const key = keys[index];
78688
- const descriptor = Object.getOwnPropertyDescriptor(
78818
+ const descriptor = intrinsicObjectGetOwnPropertyDescriptor(
78689
78819
  target2,
78690
78820
  key
78691
78821
  );
78692
- const entry2 = /* @__PURE__ */ Object.create(null);
78822
+ const entry2 = intrinsicObjectCreate(null);
78693
78823
  defineReadonly(entry2, "key", key);
78694
78824
  defineReadonly(entry2, "descriptor", captureDescriptor(descriptor));
78695
- defineReadonly(entries2, String(index), Object.freeze(entry2));
78825
+ defineReadonly(entries2, `${index}`, intrinsicObjectFreeze(entry2));
78696
78826
  }
78697
- const snapshot = /* @__PURE__ */ Object.create(null);
78827
+ const snapshot = intrinsicObjectCreate(null);
78698
78828
  defineReadonly(snapshot, "label", label2);
78699
78829
  defineReadonly(snapshot, "target", target2);
78700
- defineReadonly(snapshot, "entries", Object.freeze(entries2));
78701
- return Object.freeze(snapshot);
78830
+ defineReadonly(snapshot, "entries", intrinsicObjectFreeze(entries2));
78831
+ return intrinsicObjectFreeze(snapshot);
78702
78832
  }
78703
- var intrinsicMathFround, intrinsicNumberIsFinite2, intrinsicObjectIs, u32Schema, finiteNumberSchema, f32NumberSchema, protectedPrototypes, contextFrameKindV1Schema, contextProvenanceV1Schema, contextFrameEmbeddingV1Schema, contextRelationV1Schema, contextRepresentationV1Schema, contextContentFidelityV1Schema, contextInlineContentRequirementV1Schema, contextContentRefV1Schema, contextTransformV1Schema, contextFrameObjectV1Schema, contextFrameV1Schema, contextQueryV1Schema;
78833
+ var intrinsicMathFround, intrinsicNumberIsFinite2, intrinsicObjectCreate, intrinsicObjectDefineProperty, intrinsicObjectFreeze, intrinsicObjectGetOwnPropertyDescriptor, intrinsicObjectHasOwn, intrinsicObjectIs, intrinsicReflectOwnKeys, u32Schema, finiteNumberSchema, f32NumberSchema, protectedTargets, protectedPrototypes, contextFrameKindV1Schema, contextProvenanceV1Schema, contextFrameEmbeddingV1Schema, contextRelationV1Schema, contextRepresentationV1Schema, contextContentFidelityV1Schema, contextInlineContentRequirementV1Schema, contextContentRefV1Schema, contextTransformV1Schema, contextFrameObjectV1Schema, contextFrameV1Schema, contextQueryV1Schema;
78704
78834
  var init_contextgraph = __esm({
78705
78835
  "../../packages/run-evidence/src/contextgraph.ts"() {
78706
78836
  "use strict";
@@ -78709,7 +78839,13 @@ var init_contextgraph = __esm({
78709
78839
  init_json_wire();
78710
78840
  intrinsicMathFround = Math.fround;
78711
78841
  intrinsicNumberIsFinite2 = Number.isFinite;
78842
+ intrinsicObjectCreate = Object.create;
78843
+ intrinsicObjectDefineProperty = Object.defineProperty;
78844
+ intrinsicObjectFreeze = Object.freeze;
78845
+ intrinsicObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
78846
+ intrinsicObjectHasOwn = Object.hasOwn;
78712
78847
  intrinsicObjectIs = Object.is;
78848
+ intrinsicReflectOwnKeys = Reflect.ownKeys;
78713
78849
  u32Schema = external_exports.number().int().min(0).max(4294967295).refine((value) => !intrinsicObjectIs(value, -0), {
78714
78850
  message: "u32 value must not be negative zero"
78715
78851
  });
@@ -78718,28 +78854,27 @@ var init_contextgraph = __esm({
78718
78854
  (value) => intrinsicNumberIsFinite2(intrinsicMathFround(value)),
78719
78855
  { message: "embedding value must be representable as a finite f32" }
78720
78856
  );
78721
- protectedPrototypes = createIndexedSnapshot(4);
78722
- defineReadonly(
78723
- protectedPrototypes,
78724
- "0",
78725
- capturePrototype("Array.prototype", Array.prototype)
78726
- );
78727
- defineReadonly(
78728
- protectedPrototypes,
78729
- "1",
78730
- capturePrototype("Object.prototype", Object.prototype)
78731
- );
78732
- defineReadonly(
78733
- protectedPrototypes,
78734
- "2",
78735
- capturePrototype("Set.prototype", Set.prototype)
78736
- );
78737
- defineReadonly(
78738
- protectedPrototypes,
78739
- "3",
78740
- capturePrototype("String.prototype", String.prototype)
78741
- );
78742
- Object.freeze(protectedPrototypes);
78857
+ protectedTargets = [
78858
+ ["Array.prototype", Array.prototype],
78859
+ ["Object.prototype", Object.prototype],
78860
+ ["Set.prototype", Set.prototype],
78861
+ ["String.prototype", String.prototype],
78862
+ ["Object", Object],
78863
+ ["Reflect", Reflect],
78864
+ ["JSON", JSON]
78865
+ ];
78866
+ protectedPrototypes = createIndexedSnapshot(
78867
+ protectedTargets.length
78868
+ );
78869
+ for (let index = 0; index < protectedTargets.length; index += 1) {
78870
+ const [label2, target2] = protectedTargets[index];
78871
+ defineReadonly(
78872
+ protectedPrototypes,
78873
+ `${index}`,
78874
+ capturePrototype(label2, target2)
78875
+ );
78876
+ }
78877
+ intrinsicObjectFreeze(protectedPrototypes);
78743
78878
  contextFrameKindV1Schema = external_exports.enum([
78744
78879
  "snippet",
78745
78880
  "symbol",
@@ -82748,6 +82883,16 @@ var init_run_list = __esm({
82748
82883
  * when the read did not look.
82749
82884
  */
82750
82885
  tokens: tokenCountsSchema.nullable().optional(),
82886
+ /**
82887
+ * `cost.run_totals.model_calls` and `tool_calls`: the model calls and
82888
+ * tool calls the run's rollup row counted (#4391). A wrapped run whose
82889
+ * row holds tool calls and no model call made its model calls where no
82890
+ * frame could report them, the rule `get_spend` counts such runs by.
82891
+ * Null when the run has no rollup row. Absent when the read did not
82892
+ * look.
82893
+ */
82894
+ modelCalls: external_exports.number().int().nonnegative().nullable().optional(),
82895
+ toolCalls: external_exports.number().int().nonnegative().nullable().optional(),
82751
82896
  /**
82752
82897
  * `cost.run_totals.cache_hit_rate`: cache reads over uncached input plus
82753
82898
  * cache reads, weighted by spend over the run's frames, from 0 to 1. Null
@@ -132029,15 +132174,11 @@ var init_env = __esm({
132029
132174
  // explicit "false", but the startup guard (assertRlsEnforcedInProduction)
132030
132175
  // refuses to boot in that state.
132031
132176
  TENANT_RLS_ENFORCEMENT_ENABLED: external_exports.union([external_exports.literal("true"), external_exports.literal("false")]).optional().transform((v) => v === void 0 ? isProductionRuntime() : v === "true"),
132032
- // ── Billing / usage-meter tuning (see @oxagen/billing pricing.ts) ──
132033
- // Target *blended* gross margin across all products, in (0,1). When set,
132034
- // it overrides DEFAULT_TARGET_MARGIN and re-derives the meter markup.
132035
- OXAGEN_TARGET_MARGIN: external_exports.coerce.number().gt(0).lt(1).optional(),
132036
- // Operators pin the exact solved meter markup here so the runtime gate
132037
- // never recomputes the blended-margin solve. `pnpm billing:stripe-sync`
132038
- // prints the value to set. Must be >= 1 (a markup below 1 would sell
132039
- // credits below provider cost).
132040
- OXAGEN_METER_MARKUP: external_exports.coerce.number().gte(1).optional(),
132177
+ // ── Billing / assistant credit meter (see @oxagen/billing pricing.ts) ──
132178
+ // The markup on the provider's list price for the in-app assistant's model
132179
+ // calls on Oxagen's key. Unset means 1.20. Must be >= 1 (a markup below 1
132180
+ // would sell credits below provider cost).
132181
+ OXAGEN_ASSISTANT_MARKUP: external_exports.coerce.number().gte(1).optional(),
132041
132182
  // ── Usage-purchase volume discount (hybrid SaaS + usage pricing) ──
132042
132183
  // When a customer buys usage credits they earn a volume discount of
132043
132184
  // OXAGEN_USAGE_DISCOUNT_PERCENT% off for every OXAGEN_USAGE_DISCOUNT_INCREMENT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxagen/cli",
3
- "version": "2.1.5-69",
3
+ "version": "2.1.5-76",
4
4
  "description": "Oxagen governance CLI — spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
5
5
  "type": "module",
6
6
  "bin": {