Skip to content

0.0.16 cohort: tabular data, schemas and developer views

Published on 2026-10-06. Every workstream in the 0.0.16 plan is merged, the release test below passed on the integrated tree, and every package is on crates.io and PyPI, published from main at c287f1f; see Publication.

0.0.16 makes data, schemas and the developer's own artefacts readable in the terminal:

  • Tabular data, in a new crate, rs-rich-data: one row-source contract with CSV/TSV (the reader rich --csv uses, now shared), JSON Lines, serde and Arrow adapters; type inference with its evidence; column statistics; profiles with distributions and a missing-value map; data-quality reports; SQL result sets; and windows of sources too large to hold.
  • Large tables, in rich_ext::table: a virtualised table that draws one window of millions of rows in constant memory, and conditional style rules.
  • Schemas: a format-neutral schema model read from JSON Schema, SQL DDL and Arrow; trees, diffs with breaking changes marked across formats, and a timeline of versions; ER diagrams through rs-rich-diagram, whose layout now draws DOT cluster frames and honours rank=same.
  • Developer views: merge-conflict views (rich diff --conflicts), a record inspector, and Cargo supply-chain reports from what Cargo and its tools already wrote (rich deps --features/--timings/--audit/--licenses).
  • From the shell and Python: rich profile, rich schema for SQL and Arrow with --er, --infer for file tables, and rs_rich.data.

A default build of rs-rich is unchanged, still 0.0.9, and still renders exactly like upstream rich 15.0.0.

Independent package versions

Package Version Release role
rs-rich-data 0.0.1 (new) Row sources, CSV/TSV, JSON Lines, serde and Arrow (arrow) adapters, inference, statistics, profiles, quality reports, SQL result sets, windows, ER bridge (er)
rs-rich-diagram 0.0.2 Cluster frames, rank=same, rich_diagram::er
rs-rich-mermaid 0.0.5 Manifest only: requires diagram 0.0.2
rs-rich-ext 0.0.14 Schema model, virtualised tables, style rules, record inspector, conflicts, supply-chain reports
rs-rich-micro 0.0.3 Manifest only: requires ext 0.0.14
rs-rich-record 0.0.4 record::write_selected; requires ext 0.0.14
rs-rich-interact 0.0.4 Manifest only: requires ext 0.0.14
rs-rich-cli 0.0.16 rich profile, rich schema SQL/Arrow/--er, --infer, rich deps reports, rich diff --conflicts; new off-by-default arrow feature
rs-rich on PyPI 0.0.5 rs_rich.data and the new views

rs-rich 0.0.9, rs-rich-macros 0.0.3, rs-rich-plugin-api 0.0.3, rs-rich-art 0.0.12 and rs-rich-lumis 0.0.3 do not change.

What changed

The changelog has the full list. By workstream:

