# 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 `.md`s, README CLI section. ## 1. Spec authoring - [x] 1.1 Read `../suaveplan/packages/universal/font-compress/src/cli.ts` end-to-end (369 lines) - [x] 1.2 Read `../suaveplan/packages/universal/font-compress/package.json` (confirm `bin` field shape) - [x] 1.3 Read `openspec/specs/font-compress/spec.md` (does not exist — capability spec authored fresh in this change) - [x] 1.4 Read `openspec/AGENTS.md` Sections 13, 13a, 14, 14a - [x] 1.5 Read `packages/tooling/installer/src/bin/suaveplan-install.ts` for the genesis bin pattern - [x] 1.6 Draft `proposal.md` from `openspec/templates/proposal.md` - [x] 1.7 Fill in `## Source mapping` table — every requirement cites a line range OR appears in the "no source line" table with justification - [x] 1.8 Draft `specs/font-compress/spec.md` from `openspec/templates/spec-delta.md` - [x] 1.9 Every requirement in the spec delta carries a `**Verified by:**` line naming concrete `it(...)` titles ## 2. Implementation - [x] 2.1 Add dev dep `@suaveplan/cli` (already a workspace package — argument parser, ANSI styling, progress bar) - [x] 2.2 Add dev dep `@suaveplan/readline` (interactive prompts on overwrite confirmation) - [x] 2.3 Add dep `@suaveplan/logger` (structured CLI logging) - [x] 2.4 Add `bin` field to `package.json` — `"suaveplan-font-compress": "./dist/bin/suaveplan-font-compress.js"` - [x] 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) - [x] 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 - [x] 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 - [x] 2.8 Wire `FONT_COMPRESS.CLI_INVALID_ARGS` into the existing `FONT_COMPRESS_CODES` registry (`src/error-codes.ts`) - [x] 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) - [x] 2.10 Update `tsconfig.lib.json` `include` to cover `src/bin/**` ## 3. Tests - [x] 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. - [x] 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 - [x] 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` - [x] 3.4 `src/bin/format-utils.test.ts` — pure unit tests for `formatBytes`, `formatRatio` - [x] 3.5 Every `it(...)` carries `{ timeout: 5000 }` (or 30000 for genuinely async like the integration roundtrip) ## 4. Documentation - [x] 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 - [x] 4.2 `src/bin/format-utils.md` — sibling doc for the helper module - [x] 4.3 README adds a new `## CLI` section linking the bin doc and showing an end-to-end example - [x] 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) - [x] 5.1 `bun run check` — Biome 0 errors / 0 warnings / 0 info - [x] 5.2 `bunx turbo lint typecheck test --filter=@suaveplan/font-compress` — green - [x] 5.3 `bunx turbo test:coverage --filter=@suaveplan/font-compress` — 100/100/100/100 - [x] 5.4 `bun scripts/openspec-conformance.ts @suaveplan/font-compress` — exit 0, no `error` findings - [x] 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 - [x] 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) - [x] 6.1 Generics threaded; `expectTypeOf` assertions on the parser-result discriminated union - [x] 6.2 Zod schemas wired at every public boundary (parsed args validated before any FS work) - [x] 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) - [x] 6.4 Strict-mode behaviors tested both on and off (`--force` on/off, `--preserve-structure` on/off) - [x] 6.5 OTel span `font-compress.cli.run` emitted from production paths and asserted with a real in-memory `TracerProvider` - [x] 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`) - [x] 6.7 No retroactive tick — every box above reflects work done in this change ## 7. Archive - [x] 7.1 Fold spec delta into `openspec/specs/font-compress/spec.md` (creates the canonical capability spec from scratch since none exists) - [x] 7.2 Move `openspec/changes/font-compress-cli/` → `openspec/archive/-font-compress-cli/` - [x] 7.3 Refresh `MANIFEST.md` (the `bin` field is a new package surface; manifest should reflect it)