> Closed 2026-04-19 — all tasks landed. # Tasks: enterprise-random-family ## Pre-work - [x] 1. Add catalog entries to root `package.json` (if not already present from crypto-family): no new external deps needed for pseudo-random or random; noise needs none either ## Wave 1 — @suaveplan/pseudo-random (no workspace deps beyond error + types) - [x] 2. Scaffold `packages/universal/pseudo-random`: `package.json` (deps: `@suaveplan/error`, `@suaveplan/types`, `tslib`, `zod`), `tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts` (100% thresholds) - [x] 3. `errors/`: `PseudoRandomError`, `PRNG_CODES` - [x] 4. `seed/normalize.ts` + test + md: `normalizeSeed(seed: string | number): number` — splitmix64 mixing, rejects NaN/Infinity/non-safe-int - [x] 5. `types/seeded-rng.types.ts` + md: `SeededRng` interface, `RngCheckpoint` - [x] 6. `algorithms/mulberry32.ts` + test + md: implements `SeededRng`; byte-identical to `@suaveplan/testing` inline impl - [x] 7. `algorithms/sfc32.ts` + test + md: 128-bit state, 12 warmup rounds; byte-identical to bingo `BulletproofPRNG` (SFC32 mode) - [x] 8. `algorithms/xoshiro256.ts` + test + md: 256-bit state, algebraic jump for 2^128 and 2^192 - [x] 9. `algorithms/counter-rng.ts` + test + md: splitmix64 hash counter, O(1) `at(offset)` - [x] 10. Verify all `SeededRng` shared behaviours: `fork`, `checkpoint`/`restore`, `at` returns new instance, `skip` mutates self - [x] 11. `utils/shuffle.ts` + test + md: `shuffle`, `shuffleInPlace` - [x] 12. `utils/sample.ts` + test + md: `sample`, `weightedChoice` - [x] 13. `constants/index.ts`; barrel `src/index.ts`; subpath exports in `package.json` - [x] 14. fast-check property tests: determinism, fork independence (10k samples, correlation < 0.01), checkpoint round-trip - [x] 15. mitata benchmarks: `nextUint32` throughput for each algorithm - [x] 16. `tests/no-disallowed.test.ts` (no `Math.random`, `crypto.getRandomValues` in `src/`); `tests/tree-shake.test.ts` - [x] 17. `README.md` - [x] 18. `bunx turbo lint typecheck test:coverage --filter=@suaveplan/pseudo-random --force` → green at 100% - [x] 19. `bun scripts/publish.ts --package @suaveplan/pseudo-random` ## Wave 2 — @suaveplan/random (depends on types + error; pseudo-random optional peer) - [x] 20. Scaffold `packages/universal/random`: `package.json` (deps: `@suaveplan/types`, `@suaveplan/error`, `tslib`, `zod`), configs, 100% thresholds - [x] 21. `errors/`: `RandomError`, `RANDOM_CODES` - [x] 22. `source/crypto-rng.ts` + test + md: `cryptoRng()` factory — single `crypto.getRandomValues` callsite - [x] 23. `source/default-rng.ts` + test + md: `getDefaultRng`, `setDefaultRng` - [x] 24. `bytes/random-bytes.ts` + test + md - [x] 25. `numbers/random-int.ts` + test + md; `numbers/random-float.ts` + test + md - [x] 26. `strings/random-string.ts` + test + md: all 8 presets + custom charset, mutual-exclusion validation - [x] 27. `ids/uuid.ts` + test + md: v4 + v7 (monotonic sequence counter within same ms) - [x] 28. `ids/uuid.ts` (cont.): `randomULID`, `randomNanoid` - [x] 29. `collections/shuffle.ts` + `sample.ts` + `choice.ts` + `weighted.ts` + tests + mds - [x] 30. `objects/random-key.ts` + `random-value.ts` + `random-entry.ts` + `random-subset.ts` + tests + mds - [x] 31. `game/dice.ts` + test + md: `coin`, `dice`, `roll` - [x] 32. `distributions/continuous/normal.ts` + test + md (Box-Muller) - [x] 33. `distributions/continuous/log-normal.ts`, `exponential.ts`, `gamma.ts` (Marsaglia-Tsang + Ahrens-Dieter), `beta.ts` + tests + mds - [x] 34. `distributions/continuous/pareto.ts`, `weibull.ts`, `cauchy.ts`, `logistic.ts` + tests + mds - [x] 35. `distributions/discrete/bernoulli.ts`, `geometric.ts`, `binomial.ts`, `poisson.ts` (Knuth + rejection) + tests + mds - [x] 36. `distributions/sampler.ts` + test + md: `DistributionConfig`, `createSampler`, `sample` - [x] 37. fast-check: mean/variance within 5% of theoretical values for each distribution at 10k samples - [x] 38. `DistributionConfig` JSON round-trip test for all distribution types - [x] 39. `constants/index.ts`; barrel `src/index.ts`; subpath exports - [x] 40. `tests/no-disallowed.test.ts` (no `Math.random`, `crypto.getRandomValues` outside `src/source/crypto-rng.ts`); `tests/tree-shake.test.ts` - [x] 41. mitata benchmarks: `randomInt`, `shuffle(1000)`, `normal` sampler throughput - [x] 42. `README.md` - [x] 43. `bunx turbo lint typecheck test:coverage --filter=@suaveplan/random --force` → green at 100% - [x] 44. `bun scripts/publish.ts --package @suaveplan/random` ## Wave 3 — @suaveplan/noise (independent, only needs error) - [x] 45. Scaffold `packages/universal/noise`: `package.json` (deps: `@suaveplan/error`, `tslib`), configs, 100% thresholds - [x] 46. `errors/`: `NoiseError`, `NOISE_CODES` - [x] 47. `perlin/perlin.ts` + test + md: `perlin2`, `perlin3` - [x] 48. `simplex/simplex.ts` + test + md: `simplex2`, `simplex3`, `simplex4` - [x] 49. `value/value.ts` + test + md: `value2`, `value3` - [x] 50. `worley/worley.ts` + test + md: `worley2`, `worley3`, `WorleyMode` - [x] 51. `fbm/fbm.ts` + test + md: `fbm2`, `fbm3`, `FbmOptions` - [x] 52. `blue/blue.ts` + test + md: `blueNoiseSample`, Bridson's algorithm, `maxSamples` guard - [x] 53. `constants/index.ts`; barrel `src/index.ts`; subpath exports - [x] 54. fast-check: determinism + output range `[-1,1]` (or `[0,1]` for Worley) for all functions - [x] 55. mitata benchmarks: each function at 1k and 100k evaluations - [x] 56. `tests/tree-shake.test.ts` - [x] 57. `README.md` - [x] 58. `bunx turbo lint typecheck test:coverage --filter=@suaveplan/noise --force` → green at 100% - [x] 59. `bun scripts/publish.ts --package @suaveplan/noise` ## Close-out - [x] 60. Update `CLAUDE.md` package listing and counts for all 3 new packages - [x] 61. Update `PACKAGES.yml` / `STRUCTURE.yml` - [x] 62. Archive `openspec/changes/enterprise-random-family/` → `openspec/archive/2026-04-18-enterprise-random-family/`