Files
suaveplan/openspec/changes/_superseded-narrow-deferrals-2026-05-17/add-storage-mux/tasks.md
2026-05-27 23:29:53 +01:00

5.2 KiB
Raw Blame History

Tasks — storage-mux

Every checkbox MUST reflect work actually done in this change.

1. Spec authoring

  • 1.1 Read openspec/specs/storage/spec.md and confirm AbstractStorage surface
  • 1.2 Read openspec/AGENTS.md §0c, §13, §14
  • 1.3 Read archived openspec/archive/2026-05-16-add-storage-cdn/ for the deferral and family conventions
  • 1.4 Read packages/flow/retry/src/retry/retry.ts to confirm runWithRetry + RetryStrategy surface
  • 1.5 Draft proposal.md, design.md, specs/storage-mux/spec.md, tasks.md
  • 1.6 Numbered Requirement/Scenario checklist per §0c step 6

2. Scaffolding

  • 2.1 Create packages/storage/storage-mux/ mirroring packages/storage/storage-cdn/ conventions
  • 2.2 package.json v0.0.0, "sideEffects": false, subpath exports per feature
  • 2.3 Deps: @suaveplan/error, @suaveplan/events, @suaveplan/retry, @suaveplan/storage, @suaveplan/types, @opentelemetry/api, zod, tslib
  • 2.4 DevDeps: @suaveplan/testing, @vitest/coverage-istanbul, fast-check, mitata, typescript, vite, vite-plugin-dts, vitest
  • 2.5 tsconfig, vite.config.ts, vitest.config.ts via createTestConfig
  • 2.6 README.md root with Modules section linking every .md

3. Error registry

  • 3.1 src/error-codes.ts — defineCodes("STORAGE_MUX", [...]) with 8 codes (ALL_BACKENDS_DOWN, NO_BACKENDS_CONFIGURED, HEALTHCHECK_FAILED, BACKEND_TIMEOUT, INVALID_POLICY, INVALID_WEIGHT, WRITE_FANOUT_PARTIAL, BACKEND_ABORTED)
  • 3.2 src/error-codes.ts — StorageMuxError extends SuaveplanError<StorageMuxErrorCode> with backendName, attemptIndex, attemptCount discriminants

4. Types & schemas

  • 4.1 src/types/backend-entry.types.ts — BackendEntry interface (name, storage, weight?, healthcheck?)
  • 4.2 src/types/mux-options.types.ts — MuxPolicy discriminated string union, StorageMuxOptions
  • 4.3 src/types/mux-options.schemas.ts — Zod schemas validating non-empty backends, policy whitelist, weight ≥ 0

5. Selectors / policies

  • 5.1 src/policies/selector.types.ts — BackendSelector interface (select(op, key?, healthy): BackendEntry)
  • 5.2 src/policies/classify.ts + .md + .test.ts — pure error classification per design §4 table
  • 5.3 src/policies/failover/failover.ts + .md + .test.ts — fall-through + retry composition
  • 5.4 src/policies/round-robin/round-robin.ts + .md + .test.ts — atomic counter, skip down
  • 5.5 src/policies/sticky-by-key/sticky-by-key.ts + .md + .test.ts — FNV-1a hash, deterministic
  • 5.6 src/policies/shield/shield.ts + .md + .test.ts — read cascade, write fan-out, partial signal

6. Health

  • 6.1 src/health/health.ts + .md + .test.ts — BackendHealth tracker, exponential cooldown, recovery probe, active healthcheck via injected Clock

7. Mux core

  • 7.1 src/mux/mux.ts + .md — StorageMux extends AbstractStorage, per-op routing through BackendSelector + runWithRetry, per-backend timeout race, AbortSignal linking
  • 7.2 src/mux/mux.test.ts — construction validation, policy dispatch, abort surfacing
  • 7.3 src/mux/mux.spec-conformance.test.ts — runStorageConformance × 4 policies × 3 MemoryStorage backends

8. Observability

  • 8.1 src/observability/events.ts + .md + .test.ts — event topic constants (storage-mux.backend.down, .recovered, .failover, .fanout-partial), emit* helpers consuming EventBusLike
  • 8.2 src/observability/otel.ts + .md + .test.ts — span attribute helpers (mux.backend.name, mux.attempt.index, mux.policy)

9. Barrel + exports

  • 9.1 src/index.ts — explicit named re-exports per §6a (NO export *)
  • 9.2 package.json subpath exports match every feature directory

10. Tests

  • 10.1 src/error-codes/error-codes.test.ts — every STORAGE_MUX_* code reachable from a real call site
  • 10.2 All test imports via @suaveplan/testing/runner (§7)
  • 10.3 Every it(...) carries { timeout: 5000 } (or 30000 for async health)
  • 10.4 Backend isolation test: hung-promise primary does NOT block fallback within backendTimeoutMs

11. Documentation

  • 11.1 Sibling .md for every implementation .ts (≥ 200 words, all required sections)
  • 11.2 README.md documents each policy with a usage example

12. Gates

  • 12.1 bun run check
  • 12.2 bunx turbo lint typecheck test --filter=@suaveplan/storage-mux
  • 12.3 bunx turbo test:coverage --filter=@suaveplan/storage-mux (100/100/100/100)
  • 12.4 bun scripts/lint/check-test-runner-imports.ts
  • 12.5 Tier-purity grep grep -rnE "from ['\"](node:|bun:)" packages/storage/storage-mux/src/ returns empty
  • 12.6 Banned-pattern scan returns empty
  • 12.7 bun scripts/openspec-conformance.ts @suaveplan/storage-mux

13. Manifest & archival

  • 13.1 bun scripts/folder-reorg/generate-manifest.ts
  • 13.2 bun scripts/generate-missing.ts
  • 13.3 Update STATUS.md and SUMMARY.md
  • 13.4 bunx markdownlint-cli2 --fix
  • 13.5 Fold specs/storage-mux/spec.md → openspec/specs/storage-mux/spec.md
  • 13.6 Move change folder → openspec/archive/<yyyy-mm-dd>-add-storage-mux/