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

6.8 KiB

Tasks — Font compress CLI

Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes.

Audit Note (2026-05-02)

Minimal progress beyond spec authoring — DEFERRED, do not archive.

  • §1 Spec authoring (9 tasks) is checked, and proposal.md + tasks.md exist — that's the only completed work.
  • No packages/fonts/font-compress/src/bin/ directory exists. Existing src dirs: constants, packer, unpacker, utils.
  • package.json has no bin field — confirmed via grep.
  • bunx turbo lint typecheck test --filter=@suaveplan/font-compress is GREEN — the green is for the existing pure-library surface; no CLI ships.
  • 35 of 44 tasks remain: dev-dep wiring (@suaveplan/cli, @suaveplan/readline, @suaveplan/logger), bin field, suaveplan-font-compress.ts entry, format-utils.ts, FONT_COMPRESS.CLI_INVALID_ARGS, Vite shebang config, unit + spec-conformance + integration tests, sibling .mds, README CLI section.

1. Spec authoring

  • 1.1 Read ../suaveplan/packages/universal/font-compress/src/cli.ts end-to-end (369 lines)
  • 1.2 Read ../suaveplan/packages/universal/font-compress/package.json (confirm bin field shape)
  • 1.3 Read openspec/specs/font-compress/spec.md (does not exist — capability spec authored fresh in this change)
  • 1.4 Read openspec/AGENTS.md Sections 13, 13a, 14, 14a
  • 1.5 Read packages/tooling/installer/src/bin/suaveplan-install.ts for the genesis bin pattern
  • 1.6 Draft proposal.md from openspec/templates/proposal.md
  • 1.7 Fill in ## Source mapping table — every requirement cites a line range OR appears in the "no source line" table with justification
  • 1.8 Draft specs/font-compress/spec.md from openspec/templates/spec-delta.md
  • 1.9 Every requirement in the spec delta carries a **Verified by:** line naming concrete it(...) titles

2. Implementation

  • 2.1 Add dev dep @suaveplan/cli (already a workspace package — argument parser, ANSI styling, progress bar)
  • 2.2 Add dev dep @suaveplan/readline (interactive prompts on overwrite confirmation)
  • 2.3 Add dep @suaveplan/logger (structured CLI logging)
  • 2.4 Add bin field to package.json — "suaveplan-font-compress": "./dist/bin/suaveplan-font-compress.js"
  • 2.5 Add ./bin/suaveplan-font-compress subpath to package.json exports (so the bin script is in the dist tree and resolvable for tests)
  • 2.6 Author src/bin/suaveplan-font-compress.ts — shebang, argument parser via @suaveplan/cli, dispatch (binary input → @suaveplan/font-convert::FontConverter or BatchConverter, then BinaryFontPacker; JSON input → BinaryFontPacker directly), output writer, summary printer
  • 2.7 Author src/bin/format-utils.ts — pure helpers (formatBytes, formatRatio, ANSI colour wrappers); separate file so the bin entry stays under the 250-line soft / 300-line hard budget
  • 2.8 Wire FONT_COMPRESS.CLI_INVALID_ARGS into the existing FONT_COMPRESS_CODES registry (src/error-codes.ts)
  • 2.9 Update Vite build config so the bin entry is emitted as a separate chunk with the shebang preserved (vite-plugin-shebang or equivalent)
  • 2.10 Update tsconfig.lib.json include to cover src/bin/**

3. Tests

  • 3.1 src/bin/suaveplan-font-compress.test.ts — unit tests for the argument parser (every flag, conflicting flags, missing positional, unknown flag), exit-code mapping, --help / --version short-circuit. Drive main() directly with process.argv-equivalent injection.
  • 3.2 src/bin/suaveplan-font-compress.spec-conformance.test.ts — pins FONT_COMPRESS.CLI_INVALID_ARGS emission, structured logging through @suaveplan/logger, OTel span font-compress.cli.run recorded via in-memory tracer
  • 3.3 src/bin/integration/cli-roundtrip.test.ts — integration test using a fixture TTF in src/bin/integration/fixtures/: invokes the bin via Bun.spawn, verifies stdout banner, verifies .btf file written, verifies the .btf round-trips through BinaryFontUnpacker
  • 3.4 src/bin/format-utils.test.ts — pure unit tests for formatBytes, formatRatio
  • 3.5 Every it(...) carries { timeout: 5000 } (or 30000 for genuinely async like the integration roundtrip)

4. Documentation

  • 4.1 src/bin/suaveplan-font-compress.md — sibling doc, ≥200 words, basic + advanced examples (single file, directory, recursive, JSON intermediate, custom output), full flag reference, exit-code table, implementation notes covering the convert→pack pipeline composition
  • 4.2 src/bin/format-utils.md — sibling doc for the helper module
  • 4.3 README adds a new ## CLI section linking the bin doc and showing an end-to-end example
  • 4.4 Update CLAUDE.md font-compress listing to mention the bin entry: "Bin: suaveplan-font-compress (TTF/OTF/WOFF/WOFF2 → BTF pipeline)"

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

  • 5.1 bun run check — Biome 0 errors / 0 warnings / 0 info
  • 5.2 bunx turbo lint typecheck test --filter=@suaveplan/font-compress — green
  • 5.3 bunx turbo test:coverage --filter=@suaveplan/font-compress — 100/100/100/100
  • 5.4 bun scripts/openspec-conformance.ts @suaveplan/font-compress — exit 0, no error findings
  • 5.5 bunx turbo build --filter=@suaveplan/font-compress — green AND dist/bin/suaveplan-font-compress.js starts with #!/usr/bin/env node AND is executable
  • 5.6 Smoke test: node packages/fonts/font-compress/dist/bin/suaveplan-font-compress.js --version prints the version

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

  • 6.1 Generics threaded; expectTypeOf assertions on the parser-result discriminated union
  • 6.2 Zod schemas wired at every public boundary (parsed args validated before any FS work)
  • 6.3 Every error code in error-codes.ts thrown by at least one production path (FONT_COMPRESS.CLI_INVALID_ARGS covered by the bad-args scenario)
  • 6.4 Strict-mode behaviors tested both on and off (--force on/off, --preserve-structure on/off)
  • 6.5 OTel span font-compress.cli.run emitted from production paths and asserted with a real in-memory TracerProvider
  • 6.6 Lifecycle dedup tested where claimed (multiple invocations against the same input directory with --force off skip already-converted files; verified by spy on BinaryFontPacker.pack)
  • 6.7 No retroactive tick — every box above reflects work done in this change

7. Archive

  • 7.1 Fold spec delta into openspec/specs/font-compress/spec.md (creates the canonical capability spec from scratch since none exists)
  • 7.2 Move openspec/changes/font-compress-cli/ → openspec/archive/<yyyy-mm-dd>-font-compress-cli/
  • 7.3 Refresh MANIFEST.md (the bin field is a new package surface; manifest should reflect it)