@rulvar/evals 1.19.0 → 1.21.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/dist/index.js +39 -21
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -20,16 +20,27 @@ import { createHash } from "node:crypto";
|
|
|
20
20
|
* invocation and is never persisted.
|
|
21
21
|
*
|
|
22
22
|
* Accounting is integer micro-USD and conservative at the
|
|
23
|
-
* representation boundary (v1.17.0 review P1-4, hardened by the
|
|
24
|
-
* review P1-4
|
|
25
|
-
* (ceil), only ULP-scale
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
23
|
+
* representation boundary (v1.17.0 review P1-4, hardened by the
|
|
24
|
+
* v1.18.0 review P1-4 and the v1.19.0 review P1-3): the cap converts
|
|
25
|
+
* DOWN (floor), every debit converts UP (ceil), only ULP-scale
|
|
26
|
+
* representation noise may snap to the neighboring integer, amounts at
|
|
27
|
+
* or above 2^49 micro-USD (about $563M, where the noise window would
|
|
28
|
+
* reach half a micro and the nearest integer would stop being unique)
|
|
29
|
+
* are rejected, and a cap below one micro-USD is rejected outright.
|
|
30
|
+
*
|
|
31
|
+
* The exact input interpretation: every USD amount is a JavaScript
|
|
32
|
+
* double, and the envelope interprets a double within SNAP_ULPS ULPs
|
|
33
|
+
* of an integer micro value AS that integer; anything farther rounds
|
|
34
|
+
* in the conservative direction. Under that interpretation the sum of
|
|
35
|
+
* admitted ceilings can never exceed maxTotalUsd, and no positive
|
|
36
|
+
* ceiling ever debits zero. The honest raw-double bound: each admitted
|
|
37
|
+
* amount's double may sit below its interpreted integer by at most the
|
|
38
|
+
* noise window (4 ULPs, always under half a micro in-domain), so the
|
|
39
|
+
* sum of raw doubles can exceed the cap by at most half a micro-USD
|
|
40
|
+
* per admitted amount; distinguishing finer than that is impossible in
|
|
41
|
+
* double precision at the top of the domain. Amounts that are integer
|
|
42
|
+
* micro-USD up to float noise stay exact, so 0.1 + 0.2 against a 0.3
|
|
43
|
+
* envelope is a fit, not a float rejection.
|
|
33
44
|
*/
|
|
34
45
|
const MICRO = 1e6;
|
|
35
46
|
/**
|
|
@@ -51,16 +62,23 @@ function microOf(usd, direction) {
|
|
|
51
62
|
return direction === "floor" ? Math.floor(raw) : Math.ceil(raw);
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
|
-
* The accounting domain is integer micro-USD
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
65
|
+
* The accounting domain is integer micro-USD strictly below 2^49
|
|
66
|
+
* (at most $562,949,953.421311). Two limits meet there. Outside the
|
|
67
|
+
* safe integer range the arithmetic silently degrades: a
|
|
68
|
+
* Number.MAX_VALUE cap overflowed to Infinity and admitted EVERYTHING
|
|
69
|
+
* with remainingUsd NaN (v1.18.0 review P1-4). Well before that, from
|
|
70
|
+
* 2^49 micro upward, the SNAP_ULPS window reaches half a micro-USD:
|
|
71
|
+
* the nearest integer stops being unique and the snap absorbs genuine
|
|
72
|
+
* sub-micro remainders, so a ceil debit could round DOWN and admit an
|
|
73
|
+
* aggregate whose raw doubles sum above the cap by more than the
|
|
74
|
+
* documented noise bound (v1.19.0 review P1-3). Below 2^49 the window
|
|
75
|
+
* stays strictly under half a micro, the snap target is unique, and
|
|
76
|
+
* only representation noise is absorbed. Out-of-domain amounts are
|
|
77
|
+
* rejected up front.
|
|
61
78
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
79
|
+
const MAX_MICRO_EXCLUSIVE = 2 ** 49;
|
|
80
|
+
function requireDomainMicro(micro, what, usd) {
|
|
81
|
+
if (!Number.isSafeInteger(micro) || micro >= MAX_MICRO_EXCLUSIVE) throw new ConfigError(`${what} ${String(usd)} USD is outside the micro-USD accounting domain (at most \$562949953.421311)`);
|
|
64
82
|
return micro;
|
|
65
83
|
}
|
|
66
84
|
/** Thrown when authorizing a run's ceiling would exceed the envelope. */
|
|
@@ -93,7 +111,7 @@ var SpendEnvelope = class {
|
|
|
93
111
|
constructor(maxTotalUsd) {
|
|
94
112
|
if (!Number.isFinite(maxTotalUsd) || maxTotalUsd <= 0) throw new ConfigError(`SpendEnvelope maxTotalUsd must be a positive finite number, got ${String(maxTotalUsd)}`);
|
|
95
113
|
this.maxTotalUsd = maxTotalUsd;
|
|
96
|
-
this.maxMicroUsd =
|
|
114
|
+
this.maxMicroUsd = requireDomainMicro(microOf(maxTotalUsd, "floor"), "SpendEnvelope maxTotalUsd", maxTotalUsd);
|
|
97
115
|
if (this.maxMicroUsd < 1) throw new ConfigError(`SpendEnvelope maxTotalUsd ${String(maxTotalUsd)} is below the 1 micro-USD accounting granularity (\$0.000001); such an envelope could never admit a run`);
|
|
98
116
|
}
|
|
99
117
|
/** Total authorized so far (debit-only; never decreases). */
|
|
@@ -111,7 +129,7 @@ var SpendEnvelope = class {
|
|
|
111
129
|
*/
|
|
112
130
|
authorize(ceilingUsd, runLabel) {
|
|
113
131
|
if (ceilingUsd === void 0 || !Number.isFinite(ceilingUsd) || ceilingUsd <= 0) throw new ConfigError(`the spend envelope requires an explicit positive per-run ceiling for ${runLabel}; got ${String(ceilingUsd)} (an unbounded run under an aggregate envelope would be unaccountable)`);
|
|
114
|
-
const micro =
|
|
132
|
+
const micro = requireDomainMicro(Math.max(1, microOf(ceilingUsd, "ceil")), `per-run ceiling for ${runLabel}`, ceilingUsd);
|
|
115
133
|
if (this.authorizedMicroUsd + micro > this.maxMicroUsd) throw new SweepBudgetError(runLabel, ceilingUsd, this.authorizedUsd, this.maxTotalUsd);
|
|
116
134
|
this.authorizedMicroUsd += micro;
|
|
117
135
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/evals",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "Rulvar evals: eval cases, golden outputs, rubric and judge graders, matrix sweeps, canary fingerprint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rulvar/
|
|
26
|
-
"@rulvar/
|
|
25
|
+
"@rulvar/core": "1.21.0",
|
|
26
|
+
"@rulvar/testing": "1.21.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.20.0",
|