Files
2026-05-27 23:29:53 +01:00

8.3 KiB
Raw Permalink Blame History

Tasks — seed

Every checkbox MUST reflect work actually done in this change.

1. Spec authoring

  • 1.1 Read openspec/AGENTS.md §0, §0a, §0b, §0c, §6a, §7, §13, §14 end-to-end
  • 1.2 Read ../suaveplan/packages/server/seed/src/ — all 17 implementation files
  • 1.3 Read ../suaveplan/enterprise/seed.md in full
  • 1.4 Read openspec/archive/2026-05-16-add-storage-http/ end-to-end as the closest precedent (universal-tier, error-coded, AbortSignal-plumbed migration)
  • 1.5 Draft proposal.md with parity checklist, source mapping, affected dependents
  • 1.6 Draft design.md covering layout, rename rationale, error-code map, topoSort rewrite, LoggerLike injection, AbortSignal plumbing
  • 1.7 Draft specs/seed/spec.md in OpenSpec ### Requirement: / #### Scenario: form
  • 1.8 Every requirement carries a **Verified by:** line naming concrete planned it(...) titles
  • 1.9 Build the numbered Requirement/Scenario implementation checklist (§0c step 6)

2. Scaffolding

  • 2.1 Create packages/database/seed/ mirroring the storage-http layout
  • 2.2 Write package.json v0.0.0, "sideEffects": false, subpath exports for ./builder/builder, ./registry/registry, ./runner/runner, ./fixtures/fixtures, ./utils/topo-sort/topo-sort, ./types/common, ./constants, ./error-codes/error-codes
  • 2.3 Wire deps: @suaveplan/error: workspace:^, @suaveplan/types: workspace:^, tslib: catalog:build
  • 2.4 Wire devDeps: @suaveplan/testing: workspace:*, @vitest/coverage-istanbul: catalog:, fast-check: catalog:, typescript: catalog:, vite: catalog:build, vite-plugin-dts: catalog:build, vitest: catalog:
  • 2.5 Write tsconfig.json, tsconfig.lib.json extending @suaveplan/typescript-config
  • 2.6 Write vite.config.ts (multi-entry build for every subpath export)
  • 2.7 Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config
  • 2.8 Write README.md (≥ 200 words, required sections per CLAUDE.md docs gate)

3. Implementation — constants & errors

  • 3.1 src/constants/index.ts — DEFAULT_ENVIRONMENTS, MAX_DEPENDENCY_DEPTH, DEFAULT_BATCH_SIZE, SEED_STATUS (as-const)
  • 3.2 src/error-codes/error-codes.ts — defineCodes("SEED", [...]) registry (7 codes), SeedError extends SuaveplanError<SeedErrorCode> with seedName? / dependency? discriminants
  • 3.3 src/error-codes/error-codes.test.ts — every code is reachable via SeedError construction; cause-chain preservation verified
  • 3.4 src/error-codes/error-codes.md — Purpose / Features / Usage Basic / Usage Advanced / API Reference / Implementation Notes

4. Implementation — types

  • 4.1 src/types/common.ts — every public type from upstream types/common.ts preserved verbatim; SeedStore methods gain optional signal?: AbortSignal; SeedRunConfig gains optional signal?: AbortSignal
  • 4.2 src/types/common.md — co-located doc per docs-coverage gate

5. Implementation — builder

  • 5.1 src/builder/builder.types.ts — ISeedBuilder interface mirroring the fluent surface
  • 5.2 src/builder/builder.ts — SeedBuilder class + defineSeed(name) convenience, behaviour-identical to upstream
  • 5.3 src/builder/builder.test.ts — every fluent method, including default-table-equals-name, environments empty-vs-set, dataFactory wins over data, build() output shape
  • 5.4 src/builder/builder.md — Purpose / Features / Usage Basic / Usage Advanced / API Reference / Implementation Notes
  • 5.5 src/builder/index.ts — explicit named re-exports (no export *)

6. Implementation — registry

  • 6.1 src/registry/registry.types.ts — ISeedRegistry interface
  • 6.2 src/registry/registry.ts — SeedRegistry class; register raises SeedError({ code: SEED.DUPLICATE_NAME, seedName }) on collision; getForEnvironment returns defensive copies
  • 6.3 src/registry/registry.test.ts — register/registerMany/get/getAll/getForEnvironment/has/remove/clear/size/names + duplicate-name error
  • 6.4 src/registry/registry.md
  • 6.5 src/registry/index.ts — explicit named re-exports

