9.5 KiB
9.5 KiB
Tasks — @suaveplan/i18n-backend-fs-multifile (Node fs/promises multi-file translation backend, server-tier)
Every checkbox MUST reflect work actually done in this change. Do not retroactively tick.
1. Spec authoring
- 1.1 Read
openspec/cross-cutting-designs/2026-05-05-i18n-modular-split.mdend-to-end (especially §3, §6, §6.1 — the only Wave 5 backend on a different tier) - 1.2 Read
openspec/AGENTS.mdSections 0, 0a, 6a, 7, 9, 13 - 1.3 Read source:
packages/i18n/i18n/src/core/backend/multi-file-fs/multi-file-fs-backend.ts,multi-file-fs-backend.test.ts,multi-file-fs-backend.schemas.ts,multi-file-fs-backend.md, pluspackages/i18n/i18n/src/core/backend/backend.types.ts - 1.4 Draft
proposal.mdfromopenspec/templates/proposal.md - 1.5 Document the tier split rationale in proposal.md (
### Tier split rationale (server-only, NOT universal)section) - 1.6 Fill
## Source mappingtable with verified line ranges from monolith - 1.7 Draft
specs/i18n-backend-fs-multifile/spec.mdfromopenspec/templates/spec-delta.md - 1.8 Every requirement carries a
**Verified by:**line naming concreteit(...)titles - 1.9
openspec change validate i18n-backend-fs-multifileexits with no errors
2. Package scaffold
- 2.1
mkdir -p packages/i18n/i18n-backend-fs-multifile/src - 2.2 Author
package.json— name@suaveplan/i18n-backend-fs-multifile, version0.1.0, typemodule, sideEffectsfalse. Server tier: declare"engines": { "node": ">=20" }; OMIT"browser"field. Deps:@suaveplan/i18n-shared workspace:^,@suaveplan/types workspace:^,@suaveplan/error workspace:^,@opentelemetry/api catalog:observability,tslib catalog:build,zod catalog:forms. devDeps:@suaveplan/testing workspace:^,@suaveplan/typescript-config workspace:^,@vitest/coverage-istanbul catalog:testing,vitest catalog:testing. Optional peerDeps:yaml,json5(markedOptional viapeerDependenciesMeta). - 2.3 Author
tsconfig.jsonextending@suaveplan/typescript-config/library-node.json(server-tier) - 2.4 Author
vite.config.tsusingcreateTestConfig()from@suaveplan/testing/config - 2.5 Author
README.md(≥200 words, includes Modules table linking to each.md; opens with a server-tier marker callout) - 2.6 Add
package.jsonexportsmap with subpaths.,./backend,./factory,./path-resolver,./payload-codec,./fs-error-classifier
3. Implementation
- 3.1 Author
src/backend.types.ts— portMultiFileFsBackendOptions,MultiFileFsLayout,MultiFileFsLikefrom monolith L15-L51 verbatim - 3.2 Author
src/backend.schemas.ts— portMultiFileFsBackendOptionsSchemaZod schema verbatim (15 lines) - 3.3 Author
src/path-resolver.ts— extract#resolvePathbody into a standaloneresolvePath(root, layout, extension, globPattern, locale, namespace): stringplusjoinPathhelper - 3.4 Author
src/payload-codec.ts— extractparsePayload,parseJson,parseWithPeer,encodePayloadfrom monolith L313-L400 as standalone exports - 3.5 Author
src/fs-error-classifier.ts— extractclassifyFsErrorfrom monolith L297-L311 as a standalone export - 3.6 Author
src/observability.ts— inline equivalents ofrecordRead/recordWrite; export histograms and counters withi18n.backend.fs_multifile.prefix; includelayoutattribute on counters - 3.7 Author
src/backend.ts— portMultiFileFsBackendclass from monolith L67-L284; rewire imports; use helpers fromsrc/path-resolver.ts,src/payload-codec.ts,src/fs-error-classifier.ts; emit metrics viasrc/observability.ts; add optionalsignal?: AbortSignalparameter onread/saveand throwI18nError(I18N.BACKEND_TIMEOUT)when signal aborts; LEADING SOURCE COMMENT:// Server-tier package — uses node:fs/promises. Browser consumers: use @suaveplan/i18n-backend-http or @suaveplan/i18n-backend-storage.
4. Factory function
- 4.1 Author
src/factory.ts—multiFileFsBackend(options: MultiFileFsBackendOptions): MultiFileFsBackendreturningnew MultiFileFsBackend(options)
5. Documentation (sibling .md per implementation file)
- 5.1
src/backend.md— port frompackages/i18n/i18n/src/core/backend/multi-file-fs/multi-file-fs-backend.md; ≥200 words; opens with server-tier marker; basic + advanced examples (per layout, with file-watch, with YAML peer) - 5.2
src/factory.md— ≥200 words; basic + advanced examples - 5.3
src/path-resolver.md— per-layout path shapes; glob substitution rules - 5.4
src/payload-codec.md— supported extensions; peer-detection contract; missing-peer error shape - 5.5
src/fs-error-classifier.md— errno → I18N code mapping table - 5.6
src/observability.md— emitted metrics + units + cardinality - 5.7
README.md## Modulessection links every.md; opens with> **Server-tier package** — usesnode:fs/promises. For browser consumers, use@suaveplan/i18n-backend-httpor@suaveplan/i18n-backend-storage.
6. Tests (Vitest, runner-neutral imports per CLAUDE.md §11)
- 6.1
src/backend.test.ts— port every test frompackages/i18n/i18n/src/core/backend/multi-file-fs/multi-file-fs-backend.test.ts(556 lines); sameit(...)titles for conformance traceability; covernested,flat,globlayouts;readhit/miss/parse-failure;saveround-trip;lastModified;init/disposelifecycle; YAML / JSON5 peer-detect happy path AND missing-peer path;fs.watchintegration via injectedMultiFileFsLike - 6.2
src/backend.spec-conformance.test.ts— oneit(...)per spec requirement; titles match**Verified by:**lines exactly - 6.3
src/factory.test.ts—multiFileFsBackend()returnsMultiFileFsBackendinstance; defaultname === "multi-file-fs" - 6.4
src/path-resolver.test.ts—nestedproduces<root>/<locale>/<namespace>.<ext>;flatproduces<root>/<locale>.<namespace>.<ext>;globsubstitutes both placeholders - 6.5
src/payload-codec.test.ts— JSON parse; YAML peer-detect happy + missing; JSON5 peer-detect happy + missing; unknown extension →BACKEND_READ_FAILED; non-object payload →BACKEND_READ_FAILED; encode for unsupported extension →BACKEND_WRITE_FAILED - 6.6
src/fs-error-classifier.test.ts—ENOENTandENOTDIR→BACKEND_LOCALE_NOT_AVAILABLE;EACCESandEBUSY→BACKEND_READ_FAILED - 6.7
src/index.test.ts— every documented public export resolves through.,./backend,./factory,./path-resolver,./payload-codec,./fs-error-classifier;package.jsondeclaresengines.node >=20AND omitsbrowserfield - 6.8 Add an AbortSignal cancellation test — pre-aborted signal causes
readto throwI18nError(I18N.BACKEND_TIMEOUT) - 6.9 Every
it(...)carries{ timeout: 5000 } - 6.10 All test imports go through
@suaveplan/testing/runner(CLAUDE.md §11) — verified bygrep -rnE "from ['\"](vitest|bun:test)['\"]" packages/i18n/i18n-backend-fs-multifile/src/returning zero hits - 6.11 No
// biome-ignoresuppressions (CLAUDE.md §9) - 6.12 No
export *in any non-root barrel (CLAUDE.md §10)
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-backend-fs-multifile— green - 7.3
bunx turbo test:coverage --filter=@suaveplan/i18n-backend-fs-multifile— 100/100/100/100 - 7.4
bun scripts/openspec-conformance.ts @suaveplan/i18n-backend-fs-multifile— exit 0 - 7.5
bunx turbo build --filter=@suaveplan/i18n-backend-fs-multifile— green
8. Pre-archive 7-row checklist (AGENTS.md Section 13)
- 8.1 Generics threaded —
MultiFileFsLikeinjection contract typed; layout discriminator union exhaustively narrowed - 8.2 Zod schemas wired at the public boundary —
MultiFileFsBackendOptionsSchemaparses constructor input;globPatternrequired whenlayout: "glob"enforced viaINVALID_OPTIONS - 8.3 Every error code thrown by at least one production path:
INVALID_OPTIONS(constructor),BACKEND_LOCALE_NOT_AVAILABLE(ENOENT/ENOTDIR),BACKEND_READ_FAILED(other fs errors / parse failure / unknown extension / missing peer),BACKEND_WRITE_FAILED(writeFile failure / unsupported extension),BACKEND_TIMEOUT(signal aborted) - 8.4 Strict-mode tested — exhaustive switch on
MultiFileFsLayoutenforced viaexpectTypeOf - 8.5 OTel histograms emitted from production paths:
i18n.backend.fs_multifile.read_duration_ms,i18n.backend.fs_multifile.write_duration_ms; counters withlayoutattribute - 8.6 Lifecycle dedup —
initis idempotent (re-calling does not start a second watcher);disposeis idempotent (re-calling is a no-op) - 8.7 No retroactive tick — every box reflects work done in this change
9. Manifest + ecosystem awareness
- 9.1 Add
@suaveplan/i18n-backend-fs-multifileentry to rootCLAUDE.mdpackage listing under the i18n cluster with a(server-tier)marker - 9.2 Run
bun scripts/folder-reorg/generate-manifest.tsto refreshMANIFEST.md - 9.3 Append
@suaveplan/i18n-backend-fs-multifiletoSTATUS.mdCompleted list with a server-tier marker
10. Archive
- 10.1 Fold spec delta into
openspec/specs/i18n-backend-fs-multifile/spec.md(NEW capability spec — first delta becomes canonical) - 10.2 Move
openspec/changes/i18n-backend-fs-multifile/→openspec/archive/<yyyy-mm-dd>-i18n-backend-fs-multifile/