0.0.5 preparation plan¶
Proposed scope; implementation is incremental. This plan follows the 0.0.4 release and does not bump manifests, create a tag or authorize publication. Use 0.0.4 as the starting baseline. Each implementation will land through its own reviewed PR, with tests, actual CLI evidence and corresponding site updates.
The current baseline already includes the #15 fixture families for truecolor,
8-bit and standard color systems, HTML/SVG exports, wrapping, tables and
layouts. The capture script now verifies the installed Python rich version
against UPSTREAM.toml before writing any fixture. Remaining #15 work is
additional module coverage and should be added as the corresponding ports land;
it is not a reason to regenerate existing fixtures from an unverified
environment.
The first #34 differential harness is also in place: scripts/diff_rich.py
replays a small JSONL corpus through pinned Python rich and the Rust
diff_render probe, compares exact terminal bytes, records mismatches with a
bounded source shrink, and has a mutation mode that proves the detector fails
closed. Keep this corpus small in ordinary CI; use generated cases locally or in
a separate bounded job when expanding search volume.
For #35, cargo run --release -p rs-rich --example library_bench -- --revision
<sha> now emits JSON samples for markup parsing, Text wrap/justify, Table layout
and Console rendering, including setup timings, output hashes and whether the
syntax-cache cfg is active. Store default and syntax-cache results as
separate artifacts when measuring release candidates.
For #64, the CLI now has explicit --sanitize wiring backed by
rich-ext::sanitize_terminal_controls. It preserves defaults, then opt-in
sanitizes decoded file/stdin/URL text, literal --print input, JSON string
values decoded from escape sequences, notebook string values, panel/table titles
and captions, rule titles and SVG document titles. LF and TAB stay intact for
layout and CSV/TSV structure; ESC, DEL, other C0 controls and C1 controls become
visible inert text before core rendering, so renderer-owned ANSI styling is not
stripped. GIF/diff binary workflows do not consume this text path.
Goal¶
Catch rendering regressions earlier and give users an explicit way to neutralize terminal controls in input. Preserve the faithful core, existing default output, independent package versions and the protected release path.
Proposed work¶
| Order | Issue | Deliverable | Acceptance |
|---|---|---|---|
| 1 | #15: golden coverage and capture tooling | Audit current fixtures and add a named, bounded matrix of missing color, Unicode, wrapping and layout cases. | Record exactly which cases are added; verify the installed Rich oracle pin before capture; regenerate fixtures with a clean diff and preserve authoritative parity CI. |
| 2 | #34: differential fuzzing | A deterministic first harness for markup, styles and Text wrapping/overflow, with replay and bounded shrinking. | Store seeds, complete cases and both implementations' results; reproduce a deliberately introduced mismatch; minimize failures and promote confirmed defects into permanent regressions. Initial corpus and CI replay are now present; broader generated runs remain future expansion. |
| 3 | #35: library benchmarks | Repeatable library measurements for markup parsing, Text wrap/justify, Table layout and Console rendering to a controlled sink; publish CI artifacts. | Validate output, retain fixture/revision/toolchain metadata and distributions, separate cold setup from repeated rendering, and report default and syntax-cache builds independently. Initial JSON probe is present; artifact publication remains release-candidate work. |
| 4 | #64: opt-in input sanitization | Define and implement an explicit CLI option with extension-owned policy for neutralizing input terminal controls. | Default invocations remain byte-compatible for files, stdin and URLs. Enabled behavior has a documented format/source matrix, adversarial control-sequence tests and real terminal evidence. Initial --sanitize implementation and regression tests are present; release-candidate evidence should add terminal captures. |
Start with the oracle/case definitions in #15, then the replayable harness in issue #34. Library baselines can proceed independently. Specify and test the sanitizer contract before implementing it. These are bounded deliverables: #15 and #34 remain open if broader coverage is still outstanding.
CLI expansion decision¶
The CLI roadmap was reviewed as a possible 0.0.5 expansion. It is not a commitment to deliver all seven issues. The release slice is gated by a stable contract, dependency order, implementation size and evidence that can fit the release gates.
Prioritized slice¶
- #137 — scalable subcommand architecture. Establish the command boundary and dispatch model first, without changing existing invocation behavior.
- #143 — stable output formats and structured exit codes. Define the machine-readable output and exit-code contract on top of the command boundary, preserving current human-readable output by default.
- #138 — streaming JSONL and log rendering. Include this only if #137 and #143 land with a bounded format contract and streaming behavior can be tested without buffering the complete input.
The remaining roadmap items are deferred from 0.0.5 unless separately promoted after implementation evidence:
-
139 watch mode¶
-
140 pager integration¶
-
141 persistent configuration profiles and themes¶
-
142 batch conversion and multi-input workflows¶
This ordering intentionally favors stable interfaces and bounded behavior over the larger workflow features. A selected issue is release-eligible only when its CLI help, exit-status matrix, stdout/stderr behavior, streaming/memory properties where applicable, regression tests, and user documentation are complete. A roadmap issue that misses those gates remains open for a later release; it is not partially represented in the 0.0.5 changelog.
Reuse the evidence already available¶
The statement in the older #35 issue that no benchmarks exist is historical.
The 0.0.4 measurements, scripts/bench_v004.py, CLI baseline,
output hashes and repeated-library Syntax probe already exist. Extend that work;
do not replace it with an incomparable corpus or claim a baseline is new.
Keep the original Linux measurements as historical evidence. Establish paired before/after results on the same host for each new comparison, with fixed widths, color settings, warmups, repeated samples and input/output hashes. Measure memory separately where meaningful. Shared-runner timing reports start as advisory; choose failure thresholds only after recorded variance supports them. Correctness and output checks remain blocking from the start.
Differential-test contract¶
- Use the pinned Python Rich version from
UPSTREAM.tomlin an isolated oracle environment, and fail immediately if the installed version differs. Keep the rich-cli semantic oracle in a separate environment. - Define cases independently of either renderer: input, width, color system, styles and overflow settings. Start with an explicit supported matrix.
- Preserve the seed, complete case, source revisions, toolchain/oracle versions, stdout, stderr and exit status. Enforce per-case and total-run timeouts.
- Prove replay and mismatch detection using an intentional comparator/fixture mutation. Bound shrinking and retain the failure category while minimizing.
- Compare exact output where parity is promised. Record reviewed divergences narrowly; do not normalize away whitespace, color or Unicode differences.
- Keep a small deterministic corpus in ordinary CI. Larger generated runs use a separate bounded job, with failures saved as artifacts and reproducible locally.
Sanitizer contract before code¶
The core intentionally preserves ESC, matching upstream. This addition belongs
in rich-ext, with CLI wiring at the relevant input boundaries. Check the pinned
rich-cli behavior before choosing the final flag spelling; --sanitize is a
candidate, not an implemented option.
Document whether controls are removed or visibly escaped and which inputs are covered. Keep LF and TAB where required for content and CSV/TSV structure, and preserve valid Unicode. Test CSI, OSC with BEL/ST terminators, C1 controls, and malformed or truncated sequences.
Sanitizing raw file bytes alone is insufficient: JSON and notebook parsing can
decode \u001b into ESC later, and markup or hyperlink destinations can feed
terminal controls. Cover decoded user text and link destinations before they
reach terminal output. Audit titles, captions, filenames and diagnostics too;
list any exclusions explicitly rather than promising that arbitrary input is safe.
Do not strip the renderer's own styling from the final output stream.
The acceptance matrix includes supported files, stdin and URLs; plain text, syntax, CSV/TSV, JSON, Markdown and notebook text; PTY, pipe, HTML and SVG output. Check default and enabled behavior separately. Only test dangerous control input inside an isolated terminal capture. GIF/binary modes must either reject the option clearly or have an explicitly documented contract. Defaults remain unchanged for every source, including URLs.
Maintenance before accepting upgrades¶
Audit open dependency PRs individually against fresh main; branch names can be older than their updated titles. As reviewed on 2026-09-10:
| PR | Review focus |
|---|---|
| #95: ureq | Locked dependency resolution, the declared MSRV, fetch feature builds, URL decoding and diagnostics. |
| #97: icy_sixel | Breaking API/encoding behavior, dimensions, transparency, image fixtures and optional-feature builds. |
| #96: checkout | Main already uses v7 in most jobs; check the remaining v4 reference in the RC branch guard and avoid stale changes. |
| #52: github-script, #53: deploy-pages, #54: upload-pages-artifact | Runtime/API compatibility, workflow regressions, a successful docs deployment and least-privilege permissions. |
This is a triage list, not approval to merge every upgrade. Keep dependency
changes separate from feature changes. PR #41 remains marked do-not-merge;
it is excluded from the release plan.
Versions and completion gates¶
Do not preemptively set every crate to 0.0.5. Tooling-only changes may require no package release. If the sanitizer ships in ext and CLI, those packages and their affected internal requirements advance; core and art need not change solely for that work. Any confirmed core fix requires its own version/dependency assessment. Select the coordinated or per-crate tag only after the changed package set is known.
Each implementation must pass formatting, Clippy, appropriate workspace/feature and MSRV checks, pinned goldens, targeted regressions and strict MkDocs. Require independent sub-agent review before merge. Include actual CLI screenshots in the PR and chat; retain input, terminal output/export and reproduction commands. GIF changes, if needed, require playback or sequential captures. Verify deployed pages and image links after documentation merges.
Before publication, perform clean package dry runs, validate tag ancestry and scope, and use the protected release workflow for exact registry consumers. Preparation and implementation do not themselves authorize uploading a release.
Deferred¶
Theme-stack and Progress/Live API expansion, pre-VT Windows support, proc macros, derive/serde rendering, clap integration, additional terminal graphics protocols, a new syntax engine and bounded-memory CSV processing remain separate projects. The broad tracking issues (#3, #6, #9, #10, #12, #14 and #16) need current-source audits; an open issue alone is not evidence that its entire feature is missing.