@rulvar/testing 1.0.0 → 1.2.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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as FAKE_MODEL, c as FakeAdapterOptions, d as FakeToolCallsValue, f as FakeWireErrorValue, i as createTestEngine, l as FakeCall, m as fakeWireError, n as TestEngine, o as FAKE_MODEL_REF, p as fakeToolCalls, r as TestRunHandle, s as FakeAdapter, t as CreateTestEngineOptions, u as FakeResponder } from "./test-engine-kYp9C72n.js";
1
+ import { a as FAKE_MODEL, c as FakeAdapterOptions, d as FakeToolCallsValue, f as FakeWireErrorValue, i as createTestEngine, l as FakeCall, m as fakeWireError, n as TestEngine, o as FAKE_MODEL_REF, p as fakeToolCalls, r as TestRunHandle, s as FakeAdapter, t as CreateTestEngineOptions, u as FakeResponder } from "./test-engine-DwJtTU7M.js";
2
2
  import { AgentProfile, ChatEvent, ChatRequest, InvocationRole, JournalEntry, JournalStore, ModelCaps, ModelSpec, ProviderAdapter, ResumePreview, RunOutcome, WireError, Workflow, createEngine } from "@rulvar/core";
3
3
 
4
4
  //#region src/replay-strict.d.ts
@@ -36,7 +36,7 @@ interface CassetteFixture {
36
36
  }
37
37
  declare function buildM2CassetteFixtures(): CassetteFixture[];
38
38
  /**
39
- * The frozen v1 journal (docs/11, section "Frozen journal fixtures"): a
39
+ * The frozen v1 journal: a
40
40
  * round-1 JSONL file with kinds agent, step, rand, external, approval and
41
41
  * the legacy `v: 1` field (no hashVersion member). Returned as raw
42
42
  * JSON-ready objects, one per line.
@@ -68,7 +68,7 @@ declare function normalizeM6Entries(entries: readonly JournalEntry[]): JournalEn
68
68
  * Phase 1: record the pre-crash journal. The transcripts store carries
69
69
  * the boundary checkpoint the resume restores from; the recorder keeps
70
70
  * it in memory because the cassette pins only journal bytes (checkpoint
71
- * blobs are engine-internal at-least-once state, docs/03 section 11).
71
+ * blobs are engine-internal at-least-once state).
72
72
  */
