# CLI Launch Reflight Plan

Date: 2026-02-09
Owner: Fullbleed CLI team
Scope: Prepare the Python-first CLI for a reliable release without disrupting the Rust engine.

## Goals
- Ship a stable `fullbleed` CLI with enterprise-grade contracts and agent-friendly behavior.
- Preserve existing CLI features and schemas while adding agent-mode capabilities.
- Avoid Rust engine changes unless absolutely required.

## Non-Goals
- Re-architecting the Rust engine or renderer.
- Introducing breaking changes to existing CLI flags or JSON schemas.
- Adding a built-in server mode.

## Launch Decision Log
- [x] Chosen strategy: Option A (`fullbleed = "fullbleed_cli.cli:main"`).
- [x] Root entrypoint switched to `fullbleed_cli.cli:main` in `pyproject.toml`.
- [x] `python/fullbleed_cli/**` included in packaging include list.
- [x] `python -m fullbleed` updated to delegate to `fullbleed_cli.cli`.
- [x] Root pytest suite passes (`132 passed`).
- [x] `pip install fullbleed` smoke test passes from wheel artifact.
- [x] Legacy parity decision made: `build` and `watch` are intentionally dropped for this launch.

## Current State Snapshot
- New Python-first CLI exists in `fullbleed_cli/` with full unit coverage in that subtree.
- Agent-mode flags are implemented: `--json-only`, `--no-prompts`, `--schema`, `--emit-manifest`.
- Root test collection is stable (`.txt` files excluded from pytest collection).

## Engine Capability Inventory (What is already in the backend)
- Single render: buffer and file output.
- Rich render artifacts: page data and glyph report.
- Batch render APIs: multiple HTML documents in one run.
- Batch render with per-job CSS.
- Parallel batch render APIs.
- Asset bundle registration and asset kinds (css, font, image, svg).
- PDF profile and color-space options (`none`, `pdfa2b`, `pdfx4`, `tagged`; `rgb`, `cmyk`).
- Headers, footers, watermark controls.
- JIT modes and perf/jit log outputs.

## Human+AI Feature Mapping

| Feature | Engine Support | CLI Support | Launch Status | Work Required |
| --- | --- | --- | --- | --- |
| `fullbleed plan` (compile-only) | Not required | Implemented | `Launch` | Emits `fullbleed.plan_result.v1` with manifest + warnings |
| `--policy <file>` | Not required | Not implemented | `Launch+1` | CLI policy evaluator (offline/domain/license/size/meta rules) |
| `assets verify --lock --strict` | Hash + asset data available | Implemented | `Launch` | Lock compare + strict nonzero exit on mismatch |
| `render-many --manifest jobs.json` | Yes (batch + parallel APIs exist) | Not implemented | `Launch+1` | CLI command wiring to existing batch backend calls |
| `--repro` hard deterministic mode | Core determinism is engine-level | Partial (`--deterministic-hash`, `--repro-record`, `--repro-check`) | `Launch` (record/check), `Launch+1` (`--repro` shorthand) | Add optional `--repro` shorthand + byte-for-byte fixture corpus |
| Structured errors with remediation/docs | Not required | Partial (`code` + `message`) | `Launch+1` | Extend error schema and map error taxonomy |
| `fullbleed attest` provenance output | Not required | Not implemented | `Post-launch` | CLI-only attestation format and optional signing |
| `fullbleed capabilities --json` | Inputs available | Implemented | `Launch` | Machine-readable command/agent/engine capability map |
| `--dry-run --explain` | Not required | Not implemented | `Launch+1` | CLI execution planner and explanation output |
| `assets audit` (license/compliance) | Metadata partially present | Not implemented | `Post-launch` | CLI audit report + policy hooks |
| `doctor --strict` CI gate | Not required | Implemented | `Launch` | Health checks + strict nonzero exit |
| `--output-dir` and `--artifacts-dir` | Not required | Not implemented | `Launch+1` | CLI path orchestration for artifacts |
| `fullbleed pack` offline bundle | Not required | Not implemented | `Post-launch` | Bundle format + restore workflow |
| `fullbleed replay manifest.json` | Yes (render paths exist) | Partial (`--emit-manifest`) | `Post-launch` | Add command to consume manifest and rerun |
| `--trace-jsonl` unified observability | Perf/JIT already available | Partial (`--emit-perf`, `--emit-jit`) | `Post-launch` | CLI merger/normalization pipeline |
| `fullbleed serve` | N/A | Rejected | `Out of scope` | Keep external-serving model by design |

