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

3.9 KiB

Tasks: enterprise-font-decompress

Change ID: enterprise-font-decompress Package: @suaveplan/font-decompress Target path: universal/compression/font-decompress Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/mime, @suaveplan/font-compress


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. Scaffold

  • Create directory universal/compression/font-decompress/ with src/, tests/, src/__benchmarks__/, and all feature subdirectories per the layout in proposal.md.
  • Write package.json at version 0.1.0 with "type": "module", "sideEffects": false, full exports map, deps: @suaveplan/error workspace:^, @suaveplan/types workspace:^, @suaveplan/mime workspace:^, @suaveplan/font-compress workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability.
  • Write tsconfig.json extending @suaveplan/typescript-config/library.json.
  • Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config.
  • Add lint, typecheck, test, test:coverage, build, docs:check scripts.

2. Types + errors

  • Write src/types/common.ts — GlyphInfo, CmapEntry, DecompressResult, FontDecompressAdapter, FontDecompressorOptions. Re-export FontFormat, FontMetadata from @suaveplan/font-compress.
  • Write src/types/common.md.
  • Write src/error-codes.ts — FontDecompressErrorCode, FONT_DECOMPRESS_ERROR_METADATA, registerFontDecompressErrorCodes().
  • Write Zod schemas: GlyphInfoSchema, CmapEntrySchema, DecompressResultSchema, FontDecompressorOptionsSchema.

3. NullFontDecompressAdapter

  • Implement NullFontDecompressAdapter — probe returns fixture metadata, decompress returns input bytes with a fixture result (decompressedSize = originalSize * 1.2), enumerateGlyphs returns N fixture glyphs, getCmapTable returns N fixture cmap entries.
  • Write null-adapter.test.ts and null-adapter.md.

4. Utils

  • Implement detectFontFormat (re-use pattern from font-compress, delegates to @suaveplan/mime).
  • Write format-detect.test.ts and format-detect.md.

5. FontDecompressor

  • Implement FontDecompressor — probe, decompress, enumerateGlyphs, getCmapTable delegate to adapter; wire AbortSignal.
  • Wire OTel: span font.decompress, counter font_decompress_total, histogram font_decompress_duration_ms.
  • Write font-decompressor.test.ts (≤500 lines): each method, abort, unsupported format throws.
  • Write font-decompressor.md.

6. Benchmarks

  • Write src/__benchmarks__/font-decompress.bench.ts — decompress 50 kB WOFF2 (null adapter), enumerate glyphs 200 kB TTF.

7. Tests

  • Write tests/integration.test.ts.
  • Write tests/property.test.ts (fast-check) — decompressed size ≥ original, glyph count > 0.

8. Docs + verify + publish

  • All co-located .md files (≥200 words each).
  • Write README.md at package root.
  • bunx turbo lint typecheck test --filter=@suaveplan/font-decompress — green.
  • bunx turbo test:coverage --filter=@suaveplan/font-decompress — 100%.
  • bun scripts/publish.ts --package @suaveplan/font-decompress.
  • Archive to openspec/archive/2026-04-24-enterprise-font-decompress/.