Files
suaveplan/openspec/changes/enterprise-testing-load-perf/tasks.md
2026-05-27 23:29:53 +01:00

5.3 KiB

0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Catalog setup

  • 1.1 Add autocannon to root package.json catalogs.testing (k6 runs via the grafana/k6 container; no npm entry needed)
  • 1.2 Run bun install; confirm lockfile updates cleanly

2. Package skeleton — @suaveplan/testing-load

  • 2.1 Create packages/testing/testing-load/ with package.json (version 0.1.0, type: "module", sideEffects: false, @suaveplan/types workspace dep, external catalog deps only)
  • 2.2 Create tsconfig.lib.json extending @suaveplan/typescript-config/library.json
  • 2.3 Create vite.config.ts (preserveModules, ESM only)
  • 2.4 Create vitest.config.ts consuming @suaveplan/testing/config once available; thresholds at 100/100/100/100 (istanbul)
  • 2.5 Create README.md with purpose, install, quick-start, error-code index, links to module .md files
  • 2.6 Subpath exports in package.json for every feature module per openspec/AGENTS.md §6

3. Public API — scenario, driver, runner

  • 3.1 src/scenario/scenario.ts — defineLoadScenario, LoadScenario, LoadScenarioSpec; Zod schemas in scenario.schemas.ts
  • 3.2 src/scenario/presets.ts — smoke, load, stress, spike constants composing vus/stages/duration
  • 3.3 src/driver/driver.ts — LoadDriver interface, LoadSummary normalised shape
  • 3.4 src/driver/k6-driver.ts — k6 implementation; injectable exec (testcontainers) + fetch for self-testability
  • 3.5 src/driver/autocannon-driver.ts — autocannon implementation; in-process Node fallback
  • 3.6 src/runner/run-load-scenario.ts — runLoadScenario(scenario, opts); resolves driver default to k6 if reachable, autocannon otherwise; honours AbortSignal
  • 3.7 src/thresholds/assert-thresholds.ts — assertThresholds(summary); throws TestingLoadError("TESTING_LOAD.THRESHOLD_VIOLATION", …) listing every failed predicate

4. Errors and observability

  • 4.1 src/errors/testing-load-error.ts — TestingLoadError extends Error with { code, cause?, context? }
  • 4.2 src/errors/codes.ts — TESTING_LOAD.THRESHOLD_VIOLATION, TESTING_LOAD.DRIVER_FAILED, TESTING_LOAD.CONFIG_INVALID, TESTING_LOAD.DRIVER_UNAVAILABLE, TESTING_LOAD.ABORTED
  • 4.3 OTel counters/histograms via @opentelemetry/api per existing testing/spec.md pattern; spans for runLoadScenario only

5. Tests, docs, schemas

  • 5.1 Co-locate *.test.ts per implementation file; 100% Istanbul coverage (statements / branches / functions / lines)
  • 5.2 Co-locate *.md per implementation file (≥ 200 words, simple + advanced examples, API reference, implementation notes) per openspec/AGENTS.md §4
  • 5.3 Co-locate *.schemas.ts per implementation file; tree-shake test proving schemas don't bloat functional bundle
  • 5.4 Property tests (fast-check) for assertThresholds predicate evaluation, scenario merge associativity
  • 5.5 Mitata benchmarks under src/__benchmarks__/ for scenario-build and threshold-evaluation hot paths

6. App integration — *.smoke.load.ts

  • 6.1 apps/testbed/tests/load/healthz.smoke.load.ts — smoke scenario for GET /healthz
  • 6.2 One *.smoke.load.ts per route declared in apps/testbed/src/routes.ts
  • 6.3 apps/websocket-gateway/tests/load/connection.smoke.load.ts — websocket-fan-out smoke scenario
  • 6.4 Each app's package.json exposes test:load:smoke invoking its smoke files via the package's own runner

7. CI integration

  • 7.1 Nightly job: run every *.smoke.load.ts against the app's Docker staging stack
  • 7.2 Failure on any threshold violation breaks the build
  • 7.3 Weekly job (or manual workflow_dispatch): run load, stress, spike modes against staging
  • 7.4 Cross-link smoke result into the release-readiness gate (audit §7) once that gate lands

8. Spec deltas and validation

  • 8.1 openspec validate enterprise-testing-load-perf --type change passes
  • 8.2 Fold specs/testing-load/spec.md ADDED Requirements into a new openspec/specs/testing-load/spec.md
  • 8.3 Fold specs/testing/spec.md ADDED Requirement into the existing openspec/specs/testing/spec.md
  • 8.4 Move this change folder to openspec/archive/<yyyy-mm-dd>-enterprise-testing-load-perf/

9. Pre-publish gate and publish

  • 9.1 bunx turbo lint typecheck test --filter=@suaveplan/testing-load green
  • 9.2 bunx turbo test:coverage --filter=@suaveplan/testing-load reports 100% statements / branches / functions / lines
  • 9.3 bun scripts/publish.ts --package @suaveplan/testing-load --dry-run produces a sane diff
  • 9.4 bun scripts/publish.ts --package @suaveplan/testing-load — publish 0.1.0 to Verdaccio