Initial Commit
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: testing (testing)
|
||||
|
||||
**Package**: `@suaveplan/testing`
|
||||
**Status**: PROPOSED
|
||||
|
||||
> Every requirement below carries a `**Verified by:**` line at authoring time. No exceptions.
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Rng surface re-exports the canonical type
|
||||
|
||||
`@suaveplan/testing` SHALL re-export the canonical `Rng` interface from `@suaveplan/types` rather than declaring a local `interface Rng`. The re-export lives at `src/context/context.ts` and is named `Rng`, preserving the existing consumer import path (`import type { Rng } from "@suaveplan/testing"`) for one release cycle. The local `cryptoRng` and `seededRng(seed)` factories SHALL continue to satisfy the canonical type — they provide the required `nextUint32` / `nextFloat` members and omit the optional `nextBytes` / `nextIntInRange` members. The package SHALL add `@suaveplan/types` to `dependencies` as `workspace:^`; this is the sole `@suaveplan/*` runtime dependency permitted for testing-infrastructure packages under CLAUDE.md rule 8, and is allowed because `@suaveplan/types` is types-only and emits zero runtime (verified by the byte-size guard).
|
||||
|
||||
**Verified by:** `packages/testing/testing/src/context/context.ts` (re-export line `export type { Rng } from "@suaveplan/types"`) AND `packages/testing/testing/src/context/context.test.ts::"cryptoRng satisfies canonical Rng"` AND `packages/testing/testing/src/context/context.test.ts::"seededRng satisfies canonical Rng"` AND `packages/testing/testing/package.json` `dependencies` contains `"@suaveplan/types": "workspace:^"` AND `bunx turbo test --filter=...@suaveplan/testing` (foundation dependent sweep).
|
||||
|
||||
#### Scenario: local Rng re-export forwards canonical
|
||||
|
||||
- **WHEN** a consumer writes `import type { Rng } from "@suaveplan/testing"`
|
||||
- **THEN** the imported type is structurally identical to `import type { Rng } from "@suaveplan/types"`
|
||||
|
||||
#### Scenario: cryptoRng satisfies canonical
|
||||
|
||||
- **WHEN** `const r: import("@suaveplan/types").Rng = cryptoRng`
|
||||
- **THEN** `tsc` accepts (cryptoRng provides nextUint32 + nextFloat; optional members omitted)
|
||||
|
||||
#### Scenario: seededRng satisfies canonical
|
||||
|
||||
- **WHEN** `const r: import("@suaveplan/types").Rng = seededRng(42)`
|
||||
- **THEN** `tsc` accepts AND `r.nextUint32()` is deterministic given seed 42
|
||||
|
||||
#### Scenario: byte-size guard remains green
|
||||
|
||||
- **WHEN** the testing-infra byte-size guard runs after `@suaveplan/types` is added as a dependency
|
||||
- **THEN** the guard exits zero (because `@suaveplan/types` emits zero runtime bytes — it is a types-only package)
|
||||
Reference in New Issue
Block a user