@trazum/core 1.50.9 → 1.50.11

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,QAAQ,GACT,MAAM,YAAY,CAAC;AAWpB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAClF,gFAAgF;AAChF,4EAA4E;AAC5E,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEtF,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,0EAA0E;AAC1E,yCAAyC;AACzC,4EAA4E;AAC5E,qDAAqD;AACrD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,eAAe,CAAC;AAQvB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAQzF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUvD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,aAAa,CAAC;AASrB,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAiB1B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAYpF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAW7E,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAqB7E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAU7E,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAiBxB,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAExE,2EAA2E;AAC3E,8DAA8D;AAC9D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACnE,2EAA2E;AAC3E,+DAA+D;AAC/D,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGxF,yEAAyE;AACzE,mEAAmE;AACnE,2BAA2B;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACxF,4EAA4E;AAC5E,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOhF,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI1C,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQpG,OAAO,EACL,MAAM,EACN,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAC;AAItB,uEAAuE;AACvE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,UAAU;AACV,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAErF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAQvB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,+EAA+E;AAC/E,+EAA+E;AAC/E,6DAA6D;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAS/C,gFAAgF;AAChF,gFAAgF;AAChF,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOtE,4EAA4E;AAC5E,6EAA6E;AAC7E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtF,8EAA8E;AAC9E,2EAA2E;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,EACf,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAWlB,uBAAuB;AACvB,OAAO,EACL,cAAc,EACd,OAAO,EACP,WAAW,EACX,QAAQ,EACR,WAAW,EACX,aAAa,EACb,EAAE,EACF,EAAE,GACH,MAAM,iBAAiB,CAAC;AAGzB,sBAAsB;AACtB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEpE,kDAAkD;AAClD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,eAAe,EACf,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAGlB,6BAA6B;AAC7B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGpE,qEAAqE;AACrE,OAAO,EAAE,cAAc,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAG3E,kFAAkF;AAClF,kFAAkF;AAClF,wCAAwC;AACxC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGzF,mEAAmE;AACnE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGjE,gCAAgC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQ9C,0EAA0E;AAC1E,+EAA+E;AAC/E,8EAA8E;AAC9E,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEzD,8EAA8E;AAC9E,6EAA6E;AAC7E,2DAA2D;AAC3D,OAAO,EACL,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,SAAS,EACT,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Whose budget — the question that decides whether anything on the list gets
3
+ * done.
4
+ *
5
+ * The fleet answered *which service* in 1.37. Nobody has answered *whose
6
+ * money*, and until somebody does, every finding this product makes lands on a
7
+ * desk with no name on it. A report that says "the bill is $40,000 and here is
8
+ * how to save $9,000" is read by four people who each assume it is one of the
9
+ * other three's problem.
10
+ *
11
+ * ## The unallocated is its own line, and it is never spread
12
+ *
13
+ * The one rule worth breaking the module over.
14
+ *
15
+ * Splitting unattributed spend proportionally across the owners you *do* know
16
+ * is the single most common lie in cost reporting. It is attractive because it
17
+ * makes the numbers add up and every line look complete. What it actually does
18
+ * is make **every team's figure wrong**, by an amount nobody can see, in a
19
+ * direction nobody can check — and it does it most to the teams with the
20
+ * cleanest instrumentation, because they are the ones whose known spend is
21
+ * largest and who therefore absorb the biggest share of somebody else's
22
+ * mystery.
23
+ *
24
+ * So the unallocated stays a line of its own, with its own dollar figure, until
25
+ * a human claims it. It is loud on purpose: an unallocated share that grows
26
+ * quietly is a chargeback report becoming fiction one month at a time.
27
+ *
28
+ * ## Shared cost is declared, never inferred
29
+ *
30
+ * A workload two teams use is split by a rule somebody wrote down, and **the
31
+ * rule travels with the report**. That is the whole design: the argument then
32
+ * happens about the rule — "why is search 60/40?" — rather than about the
33
+ * number, which is an argument nobody can win because nobody can see where the
34
+ * number came from.
35
+ *
36
+ * A split that does not sum to one is a configuration error and not a rounding
37
+ * problem, because the alternative is silently losing or inventing money.
38
+ *
39
+ * ## An owner with no measured data is not an owner under budget
40
+ *
41
+ * `fleetBudgetMissing`, from 1.37, applied to people. A team whose logs never
42
+ * arrived passes every budget it has, forever, and a report that renders that
43
+ * as a green tick has told somebody the opposite of the truth.
44
+ */
45
+ /** How one workload's spend is divided between owners. Sums to 1. */
46
+ export type SharedSplit = Record<string, number>;
47
+ export interface OwnersConfig {
48
+ /** Label patterns per owner. Most specific wins, as everywhere in this tool. */
49
+ patterns: Record<string, string[]>;
50
+ /**
51
+ * Workloads two or more owners share, split by a rule a human wrote.
52
+ *
53
+ * Keyed by the exact label rather than by a pattern: a shared split is a
54
+ * negotiated fact about one workload, and letting it match a glob would mean
55
+ * a new label silently joining somebody's bill.
56
+ */
57
+ shared?: Record<string, SharedSplit>;
58
+ /** Monthly budgets per owner, in dollars. */
59
+ budgets?: Record<string, number>;
60
+ }
61
+ export type OwnerProblem = {
62
+ kind: 'split-does-not-sum';
63
+ label: string;
64
+ total: number;
65
+ } | {
66
+ kind: 'split-names-unknown-owner';
67
+ label: string;
68
+ owner: string;
69
+ } | {
70
+ kind: 'split-has-one-owner';
71
+ label: string;
72
+ owner: string;
73
+ } | {
74
+ kind: 'budget-for-unknown-owner';
75
+ owner: string;
76
+ } | {
77
+ kind: 'negative-share';
78
+ label: string;
79
+ owner: string;
80
+ share: number;
81
+ };
82
+ /**
83
+ * Everything wrong with an ownership config, before any money is attributed.
84
+ *
85
+ * Returned rather than thrown, so all of it can be reported at once. A
86
+ * chargeback config fixed one error per run is a chargeback config somebody
87
+ * abandons halfway and then never trusts.
88
+ */
89
+ export declare function validateOwners(config: OwnersConfig): OwnerProblem[];
90
+ /** One workload's spend, as the caller measured it. */
91
+ export interface LabelSpend {
92
+ label: string;
93
+ usd: number;
94
+ calls: number;
95
+ }
96
+ export type OwnerVerdict = 'within' | 'over' | 'not-measured' | 'no-budget';
97
+ export interface OwnerLine {
98
+ owner: string;
99
+ usd: number;
100
+ calls: number;
101
+ /** Which labels landed here, and how — so the attribution is checkable. */
102
+ from: Array<{
103
+ label: string;
104
+ usd: number;
105
+ via: 'pattern' | 'shared';
106
+ share?: number;
107
+ }>;
108
+ budgetUsd: number | null;
109
+ verdict: OwnerVerdict;
110
+ }
111
+ export interface Allocation {
112
+ owners: OwnerLine[];
113
+ /**
114
+ * Spend that matched no owner — its own line, never spread.
115
+ *
116
+ * `labels` names them, because "unallocated: $4,300" invites somebody to
117
+ * divide it and "unallocated: $4,300 across `search-v2` and `internal-eval`"
118
+ * invites somebody to claim it.
119
+ */
120
+ unallocated: {
121
+ usd: number;
122
+ calls: number;
123
+ labels: string[];
124
+ };
125
+ /** The shared rules that were applied, carried so the report can print them. */
126
+ sharedApplied: Array<{
127
+ label: string;
128
+ split: SharedSplit;
129
+ }>;
130
+ problems: OwnerProblem[];
131
+ }
132
+ export declare function allocate(spend: readonly LabelSpend[], config: OwnersConfig): Allocation;
133
+ //# sourceMappingURL=owners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owners.d.ts","sourceRoot":"","sources":["../src/owners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAKH,qEAAqE;AACrE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,2BAA2B,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,0BAA0B,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,EAAE,CAoCnE;AAED,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,cAAc,GAAG,WAAW,CAAC;AAE5E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,IAAI,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,SAAS,GAAG,QAAQ,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;;;;;;OAMG;IACH,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9D,gFAAgF;IAChF,aAAa,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAC5D,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,UAAU,CA+GvF"}
package/dist/owners.js ADDED
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Whose budget — the question that decides whether anything on the list gets
3
+ * done.
4
+ *
5
+ * The fleet answered *which service* in 1.37. Nobody has answered *whose
6
+ * money*, and until somebody does, every finding this product makes lands on a
7
+ * desk with no name on it. A report that says "the bill is $40,000 and here is
8
+ * how to save $9,000" is read by four people who each assume it is one of the
9
+ * other three's problem.
10
+ *
11
+ * ## The unallocated is its own line, and it is never spread
12
+ *
13
+ * The one rule worth breaking the module over.
14
+ *
15
+ * Splitting unattributed spend proportionally across the owners you *do* know
16
+ * is the single most common lie in cost reporting. It is attractive because it
17
+ * makes the numbers add up and every line look complete. What it actually does
18
+ * is make **every team's figure wrong**, by an amount nobody can see, in a
19
+ * direction nobody can check — and it does it most to the teams with the
20
+ * cleanest instrumentation, because they are the ones whose known spend is
21
+ * largest and who therefore absorb the biggest share of somebody else's
22
+ * mystery.
23
+ *
24
+ * So the unallocated stays a line of its own, with its own dollar figure, until
25
+ * a human claims it. It is loud on purpose: an unallocated share that grows
26
+ * quietly is a chargeback report becoming fiction one month at a time.
27
+ *
28
+ * ## Shared cost is declared, never inferred
29
+ *
30
+ * A workload two teams use is split by a rule somebody wrote down, and **the
31
+ * rule travels with the report**. That is the whole design: the argument then
32
+ * happens about the rule — "why is search 60/40?" — rather than about the
33
+ * number, which is an argument nobody can win because nobody can see where the
34
+ * number came from.
35
+ *
36
+ * A split that does not sum to one is a configuration error and not a rounding
37
+ * problem, because the alternative is silently losing or inventing money.
38
+ *
39
+ * ## An owner with no measured data is not an owner under budget
40
+ *
41
+ * `fleetBudgetMissing`, from 1.37, applied to people. A team whose logs never
42
+ * arrived passes every budget it has, forever, and a report that renders that
43
+ * as a green tick has told somebody the opposite of the truth.
44
+ */
45
+ import { mostSpecificMatch } from './glob.js';
46
+ import { UNLABELLED } from './usage.js';
47
+ /**
48
+ * Everything wrong with an ownership config, before any money is attributed.
49
+ *
50
+ * Returned rather than thrown, so all of it can be reported at once. A
51
+ * chargeback config fixed one error per run is a chargeback config somebody
52
+ * abandons halfway and then never trusts.
53
+ */
54
+ export function validateOwners(config) {
55
+ const problems = [];
56
+ const known = new Set(Object.keys(config.patterns));
57
+ for (const [label, split] of Object.entries(config.shared ?? {})) {
58
+ const entries = Object.entries(split);
59
+ if (entries.length === 1) {
60
+ // A "shared" workload with one owner is a pattern written the long way,
61
+ // and reading it as a share invites a second one to be added without the
62
+ // first being adjusted.
63
+ problems.push({ kind: 'split-has-one-owner', label, owner: entries[0]?.[0] ?? '' });
64
+ }
65
+ let total = 0;
66
+ for (const [owner, share] of entries) {
67
+ if (!known.has(owner))
68
+ problems.push({ kind: 'split-names-unknown-owner', label, owner });
69
+ if (share < 0)
70
+ problems.push({ kind: 'negative-share', label, owner, share });
71
+ total += share;
72
+ }
73
+ /**
74
+ * Summing to one, within a hair for floating point.
75
+ *
76
+ * Not a rounding problem to be normalised away: a split that sums to 0.9
77
+ * loses a tenth of that workload's money and a split that sums to 1.1
78
+ * invents a tenth. Both are silent, and both are the kind of error a
79
+ * chargeback report exists to make impossible.
80
+ */
81
+ if (entries.length > 0 && Math.abs(total - 1) > 1e-9) {
82
+ problems.push({ kind: 'split-does-not-sum', label, total });
83
+ }
84
+ }
85
+ for (const owner of Object.keys(config.budgets ?? {})) {
86
+ if (!known.has(owner))
87
+ problems.push({ kind: 'budget-for-unknown-owner', owner });
88
+ }
89
+ return problems;
90
+ }
91
+ export function allocate(spend, config) {
92
+ const problems = validateOwners(config);
93
+ const lines = new Map();
94
+ const ensure = (owner) => {
95
+ let line = lines.get(owner);
96
+ if (line === undefined) {
97
+ const budgetUsd = config.budgets?.[owner] ?? null;
98
+ line = { owner, usd: 0, calls: 0, from: [], budgetUsd, verdict: 'no-budget' };
99
+ lines.set(owner, line);
100
+ }
101
+ return line;
102
+ };
103
+ /**
104
+ * Every declared owner gets a line, measured or not.
105
+ *
106
+ * An owner absent from the report is an owner nobody looks at, and the
107
+ * refusal below — "not measured is not under budget" — cannot be printed for
108
+ * somebody who is not on the page.
109
+ */
110
+ for (const owner of Object.keys(config.patterns))
111
+ ensure(owner);
112
+ const unallocatedLabels = [];
113
+ let unallocatedUsd = 0;
114
+ let unallocatedCalls = 0;
115
+ // Flattened so specificity decides across owners, as `assignSources` does.
116
+ const patterns = [];
117
+ for (const [owner, globs] of Object.entries(config.patterns)) {
118
+ for (const pattern of globs)
119
+ patterns.push({ pattern, owner });
120
+ }
121
+ const sharedApplied = [];
122
+ const brokenSplits = new Set(problems
123
+ .filter((p) => p.kind === 'split-does-not-sum' || p.kind === 'negative-share')
124
+ .map((p) => p.label));
125
+ for (const entry of spend) {
126
+ const split = config.shared?.[entry.label];
127
+ /**
128
+ * A broken split allocates **nothing**, and the workload falls to
129
+ * unallocated.
130
+ *
131
+ * Applying a split that sums to 0.9 would put ten per cent of that
132
+ * workload nowhere while every line still looked complete. Falling to
133
+ * unallocated puts the whole workload somewhere visible, next to the
134
+ * problem that explains it.
135
+ */
136
+ if (split !== undefined && !brokenSplits.has(entry.label)) {
137
+ sharedApplied.push({ label: entry.label, split });
138
+ for (const [owner, share] of Object.entries(split)) {
139
+ const line = ensure(owner);
140
+ line.usd += entry.usd * share;
141
+ line.calls += entry.calls * share;
142
+ line.from.push({ label: entry.label, usd: entry.usd * share, via: 'shared', share });
143
+ }
144
+ continue;
145
+ }
146
+ const matched = entry.label === UNLABELLED
147
+ ? null
148
+ : mostSpecificMatch(patterns.map((p) => p.pattern), entry.label);
149
+ const owner = matched === null ? null : patterns.find((p) => p.pattern === matched)?.owner ?? null;
150
+ if (owner === null) {
151
+ unallocatedUsd += entry.usd;
152
+ unallocatedCalls += entry.calls;
153
+ unallocatedLabels.push(entry.label);
154
+ continue;
155
+ }
156
+ const line = ensure(owner);
157
+ line.usd += entry.usd;
158
+ line.calls += entry.calls;
159
+ line.from.push({ label: entry.label, usd: entry.usd, via: 'pattern' });
160
+ }
161
+ for (const line of lines.values()) {
162
+ line.from.sort((a, b) => b.usd - a.usd);
163
+ /**
164
+ * `not-measured` rather than `within`, and they are different words on
165
+ * purpose.
166
+ *
167
+ * A team whose logs never arrived passes every budget it has, forever. A
168
+ * report that renders that as a green tick has told somebody the opposite
169
+ * of the truth — the 1.37 refusal, applied to people rather than services.
170
+ */
171
+ line.verdict =
172
+ line.budgetUsd === null
173
+ ? 'no-budget'
174
+ : line.calls === 0
175
+ ? 'not-measured'
176
+ : line.usd > line.budgetUsd
177
+ ? 'over'
178
+ : 'within';
179
+ }
180
+ return {
181
+ owners: [...lines.values()].sort((a, b) => b.usd - a.usd),
182
+ unallocated: {
183
+ usd: unallocatedUsd,
184
+ calls: unallocatedCalls,
185
+ labels: [...new Set(unallocatedLabels)].sort(),
186
+ },
187
+ sharedApplied,
188
+ problems,
189
+ };
190
+ }
191
+ //# sourceMappingURL=owners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owners.js","sourceRoot":"","sources":["../src/owners.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"savings.d.ts","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,aAAa,GAAE,MAA+B,GAC7C,aAAa,CAKf;AAUD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,EAAE,GAAE,IAAiB,EACrB,OAAO,GAAE,gBAAoC,GAC5C,aAAa,CAsCf;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrD"}
1
+ {"version":3,"file":"savings.d.ts","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,aAAa,GAAE,MAA+B,GAC7C,aAAa,CAKf;AAUD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,EACnB,EAAE,GAAE,IAAiB,EACrB,OAAO,GAAE,gBAAoC,GAC5C,aAAa,CAsCf;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoB/C;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrD"}
package/dist/savings.js CHANGED
@@ -57,12 +57,25 @@ export function computeSavings(tokensBefore, tokensAfter, usage, on = new Date()
57
57
  export function formatUsd(value) {
58
58
  if (value === 0)
59
59
  return '$0';
60
+ /**
61
+ * The branch is chosen on the **rounded** value, not the raw one.
62
+ *
63
+ * `999.998` is under a thousand, so the old version took the two-decimal
64
+ * branch and rendered `$1000.00` — a string the thousands branch would never
65
+ * produce, sitting in a column beside `$5,000` and looking like a different
66
+ * currency format for the same magnitude. Floating point puts values there
67
+ * routinely: a saving of exactly a thousand dollars, computed as
68
+ * `5000 - 5000 * 0.8`, lands at `999.9999999999999`.
69
+ *
70
+ * Rounding first makes the boundary the number a reader sees rather than the
71
+ * number the machine holds.
72
+ */
60
73
  const abs = Math.abs(value);
61
74
  if (abs < 0.01)
62
75
  return `$${value.toFixed(5)}`;
63
76
  if (abs < 1)
64
77
  return `$${value.toFixed(4)}`;
65
- if (abs < 1000)
78
+ if (Math.round(abs * 100) / 100 < 1000)
66
79
  return `$${value.toFixed(2)}`;
67
80
  return `$${value.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;
68
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"savings.js","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"savings.js","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trazum/core",
3
- "version": "1.50.9",
3
+ "version": "1.50.11",
4
4
  "description": "Trazum core: priced advisories for LLM prompts (caching, model tier, batching, schemas), plus deterministic trimming, token counting and pricing.",
5
5
  "license": "MIT",
6
6
  "author": "David Mu\u00f1oz Rey",
@@ -0,0 +1,208 @@
1
+ /**
2
+ * What a committed-use deal would have been worth **on the traffic you
3
+ * actually had**.
4
+ *
5
+ * Providers sell committed-use and reserved-capacity contracts, and every team
6
+ * that signs one is doing arithmetic in a spreadsheet against a number they
7
+ * guessed. That is exactly the failure this product exists to end — and it is
8
+ * the highest-stakes instance of it, because the guess is annual and signed.
9
+ *
10
+ * ## An as-if calculation, and the wording never blurs it
11
+ *
12
+ * "On the traffic you actually had, this commitment would have saved $X" is a
13
+ * measurement of the past.
14
+ *
15
+ * "You will save $X" is a claim about the future, and this product has refused
16
+ * that at every scale since 1.27. Nothing here projects, extrapolates, fits a
17
+ * trend or annualises a partial month. Every figure describes months that
18
+ * happened, and the type says so in a field a machine reader can check.
19
+ *
20
+ * ## Both directions, because one direction is the sales pitch
21
+ *
22
+ * A commitment is a **floor** as well as a discount. Below the floor you pay
23
+ * for capacity you did not use, and a saving quoted without that half is not
24
+ * an analysis — it is the vendor's slide.
25
+ *
26
+ * So every month is priced both ways, the months that would have fallen short
27
+ * are counted and named, and what the unused floor would have cost is its own
28
+ * figure rather than netted quietly against the good months.
29
+ *
30
+ * ## The shortfall risk is a count, not a probability
31
+ *
32
+ * "Three of your last twelve months would have fallen short, by $400, $150 and
33
+ * $2,900" is a measurement. "There is a 25% chance of shortfall" is a model of
34
+ * a distribution nobody fitted, presented with the authority of arithmetic.
35
+ * Only the first is available from a log, so only the first is printed.
36
+ */
37
+
38
+ /** The deal, as the provider states it. */
39
+ export interface CommitmentTerms {
40
+ /**
41
+ * What you commit to spending each month, **after** the discount — which is
42
+ * how these contracts are almost always written.
43
+ *
44
+ * If your discounted usage comes in under this, you pay this anyway.
45
+ */
46
+ monthlyFloorUsd: number;
47
+ /** The discount, 0-1. 0.2 is twenty per cent off. */
48
+ discount: number;
49
+ /** How many months the commitment runs. */
50
+ months: number;
51
+ }
52
+
53
+ /** One measured month, as the caller sliced it. */
54
+ export interface MeasuredMonth {
55
+ /** `YYYY-MM`. */
56
+ month: string;
57
+ usd: number;
58
+ }
59
+
60
+ export interface MonthReplay {
61
+ month: string;
62
+ /** What was actually paid, with no commitment. */
63
+ listUsd: number;
64
+ /** What the discounted usage would have come to. */
65
+ discountedUsd: number;
66
+ /** What would actually have been paid: the floor, or the discounted usage. */
67
+ paidUsd: number;
68
+ /** Positive means the commitment saved money that month. */
69
+ savingUsd: number;
70
+ /** Whether the floor was the binding number — a month that fell short. */
71
+ shortfall: boolean;
72
+ /** What the unused floor cost, in a month that fell short. Zero otherwise. */
73
+ unusedFloorUsd: number;
74
+ }
75
+
76
+ export type CommitmentUnknown =
77
+ | 'no-history'
78
+ | 'too-few-months'
79
+ | 'partial-months-excluded-everything';
80
+
81
+ export interface CommitmentReplay {
82
+ /**
83
+ * Always `measured-past`. There is no other value, and the field exists so a
84
+ * machine reader cannot mistake this for a projection — the same reason
85
+ * every other document in this product carries its provenance.
86
+ */
87
+ provenance: 'measured-past';
88
+ months: MonthReplay[];
89
+ /** Summed over the months replayed, positive meaning the deal won. */
90
+ netUsd: number;
91
+ /** What the good months saved, before the shortfalls are taken off. */
92
+ savedInGoodMonthsUsd: number;
93
+ /**
94
+ * What the shortfall months cost, kept as its own figure.
95
+ *
96
+ * Netted against the savings it disappears, and the disappearing is the
97
+ * whole trick a vendor's slide relies on.
98
+ */
99
+ lostToUnusedFloorUsd: number;
100
+ /** How many of the measured months would have fallen short. A count, never a rate. */
101
+ shortfallMonths: number;
102
+ /**
103
+ * The monthly spend at which the commitment stops losing money.
104
+ *
105
+ * Equal to the floor: below it you pay the floor for less usage. Above it
106
+ * the saving grows, first as (spend − floor) and then, once discounted usage
107
+ * clears the floor, as spend × discount.
108
+ */
109
+ breakEvenMonthlyUsd: number;
110
+ /**
111
+ * Measured spread across the months replayed — lowest and highest, and how
112
+ * far the range spans as a share of the median.
113
+ *
114
+ * The honest form of "shortfall risk": a reader looking at a range wider than
115
+ * the floor can see the deal is a bet, without anybody modelling a
116
+ * distribution nobody fitted.
117
+ */
118
+ spread: { lowUsd: number; highUsd: number; medianUsd: number } | null;
119
+ /** Set when nothing could be replayed. A refusal never arrives bare. */
120
+ unknown: CommitmentUnknown | null;
121
+ /** How many whole months would settle it, when there are too few. */
122
+ monthsNeeded: number | null;
123
+ }
124
+
125
+ /**
126
+ * The fewest whole months worth replaying a commitment against.
127
+ *
128
+ * Three. Two months cannot show a shortfall pattern and one cannot show
129
+ * anything at all — and a commitment is signed for a year, so an answer from a
130
+ * single month is a year-long decision made on a fortnight of evidence.
131
+ */
132
+ export const MIN_MONTHS_FOR_REPLAY = 3;
133
+
134
+ export function replayCommitment(
135
+ history: readonly MeasuredMonth[],
136
+ terms: CommitmentTerms,
137
+ ): CommitmentReplay {
138
+ const bare = (unknown: CommitmentUnknown, have: number): CommitmentReplay => ({
139
+ provenance: 'measured-past',
140
+ months: [],
141
+ netUsd: 0,
142
+ savedInGoodMonthsUsd: 0,
143
+ lostToUnusedFloorUsd: 0,
144
+ shortfallMonths: 0,
145
+ breakEvenMonthlyUsd: terms.monthlyFloorUsd,
146
+ spread: null,
147
+ unknown,
148
+ monthsNeeded: Math.max(0, MIN_MONTHS_FOR_REPLAY - have),
149
+ });
150
+
151
+ if (history.length === 0) return bare('no-history', 0);
152
+ if (history.length < MIN_MONTHS_FOR_REPLAY) return bare('too-few-months', history.length);
153
+
154
+ const months: MonthReplay[] = history.map((entry) => {
155
+ const discountedUsd = entry.usd * (1 - terms.discount);
156
+ const shortfall = discountedUsd < terms.monthlyFloorUsd;
157
+ const paidUsd = shortfall ? terms.monthlyFloorUsd : discountedUsd;
158
+ return {
159
+ month: entry.month,
160
+ listUsd: entry.usd,
161
+ discountedUsd,
162
+ paidUsd,
163
+ savingUsd: entry.usd - paidUsd,
164
+ shortfall,
165
+ // What the floor bought that nobody used. Its own figure, never netted.
166
+ unusedFloorUsd: shortfall ? terms.monthlyFloorUsd - discountedUsd : 0,
167
+ };
168
+ });
169
+
170
+ const sorted = [...history].map((m) => m.usd).sort((a, b) => a - b);
171
+ const mid = Math.floor(sorted.length / 2);
172
+ const medianUsd =
173
+ sorted.length % 2 === 0 ? ((sorted[mid - 1] ?? 0) + (sorted[mid] ?? 0)) / 2 : (sorted[mid] ?? 0);
174
+
175
+ return {
176
+ provenance: 'measured-past',
177
+ months,
178
+ netUsd: months.reduce((sum, m) => sum + m.savingUsd, 0),
179
+ savedInGoodMonthsUsd: months.filter((m) => !m.shortfall).reduce((sum, m) => sum + m.savingUsd, 0),
180
+ lostToUnusedFloorUsd: months.reduce((sum, m) => sum + m.unusedFloorUsd, 0),
181
+ shortfallMonths: months.filter((m) => m.shortfall).length,
182
+ breakEvenMonthlyUsd: terms.monthlyFloorUsd,
183
+ spread: { lowUsd: sorted[0] ?? 0, highUsd: sorted[sorted.length - 1] ?? 0, medianUsd },
184
+ unknown: null,
185
+ monthsNeeded: null,
186
+ };
187
+ }
188
+
189
+ /**
190
+ * Whether the replay covers as long as the commitment runs.
191
+ *
192
+ * Kept separate from the refusals because it does not stop the arithmetic: six
193
+ * months of history against a twelve-month deal is a real answer about six
194
+ * months, and saying so is more useful than refusing. What it must not do is
195
+ * go unsaid — a twelve-month decision read off half a year of evidence, with
196
+ * nothing on the page marking the gap, is the spreadsheet this module was
197
+ * written to replace.
198
+ */
199
+ export function coversTheTerm(
200
+ replay: CommitmentReplay,
201
+ terms: CommitmentTerms,
202
+ ): { covered: number; ofMonths: number; short: boolean } {
203
+ return {
204
+ covered: replay.months.length,
205
+ ofMonths: terms.months,
206
+ short: replay.months.length < terms.months,
207
+ };
208
+ }