@rulvar/testing 1.33.0 → 1.35.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
@@ -154,7 +154,10 @@ interface VcrRow {
154
154
  * seeds its counters past the numbers already on disk, so the
155
155
  * numbering continues across sequential sessions; a duplicate
156
156
  * number inside a fully numbered group refuses replay as ambiguous
157
- * (v1.32.0 review P2).
157
+ * (v1.32.0 review P2). The numbering ends at
158
+ * `Number.MAX_SAFE_INTEGER`: a session refuses with a typed
159
+ * ConfigError to claim a number past it, before dispatching the
160
+ * provider and before touching the file (v1.33.0 review P3).
158
161
  */
159
162
  occurrence?: number;
160
163
  requestHash: string;
@@ -210,7 +213,14 @@ declare function requestHash(req: ChatRequest): string;
210
213
  * recorder session may be active on a cassette at a time: two
211
214
  * concurrently constructed recorders seed identically and claim
212
215
  * colliding numbers, which replay refuses as ambiguous instead of
213
- * silently serving either order. The wrapped adapters are drop-in:
216
+ * silently serving either order. The numbering ends at
217
+ * `Number.MAX_SAFE_INTEGER`: a group that already numbers it refuses
218
+ * the appending session at construction, and a session whose counter
219
+ * would pass it refuses that call before dispatching the provider,
220
+ * both with a typed ConfigError and without touching the file,
221
+ * because the next float increment would stall at 2 ** 53 and
222
+ * silently duplicate one unsafe number on every following row
223
+ * (v1.33.0 review P3). The wrapped adapters are drop-in:
214
224
  * same ids, providers, caps, and event streams.
215
225
  */
216
226
  declare function record(options: {
package/dist/index.js CHANGED
@@ -389,7 +389,14 @@ function groupRows(rows, cassette) {
389
389
  * recorder session may be active on a cassette at a time: two
390
390
  * concurrently constructed recorders seed identically and claim
391
391
  * colliding numbers, which replay refuses as ambiguous instead of
392
- * silently serving either order. The wrapped adapters are drop-in:
392
+ * silently serving either order. The numbering ends at
393
+ * `Number.MAX_SAFE_INTEGER`: a group that already numbers it refuses
394
+ * the appending session at construction, and a session whose counter
395
+ * would pass it refuses that call before dispatching the provider,
396
+ * both with a typed ConfigError and without touching the file,
397
+ * because the next float increment would stall at 2 ** 53 and
398
+ * silently duplicate one unsafe number on every following row
399
+ * (v1.33.0 review P3). The wrapped adapters are drop-in:
393
400
  * same ids, providers, caps, and event streams.
394
401
  */
395
402
  function record(options) {
@@ -401,8 +408,10 @@ function record(options) {
401
408
  for (const [adapterId, forAdapter] of groupRows(existing.rows, options.cassette)) {
402
409
  const forSeeds = /* @__PURE__ */ new Map();
403
410
  for (const [hash, rows] of forAdapter) {
404
- const numbered = rows.map((row) => row.occurrence).filter((value) => value !== void 0);
405
- forSeeds.set(hash, numbered.length === 0 ? 0 : Math.max(...numbered) + 1);
411
+ let highest = -1;
412
+ for (const row of rows) if (row.occurrence !== void 0 && row.occurrence > highest) highest = row.occurrence;
413
+ if (highest >= Number.MAX_SAFE_INTEGER) throw new ConfigError(`${options.cassette} already numbers occurrence ${String(Number.MAX_SAFE_INTEGER)} for adapter '${adapterId}' hash ${hash.slice(0, 12)}; the numbering has reached the safe integer ceiling, so no further exchange for this request can be appended; record a fresh cassette instead`);
414
+ forSeeds.set(hash, highest + 1);
406
415
  }
407
416
  seeds.set(adapterId, forSeeds);
408
417
  }
@@ -417,6 +426,7 @@ function record(options) {
417
426
  stream(req, signal) {
418
427
  const hash = requestHash(req);
419
428
  const occurrence = occurrences.get(hash) ?? 0;
429
+ if (!Number.isSafeInteger(occurrence)) throw new ConfigError(`${options.cassette} has no safe occurrence number left for adapter '${adapter.id}' hash ${hash.slice(0, 12)}; an earlier call in this session claimed ${String(Number.MAX_SAFE_INTEGER)}, so this exchange cannot be numbered; record a fresh cassette instead`);
420
430
  occurrences.set(hash, occurrence + 1);
421
431
  return (async function* () {
422
432
  const events = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/testing",
3
- "version": "1.33.0",
3
+ "version": "1.35.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.33.0"
29
+ "@rulvar/core": "1.35.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.20.0",