## Release Readiness Checklist

### 1) Packaging and Entry Point Alignment (Critical)
- [x] Option A implemented in `pyproject.toml`.
- [x] Ensure `fullbleed_cli` is included in build artifacts and wheels.
- [x] Verify `pip install fullbleed` exposes new CLI and passes smoke run (`fullbleed doctor --json`).

Status:
- Current wheel artifact (`target/wheels/fullbleed-0.1.0-cp311-cp311-win_amd64.whl`) installs and passes user E2E checks (`doctor/init/new/assets/plan/render/verify/debug-*`) including `--fail-on overflow`, `--fail-on budget`, and repro record/check flows.

### 2) Contract and Schema Stability (Critical)
- [x] `--schema` emits `fullbleed.schema.v1` with target + definition.
- [x] `--json-only` suppresses human warnings in render/verify paths.
- [x] `--emit-manifest` emits `fullbleed.compiler_input.v1`.
- [x] Schema list is documented in `CLI_EPOCH.md`.
- [x] JSON result contract normalized (`bytes_written` scalar + structured `failures` payloads).

### 3) CLI Parity and Behavior (High)
- [x] Core commands verified: `render`, `verify`, `plan`, `capabilities`, `debug-perf`, `debug-jit`, `doctor`, `assets`, `cache`, `init`, `new`, `run`.
- [x] `--fail-on` semantics enforced for `overflow`, `missing-glyphs`, `font-subst`, and `budget`.
- [x] `run --html-str` works without `--html`.
- [x] Repro flow available via `--repro-record` and `--repro-check`.
- [x] `--allow-remote-assets` remains explicit opt-in.
- [x] Legacy parity policy: `build` and `watch` will not be ported; removed from launch scope.

### 4) Platform and CI (High)
- [x] Local: `python -m pytest` and `cargo test` pass.
- [ ] CI matrix for Windows/macOS/Linux launch gate.
- [ ] Wheel build + CLI smoke test per platform.

## Risks and Mitigations
- Risk: stale local extension binaries in `python/fullbleed/` can collide with maturin extension output during wheel builds.
- Mitigation: keep packaged Python tree source-only (no checked-in `.pyd`) and validate wheel contents in CI.
- Risk: users relying on legacy `build`/`watch` commands may fail after upgrade.
- Mitigation: document removal clearly in release notes with migration guidance to `render`/`verify`/`plan`.
- Risk: claims of determinism without byte-level validation.
- Mitigation: add reproducibility fixtures before announcing `--repro`.

## Proposed Sequence (Updated)
1. Complete wheel build and rerun `pip install` E2E smoke test. (`done`)
2. Implement remaining `Launch+1` items: `render-many`, `--policy`, `--repro` shorthand flag, richer structured errors.
3. Add CI release gates for wheel build and CLI smoke tests.
4. Tag RC and run compatibility suite.

## Launch Gate Analysis (`[sat]` / `[pass]` / `[fail]`)

Date: 2026-02-10  
Scope: launch-readiness assessment for CLI + Python bindings while in active/dirty dev tree.

Legend:
- `[sat]` fully satisfied with direct evidence
- `[pass]` acceptable to launch with explicit caveats
- `[fail]` launch blocker or claim mismatch that should be resolved before tag

Overall Decision (today): **`[pass]` with explicit blockers**
- Product behavior is largely launch-ready.
- Release process and docs contract still have concrete blockers (below) before a clean public tag.

### Evidence Snapshot
- `python -m pytest -q` -> `140 passed, 1 warning`
- `cargo test -q` -> `44 passed`
- Wheel smoke install in clean venv (`target/wheels/fullbleed-0.1.0-cp311-cp311-win_amd64.whl`) succeeded.
- Wheel command checks passed:
  - `fullbleed --json capabilities` includes `compliance` and agent flags.
  - `fullbleed --json compliance` returns `ok: true` with zero flags.
