Files
suaveplan/openspec/archive/2026-04-19-enterprise-timing/proposal.md
2026-05-27 23:29:53 +01:00

121 lines
4.6 KiB
Markdown

# OpenSpec Change: enterprise-timing
- **Change ID**: enterprise-timing
- **Package**: `@suaveplan/timing`
- **Category**: universal
- **Target path**: `packages/universal/timing`
- **Status**: IN PROGRESS
- **Date**: 2026-04-18
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/timing.md`
## Summary
Greenfield implementation of `@suaveplan/timing` for the genesis branch. The existing main-branch timing package provides the baseline public-API surface to preserve; this change delivers enterprise-grade timing and scheduling utilities — stopwatch, throttle/debounce, scheduler, exponential decay, and vector clock — with injectable clock, `AbortSignal` support, structured errors, Zod schemas, property-based tests, OTel instrumentation, and benchmarks.
## Current-state audit (genesis)
The package does not exist on genesis yet — this is a fresh build.
## Available workspace deps on genesis
| Package | Available |
|---------|-----------|
| `@suaveplan/error` | ✅ |
| `@suaveplan/types` | ✅ |
| `@suaveplan/events` | ✅ |
| `@suaveplan/streams` | ❌ not yet built — not required |
| `@suaveplan/opentelemetry` | ❌ not yet built — use `@opentelemetry/api` directly |
| `@suaveplan/feature-flags` | ❌ not yet built — skip |
| `@suaveplan/schema-registry` | ❌ not yet built — export Zod schemas directly |
External deps (via catalog):
- `zod` → `catalog:forms`
- `@opentelemetry/api` → `catalog:observability`
- `tslib` → `catalog:build`
Dev deps (via catalog):
- `vitest`, `@vitest/coverage-istanbul` → `catalog:testing`
- `fast-check` → `catalog:testing`
- `mitata` → `catalog:testing`
## Preserved public API surface (from main branch)
All of the following must be re-exported from the genesis build.
### Decay module (`src/decay/`)
- `createDecay(opts)` — returns a `Decay` instance with `.tick(elapsed)`, `.reset()`, `.value` getter
- `DecayOptions`, `DecayFunction`, `Decay` (types)
### Scheduler module (`src/scheduler/`)
- `createScheduler(opts?)` — returns a `Scheduler` with `.schedule(fn, delay)`, `.cancel(id)`, `.drain(signal?)`, `.dispose()`
- `SchedulerOptions`, `SchedulerHandle`, `Scheduler` (types)
### Stopwatch module (`src/stopwatch/`)
- `createStopwatch(opts?)` — returns a `Stopwatch` with `.start()`, `.stop()`, `.reset()`, `.lap()`, `.elapsed` getter, `.laps` getter
- `StopwatchOptions`, `StopwatchLap`, `Stopwatch` (types)
### Throttle module (`src/throttle/`)
- `throttle(fn, wait, opts?)` — leading/trailing edge configurable
- `debounce(fn, wait, opts?)` — with `.flush()` and `.cancel()` methods on the returned function
- `ThrottleOptions`, `DebounceOptions`, `ThrottledFunction`, `DebouncedFunction` (types)
### Timer module (`src/timer/`)
- `createTimer(opts)` — interval-based with `.start()`, `.stop()`, `.reset()`, `.tick` event
- `createCountdown(duration, opts?)` — countdown with `.start()`, `.pause()`, `.resume()`, `.stop()`, `.remaining` getter
- `TimerOptions`, `CountdownOptions`, `Timer`, `Countdown` (types)
### Vector clock module (`src/vector-clock/`)
- `createVectorClock(nodeId, opts?)` — returns a `VectorClock` with `.increment()`, `.update(remote)`, `.compare(other)`, `.toJSON()`, `.fromJSON(raw)`
- `vectorClockCompare(a, b)` → `'before' | 'after' | 'concurrent' | 'equal'`
- `VectorClockOptions`, `VectorClockState`, `VectorClock` (types)
## New additions for genesis
### Structured errors
- `TimingError` extends `SuaveplanError` with codes under `TIMING.*` namespace
- Codes: `TIMING.SCHEDULER.DISPOSED`, `TIMING.COUNTDOWN.INVALID_DURATION`, `TIMING.VECTOR_CLOCK.UNKNOWN_NODE`
### Zod schemas
- `SchedulerOptionsSchema`, `StopwatchOptionsSchema`, `TimerOptionsSchema`, `CountdownOptionsSchema`, `VectorClockOptionsSchema`
### Injectable clock
- All time-reading functions accept optional `{ clock?: Clock }` from `@suaveplan/types`
- Scheduler and timer use injected clock for deterministic tests
### AbortSignal support
- `Scheduler.drain(signal?)`, `Countdown` start/pause all honour `AbortSignal`
### OTel instrumentation
- Histograms for stopwatch elapsed, scheduler queue depth; counters for timer ticks
### Property-based tests (fast-check)
- Vector-clock ordering: transitivity, anti-symmetry
- Throttle: output count ≤ ceil(events / wait)
- Decay: monotonically decreasing (or increasing) toward target
### Benchmarks (mitata)
- `throttle` 10 000 events at 16ms window
- `createVectorClock` merge 1 000 nodes
- `createScheduler` drain 1 000 tasks
## Impact
- Adds one new package: `packages/universal/timing`
- Adds one new spec capability: `timing`
- No existing package consumers on genesis yet