@claudexor/budget 3.0.3 → 3.1.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 joi-lab
3
+ Copyright (c) 2026 Anton Razzhigaev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/router.d.ts CHANGED
@@ -1,11 +1,36 @@
1
- import type { BillingKnowledge, CredentialRoute, EffortHint, Intent, PaidFallback, QualityTierSet, RoutingGoal } from "@claudexor/schema";
1
+ import type { AuthVerification, BillingKnowledge, CredentialRoute, EffortHint, Intent, PaidFallback, QualityTierSet, RouteRankingRationale, RoutingGoal } from "@claudexor/schema";
2
2
  import type { BudgetLedger } from "./ledger.js";
3
+ /**
4
+ * The typed auth-route evidence a route ran (or would run) under — the doctor's
5
+ * `auth_sources` verification for the credential source plus the concrete
6
+ * `credential_route` receipt. This is the ONLY sanctioned source of billing
7
+ * knowledge (INV-060 / schema `auth.ts`: a credential transport alone never
8
+ * proves entitlement or zero cost, but a VERIFIED native/subscription route is
9
+ * a subscription-entitlement fact). No per-vendor price table is inferred.
10
+ */
11
+ export interface RouteAuthEvidence {
12
+ route: CredentialRoute | null;
13
+ verification: AuthVerification;
14
+ }
15
+ /**
16
+ * Billing knowledge derived STRICTLY from the typed auth route (QA-034). A
17
+ * verified vendor-native route proves `subscription_entitlement`; a managed
18
+ * API-key route is `metered` and is NEVER presumed free; every other route
19
+ * (unverified native, credential-free local, unknown) stays `unknown`. This is
20
+ * the missing production producer the schema/router already knew how to consume.
21
+ */
22
+ export declare function billingKnowledgeForAuthRoute(evidence: RouteAuthEvidence): BillingKnowledge;
3
23
  export interface RouterCandidate {
4
24
  harnessId: string;
5
25
  available: boolean;
6
26
  model?: string;
7
27
  effort?: EffortHint;
8
28
  billingKnowledge?: BillingKnowledge;
29
+ /** Typed auth-route evidence. When present it is AUTHORITATIVE for billing
30
+ * knowledge (derived via billingKnowledgeForAuthRoute), so a verified native
31
+ * route survives paid_fallback:never and ranks with a real economy tuple.
32
+ * Falls back to the explicit billingKnowledge (else unknown) when absent. */
33
+ authRoute?: RouteAuthEvidence;
9
34
  incrementalCostUsd?: number | null;
10
35
  credentialRoute?: CredentialRoute;
11
36
  /** Effective credential subject for quota filtering (release wave round-16
@@ -27,4 +52,13 @@ export declare class RoutingPreflightError extends Error {
27
52
  /** Order candidates transparently; lower tuple values win. Unknown quota remains eligible. */
28
53
  export declare function rankHarnesses(candidates: RouterCandidate[], ctx: RouteContext): RouterCandidate[];
29
54
  export declare function selectHarness(candidates: RouterCandidate[], ctx: RouteContext): RouterCandidate | null;
55
+ /**
56
+ * Explain a ranking as a typed record (QA-034): the per-candidate billing/cost
57
+ * tuple, the eligible/dropped split, and the DECISIVE reason. Kept axis-aligned
58
+ * with rankHarnesses so the recorded rationale can never disagree with the
59
+ * order actually taken. Prose-free; a surface projects it, never reconstructs it.
60
+ * The shape is the schema-owned RouteRankingRationale (snake_case) so it can be
61
+ * persisted verbatim as RunTelemetry.routing_rationale.
62
+ */
63
+ export declare function explainRanking(candidates: RouterCandidate[], ctx: RouteContext): RouteRankingRationale;
30
64
  //# sourceMappingURL=router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,MAAM,EACN,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,cAAc,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,+BAA+B;CAC7C;AAqCD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,eAAe,EAAE,CAmCjG;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,eAAe,EAAE,EAC7B,GAAG,EAAE,YAAY,GAChB,eAAe,GAAG,IAAI,CAExB"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,MAAM,EACN,YAAY,EACZ,cAAc,EAEd,qBAAqB,EAErB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,gBAAgB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,gBAAgB,CAM1F;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;iFAG6E;IAC7E,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,cAAc,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,+BAA+B;CAC7C;AA6FD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,YAAY,GAAG,eAAe,EAAE,CAuBjG;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,eAAe,EAAE,EAC7B,GAAG,EAAE,YAAY,GAChB,eAAe,GAAG,IAAI,CAExB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,eAAe,EAAE,EAC7B,GAAG,EAAE,YAAY,GAChB,qBAAqB,CAavB"}
package/dist/router.js CHANGED
@@ -1,3 +1,18 @@
1
+ /**
2
+ * Billing knowledge derived STRICTLY from the typed auth route (QA-034). A
3
+ * verified vendor-native route proves `subscription_entitlement`; a managed
4
+ * API-key route is `metered` and is NEVER presumed free; every other route
5
+ * (unverified native, credential-free local, unknown) stays `unknown`. This is
6
+ * the missing production producer the schema/router already knew how to consume.
7
+ */
8
+ export function billingKnowledgeForAuthRoute(evidence) {
9
+ if (evidence.route === "managed_api_key")
10
+ return "metered";
11
+ if (evidence.route === "vendor_native" && evidence.verification === "passed") {
12
+ return "subscription_entitlement";
13
+ }
14
+ return "unknown";
15
+ }
1
16
  export class RoutingPreflightError extends Error {
2
17
  code = "routing_preflight_refused";
3
18
  }
@@ -8,8 +23,15 @@ function tierIndex(candidate, ctx) {
8
23
  route.effort === candidate.effort));