- Source-CLI render smoke (`PYTHONPATH=python`) with `--emit-manifest` confirms `watermark` block is emitted and `underlay` normalizes to `background`.
- `run` one-time AGPL reminder verified with isolated `FULLBLEED_STATE_DIR` (`license_warning_emitted` true then false).
- PDF default header observed as `%PDF-1.7` in no-flag render output.

### Scorecard

| Gate | Status | Why |
| --- | --- | --- |
| CLI command surface (render/verify/plan/run/compliance/assets/cache/init/new/debug/capabilities) | `[sat]` | Present and exercised in tests/smoke runs. |
| Human + agent JSON contract | `[pass]` | Strong overall; parser-level usage errors still bypass JSON payload contract. |
| Reproducibility primitives (`--deterministic-hash`, `--repro-record`, `--repro-check`) | `[pass]` | Functional and tested; still not equivalent to full reproducibility certification corpus. |
| Watermark feature set | `[sat]` | Text/html/image + semantics + layer alias + manifest representation all verified. |
| PDF/X-4 ergonomics | `[pass]` | Strict checks are correct; UX improved with early ICC validation and font hint, but still strict by design. |
| Compliance workflow (`compliance`, notices, audit artifacts) | `[sat]` | Command and policy output operational with machine-readable flags. |
| Packaging/wheel readiness | `[pass]` | Fresh wheel works; build pipeline still sensitive to local `.pyd` collision in dirty env. |
| Test stability | `[pass]` | Green at end of audit; observed one transient cache-prune test failure indicates flake risk. |
| CI release gates (Win/macOS/Linux + wheel smoke) | `[fail]` | Not yet implemented as enforced launch gate. |
| Release provenance from dirty tree | `[fail]` | Known and acknowledged: current tree contains active dev artifacts; release cut must come from sanitized export. |

### README Claim Audit (annotated)

Claims in `README.md` checked against current behavior:

| Claim | Status | Annotation |
| --- | --- | --- |
| Structured JSON schemas for commands | `[sat]` | True for command execution paths. |
| `schema` always present in JSON payloads | `[fail]` | Not true for argparse usage errors (`exit=2` emits usage text, not JSON schema payload). |
| Default production target is PDF 1.7 | `[sat]` | Observed `%PDF-1.7` in default render output. |
| `run` emits one-time AGPL reminder with suppression option | `[sat]` | Verified (`license_warning_emitted` true once, then false). |
| `compliance --json` provides machine-readable legal diagnostics | `[sat]` | Verified with zero-flag output in current repo. |

### Delivered But Missing From README (must add before tag)

Because this pass is constrained to note-keeping markdown only, these are recorded here for explicit follow-up:

1. `--emit-manifest` now includes full `watermark` object:
   `text|html|image|layer|semantics|opacity|rotation|enabled`.
2. `--watermark-layer underlay` is accepted as legacy alias and normalized to `background`.
3. Output intent metadata now requires `--output-intent-icc` (early CLI validation).
4. PDF/X-4 embedded-font failure now returns actionable CLI hint (`--asset @noto-sans` + CSS font-family).

### Blocking Items To Clear For Clean Launch

1. Create release from sanitized export (`repo_fix.py` flow), not from dirty dev tree.
2. Add CI launch gate matrix (Windows/macOS/Linux) with wheel build + smoke commands.
3. Resolve/deflake cache-prune timing sensitivity in tests (or make gate robust to timing jitter).
4. Apply README deltas above so docs match delivered behavior exactly.

### Reasonable Constraints For This Stage (implicit + explicit)

These are the constraints I should keep applying unless you override:

1. No Rust behavior changes unless a CLI contract cannot be solved on Python side.
2. No undocumented claims: every launch-facing claim must have a reproducible command/test proof.
3. Source-vs-installed CLI ambiguity must be explicit in evidence (`PYTHONPATH=python` vs wheel venv).
4. Treat dirty-tree state as known but non-authoritative for release provenance.
5. Keep machine contracts backward compatible unless explicitly version-bumped.
