claudish 14.6.0 → 14.7.0

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/dist/index.js +426 -71
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -114,6 +114,7 @@ var init_launch_env = __esm(() => {
114
114
  "CLAUDISH_PANE_CWD",
115
115
  "CLAUDISH_HOOK_INBOX",
116
116
  "CLAUDISH_HOOK_SESSION",
117
+ "CLAUDISH_PARENT_SESSION",
117
118
  "CLAUDISH_BIN"
118
119
  ];
119
120
  });
@@ -166,6 +167,7 @@ var init_config = __esm(() => {
166
167
  CLAUDISH_PANE_CHILD: "CLAUDISH_PANE_CHILD",
167
168
  CLAUDISH_PANE_ENV: "CLAUDISH_PANE_ENV",
168
169
  CLAUDISH_PANE_CWD: "CLAUDISH_PANE_CWD",
170
+ CLAUDISH_PARENT_SESSION: "CLAUDISH_PARENT_SESSION",
169
171
  CLAUDISH_PANE_ROOT: "CLAUDISH_PANE_ROOT"
170
172
  };
171
173
  });
@@ -216,7 +218,8 @@ function applyPaneEnvSnapshot(env) {
216
218
  ENV.CLAUDISH_PANE_CHILD,
217
219
  ENV.CLAUDISH_PANE_CWD,
218
220
  HOOK_INBOX_VAR,
219
- HOOK_SESSION_VAR
221
+ HOOK_SESSION_VAR,
222
+ ENV.CLAUDISH_PARENT_SESSION
220
223
  ]);