73
73
  declare function recordOrchestratorCrash(): Promise<{
74
74
  entries: JournalEntry[]; /** Boundary checkpoint blobs by ref, base64: the resume restores from them. */
@@ -98,14 +98,14 @@ interface VcrHeader {
98
98
  type RedactFn = (value: string) => string;
99
99
  /**
100
100
  * Built-in redaction: authorization material never reaches cassette
101
- * bytes (docs/11, section 5.2). Deliberately aggressive; compose a
101
+ * bytes. Deliberately aggressive; compose a
102
102
  * custom hook for payload-specific secrets.
103
103
  */
104
104
  declare function defaultRedact(value: string): string;
105
105
  /**
106
106
  * The cassette key: a hash of the canonical wire-contract request. The
107
- * engine-populated telemetry namespace is excluded (docs/04, section
108
- * 1.8: never identity); everything else the adapter would send keys the
107
+ * engine-populated telemetry namespace is excluded (never identity);
108
+ * everything else the adapter would send keys the
109
109
  * row.
110
110
  */
111
111
  declare function requestHash(req: ChatRequest): string;
@@ -133,8 +133,7 @@ declare function readCassette(path: string): VcrCassette;
133
133
  /**
134
134
  * Builds replay adapters from a cassette. `onMiss: 'throw'` is the
135
135
  * hermetic CI mode; `'passthrough'` forwards unrecorded requests to the
136
- * matching live adapter in `adapters` (a development convenience only,
137
- * docs/11 section 5.1).
136
+ * matching live adapter in `adapters` (a development convenience only).
138
137
  */
139
138
  declare function replay(options: {
140
139
  cassette: string;
package/dist/index.js CHANGED
@@ -7,8 +7,7 @@ import { createHash } from "node:crypto";
7
7
  * FakeAdapter (M1-T14): a REAL ProviderAdapter that resolves calls from
8
8
  * declared patterns instead of the network, behind the same seam as live
9
9
  * adapters, so unit tests run through the full engine: journal, scheduler,
10
- * budget layers, and event stream (docs/09, section "Tier 1: FakeAdapter
11
- * and createTestEngine"). Calls cost zero USD.
10
+ * budget layers, and event stream. Calls cost zero USD.
12
11
  */
13
12
  /** Scripts a tool-calling turn from a responder. */
14
13
  function fakeToolCalls(...calls) {
@@ -204,8 +203,8 @@ var FakeAdapter = class {
204
203
  /**
205
204
  * createTestEngine (M1-T14): a full engine over FakeAdapter with zero
206
205
  * network. Orchestration logic is exercised, not mocked around: journal,
207
- * scheduler, budget layers, and event stream are all real (docs/09,
208
- * section "Tier 1"). Returned handles record their event stream so the
206
+ * scheduler, budget layers, and event stream are all real. Returned
207
+ * handles record their event stream so the
209
208
  * matchers can assert over settled runs.
210
209
  */
211
210
  function createTestEngine(options) {
@@ -257,8 +256,7 @@ function createTestEngine(options) {
257
256
  * against an existing journal and throws JournalMissError on ANY live
258
257
  * call: zero live calls or loud failure. Any production journal becomes a
259
258
  * deterministic integration test; a journal with open suspensions
260
- * completes with outcome 'suspended' and zero live calls (docs/09,
261
- * section "Tier 3: replay-strict journal runs").
259
+ * completes with outcome 'suspended' and zero live calls.
262
260
  */
263
261
  const FAKE_ROUTING = {
264
262
  loop: FAKE_MODEL_REF,
@@ -317,10 +315,9 @@ async function replayRun(wf, args, options) {
317
315
  * The COMMITTED files under repo cassettes/ and
318
316
  * packages/testing/fixtures/frozen/ are the contract; these builders
319
317
  * exist to regenerate them DELIBERATELY (scripts/record-m2-cassettes.mjs)
320
- * and to fail loudly in CI when key derivation drifts (docs/11, section
321
- * "Frozen journal fixtures": regenerating fixtures to make a test pass is
322
- * forbidden by policy; any diff requires an explicit hashVersion-bump
323
- * changeset).
318
+ * and to fail loudly in CI when key derivation drifts (regenerating
319
+ * fixtures to make a test pass is forbidden by policy; any diff requires
320
+ * an explicit hashVersion-bump changeset).
324
321
  */
325
322
  const BASE_MS$1 = Date.parse("2026-02-01T00:00:00.000Z");
326
323
  const SPAN$1 = "fixture-span";
@@ -866,7 +863,7 @@ function buildM2CassetteFixtures() {
866
863
  return fixtures;
867
864
  }
868
865
  /**
869
- * The frozen v1 journal (docs/11, section "Frozen journal fixtures"): a
866
+ * The frozen v1 journal: a
870
867
  * round-1 JSONL file with kinds agent, step, rand, external, approval and
871
868
  * the legacy `v: 1` field (no hashVersion member). Returned as raw
872
869
  * JSON-ready objects, one per line.
@@ -919,7 +916,7 @@ function buildFrozenV1JournalRaw() {
919
916
  };
920
917
  });
921
918
  }
922
- /** The docs/03 section 1.5 worked example, frozen as executable data. */
919
+ /** The agent identity worked example, frozen as executable data. */
923
920
  const WORKED_EXAMPLE_INPUT = {
924
921
  kind: "agent",
925
922
  agentType: "reviewer",
@@ -1041,7 +1038,7 @@ function buildV2GoldenIdentity() {
1041
1038
  * producer arrives with mode (c) in M6/M7. Timestamps and span ids are
1042
1039
  * normalized deterministically after recording (matching never reads
1043
1040
  * them); regeneration is DELIBERATE per the frozen-fixture policy
1044
- * (docs/11).
1041
+ * (https://docs.rulvar.com/guide/testing).
1045
1042
  */
1046
1043
  const BASE_MS = Date.parse("2026-02-01T00:00:00.000Z");
1047
1044
  const SPAN = "fixture-span";
@@ -1175,7 +1172,7 @@ function subtreeChildReport() {
1175
1172
  * The orchestrator-subtree shape: written through the KERNEL write APIs
1176
1173
  * (the same calls mode (c) spawning uses from M6), since no script-mode
1177
1174
  * producer can spawn agents under an agent scope yet; re-recorded again
1178
- * live in M7 with the orchestrator producers (docs/10, cassette plan).
1175
+ * live in M7 with the orchestrator producers.
1179
1176
  */
1180
1177
  async function recordAbandonSubtree() {
1181
1178
  let tick = 0;
@@ -1283,7 +1280,7 @@ function frozenV1JournalPath() {
1283
1280
  throw new Error("frozen v1-journal.jsonl not found next to the recorder");
1284
1281
  }
1285
1282
  /**
1286
- * effort-defaults-shift (DEF-6; docs/10 M4 gating row): the frozen v1
1283
+ * effort-defaults-shift (DEF-6): the frozen v1
1287
1284
  * prefix (recorded without effort) is closed offline the way an
1288
1285
  * operator would (the external resolves, the approval flow is
1289
1286
  * abandoned under its authority), then the SAME flow resumes LIVE under
@@ -1342,7 +1339,7 @@ function liveEngine(store, agents) {
1342
1339
  } }
1343
1340
  });
1344
1341
  }
1345
- /** An offline kernel writer over the loaded priors (docs/03, section 8). */
1342
+ /** An offline kernel writer over the loaded priors. */
1346
1343
  async function offlineReplayer(store, runId) {
1347
1344
  let tick = 500;
1348
1345
  return new Replayer({
@@ -1369,7 +1366,7 @@ function suspendedSeqOf(entries, key) {
1369
1366
  * DEF-4 timeout-vs-live-race, LIVE form: the run suspends on the
1370
1367
  * decision, the LIVE resolution wins through RunHandle.resolveExternal,
1371
1368
  * and the late timer attempt lands through the offline kernel writer as
1372
- * the journaled noop (first-wins; docs/03, 8.6).
1369
+ * the journaled noop (first-wins).
1373
1370
  */
1374
1371
  async function recordTimeoutVsLiveRace() {
1375
1372
  const store = new InMemoryStore();
@@ -1402,7 +1399,7 @@ async function recordTimeoutVsLiveRace() {
1402
1399
  * the first closes individually (applied by external); ONE class-level
1403
1400
  * decision entry closes the remaining two by class_decision with the
1404
1401
  * decisionRef, and the late class attempt against the first lands noop
1405
- * (docs/03, 8.6; the plan-side class producer has its own cassette,
1402
+ * (the plan-side class producer has its own cassette,
1406
1403
  * class-storm-single-turn).
1407
1404
  */
1408
1405
  async function recordClassDecisionFanout() {
@@ -1740,7 +1737,7 @@ function normalizeM6Entries(entries) {
1740
1737
  * Phase 1: record the pre-crash journal. The transcripts store carries
1741
1738
  * the boundary checkpoint the resume restores from; the recorder keeps
1742
1739
  * it in memory because the cassette pins only journal bytes (checkpoint
1743
- * blobs are engine-internal at-least-once state, docs/03 section 11).
1740
+ * blobs are engine-internal at-least-once state).
1744
1741
  */
1745
1742
  async function recordOrchestratorCrash() {
1746
1743
  let orchestratorTurn = 0;
@@ -1803,8 +1800,8 @@ async function recordOrchestratorCrash() {
1803
1800
  //#endregion
1804
1801
  //#region src/vcr.ts
1805
1802
  /**
1806
- * VCR cassettes at the adapter boundary (M5-T04; docs/09, section 5.2;
1807
- * docs/11, section 5): `record` wraps live adapters and captures
1803
+ * VCR cassettes at the adapter boundary (M5-T04): `record` wraps
1804
+ * live adapters and captures
1808
1805
  * request/event pairs into a redacted JSONL cassette keyed by a hash of
1809
1806
  * the canonical wire-contract request; `replay` serves recorded streams
1810
1807
  * back with `onMiss: 'throw'` (hermetic CI) or `'passthrough'` (mixed
@@ -1823,7 +1820,7 @@ async function recordOrchestratorCrash() {
1823
1820
  */
1824
1821
  /**
1825
1822
  * Built-in redaction: authorization material never reaches cassette
1826
- * bytes (docs/11, section 5.2). Deliberately aggressive; compose a
1823
+ * bytes. Deliberately aggressive; compose a
1827
1824
  * custom hook for payload-specific secrets.
1828
1825
  */
1829
1826
  function defaultRedact(value) {
@@ -1843,8 +1840,8 @@ function canonicalJson(value) {
1843
1840
  }
1844
1841
  /**
1845
1842
  * The cassette key: a hash of the canonical wire-contract request. The
1846
- * engine-populated telemetry namespace is excluded (docs/04, section
1847
- * 1.8: never identity); everything else the adapter would send keys the
1843
+ * engine-populated telemetry namespace is excluded (never identity);
1844
+ * everything else the adapter would send keys the
1848
1845
  * row.
1849
1846
  */
1850
1847
  function requestHash(req) {
@@ -1918,8 +1915,7 @@ function readCassette(path) {
1918
1915
  /**
1919
1916
  * Builds replay adapters from a cassette. `onMiss: 'throw'` is the
1920
1917
  * hermetic CI mode; `'passthrough'` forwards unrecorded requests to the
1921
- * matching live adapter in `adapters` (a development convenience only,
1922
- * docs/11 section 5.1).
1918
+ * matching live adapter in `adapters` (a development convenience only).
1923
1919
  */
1924
1920
  function replay(options) {
1925
1921
  const { rows } = readCassette(options.cassette);
@@ -1,4 +1,4 @@
1
- import { r as TestRunHandle } from "./test-engine-kYp9C72n.js";
1
+ import { r as TestRunHandle } from "./test-engine-DwJtTU7M.js";
2
2
 
3
3
  //#region src/matchers.d.ts
4
4
  interface MatcherResult {
@@ -38,7 +38,7 @@ declare function fakeWireError(error: WireError): FakeWireErrorValue;
38
38
  interface FakeAdapterOptions {
39
39
  /**
40
40
  * Patterns match on agentType, label, or a regex over the prompt; '*'
41
- * is the fallback (docs/09, section "Tier 1").
41
+ * is the fallback.
42
42
  */
43
43
  agents: Record<string, FakeResponder>;
44
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/testing",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "rulvar test harness: createTestEngine, FakeAdapter, VCR cassettes, replay-strict runs, matchers.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@rulvar/core": "1.0.0"
29
+ "@rulvar/core": "1.2.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.20.0",