@skillstate/core 0.0.1 → 2.0.1

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 (88) hide show
  1. package/dist/atomic-write.d.ts +40 -0
  2. package/dist/atomic-write.d.ts.map +1 -0
  3. package/dist/atomic-write.js +97 -0
  4. package/dist/atomic-write.js.map +1 -0
  5. package/dist/clock.d.ts +27 -0
  6. package/dist/clock.d.ts.map +1 -0
  7. package/dist/clock.js +45 -0
  8. package/dist/clock.js.map +1 -0
  9. package/dist/config.d.ts +43 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +152 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/events.d.ts +59 -0
  14. package/dist/events.d.ts.map +1 -0
  15. package/dist/events.js +36 -0
  16. package/dist/events.js.map +1 -0
  17. package/dist/index.d.ts +20 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +28 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/instrumentation.d.ts +35 -0
  22. package/dist/instrumentation.d.ts.map +1 -0
  23. package/dist/instrumentation.js +41 -0
  24. package/dist/instrumentation.js.map +1 -0
  25. package/dist/logger.d.ts +34 -0
  26. package/dist/logger.d.ts.map +1 -0
  27. package/dist/logger.js +40 -0
  28. package/dist/logger.js.map +1 -0
  29. package/dist/migrations.d.ts +35 -0
  30. package/dist/migrations.d.ts.map +1 -0
  31. package/dist/migrations.js +26 -0
  32. package/dist/migrations.js.map +1 -0
  33. package/dist/prompt-transformer.d.ts +106 -0
  34. package/dist/prompt-transformer.d.ts.map +1 -0
  35. package/dist/prompt-transformer.js +265 -0
  36. package/dist/prompt-transformer.js.map +1 -0
  37. package/dist/provider.d.ts +62 -0
  38. package/dist/provider.d.ts.map +1 -0
  39. package/dist/provider.js +46 -0
  40. package/dist/provider.js.map +1 -0
  41. package/dist/redaction.d.ts +26 -0
  42. package/dist/redaction.d.ts.map +1 -0
  43. package/dist/redaction.js +38 -0
  44. package/dist/redaction.js.map +1 -0
  45. package/dist/resilience.d.ts +83 -0
  46. package/dist/resilience.d.ts.map +1 -0
  47. package/dist/resilience.js +171 -0
  48. package/dist/resilience.js.map +1 -0
  49. package/dist/runtime.d.ts +223 -0
  50. package/dist/runtime.d.ts.map +1 -0
  51. package/dist/runtime.js +362 -0
  52. package/dist/runtime.js.map +1 -0
  53. package/dist/schemas/index.d.ts +2 -0
  54. package/dist/schemas/index.d.ts.map +1 -0
  55. package/dist/schemas/index.js +3 -0
  56. package/dist/schemas/index.js.map +1 -0
  57. package/dist/schemas/intercode-ctf.d.ts +3 -0
  58. package/dist/schemas/intercode-ctf.d.ts.map +1 -0
  59. package/dist/schemas/intercode-ctf.js +53 -0
  60. package/dist/schemas/intercode-ctf.js.map +1 -0
  61. package/dist/shutdown.d.ts +20 -0
  62. package/dist/shutdown.d.ts.map +1 -0
  63. package/dist/shutdown.js +42 -0
  64. package/dist/shutdown.js.map +1 -0
  65. package/dist/state-manager.d.ts +23 -0
  66. package/dist/state-manager.d.ts.map +1 -0
  67. package/dist/state-manager.js +129 -0
  68. package/dist/state-manager.js.map +1 -0
  69. package/dist/state-store.d.ts +48 -0
  70. package/dist/state-store.d.ts.map +1 -0
  71. package/dist/state-store.js +101 -0
  72. package/dist/state-store.js.map +1 -0
  73. package/dist/token-tracker.d.ts +104 -0
  74. package/dist/token-tracker.d.ts.map +1 -0
  75. package/dist/token-tracker.js +204 -0
  76. package/dist/token-tracker.js.map +1 -0
  77. package/dist/types.d.ts +61 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +2 -0
  80. package/dist/types.js.map +1 -0
  81. package/dist/validate.d.ts +39 -0
  82. package/dist/validate.d.ts.map +1 -0
  83. package/dist/validate.js +180 -0
  84. package/dist/validate.js.map +1 -0
  85. package/package.json +23 -5
  86. package/LICENSE +0 -21
  87. package/README.md +0 -11
  88. package/index.js +0 -3