221
224
  for (const key of Object.keys(env)) {
222
225
  if (Object.hasOwn(snapshot, key) || keep.has(key) || isPaneShellManagedKey(key))
@@ -298,7 +301,8 @@ var init_child_env = __esm(() => {
298
301
  ENV.CLAUDISH_PANE_ENV,
299
302
  ENV.CLAUDISH_PANE_CWD,
300
303
  HOOK_INBOX_VAR,
301
- HOOK_SESSION_VAR
304
+ HOOK_SESSION_VAR,
305
+ ENV.CLAUDISH_PARENT_SESSION
302
306
  ];
303
307
  PANE_SHELL_MANAGED_KEYS = [
304
308
  "COLUMNS",
@@ -5394,7 +5398,7 @@ var init_onepassword_config = __esm(() => {
5394
5398
  });
5395
5399
 
5396
5400
  // src/version.ts
5397
- var VERSION = "14.6.0";
5401
+ var VERSION = "14.7.0";
5398
5402
 
5399
5403
  // src/redact.ts
5400
5404
  function isPlaceholder(value) {
@@ -16038,7 +16042,7 @@ var init_minimax_model_dialect = __esm(() => {
16038
16042
  });
16039
16043
 
16040
16044
  // src/auth/accounts/allowance-report-schema.ts
16041
- var ALLOWANCE_REPORT_SCHEMA = "claudish.allowance.v1", iso, fraction, finite, nonNegative, quantilesOf = (t) => object({ p10: t, p25: t, p50: t, p75: t, p90: t }), alertLevel, strategyName, evidence, unit, provenance, semantics, gapKind, exactness, accountSchema, remedySchema, alertSchema, trajectorySchema, sessionSchema, allowanceReportSchema, allowanceStatusAnswerSchema;
16045
+ var ALLOWANCE_REPORT_SCHEMA = "claudish.allowance.v1", iso, fraction, finite, nonNegative, quantilesOf = (t) => object({ p10: t, p25: t, p50: t, p75: t, p90: t }), alertLevel, strategyName, evidence, unit, provenance, semantics, gapKind, exactness, accountSchema, remedySchema, alertSchema, historyPoint, trajectorySchema, sessionSchema, allowanceReportSchema, ALLOWANCE_REPORT_SECTIONS, partialReport, allowanceStatusAnswerSchema;
16042
16046
  var init_allowance_report_schema = __esm(() => {
16043
16047
  init_zod();
16044
16048
  iso = exports_iso.datetime({ offset: true });
@@ -16068,7 +16072,10 @@ var init_allowance_report_schema = __esm(() => {
16068
16072
  semantics
16069
16073
  })),
16070
16074
  lambda: union([literal(0), literal(1)]).nullable(),
16071
- calibration: object({ beta: string2(), kappa: string2().nullable() })
16075
+ calibration: object({ beta: string2(), kappa: string2().nullable() }),
16076
+ active: boolean2().optional(),
16077
+ order: number2().int().min(0).optional(),
16078
+ lostAtReset: object({ at: iso, p10: fraction, p50: fraction, p90: fraction }).nullable().optional()
16072
16079
  });
16073
16080
  remedySchema = object({
16074
16081
  kind: _enum(["cut", "pause", "not-addressable"]),
@@ -16089,19 +16096,29 @@ var init_allowance_report_schema = __esm(() => {
16089
16096
  binding: array(object({ account: string2(), window: string2() })),
16090
16097
  remedy: remedySchema
16091
16098
  });
16099
+ historyPoint = object({
16100
+ at: iso,
16101
+ remaining: finite,
16102
+ provenance: _enum(["observed", "reset-inferred"])
16103
+ });
16092
16104
  trajectorySchema = object({
16093
- history: array(object({
16094
- at: iso,
16095
- remaining: finite,
16096
- provenance: _enum(["observed", "reset-inferred"])
16097
- })),
16105
+ history: array(historyPoint),
16106
+ historyByAccount: array(object({ accountId: string2(), history: array(historyPoint) })).optional(),
16098
16107
  forecast: array(object({ at: iso, p10: finite, p50: finite, p90: finite, pBlocked: fraction })),
16099
16108
  resets: array(object({ at: iso, account: string2(), window: string2(), projected: boolean2() })),
16100
16109
  blocked: array(object({ from: iso, to: iso, kind: gapKind, probability: fraction })),
16110
+ switches: array(object({
16111
+ accountId: string2(),
16112
+ soonest: iso,
16113
+ usual: iso,
16114
+ latest: iso,
16115
+ probability: fraction
16116
+ })).optional(),
16101
16117
  spark48: string2().regex(/^[\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588\u2592\u2593\u250A ]*$/u)
16102
16118
  });
16103
16119
  sessionSchema = object({
16104
16120
  session: union([string2().max(8), literal("unattributed")]),
16121
+ parent: union([string2().max(8), _null3()]).optional(),
16105
16122
  account: string2(),
16106
16123
  window: string2(),
16107
16124
  share: fraction,
@@ -16143,11 +16160,41 @@ var init_allowance_report_schema = __esm(() => {
16143
16160
  trajectory: trajectorySchema,
16144
16161
  sessions: array(sessionSchema)
16145
16162
  });
16163
+ ALLOWANCE_REPORT_SECTIONS = [
16164
+ "accounts",
16165
+ "alerts",
16166
+ "burn",
16167
+ "combined",
16168
+ "sessions",
16169
+ "trajectory"
16170
+ ];
16171
+ partialReport = allowanceReportSchema.partial({
16172
+ accounts: true,
16173
+ alerts: true,
16174
+ burn: true,
16175
+ combined: true,
16176
+ sessions: true,
16177
+ trajectory: true
16178
+ });
16146
16179
  allowanceStatusAnswerSchema = object({
16147
16180
  contract_version: literal(1),
16148
16181
  capabilities: array(string2()),
16149
- allowance: allowanceReportSchema.nullable(),
16182
+ sections: array(_enum(ALLOWANCE_REPORT_SECTIONS)).min(1).optional(),
16183
+ allowance: partialReport.nullable(),
16150
16184
  reason: string2().optional()
16185
+ }).superRefine((answer, ctx) => {
16186
+ if (answer.allowance === null)
16187
+ return;
16188
+ const wanted = answer.sections ?? ALLOWANCE_REPORT_SECTIONS;
16189
+ for (const section of wanted) {
16190
+ if (answer.allowance[section] === undefined) {
16191
+ ctx.addIssue({
16192
+ code: "custom",
16193
+ path: ["allowance", section],
16194
+ message: `section ${section} is missing`
16195
+ });
16196
+ }
16197
+ }
16151
16198
  });
16152
16199
  });
16153
16200
 
@@ -16599,7 +16646,7 @@ function cuOf(tokens, cfg) {
16599
16646
  const uncached = Math.max(0, tokens.input - tokens.cacheRead - tokens.cacheWrite);
16600
16647
  return uncached + w.cacheRead * tokens.cacheRead + w.cacheWrite * tokens.cacheWrite + w.output * tokens.output;
16601
16648
  }
16602
- var PROVIDER_COST_PRIORS, MINUTE_MS2 = 60000, HOUR_MS2, DEFAULT_ALLOWANCE_CONFIG, LOOKAHEAD_TRAJ_PATHS = 40;
16649
+ var PROVIDER_COST_PRIORS, MINUTE_MS2 = 60000, HOUR_MS2, DEFAULT_ALLOWANCE_CONFIG, LOOKAHEAD_TRAJ_PATHS = 40, MIN_PATH_SHARE = 0.1, PACE_MAX_MULT = 64, PACE_BISECT_STEPS = 4;
16603
16650
  var init_constants = __esm(() => {
16604
16651
  PROVIDER_COST_PRIORS = {
16605
16652
  "openai-codex": { cacheRead: 0.1, cacheWrite: 1, output: 4 },
@@ -17092,7 +17139,7 @@ function fold(s, e, cfg, seen) {
17092
17139
  insertServed(account, e.at, cu);
17093
17140
  addDemand(s, hourOf(e.at), cu, 1);
17094
17141
  if (e.session !== null)
17095
- addSession(s, e.session, e.at, e.account, cu, e.tokens, e.model, 1);
17142
+ addSession(s, e.session, e.at, e.account, cu, e.tokens, e.model, 1, e.parent ?? null);
17096
17143
  }
17097
17144
  if (e.outcome === "ok")
17098
17145
  closeCensor(s, e.at);
@@ -17141,13 +17188,13 @@ function fold(s, e, cfg, seen) {
17141
17188
  if (cu > 0) {
17142
17189
  insertServed(account, mid, cu);
17143
17190
  if (e.session !== null)
17144
- addSession(s, e.session, mid, e.account, cu, e.tokens, e.model, e.n);
17191
+ addSession(s, e.session, mid, e.account, cu, e.tokens, e.model, e.n, e.parent ?? null);
17145
17192
  }
17146
17193
  const bucket = addDemand(s, e.hour, cu, e.n);
17147
17194
  bucket.censoredMinutes = Math.min(60, Math.max(bucket.censoredMinutes, e.censoredMinutes));
17148
- if (e.first !== null)
17195
+ if (e.first !== null && e.n > 1)
17149
17196
  applySnapshot(account, e.hour, e.first, cfg);
17150
- if (e.last !== null && e.n > 1)
17197
+ if (e.last !== null)
17151
17198
  applySnapshot(account, e.hour + HOUR_MS4 - 1, e.last, cfg);
17152
17199
  touch(s, e.hour + HOUR_MS4 - 1);
17153
17200
  return;
@@ -17225,7 +17272,7 @@ function sealCensor(s, from, to) {
17225
17272
  bucket.censoredMinutes = Math.min(60, Math.max(bucket.censoredMinutes, overlap / MINUTE_MS4));
17226
17273
  }
17227
17274
  }
17228
- function addSession(s, session, at, account, cu, tokens, model, n) {
17275
+ function addSession(s, session, at, account, cu, tokens, model, n, parent) {
17229
17276
  let track = s.sessions[session];
17230
17277
  if (!track) {
17231
17278
  track = {
@@ -17250,6 +17297,8 @@ function addSession(s, session, at, account, cu, tokens, model, n) {
17250
17297
  track.tokens.cacheWrite += tokens.cacheWrite;
17251
17298
  track.tokens.output += tokens.output;
17252
17299
  track.models[model] = (track.models[model] ?? 0) + n;
17300
+ if (parent !== null && (track.parent ?? null) === null)
17301
+ track.parent = parent;
17253
17302
  }
17254
17303
  function applySnapshot(account, at, readings, cfg) {
17255
17304
  const current = account.lastCompleteAt === null || at >= account.lastCompleteAt;
@@ -19221,18 +19270,88 @@ function pauseGrid(horizonMs) {
19221
19270
  out.push(hours * HOUR_MS11);
19222
19271
  return out.filter((p) => p <= Math.max(horizonMs, HOUR_MS11));
19223
19272
  }
19224
- function* remedyScan(ctx, rateLong, cfg) {
19225
- const zero = ctx.factors.map(() => 0);
19226
- const externalStarts = gapsOn(ctx, zero, cfg).filter((g) => g.kind === "7d" && g.lengthMs >= REMEDY_MIN_GAP_MS).map((g) => g.start);
19227
- yield;
19273
+ function* cutScan(ctx, rate, cfg) {
19228
19274
  let cut = null;
19229
19275
  for (const phi of CUT_GRID) {
19230
- const gs = gapsOn(ctx, ctx.factors.map((f) => phi * rateLong * f), cfg);
19276
+ const gs = gapsOn(ctx, ctx.factors.map((f) => phi * rate * f), cfg);
19231
19277
  yield;
19232
19278
  if (hasGap(gs))
19233
19279
  break;
19234
19280
  cut = phi;
19235
19281
  }
19282
+ return cut;
19283
+ }
19284
+ function refillThroughput(ctx) {
19285
+ let total = 0;
19286
+ for (const v of ctx.views.filter(isRead)) {
19287
+ const g = v.windows.find((w) => w.key === v.governing);
19288
+ if (!g || g.lengthMinutes === null || g.lengthMinutes <= 0)
19289
+ continue;
19290
+ const beta = ctx.unit === "cu" ? v.beta[g.key]?.value : undefined;
19291
+ const capacity = beta !== undefined && beta > 0 ? 1 / beta : 1;
19292
+ total += capacity / (g.lengthMinutes / 60);
19293
+ }
19294
+ return total;
19295
+ }
19296
+ function* paceScan(ctx, ev, rates, cfg) {
19297
+ const rhoL = Number.isFinite(rates.long) && rates.long > 0 ? rates.long : 0;
19298
+ if (rhoL > 0 && hasGap(ev.long)) {
19299
+ const cut = yield* cutScan(ctx, rhoL, cfg);
19300
+ return { rate: cut === null ? 0 : cut * rhoL, basis: "cut-scan" };
19301
+ }
19302
+ const anchor = Math.max(rhoL, refillThroughput(ctx));
19303
+ if (!(anchor > 0) || !Number.isFinite(anchor))
19304
+ return null;
19305
+ const clean = (rho) => !hasGap(gapsOn(ctx, ctx.factors.map((f) => rho * f), cfg));
19306
+ if (anchor > rhoL) {
19307
+ const ok = clean(anchor);
19308
+ yield;
19309
+ if (!ok)
19310
+ return { rate: yield* bisect(rhoL, anchor, clean), basis: "bisect" };
19311
+ }
19312
+ const up = yield* bracketUp(anchor, clean);
19313
+ if (up.hi === null)
19314
+ return { rate: up.lo, basis: "capped" };
19315
+ return { rate: yield* bisect(up.lo, up.hi, clean), basis: "bracket" };
19316
+ }
19317
+ function* bracketUp(anchor, clean) {
19318
+ let lo = anchor;
19319
+ for (let mult = 2;mult <= PACE_MAX_MULT; mult *= 2) {
19320
+ const ok = clean(mult * anchor);
19321
+ yield;
19322
+ if (!ok)
19323
+ return { lo, hi: mult * anchor };
19324
+ lo = mult * anchor;
19325
+ }
19326
+ return { lo, hi: null };
19327
+ }
19328
+ function* bisect(lo, hi, clean) {
19329
+ let low = lo;
19330
+ let high = hi;
19331
+ for (let i = 0;i < PACE_BISECT_STEPS; i++) {
19332
+ const mid = (low + high) / 2;
19333
+ const ok = clean(mid);
19334
+ yield;
19335
+ if (ok)
19336
+ low = mid;
19337
+ else
19338
+ high = mid;
19339
+ }
19340
+ return low;
19341
+ }
19342
+ function paceInCuPerHour(pace, burnLong) {
19343
+ if (pace.phi !== null && Number.isFinite(burnLong) && burnLong > 0) {
19344
+ return Math.max(0, pace.phi * burnLong);
19345
+ }
19346
+ if (pace.unit === "cu")
19347
+ return Math.max(0, pace.rate);
19348
+ return null;
19349
+ }
19350
+ function* remedyScan(ctx, rateLong, cfg) {
19351
+ const zero = ctx.factors.map(() => 0);
19352
+ const externalStarts = gapsOn(ctx, zero, cfg).filter((g) => g.kind === "7d" && g.lengthMs >= REMEDY_MIN_GAP_MS).map((g) => g.start);
19353
+ yield;
19354
+ const cut = yield* cutScan(ctx, rateLong, cfg);
19236
19355
  let pauseMs = null;
19237
19356
  const h0 = hourStart(ctx.now);
19238
19357
  for (const p of pauseGrid(ctx.horizonMs)) {
@@ -19273,6 +19392,25 @@ function remedyText(r, gapStart, formatTime) {
19273
19392
  function rateBin(n) {
19274
19393
  return Number.isFinite(n) && n > 0 ? String(Math.round(8 * Math.log2(n))) : "0";
19275
19394
  }
19395
+ function* paceFor(ctx, ev, rates, inputsKey, cfg, opts) {
19396
+ if (!opts.pace || opts.payload === false)
19397
+ return null;
19398
+ const key = fnvHex([inputsKey, "pace"].join("|"));
19399
+ if (opts.paceReuse?.key === key)
19400
+ return opts.paceReuse;
19401
+ const found = yield* paceScan(ctx, ev, rates, cfg);
19402
+ if (found === null)
19403
+ return null;
19404
+ const simLong = rates.long;
19405
+ return {
19406
+ key,
19407
+ rate: found.rate,
19408
+ simLong,
19409
+ phi: Number.isFinite(simLong) && simLong > 0 ? found.rate / simLong : null,
19410
+ unit: ctx.unit,
19411
+ basis: found.basis
19412
+ };
19413
+ }
19276
19414
  function* alertsSliced(s, now, prior, cal, cfg, fc, opts = {}) {
19277
19415
  const base = prior ?? initialAlertMemory();
19278
19416
  if (evidenceOf(s, now) === "none") {
@@ -19281,7 +19419,8 @@ function* alertsSliced(s, now, prior, cal, cfg, fc, opts = {}) {
19281
19419
  active: [],
19282
19420
  transitions: [],
19283
19421
  blockedNow: false,
19284
- status: "insufficient-evidence"
19422
+ status: "insufficient-evidence",
19423
+ pace: null
19285
19424
  };
19286
19425
  }
19287
19426
  const ctx = gapContext(s, now, cal, cfg);
@@ -19318,7 +19457,8 @@ function* alertsSliced(s, now, prior, cal, cfg, fc, opts = {}) {
19318
19457
  const active = [];
19319
19458
  const raised = ["critical", "warn"].filter((l) => memory[l].raised);
19320
19459
  if (raised.length === 0 || opts.payload === false) {
19321
- return { memory, active, transitions, blockedNow, status: "ok" };
19460
+ const pace = yield* paceFor(ctx, ev, rates, inputsKey, cfg, opts);
19461
+ return { memory, active, transitions, blockedNow, status: "ok", pace };
19322
19462
  }
19323
19463
  const seed = seedOf(s, now, cfg);
19324
19464
  const key = fnvHex([inputsKey, seed, raised.join(","), alertPaths(cfg)].join("|"));
@@ -19360,9 +19500,10 @@ function* alertsSliced(s, now, prior, cal, cfg, fc, opts = {}) {
19360
19500
  remedy: r
19361
19501
  });
19362
19502
  }
19363
- return { memory, active, transitions, blockedNow, status: "ok", payload };
19503
+ const pace = active.length === 0 ? yield* paceFor(ctx, ev, rates, inputsKey, cfg, opts) : null;
19504
+ return { memory, active, transitions, blockedNow, status: "ok", payload, pace };
19364
19505
  }
19365
- var HOUR_MS11 = 3600000, REMEDY_MIN_GAP_MS, CUT_GRID, MIN_PATH_SHARE = 0.1, EPISODE_BUCKET_MS;
19506
+ var HOUR_MS11 = 3600000, REMEDY_MIN_GAP_MS, CUT_GRID, EPISODE_BUCKET_MS;
19366
19507
  var init_alerts = __esm(() => {
19367
19508
  init_capacity();
19368
19509
  init_constants();
@@ -19613,6 +19754,7 @@ function contributions(s, q, cfg) {
19613
19754
  const share = calibrated ? observed > 0 ? r.fraction / observed : 0 : totalCu > 0 ? r.cu / totalCu : 0;
19614
19755
  return {
19615
19756
  session: r.session,
19757
+ parent: track?.parent ?? null,
19616
19758
  account: r.accounts.size === 1 && single ? single.account : account,
19617
19759
  window: r.window,
19618
19760
  usedFraction: calibrated && single ? r.fraction : null,
@@ -19631,6 +19773,7 @@ function contributions(s, q, cfg) {
19631
19773
  const lasts = spent.map((x) => x.lastAt).filter((t) => t !== null);
19632
19774
  out.push({
19633
19775
  session: "unattributed",
19776
+ parent: null,
19634
19777
  account,
19635
19778
  window: window2,
19636
19779
  usedFraction: calibrated && single ? unattributed : null,
@@ -19706,7 +19849,7 @@ function deliverableIn(view, unit) {
19706
19849
  const beta = view.governing === null ? undefined : view.beta[view.governing];
19707
19850
  return isStrong(beta) && beta.value > 0 ? d / beta.value : d;
19708
19851
  }
19709
- function historyOf(s, views, now, unit) {
19852
+ function historyFrom(views, now) {
19710
19853
  let from = now - WEEK_MS4;
19711
19854
  for (const v of views) {
19712
19855
  const g = v.windows.find((w) => w.key === v.governing);
@@ -19714,23 +19857,38 @@ function historyOf(s, views, now, unit) {
19714
19857
  continue;
19715
19858
  from = Math.min(from, g.resetAt - g.lengthMinutes * MINUTE_MS10);
19716
19859
  }
19860
+ return from;
19861
+ }
19862
+ function historyAt(s, views, t, unit, byAccount) {
19863
+ let remaining = 0;
19864
+ let any = false;
19865
+ let inferred = false;
19866
+ for (const v of views) {
19867
+ const at = viewAt(s, v, t);
19868
+ if (!at)
19869
+ continue;
19870
+ any = true;
19871
+ inferred ||= at.inferred;
19872
+ const own = deliverableIn(at.view, unit);
19873
+ remaining += own;
19874
+ byAccount[v.account]?.push({ at: t, remaining: own, provenance: provenanceOf(at.inferred) });
19875
+ }
19876
+ return any ? { at: t, remaining, provenance: provenanceOf(inferred) } : null;
19877
+ }
19878
+ function historyOf(s, views, now, unit) {
19879
+ const from = historyFrom(views, now);
19717
19880
  const out = [];
19881
+ const byAccount = {};
19882
+ for (const v of views)
19883
+ byAccount[v.account] = [];
19718
19884
  for (let t = now;t >= from; t -= HOUR_MS14) {
19719
- let remaining = 0;
19720
- let any = false;
19721
- let inferred = false;
19722
- for (const v of views) {
19723
- const at = viewAt(s, v, t);
19724
- if (!at)
19725
- continue;
19726
- any = true;
19727
- inferred ||= at.inferred;
19728
- remaining += deliverableIn(at.view, unit);
19729
- }
19730
- if (any)
19731
- out.push({ at: t, remaining, provenance: inferred ? "reset-inferred" : "observed" });
19885
+ const point = historyAt(s, views, t, unit, byAccount);
19886
+ if (point)
19887
+ out.push(point);
19732
19888
  }
19733
- return out.reverse();
19889
+ for (const list of Object.values(byAccount))
19890
+ list.reverse();
19891
+ return { history: out.reverse(), byAccount };
19734
19892
  }
19735
19893
  function resetsOf(views, now, end) {
19736
19894
  const out = [];
@@ -19779,13 +19937,81 @@ function blockedRuns(results, forecast) {
19779
19937
  }
19780
19938
  return out;
19781
19939
  }
19940
+ function firstTakeovers(r, from, now, end) {
19941
+ const taken = new Map;
19942
+ let prev = from;
19943
+ for (const d of r.decisions) {
19944
+ if (d.account === null || d.cu <= 0 || d.account === prev)
19945
+ continue;
19946
+ const switched = prev !== null;
19947
+ prev = d.account;
19948
+ if (!switched)
19949
+ continue;
19950
+ const t = Math.max(now, r.start + d.k * HOUR_MS14);
19951
+ if (t > end)
19952
+ break;
19953
+ if (!taken.has(d.account))
19954
+ taken.set(d.account, t);
19955
+ }
19956
+ return taken;
19957
+ }
19958
+ function switchesOf2(results, views, poolActive, now, end) {
19959
+ const order = new Map(views.map((v, i) => [v.account, i]));
19960
+ const from = poolActive !== null && order.has(poolActive) ? poolActive : null;
19961
+ const times = new Map;
19962
+ for (const r of results) {
19963
+ for (const [account, t] of firstTakeovers(r, from, now, end)) {
19964
+ const list = times.get(account) ?? [];
19965
+ list.push(t);
19966
+ times.set(account, list);
19967
+ }
19968
+ }
19969
+ const paths = Math.max(1, results.length);
19970
+ const out = [];
19971
+ for (const [account, list] of times) {
19972
+ const probability = list.length / paths;
19973
+ if (probability < MIN_PATH_SHARE)
19974
+ continue;
19975
+ out.push({ account, q: quantilesOf2(list), probability: Math.min(1, probability) });
19976
+ }
19977
+ return out.sort((a, b) => a.q.p50 - b.q.p50 || (order.get(a.account) ?? 0) - (order.get(b.account) ?? 0));
19978
+ }
19979
+ function lostAtResetOf(results, views) {
19980
+ const out = {};
19981
+ const paths = Math.max(1, results.length);
19982
+ for (const v of views) {
19983
+ const g = v.windows.find((w) => w.key === v.governing);
19984
+ if (!g || g.remaining === null || g.resetAt === null || g.semantics === "sliding")
19985
+ continue;
19986
+ const values = [];
19987
+ for (const r of results) {
19988
+ const left = r.leftoverAtReset[v.account];
19989
+ if (left !== null && left !== undefined && Number.isFinite(left)) {
19990
+ values.push(Math.min(1, Math.max(0, left)));
19991
+ }
19992
+ }
19993
+ if (values.length === 0 || values.length < MIN_PATH_SHARE * paths)
19994
+ continue;
19995
+ out[v.account] = { at: g.resetAt, q: quantilesOf2(values) };
19996
+ }
19997
+ return out;
19998
+ }
19782
19999
  function trajectory(s, now, horizonMs, cal, cfg) {
19783
20000
  const all = accountViews(s, now, cfg).filter(isRead);
19784
20001
  const unit = strongBetas(all) ? "cu" : "account-fraction";
19785
- const history = historyOf(s, all, now, unit);
20002
+ const { history, byAccount: historyByAccount } = historyOf(s, all, now, unit);
19786
20003
  const end = now + Math.max(0, horizonMs);
19787
20004
  const resets = resetsOf(all, now, end);
19788
- const empty = { unit, history, forecast: [], resets, blocked: [] };
20005
+ const empty = {
20006
+ unit,
20007
+ history,
20008
+ forecast: [],
20009
+ resets,
20010
+ blocked: [],
20011
+ switches: [],
20012
+ lostAtReset: {},
20013
+ historyByAccount
20014
+ };
19789
20015
  if (evidenceOf(s, now) === "none" || all.length === 0)
19790
20016
  return empty;
19791
20017
  const views = unit === "cu" ? all : all.map(inFractions);
@@ -19823,7 +20049,16 @@ function trajectory(s, now, horizonMs, cal, cfg) {
19823
20049
  }
19824
20050
  forecast.push({ at, q: quantilesOf2(values), pBlocked: blocked / paths });
19825
20051
  }
19826
- return { unit, history, forecast, resets, blocked: blockedRuns(results, forecast) };
20052
+ return {
20053
+ unit,
20054
+ history,
20055
+ forecast,
20056
+ resets,
20057
+ blocked: blockedRuns(results, forecast),
20058
+ switches: switchesOf2(results, views, s.poolActive ?? null, now, end),
20059
+ lostAtReset: lostAtResetOf(results, views),
20060
+ historyByAccount
20061
+ };
19827
20062
  }
19828
20063
  function sparkline(t, cells) {
19829
20064
  const n = Math.max(0, Math.floor(cells));
@@ -19886,7 +20121,7 @@ function sparkline(t, cells) {
19886
20121
  return LEVELS[Math.max(0, level)] ?? " ";
19887
20122
  }).join("");
19888
20123
  }
19889
- var MINUTE_MS10 = 60000, HOUR_MS14 = 3600000, WEEK_MS4, BLOCKED_SHARE = 0.5, WIDE_BAND = 0.15, LEVELS;
20124
+ var MINUTE_MS10 = 60000, HOUR_MS14 = 3600000, WEEK_MS4, BLOCKED_SHARE = 0.5, WIDE_BAND = 0.15, LEVELS, provenanceOf = (inferred) => inferred ? "reset-inferred" : "observed";
19890
20125
  var init_trajectory = __esm(() => {
19891
20126
  init_alerts();
19892
20127
  init_calibrate();
@@ -20032,6 +20267,9 @@ function buildResponseRow(input) {
20032
20267
  finalInTok: count(input.finalInput),
20033
20268
  windows: readingsOf(input.provider, input.usage)
20034
20269
  };
20270
+ const parent = input.parent;
20271
+ if (parent && SESSION_PATTERN.test(parent) && parent !== row.session)
20272
+ row.parent = parent;
20035
20273
  return responseRowSchema.safeParse(row).success ? row : null;
20036
20274
  }
20037
20275
  function buildNoEligibleRow(provider, at) {
@@ -20085,7 +20323,8 @@ function toEvent(row) {
20085
20323
  tokens: tokensOf(row),
20086
20324
  finalInput: row.finalInTok,
20087
20325
  windows: row.windows,
20088
- outcome: row.outcome
20326
+ outcome: row.outcome,
20327
+ parent: row.parent ?? null
20089
20328
  };
20090
20329
  case "no-eligible":
20091
20330
  return row.until === undefined ? { kind: "no-eligible", at: row.at } : {
@@ -20106,7 +20345,8 @@ function toEvent(row) {
20106
20345
  tokens: { ...row.tokens },
20107
20346
  first: row.first,
20108
20347
  last: row.last,
20109
- censoredMinutes: row.censoredMinutes
20348
+ censoredMinutes: row.censoredMinutes,
20349
+ parent: row.parent ?? null
20110
20350
  };
20111
20351
  }
20112
20352
  }
@@ -20189,7 +20429,8 @@ var init_ledger_row = __esm(() => {
20189
20429
  cacheWriteTok: tokenCount,
20190
20430
  outTok: tokenCount,
20191
20431
  finalInTok: tokenCount,
20192
- windows: array(windowReadingSchema).max(16).nullable()
20432
+ windows: array(windowReadingSchema).max(16).nullable(),
20433
+ parent: string2().regex(SESSION_PATTERN).nullable().optional()
20193
20434
  });
20194
20435
  noEligibleRowSchema = object({
20195
20436
  v: literal(LEDGER_ROW_VERSION),
@@ -20218,7 +20459,8 @@ var init_ledger_row = __esm(() => {
20218
20459
  tokens: tokenCountsSchema,
20219
20460
  first: array(windowReadingSchema).max(16).nullable(),
20220
20461
  last: array(windowReadingSchema).max(16).nullable(),
20221
- censoredMinutes: number2().finite().min(0).max(60)
20462
+ censoredMinutes: number2().finite().min(0).max(60),
20463
+ parent: string2().regex(SESSION_PATTERN).nullable().optional()
20222
20464
  });
20223
20465
  ledgerRowSchema = discriminatedUnion("kind", [
20224
20466
  responseRowSchema,
@@ -20736,6 +20978,7 @@ function* rollupDaySteps(day, rows, openAtStart) {
20736
20978
  }
20737
20979
  }
20738
20980
  const hh = String(new Date(hour).getUTCHours()).padStart(2, "0");
20981
+ const parent = group.find((r) => r.parent)?.parent ?? null;
20739
20982
  const rollup = {
20740
20983
  v: LEDGER_ROW_VERSION,
20741
20984
  kind: "rollup",
@@ -20754,7 +20997,8 @@ function* rollupDaySteps(day, rows, openAtStart) {
20754
20997
  },
20755
20998
  first: first.size > 0 ? [...first.values()] : null,
20756
20999
  last: last.size > 0 ? [...last.values()] : null,
20757
- censoredMinutes: censored.get(head.provider)?.get(hour) ?? 0
21000
+ censoredMinutes: censored.get(head.provider)?.get(hour) ?? 0,
21001
+ ...parent ? { parent } : {}
20758
21002
  };
20759
21003
  lines.push(JSON.stringify(rollup));
20760
21004
  }
@@ -21858,6 +22102,12 @@ function readAlertsFile(env) {
21858
22102
  return emptyAlertsFile();
21859
22103
  }
21860
22104
  }
22105
+ function delegatingSession(env) {
22106
+ const value = env[ENV.CLAUDISH_PARENT_SESSION];
22107
+ if (!value || !isPaneChild(env))
22108
+ return null;
22109
+ return SESSION_PATTERN.test(value) ? value : null;
22110
+ }
21861
22111
 
21862
22112
  class AllowanceService {
21863
22113
  env;
@@ -21870,9 +22120,12 @@ class AllowanceService {
21870
22120
  nextFlight = 0;
21871
22121
  threads = new Map;
21872
22122
  models = new Map;
22123
+ reportStateStore = null;
22124
+ parentSession;
21873
22125
  constructor(env = process.env, clock = Date.now) {
21874
22126
  this.env = env;
21875
22127
  this.clock = clock;
22128
+ this.parentSession = delegatingSession(env);
21876
22129
  }
21877
22130
  record(attempt) {
21878
22131
  try {
@@ -21890,7 +22143,8 @@ class AllowanceService {
21890
22143
  outcome: attempt.outcome,
21891
22144
  tokens: attempt.tokens,
21892
22145
  finalInput: attempt.finalInput,
21893
- usage: attempt.usage
22146
+ usage: attempt.usage,
22147
+ parent: this.parentSession
21894
22148
  });
21895
22149
  if (!row) {
21896
22150
  this.warnOnce("a usage row failed its guards and was not written");
@@ -22070,9 +22324,21 @@ class AllowanceService {
22070
22324
  cal: m.cal,
22071
22325
  fc: m.fc,
22072
22326
  alerts: m.lastAlerts,
22073
- labels
22327
+ labels,
22328
+ poolActive: this.activeNow(provider, s)
22074
22329
  });
22075
22330
  }
22331
+ activeNow(provider, s) {
22332
+ try {
22333
+ this.reportStateStore ??= new StateStore({ path: statePath(this.env) });
22334
+ const read = this.reportStateStore.read();
22335
+ if (read.kind === "failed")
22336
+ return s.poolActive ?? null;
22337
+ return read.state.providers[provider]?.active ?? null;
22338
+ } catch {
22339
+ return s.poolActive ?? null;
22340
+ }
22341
+ }
22076
22342
  modelFor(provider) {
22077
22343
  let m = this.models.get(provider);
22078
22344
  if (!m) {
@@ -22103,7 +22369,8 @@ class AllowanceService {
22103
22369
  sinks: new Set,
22104
22370
  label: undefined,
22105
22371
  payload: null,
22106
- lastAlerts: { active: [], blockedNow: false, status: "insufficient-evidence" }
22372
+ pace: null,
22373
+ lastAlerts: { active: [], blockedNow: false, status: "insufficient-evidence", pace: null }
22107
22374
  };
22108
22375
  this.models.set(provider, m);
22109
22376
  }
@@ -22296,14 +22563,21 @@ class AllowanceService {
22296
22563
  let won = [];
22297
22564
  let landed = null;
22298
22565
  for (let attempt = 0;attempt < ALERTS_CAS_ATTEMPTS && landed === null; attempt++) {
22299
- const result = await runSliced(alertsSliced(state, now, peek, m.cal, m.cfg, fc, { reuse: m.payload }));
22566
+ const result = await runSliced(alertsSliced(state, now, peek, m.cal, m.cfg, fc, {
22567
+ reuse: m.payload,
22568
+ pace: !announce,
22569
+ paceReuse: m.pace
22570
+ }));
22300
22571
  if (result.payload)
22301
22572
  m.payload = result.payload;
22573
+ if (result.pace)
22574
+ m.pace = result.pace;
22302
22575
  if (!announce) {
22303
22576
  m.lastAlerts = {
22304
22577
  active: result.active,
22305
22578
  blockedNow: result.blockedNow,
22306
- status: result.status
22579
+ status: result.status,
22580
+ pace: result.pace
22307
22581
  };
22308
22582
  return [];
22309
22583
  }
@@ -22354,7 +22628,12 @@ class AllowanceService {
22354
22628
  log(`[allowance] ${provider}: the alert memory kept moving; step skipped`);
22355
22629
  return [];
22356
22630
  }
22357
- m.lastAlerts = { active: landed.active, blockedNow: landed.blockedNow, status: landed.status };
22631
+ m.lastAlerts = {
22632
+ active: landed.active,
22633
+ blockedNow: landed.blockedNow,
22634
+ status: landed.status,
22635
+ pace: null
22636
+ };
22358
22637
  const active = landed.active;
22359
22638
  const status = landed.status;
22360
22639
  const accounts = accountViews(m.state, now, m.cfg).length;
@@ -22490,19 +22769,27 @@ function poolRemaining(views) {
22490
22769
  }
22491
22770
  return { remainingNow: now.value, capacity, unit: now.unit };
22492
22771
  }
22772
+ function sustainableOf(top, pace, burnLong) {
22773
+ const long = Number.isFinite(burnLong) ? Math.max(0, burnLong) : 0;
22774
+ if (top)
22775
+ return top.remedy.kind === "cut" ? top.remedy.cutToFraction * long : 0;
22776
+ return pace ? paceInCuPerHour(pace, long) : null;
22777
+ }
22493
22778
  function buildReport(input) {
22494
22779
  const { s, now, cfg, cal, fc } = input;
22495
22780
  const horizonMs = Math.min(168 * HOUR_MS16, Math.max(HOUR_MS16, input.horizonMs));
22496
22781
  const evidence = evidenceOf(s, now);
22497
22782
  const none = evidence === "none";
22498
22783
  const views = accountViews(s, now, cfg);
22499
- const traj = trajectory(s, now, horizonMs, cal, cfg);
22784
+ const poolActive = input.poolActive !== undefined ? input.poolActive : s.poolActive ?? null;
22785
+ const traj = trajectory({ ...s, poolActive }, now, horizonMs, cal, cfg);
22500
22786
  const unit = fc?.unit ?? traj.unit;
22501
22787
  const burn = none ? { long: 0, short: 0 } : burnRates(s, now, cal, cfg);
22502
22788
  const ledgerHours = ledgerDays(s, now) * 24;
22503
22789
  const label = (id) => input.labels.get(id) ?? id;
22504
22790
  const pool = poolRemaining(views);
22505
22791
  const top = input.alerts.active[0];
22792
+ const status = none ? "insufficient-evidence" : input.alerts.status;
22506
22793
  const fmt = (at) => formatLocalTime(at);
22507
22794
  const report = {
22508
22795
  schema: ALLOWANCE_REPORT_SCHEMA,
@@ -22518,6 +22805,7 @@ function buildReport(input) {
22518
22805
  accounts: views.map((v) => {
22519
22806
  const g = v.governing === null ? undefined : v.beta[v.governing];
22520
22807
  const k = v.binding === null || v.binding === v.governing ? undefined : v.kappa[v.binding];
22808
+ const lost = traj.lostAtReset[v.account];
22521
22809
  return {
22522
22810
  label: label(v.account),
22523
22811
  id: v.account,
@@ -22533,7 +22821,15 @@ function buildReport(input) {
22533
22821
  semantics: w.semantics
22534
22822
  })),
22535
22823
  lambda: null,
22536
- calibration: { beta: g?.quality ?? "prior", kappa: k?.quality ?? null }
22824
+ calibration: { beta: g?.quality ?? "prior", kappa: k?.quality ?? null },
22825
+ active: poolActive !== null && v.account === poolActive,
22826
+ order: v.order,
22827
+ lostAtReset: lost ? {
22828
+ at: iso2(lost.at),
22829
+ p10: Math.min(1, Math.max(0, lost.q.p10)),
22830
+ p50: Math.min(1, Math.max(0, lost.q.p50)),
22831
+ p90: Math.min(1, Math.max(0, lost.q.p90))
22832
+ } : null
22537
22833
  };
22538
22834
  }),
22539
22835
  combined: {
@@ -22543,7 +22839,7 @@ function buildReport(input) {
22543
22839
  burn: {
22544
22840
  long: ledgerHours < cfg.BURN_LONG_HL_H ? null : burn.long,
22545
22841
  short: ledgerHours < cfg.BURN_SHORT_HL_H ? null : burn.short,
22546
- sustainable: top ? top.burn.sustainable : null,
22842
+ sustainable: status === "ok" ? sustainableOf(top, input.alerts.pace ?? null, burn.long) : null,
22547
22843
  unit: "cu/h"
22548
22844
  },
22549
22845
  alerts: none ? [] : input.alerts.active.map((a) => {
@@ -22579,7 +22875,7 @@ function buildReport(input) {
22579
22875
  };
22580
22876
  }),
22581
22877
  blockedNow: none ? false : input.alerts.blockedNow,
22582
- status: none ? "insufficient-evidence" : input.alerts.status,
22878
+ status,
22583
22879
  trajectory: {
22584
22880
  history: traj.history.map((h) => ({
22585
22881
  at: iso2(h.at),
@@ -22605,6 +22901,17 @@ function buildReport(input) {
22605
22901
  kind: b.kind,
22606
22902
  probability: b.probability
22607
22903
  })),
22904
+ historyByAccount: none ? [] : views.filter((v) => traj.historyByAccount[v.account] !== undefined).map((v) => ({
22905
+ accountId: v.account,
22906
+ history: (traj.historyByAccount[v.account] ?? []).filter((h) => h.at >= now - 24 * HOUR_MS16).map((h) => ({ at: iso2(h.at), remaining: h.remaining, provenance: h.provenance }))
22907
+ })),
22908
+ switches: traj.switches.map((sw) => ({
22909
+ accountId: sw.account,
22910
+ soonest: iso2(sw.q.p10),
22911
+ usual: iso2(sw.q.p50),
22912
+ latest: iso2(sw.q.p90),
22913
+ probability: Math.min(1, Math.max(0, sw.probability))
22914
+ })),
22608
22915
  spark48: sparkline({
22609
22916
  ...traj,
22610
22917
  history: traj.history.filter((h) => h.at >= now - 24 * HOUR_MS16),
@@ -22613,6 +22920,7 @@ function buildReport(input) {
22613
22920
  },
22614
22921
  sessions: none ? [] : contributions(s, { now, window: "binding" }, cfg).map((c) => ({
22615
22922
  session: c.session === "unattributed" ? "unattributed" : c.session.slice(0, 8),
22923
+ parent: c.parent === null ? null : c.parent.slice(0, 8),
22616
22924
  account: c.account === "all" ? "all" : label(c.account),
22617
22925
  window: c.window,
22618
22926
  share: Math.min(1, Math.max(0, c.share)),
@@ -22682,7 +22990,9 @@ function getAllowanceService() {
22682
22990
  }
22683
22991
  var THREAD_MAP_MAX = 512, THREAD_IDLE_MS, HOUR_MS16 = 3600000, DAY_MS6, LOAD_HISTORY_MS, LOAD_RAW_MS, LOAD_DEFER_MS = 1000, REFRESH_MIN_MS = 60000, SERVED_RECENTLY_MS, ALERTS_LOCK_WAIT_MS = 200, ALERTS_LOCK_STALE_MS = 1e4, ALERTS_CAS_ATTEMPTS = 3, IN_FLIGHT_MAX_MS, PENDING_MAX = 4096, LOAD_RETRY_MIN_MS = 60000, LOAD_RETRY_MAX_MS, ANNOUNCED_MAX = 256, CALENDAR_FUTURE_MS, DECLINE = () => null, iso2 = (at) => new Date(at).toISOString(), instance, safeRankerWarned = false;
22684
22992
  var init_allowance_service = __esm(() => {
22993
+ init_config();
22685
22994
  init_logger();
22995
+ init_child_env();
22686
22996
  init_allowance_report_schema();
22687
22997
  init_alerts();
22688
22998
  init_capacity();
@@ -90904,6 +91214,7 @@ function buildPaneEnv(input) {
90904
91214
  env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
90905
91215
  if (input.parentEnv.CLAUDE_CODE_NATIVE_CURSOR === undefined)
90906
91216
  env.CLAUDE_CODE_NATIVE_CURSOR = "1";
91217
+ delete env[ENV.CLAUDISH_PARENT_SESSION];
90907
91218
  Object.assign(env, input.slotEnv);
90908
91219
  if (input.configFile !== null)
90909
91220
  env.CLAUDISH_CONFIG = input.configFile;
@@ -97980,7 +98291,8 @@ async function startModelsIn(flight, sessionPath, opts) {
97980
98291
  kind: "team",
97981
98292
  id: `${runId}:${e.id}`,
97982
98293
  role: kind === "judge" ? "judge" : "slot"
97983
- })
98294
+ }),
98295
+ ...opts.parentClaudeSessionId ? { [ENV.CLAUDISH_PARENT_SESSION]: opts.parentClaudeSessionId } : {}
97984
98296
  },
97985
98297
  shape: "one-shot",
97986
98298
  initialPrompt: inputContent,
@@ -98207,6 +98519,7 @@ async function judgeResponses(sessionPath, opts = {}) {
98207
98519
  await runModels(judgePath, {
98208
98520
  claudeFlags: opts.claudeFlags,
98209
98521
  kind: "judge",
98522
+ ...opts.parentClaudeSessionId ? { parentClaudeSessionId: opts.parentClaudeSessionId } : {},
98210
98523
  ...opts.parentEnv ? { parentEnv: opts.parentEnv } : {},
98211
98524
  ...opts.paneTimings ? { paneTimings: opts.paneTimings } : {}
98212
98525
  });
@@ -99026,7 +99339,8 @@ class SessionManager {
99026
99339
  [ENV.CLAUDISH_TOKEN_FILE]: entry.tokenFile,
99027
99340
  [UPSTREAM_ERROR_LOG_ENV]: entry.upstreamErrorLogPath,
99028
99341
  ...entry.inboxPath ? { [HOOK_INBOX_ENV]: entry.inboxPath } : {},
99029
- [HOOK_SESSION_ENV]: JSON.stringify({ kind: "channel", id: info.sessionId, role: null })
99342
+ [HOOK_SESSION_ENV]: JSON.stringify({ kind: "channel", id: info.sessionId, role: null }),
99343
+ ...info.parentClaudeSessionId ? { [ENV.CLAUDISH_PARENT_SESSION]: info.parentClaudeSessionId } : {}
99030
99344
  },
99031
99345
  shape: info.shape,
99032
99346
  ...opts.prompt ? { initialPrompt: opts.prompt } : {},
@@ -100854,9 +101168,32 @@ async function allowanceStatus(horizonMs) {
100854
101168
  return { ...meta, allowance: null, reason: `the allowance report failed: ${message}` };
100855
101169
  }
100856
101170
  }
101171
+ function allowanceSectionsArg(value) {
101172
+ if (value === undefined)
101173
+ return;
101174
+ const known = ALLOWANCE_REPORT_SECTIONS;
101175
+ if (!Array.isArray(value) || value.length === 0)
101176
+ throw new ContractErrorException("invalid_args", `'sections' must be a non-empty array of ${known.join(", ")}`);
101177
+ for (const name of value) {
101178
+ if (typeof name !== "string" || !known.includes(name))
101179
+ throw new ContractErrorException("invalid_args", `'sections' has an unknown section ${JSON.stringify(name)}; known: ${known.join(", ")}`);
101180
+ }
101181
+ return [...new Set(value)].sort();
101182
+ }
101183
+ function allowanceSections(answer, sections) {
101184
+ if (sections === undefined || answer.allowance === null)
101185
+ return answer;
101186
+ const dropped = new Set(ALLOWANCE_REPORT_SECTIONS.filter((section) => !sections.includes(section)));
101187
+ const allowance = Object.fromEntries(Object.entries(answer.allowance).filter(([key]) => !dropped.has(key)));
101188
+ const { contract_version, capabilities, ...rest } = answer;
101189
+ return { contract_version, capabilities, sections, ...rest, allowance };
101190
+ }
100857
101191
  function contractAnswer(value) {
100858
101192
  return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
100859
101193
  }
101194
+ function compactAnswer(value) {
101195
+ return { content: [{ type: "text", text: JSON.stringify(value) }] };
101196
+ }
100860
101197
  function contractErrorAnswer(e) {
100861
101198
  const err = e instanceof ContractErrorException ? e : new ContractErrorException("invalid_args", e instanceof Error ? e.message : String(e));
100862
101199
  return {
@@ -101443,11 +101780,15 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101443
101780
  models?.[givenModels?.indexOf(m) ?? -1] ?? m,
101444
101781
  level
101445
101782
  ])) : undefined;
101783
+ const runsModels = mode === "run" || mode === "run-and-judge";
101784
+ const runsJudges = mode === "judge" || mode === "run-and-judge";
101785
+ const parentClaudeSessionId = runsModels || runsJudges ? await parentSessionForCall({ hostPid: sessionManager.hostPid }) : undefined;
101446
101786
  const runOpts = {
101447
101787
  requirePattern,
101448
101788
  minOutputBytes,
101449
101789
  claudeFlags: childFlags,
101450
101790
  efforts,
101791
+ parentClaudeSessionId,
101451
101792
  onProgress: (u) => {
101452
101793
  ctx.reportProgress(`team: ${u.phase}`);
101453
101794
  }
@@ -101458,8 +101799,6 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101458
101799
  const existing = join56(resolved, "input.md");
101459
101800
  return existsSync39(existing) ? readFileSync45(existing, "utf-8") : undefined;
101460
101801
  };
101461
- const runsModels = mode === "run" || mode === "run-and-judge";
101462
- const runsJudges = mode === "judge" || mode === "run-and-judge";
101463
101802
  const choice = modelChoiceStop([
101464
101803
  ...runsModels && givenModels && models ? givenModels.map((given, i) => ({ given, spec: models[i] })) : [],
101465
101804
  ...runsJudges && givenJudges && judges ? givenJudges.map((given, i) => ({ given, spec: judges[i] })) : []
@@ -101484,9 +101823,6 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101484
101823
  requirePattern
101485
101824
  });
101486
101825
  setupSession(resolved, models, input);
101487
- const parentClaudeSessionId = await parentSessionForCall({
101488
- hostPid: sessionManager.hostPid
101489
- });
101490
101826
  const monitorRecord = sessionManager.recordTeamRun({
101491
101827
  teamPath: resolved,
101492
101828
  slots: models.length,
@@ -101539,7 +101875,11 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101539
101875
  };
101540
101876
  }
101541
101877
  case "judge": {
101542
- const verdict = await judgeResponses(resolved, { judges, claudeFlags: childFlags });
101878
+ const verdict = await judgeResponses(resolved, {
101879
+ judges,
101880
+ claudeFlags: childFlags,
101881
+ parentClaudeSessionId
101882
+ });
101543
101883
  const out = providerNote ? { ...verdict, provider_note: providerNote } : verdict;
101544
101884
  return { content: [{ type: "text", text: JSON.stringify(out, null, 2) }] };
101545
101885
  }
@@ -101557,7 +101897,11 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101557
101897
  const handle = await startModels(resolved, runOpts);
101558
101898
  await handle.done;
101559
101899
  const run = teamRunRow(resolved, handle.runId);
101560
- const verdict = await judgeResponses(resolved, { judges, claudeFlags: childFlags });
101900
+ const verdict = await judgeResponses(resolved, {
101901
+ judges,
101902
+ claudeFlags: childFlags,
101903
+ parentClaudeSessionId
101904
+ });
101561
101905
  return {
101562
101906
  content: [
101563
101907
  {
@@ -101743,7 +102087,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
101743
102087
  });
101744
102088
  tools.push({
101745
102089
  name: "allowance_status",
101746
- description: "Report the local Codex account pool's allowance: {contract_version, capabilities, allowance, reason?}. `allowance` is the claudish.allowance.v1 report of THIS machine's claudish sessions (accounts, remaining capacity, burn rate, projected gaps with remedies, trajectory, per-session shares), or null with a `reason` when there is no account pool. Read-only; it sends nothing to any vendor.",
102090
+ description: 'Report the local Codex account pool\'s allowance: {contract_version, capabilities, allowance, reason?}. `allowance` is the claudish.allowance.v1 report of THIS machine\'s claudish sessions (accounts, remaining capacity, burn rate, projected gaps with remedies, trajectory, per-session shares), or null with a `reason` when there is no account pool. `sections` limits the report to those parts (accounts, combined, burn, alerts, trajectory, sessions) beside its header, and the answer then lists them in `sections`; a frequent poll should pass ["accounts","burn","alerts"]. Read-only; it sends nothing to any vendor.',
101747
102091
  inputSchema: {
101748
102092
  type: "object",
101749
102093
  properties: {
@@ -101755,6 +102099,15 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
101755
102099
  horizon_hours: {
101756
102100
  type: "number",
101757
102101
  description: "Forecast horizon in hours, 1\u2013168 (default: 168)"
102102
+ },
102103
+ sections: {
102104
+ type: "array",
102105
+ items: {
102106
+ type: "string",
102107
+ enum: [...ALLOWANCE_REPORT_SECTIONS]
102108
+ },
102109
+ minItems: 1,
102110
+ description: 'Report only these parts beside the header (default: all). Poll with ["accounts","burn","alerts"]; the trajectory and sessions are most of the bytes.'
101758
102111
  }
101759
102112
  }
101760
102113
  },
@@ -101767,7 +102120,8 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
101767
102120
  const hours = args.horizon_hours ?? 168;
101768
102121
  if (typeof hours !== "number" || !Number.isFinite(hours) || hours < 1 || hours > 168)
101769
102122
  throw new ContractErrorException("invalid_args", "'horizon_hours' must be a number from 1 to 168");
101770
- return contractAnswer(await allowanceStatus(hours * 3600000));
102123
+ const sections = allowanceSectionsArg(args.sections);
102124
+ return compactAnswer(allowanceSections(await allowanceStatus(hours * 3600000), sections));
101771
102125
  } catch (e) {
101772
102126
  return contractErrorAnswer(e);
101773
102127
  }
@@ -102241,6 +102595,7 @@ var init_mcp_server = __esm(() => {
102241
102595
  init_types3();
102242
102596
  init_base_api_format();
102243
102597
  init_model_catalog();
102598
+ init_allowance_report_schema();
102244
102599
  init_prehydrate();
102245
102600
  init_prompt_role();
102246
102601
  init_fs_atomic();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -71,10 +71,10 @@
71
71
  "ai"
72
72
  ],
73
73
  "optionalDependencies": {
74
- "@claudish/magmux-darwin-arm64": "14.6.0",
75
- "@claudish/magmux-darwin-x64": "14.6.0",
76
- "@claudish/magmux-linux-arm64": "14.6.0",
77
- "@claudish/magmux-linux-x64": "14.6.0"
74
+ "@claudish/magmux-darwin-arm64": "14.7.0",
75
+ "@claudish/magmux-darwin-x64": "14.7.0",
76
+ "@claudish/magmux-linux-arm64": "14.7.0",
77
+ "@claudish/magmux-linux-x64": "14.7.0"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",