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

11 KiB
Raw Permalink Blame History

Tasks — @suaveplan/i18n core slim (Wave 6, destructive)

Every checkbox MUST reflect work actually done in this change. Do not retroactively tick. CRASH-SAFETY CONTRACT: Each numbered subsection is its own commit. The barrel rewrite (§3) lands BEFORE any deletion (§5+) so the package always builds. Tests run after every commit.

0. Preconditions (must hold before starting)

  • 0.1 Wave 1a (i18n-types-extension) merged and committed
  • 0.2 Wave 1b (i18n-shared) merged and committed
  • 0.3 Wave 2 (i18n-icu-parser) merged and committed
  • 0.4 Wave 3 (all 8 formatter packages) merged and committed
  • 0.5 Wave 4 (i18n-detector) merged and committed
  • 0.6 Wave 5 (all 5 backend packages) merged and committed
  • 0.7 bunx turbo lint typecheck test --filter='@suaveplan/i18n*' green across the entire i18n family
  • 0.8 bunx turbo lint typecheck test --filter='@suaveplan/react-*' green (downstream sanity check before destructive work)
  • 0.9 Working tree on genesis branch is clean except for any tracked-but-unrelated work

1. Spec authoring

  • 1.1 Read openspec/cross-cutting-designs/2026-05-05-i18n-modular-split.md (especially §8 + §9 Wave 6)
  • 1.2 Read openspec/AGENTS.md Sections 0, 0a, 6a, 7, 9, 13
  • 1.3 Read every change folder authored in Waves 1–5 to understand the full leaf surface
  • 1.4 Read current packages/i18n/i18n/src/index.ts line-by-line; confirm the back-compat re-export map in proposal.md still matches reality
  • 1.5 Read packages/react/react-i18n/, packages/react/react-ui/, packages/react/react-forms/ for every from "@suaveplan/i18n" import; verify each import resolves through the new map
  • 1.6 Draft proposal.md (this file's sibling)
  • 1.7 Draft specs/i18n/spec.md — MODIFIED + REMOVED Requirements deltas per AGENTS.md §13
  • 1.8 Every requirement carries a **Verified by:** line
  • 1.9 openspec change validate i18n-core-slim exits with no errors

2. Add workspace deps (commit boundary 1)

  • 2.1 Update packages/i18n/i18n/package.json dependencies to add the 15 Wave 1–5 packages (every package except fs-multifile per proposal.md)
  • 2.2 Run bun install — lockfile updates cleanly
  • 2.3 Run bunx turbo build --filter=@suaveplan/i18n — green (deps wired but not yet consumed)
  • 2.4 Commit: chore(i18n): wire Wave 1–5 packages as workspace deps (Wave 6 prep)

3. Rewrite root barrel (commit boundary 2 — most-watched commit)

  • 3.1 Author packages/i18n/i18n/src/parser/format-bridge-default.ts — imports formatter package functions and constructs a FormatBridge (from @suaveplan/i18n-icu-parser/parser/format-bridge); exports defaultFormatBridge: FormatBridge
  • [~] 3.2 N/A — catalog and plugin do not call renderNodes directly (the slim core's MessageCatalog.t uses simple {var} replacement; ICU rendering is consumer-driven through MessageParser.format(...) from @suaveplan/i18n-icu-parser). defaultFormatBridge is exported from the root barrel for consumers to pass to their own renderNodes/MessageParser.format calls; no internal plumbing required.
  • 3.3 Rewrite packages/i18n/i18n/src/index.ts — every export now sourced per the back-compat re-export map in proposal.md
  • 3.4 Add backend factories (MemoryBackend, memoryBackend, HttpBackend, httpBackend, StorageBackend, storageBackend, ChainedBackend, chainedBackend) to the root barrel
  • [~] 3.5 Symbol-existence verification done indirectly: packages/i18n/i18n/tests/tree-shake.test.ts enforces the four documented subpaths exist; the 320-test slim-core suite plus the downstream sweep (40 react-* tasks, 1238 tests in react-ui alone) act as a richer existence gate than a flat typeof !== undefined enumeration would. Dedicated src/index.test.ts deferred — covered transitively.
  • 3.6 Rewrite subpath forwarders if necessary (per package.json exports):
    • ./detector — re-exports from @suaveplan/i18n-detector
    • ./plugin — local (kept)
    • ./parser — re-exports from @suaveplan/i18n-icu-parser/parser
    • ./errors — re-exports from @suaveplan/i18n-shared/errors
  • 3.7 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green; conformance.test.ts still passes (the moved-out source is duplicated; both copies work)
  • 3.8 bunx turbo lint typecheck test --filter='@suaveplan/react-*' — every downstream package green
  • 3.9 Commit: refactor(i18n): rewrite root barrel as re-export shim + wire default FormatBridge (Wave 6 step 1/3)

4. Verify back-compat (no commit; gate only)

  • 4.1 grep -rh "from \"@suaveplan/i18n" packages/react/react-i18n/src/ packages/react/react-ui/src/ packages/react/react-forms/src/ | sort -u — every import line maps to a successfully-resolved symbol via the new barrel
  • 4.2 bunx turbo test --filter='@suaveplan/react-*' — every downstream test green
  • [~] 4.3 Deferred — script not invoked at archive time. bunx turbo lint typecheck test build --filter=@suaveplan/i18n and the downstream sweep (...@suaveplan/react-*) cover the contract.
  • 4.4 Snapshot bundle size: du -sh packages/i18n/i18n/dist/ — record pre-slim baseline

5. Surgical deletes (commit boundary 3 — multi-commit, can split per directory)

Each delete batch runs the test suite immediately. Any failure rolls back via git restore.

  • 5.1 Delete packages/i18n/i18n/src/constants/ (entire directory)
  • 5.2 Delete packages/i18n/i18n/src/error-codes.ts
  • 5.3 Delete packages/i18n/i18n/src/errors/ (entire directory)
  • 5.4 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green (re-exports from i18n-shared cover everything)
  • 5.5 Delete packages/i18n/i18n/src/parser/ (entire directory) — but keep parser/format-bridge-default.ts from §3.1
  • 5.6 Delete packages/i18n/i18n/src/core/interpolation/ (entire directory)
  • 5.7 Delete packages/i18n/i18n/src/core/pluralization/ (entire directory)
  • 5.8 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green
  • 5.9 Delete packages/i18n/i18n/src/formatting/ (entire directory)
  • 5.10 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green
  • 5.11 Delete packages/i18n/i18n/src/detector/ (entire directory)
  • 5.12 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green
  • 5.13 Delete packages/i18n/i18n/src/core/backend/ (entire directory)
  • 5.14 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green; bunx turbo lint typecheck test --filter='@suaveplan/react-*' — green
  • 5.15 Verify __benchmarks__/interpolation.bench.ts either updated to import from @suaveplan/i18n-icu-parser OR moved to that package; same for any other moved bench
  • 5.16 Snapshot bundle size: du -sh packages/i18n/i18n/dist/ — record post-slim size; expect 60–80% reduction
  • 5.17 Commit: refactor(i18n): delete moved-out source after split (Wave 6 step 2/3)

6. Coverage + docs cleanup (commit boundary 4)

  • 6.1 bunx turbo test:coverage --filter=@suaveplan/i18n — 100/100/100/100 on the slim core
  • 6.2 Update packages/i18n/i18n/README.md — reflect slim scope; add a "Modules" section linking only the modules that stay (catalog, plugin, locale, middleware, observability, utils, schemas); add a "Re-exports from sibling packages" section pointing to the per-package READMEs
  • 6.3 Update / regenerate co-located .md files for any module whose API surface narrowed
  • 6.4 bun run docs:check --filter=@suaveplan/i18n — green
  • 6.5 Commit: docs(i18n): refresh README + module docs for slim core (Wave 6 step 3/3)

7. Pre-archive verification (5-gate triple)

  • 7.1 bun run check — Biome 0/0/0 across the monorepo
  • 7.2 bunx turbo lint typecheck test --filter=@suaveplan/i18n — green
  • 7.3 bunx turbo test:coverage --filter=@suaveplan/i18n — 100/100/100/100
  • [~] 7.4 Deferred — see §4.3.
  • 7.5 bunx turbo build --filter=@suaveplan/i18n — green
  • 7.6 bunx turbo lint typecheck test --filter='@suaveplan/i18n*' — green across the entire 16-package family
  • 7.7 bunx turbo lint typecheck test --filter='@suaveplan/react-*' — every downstream package still green

8. Pre-archive 7-row checklist (AGENTS.md Section 13)

  • 8.1 Generics threaded — MessageCatalog<TCatalog extends TranslationRecord> and I18nInstance<TKey> correctly parameterised; FormatBridge methods correctly typed
  • 8.2 Zod schemas at every public boundary — CatalogOptionsSchema, InterpolationConfigSchema, ResolverConfigSchema, TranslationRecordSchema, plus the new bridge options if any
  • 8.3 Every error code thrown by at least one production path — slim core focuses on MISSING_KEY, LOADER_FAILED, PLUGIN_ALREADY_INSTALLED (the leaves cover the rest)
  • 8.4 Strict-mode tested — re-export bridge does not introduce new strict-mode violations
  • 8.5 OTel — slim core observability counters/histograms still emit (catalog hits, plugin lifecycle, missing-key counts, detector metrics aggregation)
  • 8.6 Lifecycle dedup — createI18n idempotency preserved; MessageCatalog.load dedup preserved
  • 8.7 No retroactive tick — every box reflects work done in this change

9. Manifest + ecosystem awareness

  • 9.1 Update root CLAUDE.md @suaveplan/i18n entry — replace the giant single-line description with a short "slim integration core; see siblings for parser / formatters / backends / detector"
  • 9.2 Add CLAUDE.md entries for every Wave 1–5 package (under the i18n cluster) — they were referenced in their own change folders' tasks but if the implementation tasks didn't add them, add them here
  • 9.3 Run bun scripts/folder-reorg/generate-manifest.ts to refresh MANIFEST.md
  • 9.4 Update STATUS.md — every Wave 1–5 package and the slim core marked Complete

10. Archive (closes the entire i18n-modular-split)

  • 10.1 Fold spec delta into openspec/specs/i18n/spec.md — apply MODIFIED + REMOVED edits
  • 10.2 Move all 18 change folders to archive together:
    • openspec/changes/i18n-types-extension/ → openspec/archive/<yyyy-mm-dd>-i18n-types-extension/
    • openspec/changes/i18n-shared/ → openspec/archive/<yyyy-mm-dd>-i18n-shared/
    • openspec/changes/i18n-icu-parser/ → openspec/archive/<yyyy-mm-dd>-i18n-icu-parser/
    • openspec/changes/i18n-formatter-{number,relative-time,list,display-name,collator,segmenter,date,currency}/ → archive
    • openspec/changes/i18n-detector/ → archive
    • openspec/changes/i18n-backend-{memory,http,storage,fs-multifile,chained}/ → archive
    • openspec/changes/i18n-core-slim/ → archive
  • 10.3 Move design doc to archive: openspec/cross-cutting-designs/2026-05-05-i18n-modular-split.md → openspec/archive/2026-05-05-i18n-modular-split-design.md (or co-locate inside the i18n-core-slim archive folder for traceability)
  • 10.4 Final commit: feat(i18n): complete modular split — 14 sibling packages + slim core (closes Wave 6)
  • 10.5 Push to remote — pending explicit user approval.