7. Implementation — topo-sort

  • 7.1 src/utils/topo-sort/topo-sort.ts — clean Kahn's-algorithm rewrite per design.md; topoSort + detectCycles; raises SeedError with UNREGISTERED_DEPENDENCY/CIRCULAR_DEPENDENCY/DEPENDENCY_DEPTH_EXCEEDED
  • 7.2 src/utils/topo-sort/topo-sort.test.ts — port every upstream test case verbatim (characterisation), plus property-based DAG tests via fast-check, plus cycle-reporter tests
  • 7.3 src/utils/topo-sort/topo-sort.md
  • 7.4 src/utils/topo-sort/index.ts — explicit named re-exports

8. Implementation — runner

  • 8.1 src/runner/runner.types.ts — ISeedRunner interface
  • 8.2 src/runner/runner.ts — SeedRunner class:
    • constructor (registry, store, logger?) with no-op LoggerLike default
    • run(config) applies only/exclude filter, env-filter, topo-sort
    • per-seed: skip if dep failed, honour truncate, batch by batchSize ?? DEFAULT_BATCH_SIZE, apply skip/update/replace strategy
    • dryRun short-circuit returns synthesised result without store IO
    • signal checked before each seed → remaining seeds marked skipped with error: "Aborted"
    • continueOnError controls whether failure halts the run
    • onProgress callback emits per completed seed
    • structured log events (seed.run.start, seed.run.complete, seed.completed, seed.skipped, seed.failed)
    • any error thrown by injected SeedStore wrapped as SeedError({ code: SEED.STORE_ERROR, cause }) and recorded on SeedResult.error
  • 8.3 src/runner/runner.test.ts — every behaviour above; mirror upstream test names where applicable; integrate with InMemorySeedStore
  • 8.4 src/runner/runner.md
  • 8.5 src/runner/index.ts — explicit named re-exports

9. Implementation — fixtures

  • 9.1 src/fixtures/fixtures.types.ts — if any local types needed
  • 9.2 src/fixtures/fixtures.ts — FixtureFactory<T>, createFixtureFactory, InMemorySeedStore, createInMemoryStore (preserve upstream SeedStore shape; gain optional signal? plumbing as no-op)
  • 9.3 src/fixtures/fixtures.test.ts — counter, overrides, createMany, store insert/update/findExisting/truncate/tableExists/getRecords/clear
  • 9.4 src/fixtures/fixtures.md
  • 9.5 src/fixtures/index.ts — explicit named re-exports

10. Root barrel & public surface

  • 10.1 src/index.ts — re-export every symbol listed in design.md "Package contract surface" using explicit named exports (no export * — rule §6a)
  • 10.2 Verify bunx turbo build --filter=@suaveplan/seed succeeds and dist contains every advertised subpath

11. Pre-archive gates

  • 11.1 bunx turbo lint --filter=@suaveplan/seed green; zero biome suppressions
  • 11.2 bunx turbo typecheck --filter=@suaveplan/seed green
  • 11.3 bunx turbo test --filter=@suaveplan/seed green; zero .skip / .only / it.todo
  • 11.4 bunx turbo test:coverage --filter=@suaveplan/seed green at 100% statement/branch/function/line (Istanbul)
  • 11.5 bun run docs:check --filter=@suaveplan/seed green
  • 11.6 grep -rnE "from ['\"](vitest|bun:test)['\"]" packages/database/seed/src/ → zero matches (rule §7)
  • 11.7 grep -rnE "^export \*" packages/database/seed/src/ → only the root barrel and exempt forms (rule §6a)
  • 11.8 grep -rnE "from ['\"](node:|bun:|fs|path|stream|net|http)['\"]" packages/database/seed/src/ → zero matches (tier purity)
  • 11.9 grep -rn "@deprecated\|TODO\|FIXME\|ts-ignore\|ts-expect-error\|\\bany\\b\|console\\.log" packages/database/seed/src/ --include="*.ts" → zero matches
  • 11.10 Every ### Requirement in specs/seed/spec.md checked off against the implementation checklist from §1.9
  • 11.11 bun scripts/folder-reorg/generate-manifest.ts run; MANIFEST.md includes @suaveplan/seed
  • 11.12 STATUS.md @suaveplan/seed row flipped from – to ✅

12. Fold + archive

  • 12.1 Fold specs/seed/spec.md into openspec/specs/seed/spec.md (canonical file is created here for the first time, since the package is net-new)
  • 12.2 Move openspec/changes/add-seed/ to openspec/archive/<yyyy-mm-dd>-add-seed/
  • 12.3 Commit per CLAUDE.md commit-style; do not push without user approval