@@ -0,0 +1,129 @@
1
+ // ---------------------------------------------------------------------------
2
+ // 1. createInitialState — Σ₀ from schema defaults + optional overrides
3
+ // ---------------------------------------------------------------------------
4
+ export function createInitialState(schema, overrides) {
5
+ const state = {};
6
+ for (const [key, field] of Object.entries(schema)) {
7
+ state[key] = field.default;
8
+ }
9
+ if (overrides) {
10
+ for (const [key, value] of Object.entries(overrides)) {
11
+ state[key] = value;
12
+ }
13
+ }
14
+ return state;
15
+ }
16
+ // ---------------------------------------------------------------------------
17
+ // 2. mergeState — ⊕ operator from SKILL.state paper
18
+ // - Non-null values overwrite
19
+ // - null values DELETE the key entirely
20
+ // - Nested dicts are merged recursively
21
+ // - Original state is NOT mutated
22
+ // ---------------------------------------------------------------------------
23
+ function isPlainObject(value) {
24
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
25
+ }
26
+ export function mergeState(state, patch) {
27
+ const result = { ...state };
28
+ for (const [key, value] of Object.entries(patch)) {
29
+ if (value === null) {
30
+ delete result[key];
31
+ }
32
+ else if (isPlainObject(value) && isPlainObject(result[key])) {
33
+ // Recursive merge for nested objects — apply null-deletion inside too
34
+ result[key] = mergeNestedObjects(result[key], value);
35
+ }
36
+ else {
37
+ result[key] = value;
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ /** Deep merge two plain objects with null-deletion semantics. */
43
+ function mergeNestedObjects(base, patch) {
44
+ const result = { ...base };
45
+ for (const [key, value] of Object.entries(patch)) {
46
+ if (value === null) {
47
+ delete result[key];
48
+ }
49
+ else if (isPlainObject(value) && isPlainObject(result[key])) {
50
+ result[key] = mergeNestedObjects(result[key], value);
51
+ }
52
+ else {
53
+ result[key] = value;
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // 3. validatePatch — reject unknown keys, wrong types; accept null for deletion
60
+ // ---------------------------------------------------------------------------
61
+ function checkType(value, field) {
62
+ if (value === null)
63
+ return true; // null is always valid (deletion)
64
+ switch (field.type) {
65
+ case 'string':
66
+ return typeof value === 'string';
67
+ case 'number':
68
+ return typeof value === 'number';
69
+ case 'boolean':
70
+ return typeof value === 'boolean';
71
+ case 'array':
72
+ return Array.isArray(value);
73
+ case 'object':
74
+ return isPlainObject(value);
75
+ default:
76
+ return false;
77
+ }
78
+ }
79
+ export function validatePatch(schema, patch) {
80
+ for (const [key, value] of Object.entries(patch)) {
81
+ const field = schema[key];
82
+ if (!field) {
83
+ return { valid: false, error: `Unknown key: ${key}`, field: key };
84
+ }
85
+ if (!checkType(value, field)) {
86
+ return {
87
+ valid: false,
88
+ error: `Invalid type for field '${key}': expected ${field.type}, got ${Array.isArray(value) ? 'array' : typeof value}`,
89
+ field: key,
90
+ };
91
+ }
92
+ }
93
+ return { valid: true };
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // 4. serializeState / deserializeState — JSON round-trip
97
+ // ---------------------------------------------------------------------------
98
+ export function serializeState(state, options) {
99
+ if (options?.pretty) {
100
+ return JSON.stringify(state, null, 2);
101
+ }
102
+ return JSON.stringify(state);
103
+ }
104
+ export function deserializeState(json) {
105
+ return JSON.parse(json);
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // 5. StateManager class — convenience wrapper with static methods
109
+ // ---------------------------------------------------------------------------
110
+ export class StateManager {
111
+ static createInitialState = createInitialState;
112
+ static mergeState = mergeState;
113
+ static validatePatch = validatePatch;
114
+ static serializeState = serializeState;
115
+ static deserializeState = deserializeState;
116
+ }
117
+ // ---------------------------------------------------------------------------
118
+ // 6. createStateManager — factory function
119
+ // ---------------------------------------------------------------------------
120
+ export function createStateManager() {
121
+ return {
122
+ createInitialState,
123
+ mergeState,
124
+ validatePatch,
125
+ serializeState,
126
+ deserializeState,
127
+ };
128
+ }
129
+ //# sourceMappingURL=state-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-manager.js","sourceRoot":"","sources":["../src/state-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { VersionedState } from './migrations.js';
2
+ /**
3
+ * @non-paper async persistence seam over versioned states.
4
+ * `snapshot` is optional: a best-effort side copy for forensics/rollback.
5
+ */
6
+ export interface StateStore {
7
+ /** Last committed state, or `null` when nothing resumable exists. */
8
+ load(): Promise<VersionedState | null>;
9
+ /** Durably commit `s` (atomic on disk-backed stores). */
10
+ save(s: VersionedState): Promise<void>;
11
+ /** Best-effort side copy of the last commit; no-op when there is none. */
12
+ snapshot?(): Promise<void>;
13
+ }
14
+ /**
15
+ * @non-paper in-memory `StateStore`. Copies on both `save` and `load`
16
+ * so callers can never alias the held commit.
17
+ */
18
+ export declare class MemoryStore implements StateStore {
19
+ private current;
20
+ private readonly snaps;
21
+ load(): Promise<VersionedState | null>;
22
+ save(s: VersionedState): Promise<void>;
23
+ snapshot(): Promise<void>;
24
+ /** Deep copies of every `snapshot()` taken so far (oldest first). */
25
+ get snapshots(): VersionedState[];
26
+ }
27
+ /**
28
+ * @non-paper disk-backed `StateStore`.
29
+ *
30
+ * - `root`/`name` resolve via `resolveStatePath` (`..` escapes throw);
31
+ * - `save` serializes the envelope with `atomicWriteFile` — a crash can
32
+ * leave a `.tmp.*` sibling but never a truncated commit;
33
+ * - snapshots land next to the commit at `<path>.snapshot` (same atomic
34
+ * write; a missing commit snapshots to a no-op).
35
+ */
36
+ export declare class FileStore implements StateStore {
37
+ private readonly root;
38
+ private readonly name;
39
+ private readonly filePath;
40
+ private readonly snapshotPath;
41
+ constructor(root: string, name: string);
42
+ /** Absolute commit path (inside `root`). */
43
+ get path(): string;
44
+ save(s: VersionedState): Promise<void>;
45
+ load(): Promise<VersionedState | null>;
46
+ snapshot(): Promise<void>;
47
+ }
48
+ //# sourceMappingURL=state-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../src/state-store.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACvC,yDAAyD;IACzD,IAAI,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;;GAGG;AACH,qBAAa,WAAY,YAAW,UAAU;IAC5C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAExC,IAAI,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAE3C;IAEK,IAAI,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3C;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAI9B;IAED,qEAAqE;IACrE,IAAI,SAAS,IAAI,cAAc,EAAE,CAEhC;CACF;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAU,YAAW,UAAU;IAKxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,YACmB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAI9B;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,IAAI,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3C;IAEK,IAAI,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAY3C;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ9B;CACF"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @non-paper crash-safe state persistence (kill-mid-run → resume).
3
+ *
4
+ * The paper is pure in-memory Algorithm 1; this module adds an OPTIONAL
5
+ * persistence seam on top WITHOUT touching paper semantics:
6
+ *
7
+ * - `StateStore` — async `{ load, save, snapshot? }` over `VersionedState`;
8
+ * - `MemoryStore` — in-memory implementation (tests, dry-runs);
9
+ * - `FileStore(root, name)` — disk implementation built on the Wave-2
10
+ * `@non-paper` primitives: `resolveStatePath` confines `name` inside
11
+ * `root` (traversal throws) and `atomicWriteFile` (temp + fsync + rename)
12
+ * guarantees readers never see a half-written commit — a kill mid-run
13
+ * resumes from the LAST COMPLETE commit on `load()`.
14
+ *
15
+ * `load()` runs `migrate()` over the parsed JSON, so pre-envelope (v0)
16
+ * bare-state files resume losslessly. Missing files and corrupted JSON
17
+ * resolve to `null` (fresh start), never throw.
18
+ *
19
+ * Zero dependencies, Node >= 20, ESM.
20
+ */
21
+ import * as fs from 'node:fs';
22
+ import { atomicWriteFile, resolveStatePath } from './atomic-write.js';
23
+ import { migrate } from './migrations.js';
24
+ import { clone } from './clock.js';
25
+ /**
26
+ * @non-paper in-memory `StateStore`. Copies on both `save` and `load`
27
+ * so callers can never alias the held commit.
28
+ */
29
+ export class MemoryStore {
30
+ current = null;
31
+ snaps = [];
32
+ async load() {
33
+ return this.current === null ? null : clone(this.current);
34
+ }
35
+ async save(s) {
36
+ this.current = clone(s);
37
+ }
38
+ async snapshot() {
39
+ if (this.current !== null) {
40
+ this.snaps.push(clone(this.current));
41
+ }
42
+ }
43
+ /** Deep copies of every `snapshot()` taken so far (oldest first). */
44
+ get snapshots() {
45
+ return this.snaps.map((s) => clone(s));
46
+ }
47
+ }
48
+ /**
49
+ * @non-paper disk-backed `StateStore`.
50
+ *
51
+ * - `root`/`name` resolve via `resolveStatePath` (`..` escapes throw);
52
+ * - `save` serializes the envelope with `atomicWriteFile` — a crash can
53
+ * leave a `.tmp.*` sibling but never a truncated commit;
54
+ * - snapshots land next to the commit at `<path>.snapshot` (same atomic
55
+ * write; a missing commit snapshots to a no-op).
56
+ */
57
+ export class FileStore {
58
+ root;
59
+ name;
60
+ filePath;
61
+ snapshotPath;
62
+ constructor(root, name) {
63
+ this.root = root;
64
+ this.name = name;
65
+ this.filePath = resolveStatePath(root, name);
66
+ this.snapshotPath = `${this.filePath}.snapshot`;
67
+ }
68
+ /** Absolute commit path (inside `root`). */
69
+ get path() {
70
+ return this.filePath;
71
+ }
72
+ async save(s) {
73
+ await atomicWriteFile(this.filePath, JSON.stringify(s));
74
+ }
75
+ async load() {
76
+ let raw;
77
+ try {
78
+ raw = await fs.promises.readFile(this.filePath, 'utf-8');
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ try {
84
+ return migrate(JSON.parse(raw));
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ async snapshot() {
91
+ let raw;
92
+ try {
93
+ raw = await fs.promises.readFile(this.filePath, 'utf-8');
94
+ }
95
+ catch {
96
+ return;
97
+ }
98
+ await atomicWriteFile(this.snapshotPath, raw);
99
+ }
100
+ }
101
+ //# sourceMappingURL=state-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store.js","sourceRoot":"","sources":["../src/state-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAenC;;;GAGG;AACH,MAAM,OAAO,WAAW;IACd,OAAO,GAA0B,IAAI,CAAC;IAC7B,KAAK,GAAqB,EAAE,CAAC;IAE9C,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAAiB;QAC1B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,SAAS;IAKD,IAAI;IACJ,IAAI;IALN,QAAQ,CAAS;IACjB,YAAY,CAAS;IAEtC,YACmB,IAAY,EACZ,IAAY;oBADZ,IAAI;oBACJ,IAAI;QAErB,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,GAAG,IAAI,CAAC,QAAQ,WAAW,CAAC;IAClD,CAAC;IAED,4CAA4C;IAC5C,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAAiB;QAC1B,MAAM,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,MAAM,eAAe,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;CACF"}
@@ -0,0 +1,104 @@
1
+ import type { TrackerConfig, ExecutionStep } from './types.js';
2
+ /**
3
+ * Paper §4.3 primary metrics — EXACTLY three, measured in raw string CHARS:
4
+ * - accuracy (Task Accuracy): accepted patches / actionable steps (null when none).
5
+ * - averagePromptSize (Average Prompt Size): mean prompt char length per call.
6
+ * - totalTokens (Total Token Cost): cumulative char burn (prompts + responses).
7
+ *
8
+ * No tokenizer lives here: `recordStep` consumes the char counts the
9
+ * runtime measured (`promptChars` / `responseChars`). Anything estimated
10
+ * (len/4 heuristics, dollar pricing) belongs to `./instrumentation.js`
11
+ * and is explicitly marked @non-paper.
12
+ */
13
+ export interface PaperMetrics {
14
+ /** Task Accuracy (§4.3). Null when no step was actionable. */
15
+ accuracy: number | null;
16
+ /** Mean prompt char length per recorded call (§4.3 Average Prompt Size). */
17
+ averagePromptSize: number;
18
+ /** Cumulative burn: prompt chars + response chars (§4.3 Total Token Cost). */
19
+ totalTokens: number;
20
+ }
21
+ /**
22
+ * @non-paper session bookkeeping beyond the §4.3 triad. Kept on a separate
23
+ * accessor (`getBookkeeping`) so the primary metrics object stays clean —
24
+ * `totalChars` here equals `totalTokens` (both are the cumulative char burn)
25
+ * and is retained for the CLI/dashboard/report consumers that grew up on it.
26
+ */
27
+ export interface BookkeepingMetrics {
28
+ stepCount: number;
29
+ /** Cumulative prompt chars across all steps. */
30
+ totalPromptChars: number;
31
+ /** Cumulative burn: prompt chars + response chars (same value as totalTokens). */
32
+ totalChars: number;
33
+ sessionName: string;
34
+ lastStepTimestamp: number | null;
35
+ }
36
+ /**
37
+ * Baseline comparison from MEASURED chars (paper Table 1 methodology):
38
+ * the conversation baseline re-sends every prior turn at each step
39
+ * (O(T²) cumulative), SKILL sends only the current Σt (O(T)).
40
+ */
41
+ interface BaselineComparison {
42
+ /** Σ(t=1..T) Σ(i=1..t) promptChars[i] — the O(T²) conversation model. */
43
+ conversationChars: number;
44
+ /** Σ(t=1..T) promptChars[t] — the O(T) state model. */
45
+ stateChars: number;
46
+ /** conversationChars / stateChars (0 when nothing was recorded). */
47
+ reductionFactor: number;
48
+ }
49
+ export declare class TokenTracker {
50
+ private config;
51
+ private steps;
52
+ private totalPromptChars;
53
+ private totalResponseChars;
54
+ private cumulativePromptChars;
55
+ private lastStepTimestamp;
56
+ private startedAt;
57
+ constructor(config: TrackerConfig);
58
+ recordStep(step: ExecutionStep): void;
59
+ /**
60
+ * Paper §4.3 primary metrics — EXACTLY three fields.
61
+ *
62
+ * This is the clean §4.3 surface: Task Accuracy, Average Prompt Size
63
+ * (mean prompt char length per call), Total Token Cost (cumulative char
64
+ * burn). Bookkeeping (stepCount, sessionName, lastStepTimestamp,
65
+ * totalPromptChars, totalChars) lives on {@link getBookkeeping} so this
66
+ * object is never contaminated by non-§4.3 concerns.
67
+ */
68
+ getMetrics(): PaperMetrics;
69
+ /**
70
+ * @non-paper session bookkeeping separate from the §4.3 triad. Keeps the
71
+ * step count, cumulative prompt chars, cumulative char burn (same value
72
+ * as `totalTokens`), session name, and last-step timestamp for the CLI,
73
+ * dashboard, and report consumers.
74
+ */
75
+ getBookkeeping(): BookkeepingMetrics;
76
+ compareWithBaseline(): BaselineComparison;
77
+ exportReport(): string;
78
+ save(overridePath?: string): void;
79
+ /**
80
+ * @non-paper best-effort persist: returns the current report and writes
81
+ * it to `overridePath ?? persistPath` when a path is available. Unlike
82
+ * `save`, NEVER throws for a missing path — teardown/flush call sites
83
+ * must be safe to run unconditionally.
84
+ */
85
+ flush(overridePath?: string): string;
86
+ /**
87
+ * @non-paper archive-and-reset: returns the current report, persists it
88
+ * to `archivePath ?? persistPath` when a path is available, then resets
89
+ * step history and char counters to zero. Session identity
90
+ * (`sessionName`/`platform`) is kept; `startedAt` restarts at now so the
91
+ * next segment reads as a fresh session tail.
92
+ */
93
+ rotate(archivePath?: string): string;
94
+ /**
95
+ * @non-paper rollback helper for budget enforcement: keep only the first
96
+ * `keep` steps and rebuild every counter through the single `recordStep`
97
+ * accounting path, so `compareWithBaseline` stays exact after truncation.
98
+ * `keep >= stepCount` is a no-op; negatives clamp to zero.
99
+ */
100
+ truncateTo(keep: number): void;
101
+ load(overridePath?: string): void;
102
+ }
103
+ export {};
104
+ //# sourceMappingURL=token-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-tracker.d.ts","sourceRoot":"","sources":["../src/token-tracker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,UAAU,kBAAkB;IAC1B,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,eAAe,EAAE,MAAM,CAAC;CACzB;AAaD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,kBAAkB,CAAK;IAG/B,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,MAAM,EAAE,aAAa,EAOhC;IAED,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAMpC;IAED;;;;;;;;OAQG;IACH,UAAU,IAAI,YAAY,CAqBzB;IAED;;;;;OAKG;IACH,cAAc,IAAI,kBAAkB,CAQnC;IAED,mBAAmB,IAAI,kBAAkB,CAmBxC;IAED,YAAY,IAAI,MAAM,CAYrB;IAED,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAWhC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CASnC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAenC;IAED;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAc7B;IAED,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAoChC;CACF"}
@@ -0,0 +1,204 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ export class TokenTracker {
4
+ config;
5
+ steps = [];
6
+ totalPromptChars = 0;
7
+ totalResponseChars = 0;
8
+ // Σ(t=1..N) Σ(i=1..t) promptChars[i], built incrementally: each new
9
+ // step adds the running prompt-char total (paper §3.3 eq.5: |C_t| = O(t)).
10
+ cumulativePromptChars = 0;
11
+ lastStepTimestamp = null;
12
+ startedAt;
13
+ constructor(config) {
14
+ this.config = {
15
+ persistPath: undefined,
16
+ sessionName: `session-${Date.now()}`,
17
+ ...config,
18
+ };
19
+ this.startedAt = Date.now();
20
+ }
21
+ recordStep(step) {
22
+ this.steps.push(step);
23
+ this.totalPromptChars += step.promptChars;
24
+ this.totalResponseChars += step.responseChars;
25
+ this.cumulativePromptChars += this.totalPromptChars;
26
+ this.lastStepTimestamp = step.timestamp;
27
+ }
28
+ /**
29
+ * Paper §4.3 primary metrics — EXACTLY three fields.
30
+ *
31
+ * This is the clean §4.3 surface: Task Accuracy, Average Prompt Size
32
+ * (mean prompt char length per call), Total Token Cost (cumulative char
33
+ * burn). Bookkeeping (stepCount, sessionName, lastStepTimestamp,
34
+ * totalPromptChars, totalChars) lives on {@link getBookkeeping} so this
35
+ * object is never contaminated by non-§4.3 concerns.
36
+ */
37
+ getMetrics() {
38
+ const stepCount = this.steps.length;
39
+ const averagePromptSize = stepCount > 0 ? this.totalPromptChars / stepCount : 0;
40
+ // Task Accuracy (paper §4.3): fraction of actionable steps whose patch
41
+ // was accepted. Steps with success === undefined are not actionable and
42
+ // are excluded from both numerator and denominator. Null when no step
43
+ // was actionable (including the zero-step session).
44
+ const actionableSteps = this.steps.filter((s) => s.success !== undefined);
45
+ const accuracy = actionableSteps.length === 0
46
+ ? null
47
+ : actionableSteps.filter((s) => s.success === true).length /
48
+ actionableSteps.length;
49
+ return {
50
+ accuracy,
51
+ averagePromptSize,
52
+ totalTokens: this.totalPromptChars + this.totalResponseChars,
53
+ };
54
+ }
55
+ /**
56
+ * @non-paper session bookkeeping separate from the §4.3 triad. Keeps the
57
+ * step count, cumulative prompt chars, cumulative char burn (same value
58
+ * as `totalTokens`), session name, and last-step timestamp for the CLI,
59
+ * dashboard, and report consumers.
60
+ */
61
+ getBookkeeping() {
62
+ return {
63
+ stepCount: this.steps.length,
64
+ totalPromptChars: this.totalPromptChars,
65
+ totalChars: this.totalPromptChars + this.totalResponseChars,
66
+ sessionName: this.config.sessionName ?? `session-${this.startedAt}`,
67
+ lastStepTimestamp: this.lastStepTimestamp,
68
+ };
69
+ }
70
+ compareWithBaseline() {
71
+ if (this.steps.length === 0) {
72
+ return {
73
+ conversationChars: 0,
74
+ stateChars: 0,
75
+ reductionFactor: 0,
76
+ };
77
+ }
78
+ const conversationChars = this.cumulativePromptChars;
79
+ const stateChars = this.totalPromptChars;
80
+ const reductionFactor = stateChars > 0 ? conversationChars / stateChars : 0;
81
+ return {
82
+ conversationChars,
83
+ stateChars,
84
+ reductionFactor,
85
+ };
86
+ }
87
+ exportReport() {
88
+ const report = {
89
+ metrics: { ...this.getMetrics(), ...this.getBookkeeping() },
90
+ steps: this.steps,
91
+ session: {
92
+ name: this.config.sessionName ?? `session-${this.startedAt}`,
93
+ platform: this.config.platform,
94
+ startedAt: this.startedAt,
95
+ },
96
+ };
97
+ return JSON.stringify(report);
98
+ }
99
+ save(overridePath) {
100
+ const filePath = overridePath ?? this.config.persistPath;
101
+ if (!filePath) {
102
+ throw new Error('No persist path configured');
103
+ }
104
+ const dir = path.dirname(filePath);
105
+ fs.mkdirSync(dir, { recursive: true });
106
+ const report = this.exportReport();
107
+ fs.writeFileSync(filePath, report, 'utf-8');
108
+ }
109
+ /**
110
+ * @non-paper best-effort persist: returns the current report and writes
111
+ * it to `overridePath ?? persistPath` when a path is available. Unlike
112
+ * `save`, NEVER throws for a missing path — teardown/flush call sites
113
+ * must be safe to run unconditionally.
114
+ */
115
+ flush(overridePath) {
116
+ const report = this.exportReport();
117
+ const filePath = overridePath ?? this.config.persistPath;
118
+ if (filePath !== undefined) {
119
+ const dir = path.dirname(filePath);
120
+ fs.mkdirSync(dir, { recursive: true });
121
+ fs.writeFileSync(filePath, report, 'utf-8');
122
+ }
123
+ return report;
124
+ }
125
+ /**
126
+ * @non-paper archive-and-reset: returns the current report, persists it
127
+ * to `archivePath ?? persistPath` when a path is available, then resets
128
+ * step history and char counters to zero. Session identity
129
+ * (`sessionName`/`platform`) is kept; `startedAt` restarts at now so the
130
+ * next segment reads as a fresh session tail.
131
+ */
132
+ rotate(archivePath) {
133
+ const report = this.exportReport();
134
+ const filePath = archivePath ?? this.config.persistPath;
135
+ if (filePath !== undefined) {
136
+ const dir = path.dirname(filePath);
137
+ fs.mkdirSync(dir, { recursive: true });
138
+ fs.writeFileSync(filePath, report, 'utf-8');
139
+ }
140
+ this.steps = [];
141
+ this.totalPromptChars = 0;
142
+ this.totalResponseChars = 0;
143
+ this.cumulativePromptChars = 0;
144
+ this.lastStepTimestamp = null;
145
+ this.startedAt = Date.now();
146
+ return report;
147
+ }
148
+ /**
149
+ * @non-paper rollback helper for budget enforcement: keep only the first
150
+ * `keep` steps and rebuild every counter through the single `recordStep`
151
+ * accounting path, so `compareWithBaseline` stays exact after truncation.
152
+ * `keep >= stepCount` is a no-op; negatives clamp to zero.
153
+ */
154
+ truncateTo(keep) {
155
+ const clamped = Math.max(0, keep);
156
+ if (clamped >= this.steps.length) {
157
+ return;
158
+ }
159
+ const kept = this.steps.slice(0, clamped);
160
+ this.steps = [];
161
+ this.totalPromptChars = 0;
162
+ this.totalResponseChars = 0;
163
+ this.cumulativePromptChars = 0;
164
+ this.lastStepTimestamp = null;
165
+ for (const step of kept) {
166
+ this.recordStep(step);
167
+ }
168
+ }
169
+ load(overridePath) {
170
+ const filePath = overridePath ?? this.config.persistPath;
171
+ if (!filePath) {
172
+ return;
173
+ }
174
+ try {
175
+ const data = fs.readFileSync(filePath, 'utf-8');
176
+ const report = JSON.parse(data);
177
+ // Restore steps through the single accounting path
178
+ this.steps = [];
179
+ this.totalPromptChars = 0;
180
+ this.totalResponseChars = 0;
181
+ this.cumulativePromptChars = 0;
182
+ this.lastStepTimestamp = null;
183
+ for (const step of report.steps ?? []) {
184
+ this.recordStep(step);
185
+ }
186
+ // Restore session metadata
187
+ if (report.session?.name) {
188
+ this.config.sessionName = report.session.name;
189
+ }
190
+ if (report.session?.startedAt) {
191
+ this.startedAt = report.session.startedAt;
192
+ }
193
+ }
194
+ catch {
195
+ // Gracefully handle missing or corrupted files — reset to defaults
196
+ this.steps = [];
197
+ this.totalPromptChars = 0;
198
+ this.totalResponseChars = 0;
199
+ this.cumulativePromptChars = 0;
200
+ this.lastStepTimestamp = null;
201
+ }
202
+ }
203
+ }
204
+ //# sourceMappingURL=token-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-tracker.js","sourceRoot":"","sources":["../src/token-tracker.ts"],"names":[],"mappings":"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"}