Workstream Pull request
Plan #661
1. Tabular foundation: rs-rich-data, the shared CSV reader, JSON Lines, serde and Arrow, inference, statistics, style rules #662
2. Large and SQL-shaped tables (#260, #235) #667
3. Profiling and data quality, rich profile (#343–#346, #269) #667
4. Schemas: the model, SQL DDL, Arrow, diffs, timeline, ER diagrams, DOT cluster frames (#268, #342, #347, #247, #240) #666
5. Records and conflicts (rich diff --conflicts) #663
6. Cargo and the supply chain (#419, #420, #421, #330, #418, #331) #664
7. The CLI, Python and docs #668
rs-rich-record integration feedback (write_selected) #665
Release test this release's release-test pull request

Migration

  • SchemaTree::schema() returns Option<&Value> (None for a tree built from a model). SchemaTree::new and JSON Schema output are unchanged.
  • rich schema sanitizes by default, like rich view and the text rich diff: terminal controls in schema names show as inert text. --no-sanitize lets them through.
  • rich deps --duplicates adds the consolidation summary after its existing output.
  • DOT clusters are framed. A DOT graph with subgraph cluster_* now draws its frames instead of a note; graphs without clusters or rank=same draw exactly as before.
  • New feature flags: rs-rich-data's arrow and er, and rs-rich-cli's arrow (Arrow IPC schemas in rich schema), all off by default.

Release test

Run on the integrated tree (main at 5f1aca5 plus this release test's fixes) on 2026-10-06:

Check Result
scripts/validate_release.py --tag rs-rich-cli-v0.0.16 passed: 3,251 tests in 223 suites, 2 ignored
Golden fixtures regenerated byte-identically against Python rich 15.0.0
scripts/diff_rich.py 57 cases match Python rich 15.0.0
release_cohort.py check and tag --dry-run every manifest matches; would tag exactly the 9 packages above, skipping the 5 already published
Docs tapes (rich record --check) 29 tapes, 85 screenshots unchanged
CLI reference, manifest-version tables, micro gallery, Python API pages all up to date (13 micro assets, 102 API pages)
MSRV Rust 1.90: the workspace, and the CLI with every feature including arrow; Rust 1.91: rs-rich-lumis and the CLI with all features
Python wheel (rs_rich-0.0.5, abi3) in a fresh virtualenv 1,259 passed, 1 skipped (no mmdc); rich-rs --version is 0.0.16
Python sdist (rs_rich-0.0.5.tar.gz) builds and installs from source in a fresh virtualenv; rs_rich.data reads CSV, profiles it and reads SQL DDL; rich-rs profile works
Consumer install (cargo install --path crates/rich-cli --features arrow) rich 0.0.16; rich profile, rich schema --er and Arrow schemas work
Docs sites mkdocs build --strict passes for both sites
Security cargo audit clean for the workspace (401 crates) and rich-py (324 crates)

What the release test found and fixed

Three independent audits covered the whole 0.0.16 delta: rs-rich-data with rich profile and --infer; the schema model, SQL DDL, diffs, timeline, DOT clusters, ER diagrams and rich schema (correctness and security); and the conflict and record views, virtualised tables, style rules, the Cargo supply-chain reports, rs-rich-record's write_selected and rs_rich.data. They found 36 issues, and all are fixed. Each was reproduced first, then fixed with a regression test that failed, hung or panicked before the fix. The main ones:

  • Panics on untrusted input. An Arrow IPC file whose footer lists a dictionary block with a negative length panicked inside arrow-ipc (arrow::read_schema now reads only the footer's schema and checks its length), and CREATE TABLE t (a INT, FOREIGN KEY REFERENCES u) panicked the SQL reader.
  • Time and memory from small inputs. One JSON Lines record of 40,000 keys took 16 s (a 64 MiB line would have taken days); keys first seen after the sample were kept without limit; a 6 MB file of mismatched conflict markers took 144 s; rich deps over 30,000 workspace members took 95 s; the SQL reader held every token at once (a 16 MB file peaked at 2.3 GB) and placed tables and key columns quadratically (100,000 tables took 272 s); and SchemaDiff, SchemaTimeline, nested DOT clusters and ER key resolution had quadratic paths (one ran past 20 minutes). Each is now linear or bounded, with the new limits documented.
  • Terminal escapes. Text from a crafted cargo audit, --timings, licence or metadata file reached the terminal raw through the supply-chain reports (retitling it, clearing it, or forging a link); it is now sanitized when drawn. rich schema ignored --sanitize, and now, like rich view and the text rich diff, sanitizes by default. Review of this release test also made it sanitize the file's name everywhere, keep DDL whitespace intact, and keep JSON property names that collide once sanitized.
  • Wrong results. SQL columns named key, index or period were dropped; PostgreSQL $$ function bodies were read as SQL; DDL without semicolons silently lost every table after the first; SQL Server's PRIMARY KEY CLUSTERED failed the file; rich schema /dev/stdin lost its first six bytes; statistics went to NaN or infinity on huge or infinite floats; streamed CSV and whole-file CSV disagreed on byte-order marks; a CVSS vector repeating a metric was scored; lower-case SPDX copyleft identifiers went unrecognised; and integer style rules compared through f64.
  • Layout. rich profile drew wider than its width between about 40 and 80 columns, and the schema timeline's "N more fields" count never showed.
  • Python. Profile(bins=10**9) hung the interpreter, VirtualTable copied every row on each call, and a JSON Schema SchemaError lacked the line its stub promised.

The micro-doctor docs tape also lost a keystroke once, typing before the shell's prompt returned; it now waits for the prompt.

Known limits

  • Cross-format schema diffs are noisy. Types compare by their source names, so JSON string against SQL TEXT, or int against integer, is a type change, and INT → BIGINT or a new NOT NULL column with a default counts as breaking. Unquoted SQL names are case-sensitive.
  • SQL dialects. The reader covers a CREATE TABLE subset; MySQL backslash escapes in strings are not read, and CHECK constraints, indexes and other statements are skipped with a note.
  • Mermaid subgraphs are still not framed (DOT clusters are). ER edges attach to a table's box, not the column's row.
  • Narrow widths. Below roughly 8 to 36 columns, depending on the data, core Table borders draw wider than the width; zero-width characters in cells can measure one or two cells off. Both are core behaviour.
  • Library renderables pass text through. ConflictView content, VirtualTable cells and the record view's title render input as given, like core rich; the CLI sanitizes at its own boundary.
  • Cargo metadata files have no input-size cap (nesting is capped at 128 levels), and feature requests miss crates whose library name differs from the package name.
  • Python has no Arrow and no conditional table styles yet.
  • Real graphics terminals. As before, the PTY tests check the bytes and cells around each graphics protocol, not the images.

Publication

RELEASES.toml lists every package's version in publication order. Tag what is due on the merged commit on main:

python3 scripts/release_cohort.py status          # what is published, tagged, or due
python3 scripts/release_cohort.py tag --dry-run   # what it would tag
python3 scripts/release_cohort.py tag             # tag and wait, one at a time

tag skips the packages already on crates.io and pushes one annotated tag at a time, waiting for each version to appear on its registry before the next:

  1. rs-rich-diagram-v0.0.2;
  2. rs-rich-mermaid-v0.0.5;
  3. rs-rich-ext-v0.0.14;
  4. rs-rich-micro-v0.0.3;
  5. rs-rich-record-v0.0.4;
  6. rs-rich-interact-v0.0.4;
  7. rs-rich-data-v0.0.1, the new crate, then its Trusted Publishing entry;
  8. rs-rich-cli-v0.0.16;
  9. python-v0.0.5.

crates.io offers Trusted Publishing only on a crate that already exists, so rs-rich-data 0.0.1 uploads with the crates-io environment's CARGO_REGISTRY_TOKEN: the workflow sees that the crate is new and uses it for that upload only; add its Trusted Publishing entry afterwards. See Registry authentication.