@skillstate/bench 2.0.0 → 2.0.2

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/README.md ADDED
@@ -0,0 +1,109 @@
1
+ <div align="center">
2
+
3
+ # @skillstate/bench
4
+
5
+ **Deterministic local benchmark harness for the skillstate runtime — conversation baseline vs SKILL.state.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@skillstate/bench)](https://www.npmjs.com/package/@skillstate/bench)
8
+ [![node](https://img.shields.io/node/v/@skillstate/bench)](https://www.npmjs.com/package/@skillstate/bench)
9
+ [![Tests](https://img.shields.io/badge/tests-755%20passing-brightgreen)](https://github.com/vitalykuzyaev/skillstate)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/vitalykuzyaev/skillstate/blob/main/LICENSE)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ `@skillstate/bench` is a fully deterministic A/B harness that measures the
17
+ O(1)/O(T) prompt-footprint claim of [`@skillstate/core`](../core) on fixed
18
+ synthetic data: mode (b) drives the real `SkillStateRuntime` for T steps, mode
19
+ (a) reconstructs the conversation baseline as prefix sums of those very state
20
+ prompts. With constant-size turns the reduction is exactly `(T+1)/2`
21
+ (paper §3.3 eq.5-7). Entry only, no bin.
22
+
23
+ > **@non-paper** — this harness is *not* the paper's evaluation. The paper's
24
+ > Table 1 / §5.2 numbers come from Gemini/Gemma runs on Warehousing tasks; this
25
+ > measures a minimal, reproducible upper-bound A/B on our own data. Do not quote
26
+ > these as paper results.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm i @skillstate/core @skillstate/bench
32
+ ```
33
+
34
+ Requires Node.js >= 20. TypeScript types are bundled.
35
+
36
+ ## Quick start
37
+
38
+ Run the whole suite (from the repo root, or any installed copy):
39
+
40
+ ```bash
41
+ npm run bench # builds then runs node ./packages/bench/dist/run.js
42
+ ```
43
+
44
+ Programmatically:
45
+
46
+ ```ts
47
+ import { runAll, formatTable, BENCH_T_VALUES, expectedReduction } from '@skillstate/bench';
48
+
49
+ const results = await runAll(BENCH_T_VALUES); // [T=10, 50, 100, 200]
50
+ console.log(formatTable(results));
51
+
52
+ for (const r of results) {
53
+ console.log(r.T, r.reductionFactor.toFixed(2), expectedReduction(r.T));
54
+ }
55
+ ```
56
+
57
+ Run a single horizon with the incremental entry point:
58
+
59
+ ```ts
60
+ import { runScenario } from '@skillstate/bench';
61
+ const r = await runScenario(100);
62
+ console.log(r.stateCumulative, r.convCumulative, r.reductionFactor);
63
+ ```
64
+
65
+ ## API / Exports
66
+
67
+ Root path `@skillstate/bench` exports the harness plus the run entry. Importing
68
+ the package is side-effect free — the benchmark only runs when the module is
69
+ the process entry (`node dist/run.js`).
70
+
71
+ **Harness (`harness.ts`):**
72
+
73
+ - `BENCH_T_VALUES` — `readonly number[]` = `[10, 50, 100, 200]`.
74
+ - `BENCH_SPEC` / `BENCH_OBSERVATION` / `BENCH_REASONING` / `BENCH_ACTION` /
75
+ `BENCH_PATCH` / `BENCH_SEED` — the fixed synthetic fixture.
76
+ - `benchResponse(): string` / `benchObservation(): Observation`.
77
+ - `runScenario(T): Promise<BenchResult>` — drive one horizon.
78
+ - `runAll(horizons): Promise<BenchResult[]>`.
79
+ - `formatTable(results): string` — human-readable text table.
80
+ - `expectedReduction(T): number` — closed form `(T+1)/2`.
81
+ - `BenchResult` — per-horizon outcome (all sizes in raw chars).
82
+
83
+ **Run entry (`run.ts`):** `main(): Promise<BenchResult[]>` — prints the table
84
+ and machine-readable JSON.
85
+
86
+ ## Notes
87
+
88
+ - **Deterministic.** No RNG anywhere — a fixed spec, a fixed 64-char
89
+ observation, a fixed mock-LLM reply. `BENCH_SEED` documents that no seed is
90
+ needed.
91
+ - **Read before quoting.** Because the spec `P` is re-sent in every
92
+ conversation-baseline turn, the measured savings are an **upper bound** on a
93
+ real baseline (which sends `P` once and re-sends cheaper turn payloads).
94
+ - The method is the quiet `TokenTracker.compareWithBaseline` model (paper §3.3
95
+ eq.5), on identical data, using the paper-exact `formatPaper` prompts. All
96
+ metrics are raw string chars (§4.3).
97
+ - Depends on [`@skillstate/core`](../core) for `SkillStateRuntime` and the
98
+ `formatPaper` prompt.
99
+
100
+ ## Related
101
+
102
+ - Paper: [arXiv:2608.26263](https://arxiv.org/abs/2608.26263).
103
+ - Core runtime: [`@skillstate/core`](../core).
104
+ - Full method, tables, and limitations: [`BENCHMARK.md`](../../BENCHMARK.md).
105
+ - Machine-readable fixture: [`tests/bench/expected.json`](../../../tests/bench/expected.json).
106
+
107
+ ## License
108
+
109
+ [MIT](LICENSE) © 2026 Vitaly Kuzyaev
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  // @skillstate/bench — deterministic local benchmark harness.
2
2
  //
3
- // NOTE: re-exporting `./run.js` also evaluates its top-level `main()`
4
- // (the `npm run bench` entry), exactly like importing the historical
5
- // `dist/bench/run.js` directly.
3
+ // NOTE: re-exporting `./run.js` is side-effect free `main` only executes
4
+ // when `run.js` is the process entry (`node dist/run.js`), never on import.
6
5
  export * from './harness.js';
7
6
  export * from './run.js';
8
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,sEAAsE;AACtE,qEAAqE;AACrE,gCAAgC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC"}
package/dist/run.d.ts CHANGED
@@ -2,6 +2,10 @@
2
2
  * `npm run bench` entry point (zero-deps, runs from compiled dist).
3
3
  *
4
4
  * @non-paper — local deterministic harness CLI, not part of the paper.
5
+ *
6
+ * Importing this module is side-effect free: the benchmark only runs when
7
+ * this file is the process entry (`node dist/run.js`, the `npm run bench`
8
+ * path), never when `@skillstate/bench` is imported as a library.
5
9
  */
6
10
  import type { BenchResult } from './harness.js';
7
11
  /** Run all horizons, print the table plus machine-readable JSON. */
package/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,oEAAoE;AACpE,wBAAsB,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAKnD"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,oEAAoE;AACpE,wBAAsB,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAKnD"}
package/dist/run.js CHANGED
@@ -2,7 +2,12 @@
2
2
  * `npm run bench` entry point (zero-deps, runs from compiled dist).
3
3
  *
4
4
  * @non-paper — local deterministic harness CLI, not part of the paper.
5
+ *
6
+ * Importing this module is side-effect free: the benchmark only runs when
7
+ * this file is the process entry (`node dist/run.js`, the `npm run bench`
8
+ * path), never when `@skillstate/bench` is imported as a library.
5
9
  */
10
+ import { pathToFileURL } from 'node:url';
6
11
  import { BENCH_T_VALUES, runAll, formatTable } from './harness.js';
7
12
  /** Run all horizons, print the table plus machine-readable JSON. */
8
13
  export async function main() {
@@ -11,5 +16,9 @@ export async function main() {
11
16
  console.log(JSON.stringify(results, null, 2));
12
17
  return results;
13
18
  }
14
- void main();
19
+ const isEntry = process.argv[1] !== undefined &&
20
+ pathToFileURL(process.argv[1]).href === import.meta.url;
21
+ if (isEntry) {
22
+ await main();
23
+ }
15
24
  //# sourceMappingURL=run.js.map
package/dist/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGnE,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGnE,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;IAC7B,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC;AAE1D,IAAI,OAAO,EAAE,CAAC;IACZ,MAAM,IAAI,EAAE,CAAC;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillstate/bench",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Deterministic local benchmark harness for the skillstate runtime (entry only).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,7 +12,9 @@
12
12
  },
13
13
  "./package.json": "./package.json"
14
14
  },
15
- "files": ["dist"],
15
+ "files": [
16
+ "dist"
17
+ ],
16
18
  "sideEffects": false,
17
19
  "engines": {
18
20
  "node": ">=20"