9
24
  return index < 0 ? null : index;
10
25
  }
26
+ /** Effective billing knowledge: the typed auth route is authoritative when
27
+ * present (QA-034), else the explicitly supplied value, else unknown. */
28
+ function effectiveBilling(candidate) {
29
+ if (candidate.authRoute)
30
+ return billingKnowledgeForAuthRoute(candidate.authRoute);
31
+ return candidate.billingKnowledge ?? "unknown";
32
+ }
11
33
  function isIncrementalPaid(candidate) {
12
- return !["proven_zero", "subscription_entitlement"].includes(candidate.billingKnowledge ?? "unknown");
34
+ return !["proven_zero", "subscription_entitlement"].includes(effectiveBilling(candidate));
13
35
  }
14
36
  function eligible(candidates, ctx) {
15
37
  const ready = candidates.filter((candidate) => candidate.available &&
@@ -21,36 +43,160 @@ function eligible(candidates, ctx) {
21
43
  return free;
22
44
  return ready;
23
45
  }
46
+ /** User-declared tier index the comparators order by (missing => MAX). Shared
47
+ * by the sort and the traced comparator so a "tier" claim is never re-derived. */
48
+ function tierValueOf(candidate, ctx) {
49
+ return tierIndex(candidate, ctx) ?? Number.MAX_SAFE_INTEGER;
50
+ }
51
+ /** Binding pace slack the `auto` comparator orders by; null = none observed. */
52
+ function autoSlack(candidate, ctx) {
53
+ return ctx.ledger.bindingPaceSlack(candidate.harnessId, candidate.credentialRoute, candidate.credentialSubjectId);
54
+ }
55
+ /** null slack collapses to this so a slack-carrying candidate always outranks a
56
+ * slack-less one, exactly as the comparator subtraction does. */
57
+ const AUTO_SLACK_ABSENT = Number.NEGATIVE_INFINITY;
58
+ /**
59
+ * The SINGLE traced comparator for `auto` (round-4 #3 — this rationale has been
60
+ * wrong three times). It returns both the pair ORDER and the AXIS that produced
61
+ * it, and is the only place the auto ordering is defined. `rankHarnesses` sorts
62
+ * by `.order`; `rankingReason` reads `.axis`. Deriving the recorded reason from
63
+ * the very comparator that ordered the pool makes it structurally impossible for
64
+ * the rationale to claim a factor the sort did not use (the axis-registry
65
+ * pattern used in arbitration, specialized to auto's conditional slack axis).
66
+ *
67
+ * The slack axis is in force whenever EITHER candidate has a non-null slack; the
68
+ * subtraction of the (null => -Infinity) effective values is what decides — so
69
+ * two EQUAL non-null slacks yield order 0 and a null axis (declared order, and
70
+ * the sort does NOT fall through to tiers). Only when BOTH slacks are absent
71
+ * does the comparator compare tier indices.
72
+ */
73
+ function compareAutoTraced(a, b, ctx) {
74
+ const aSlack = autoSlack(a, ctx);
75
+ const bSlack = autoSlack(b, ctx);
76
+ if (aSlack !== null || bSlack !== null) {
77
+ const order = (bSlack ?? AUTO_SLACK_ABSENT) - (aSlack ?? AUTO_SLACK_ABSENT);
78
+ return { order, axis: order !== 0 ? "expiring_quota_slack" : null };
79
+ }
80
+ const order = tierValueOf(a, ctx) - tierValueOf(b, ctx);
81
+ return { order, axis: order !== 0 ? "quality_tier" : null };
82
+ }
24
83
  /** Order candidates transparently; lower tuple values win. Unknown quota remains eligible. */
25
84
  export function rankHarnesses(candidates, ctx) {
26
85
  const routes = eligible(candidates, ctx);
27
86
  if (ctx.goal === "quality" && routes.every((candidate) => tierIndex(candidate, ctx) === null)) {
28
87
  throw new RoutingPreflightError(`quality routing requires a comparable user-declared tier for intent '${ctx.intent}'`);
29
88
  }
89
+ if (ctx.goal === "auto") {
90
+ return routes.toSorted((a, b) => compareAutoTraced(a, b, ctx).order);
91
+ }
30
92
  return routes.toSorted((a, b) => {
31
- const aTier = tierIndex(a, ctx) ?? Number.MAX_SAFE_INTEGER;
32
- const bTier = tierIndex(b, ctx) ?? Number.MAX_SAFE_INTEGER;
93
+ const aTier = tierValueOf(a, ctx);
94
+ const bTier = tierValueOf(b, ctx);
33
95
  if (ctx.goal === "quality")
34
96
  return aTier - bTier;
35
- if (ctx.goal === "economy") {
36
- const aPaid = isIncrementalPaid(a) ? 1 : 0;
37
- const bPaid = isIncrementalPaid(b) ? 1 : 0;
38
- const paidOrder = aPaid - bPaid;
39
- if (paidOrder !== 0)
40
- return paidOrder;
41
- const aCost = a.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
42
- const bCost = b.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
43
- return aCost - bCost || aTier - bTier;
44
- }
45
- const aSlack = ctx.ledger.bindingPaceSlack(a.harnessId, a.credentialRoute, a.credentialSubjectId);
46
- const bSlack = ctx.ledger.bindingPaceSlack(b.harnessId, b.credentialRoute, b.credentialSubjectId);
47
- if (aSlack !== null || bSlack !== null) {
48
- return (bSlack ?? Number.NEGATIVE_INFINITY) - (aSlack ?? Number.NEGATIVE_INFINITY);
49
- }
50
- return aTier - bTier;
97
+ // economy
98
+ const aPaid = isIncrementalPaid(a) ? 1 : 0;
99
+ const bPaid = isIncrementalPaid(b) ? 1 : 0;
100
+ const paidOrder = aPaid - bPaid;
101
+ if (paidOrder !== 0)
102
+ return paidOrder;
103
+ const aCost = a.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
104
+ const bCost = b.incrementalCostUsd ?? Number.POSITIVE_INFINITY;
105
+ return aCost - bCost || aTier - bTier;
51
106
  });
52
107
  }
53
108
  export function selectHarness(candidates, ctx) {
54
109
  return rankHarnesses(candidates, ctx)[0] ?? null;
55
110
  }
111
+ /**
112
+ * Explain a ranking as a typed record (QA-034): the per-candidate billing/cost
113
+ * tuple, the eligible/dropped split, and the DECISIVE reason. Kept axis-aligned
114
+ * with rankHarnesses so the recorded rationale can never disagree with the
115
+ * order actually taken. Prose-free; a surface projects it, never reconstructs it.
116
+ * The shape is the schema-owned RouteRankingRationale (snake_case) so it can be
117
+ * persisted verbatim as RunTelemetry.routing_rationale.
118
+ */
119
+ export function explainRanking(candidates, ctx) {
120
+ const rankedCandidates = rankHarnesses(candidates, ctx);
121
+ const order = rankedCandidates.map((c) => c.harnessId);
122
+ const eligibleIds = new Set(order);
123
+ const entries = candidates.map((c) => ({
124
+ harness_id: c.harnessId,
125
+ billing_knowledge: effectiveBilling(c),
126
+ incremental_cost_usd: c.incrementalCostUsd ?? null,
127
+ eligible: eligibleIds.has(c.harnessId),
128
+ }));
129
+ const dropped = candidates.filter((c) => !eligibleIds.has(c.harnessId)).map((c) => c.harnessId);
130
+ const reason = rankingReason(ctx, rankedCandidates, candidates);
131
+ return { goal: ctx.goal, paid_fallback: ctx.paidFallback, order, dropped, reason, entries };
132
+ }
133
+ /** Do the ranked candidates carry two distinct user-declared tier indices? Only
134
+ * then did the tier comparator (the auto/economy tie-break) actually decide the
135
+ * order; a single candidate or a uniform tier index leaves the declared order. */
136
+ function tiersDistinguish(ranked, ctx) {
137
+ const indices = ranked.map((c) => tierIndex(c, ctx) ?? Number.MAX_SAFE_INTEGER);
138
+ return indices.some((value) => value !== indices[0]);
139
+ }
140
+ /** Do the ranked candidates carry two distinct incremental costs (with the SAME
141
+ * missing-cost fallback the economy sort uses)? Only then did the cost
142
+ * comparator — not the paid/free split above it or the tier tie-break below —
143
+ * actually decide the order. */
144
+ function costsDistinguish(ranked) {
145
+ const costs = ranked.map((c) => c.incrementalCostUsd ?? Number.POSITIVE_INFINITY);
146
+ return costs.some((value) => value !== costs[0]);
147
+ }
148
+ /**
149
+ * The DECISIVE comparator axis. For `auto` the reason is read directly off the
150
+ * SAME traced comparator that ordered the pool (`compareAutoTraced`) — never
151
+ * re-derived from a separately-recomputed condition (round-4 #3, the third
152
+ * recurrence of a rationale that disagreed with `rankHarnesses`): the reason is
153
+ * whichever axis actually separated an adjacent ranked pair, and `declared_order`
154
+ * when the comparator broke no pair (e.g. equal non-null slacks — which do NOT
155
+ * fall through to tiers).
156
+ */
157
+ function rankingReason(ctx, ranked, candidates) {
158
+ if (ctx.goal === "quality")
159
+ return "quality_tier";
160
+ if (ctx.goal === "auto") {
161
+ // Walk the ranked order through the very comparator that produced it. Since
162
+ // the pool is sorted, any two distinct axis values leave a differing
163
+ // adjacent pair, so this sees every axis the sort actually used.
164
+ const axes = new Set();
165
+ for (let i = 0; i + 1 < ranked.length; i++) {
166
+ const traced = compareAutoTraced(ranked[i], ranked[i + 1], ctx);
167
+ if (traced.axis)
168
+ axes.add(traced.axis);
169
+ }
170
+ if (axes.has("expiring_quota_slack"))
171
+ return "expiring_quota_slack";
172
+ if (axes.has("quality_tier"))
173
+ return "quality_tier";
174
+ return "declared_order";
175
+ }
176
+ // economy: mirror the economy sort tuple EXACTLY — (isIncrementalPaid,
177
+ // incrementalCostUsd, tierIndex) — and report the FIRST axis that actually
178
+ // SEPARATED the pool. Reporting entitlement whenever ANY route is entitled was
179
+ // wrong when they are ALL entitled and cost/tier did the deciding (the same
180
+ // correction made for `auto` in 1d6a2a50).
181
+ const someEntitled = ranked.some((c) => !isIncrementalPaid(c));
182
+ // Entitlement decided when the pool actually WEIGHED an entitled route against
183
+ // a paid one — whether the paid route was ranked BELOW (sort axis 1) or DROPPED
184
+ // by paid_fallback (both are the entitled-preferred-over-paid outcome). When
185
+ // every route CONSIDERED is entitled, entitlement did not decide — cost/tier
186
+ // did (the round-3 correction; matches the pool-wide `auto` mirror in
187
+ // 1d6a2a50). The full candidate set (not just the eligible pool) is consulted
188
+ // so a paid route dropped by paid_fallback:never still attributes the outcome.
189
+ const anyPaidConsidered = candidates.some((c) => isIncrementalPaid(c));
190
+ if (someEntitled && anyPaidConsidered)
191
+ return "subscription_entitlement_first";
192
+ if (costsDistinguish(ranked))
193
+ return "lowest_incremental_cash";
194
+ if (tiersDistinguish(ranked, ctx))
195
+ return "quality_tier";
196
+ // Nothing separated the pool: distinguish "we could not compare cash at all"
197
+ // from a genuine declared-order tie.
198
+ if (ranked.length > 0 && ranked.some((c) => c.incrementalCostUsd == null))
199
+ return "all_incremental_cash_unknown";
200
+ return "declared_order";
201
+ }
56
202
  //# sourceMappingURL=router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claudexor/budget",
3
- "version": "3.0.3",
3
+ "version": "3.1.0",
4
4
  "license": "MIT",
5
5
  "description": "Budget governor: pre-call leases, circuit breaker, evidence-based routing goals, and multi-window quota pacing.",
6
6
  "type": "module",
@@ -16,8 +16,8 @@
16
16
  "dist"
17
17
  ],
18
18
  "dependencies": {
19
- "@claudexor/schema": "3.0.3",
20
- "@claudexor/util": "3.0.3"
19
+ "@claudexor/util": "3.1.0",
20
+ "@claudexor/schema": "3.1.0"
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",