Skip to content

0.0.21 plan: parity, the marketplace's foundation, and round 7's leftovers

Status: published on 2026-10-21, every crate from main at 29084d4 by one release run, with rs-rich 0.0.9 on PyPI (release notes). The first and second waves are merged (#763, #764) and the release PR (#765) prepared the cohort from c25f65e; parity (workstreams 3 to 6), the marketplace crate, workstream 2 and the rest of workstream 1 move to 0.0.22 (see Delivered). Proposed on 2026-10-19, while 0.0.20 (the intuiTUIve demo loop, rounds 2 to 7: #757) was in review; 0.0.20 was published the same day (release notes). It is stage 2 of the plan to 1.0.0, which put parity and the marketplace at 0.0.20 to 0.0.22; 0.0.20 became the demo loop's release, so both start here. The two decisions asked for were answered on 2026-10-19: the marketplace starts in this release, and the DevTools pipe ships on Unix only. The tracker is #758.

Goal: make the core's 1.0 promise, "renders what rich renders", true or written down; lay the marketplace's foundation; and finish what the demo loop's seventh round found.

  • Parity: every partial row in PORTING (41 today) is ported or recorded as a divergence, scope.py is ported, every open divergence gets a verdict, and the differential fuzzer covers the document renderers.
  • The marketplace's foundation: the listing format, its signature and hash checks, and a rs-rich-marketplace crate that resolves, downloads and locks; the rich plugin commands follow in 0.0.22.
  • The DevTools pipe on Linux and macOS; Windows keeps the port, still a documented limit.
  • Round 7's leftovers: four intuiTUIve bugs with failing tests already written, csv's filter regression, the recorder's frame rate on macOS, and rs-rich-doom on the 0.0.20 crates.

Workstreams

1. Round 7's bugs and regressions: intuituive, record

Each bug has a minimal failing test in its clone's report (docs/design/gaps/); the test goes in first, then the fix, then the clone's workaround comes out.

  • The focus after a modal: a cx.focus(x) made just before cx.modal(..) opens is where the focus returns when the modal closes, not the node focused before it (tasks).
  • A styled layers node covers the gaps its inset children leave (blocks).
  • layout::squarify gives the largest item a tile when the rest's tile is narrower than the minimum (disk).
  • A previews_keys container leaves a command_line inside it its typed letters (csv).
  • csv's million-row filter (3.3 s to 15.4 s on view_of): a bulk read on TableSource for passes, and a compiled matcher on &str in rs-rich-ext, so a regex runs on the row's text without building a Text. The test is a measurement with a bound, in the ignored-by-default benchmark set.
  • The recorder on macOS: CI kept 7 frames over 0.8 s where Linux keeps about 30 a second. Find whether the PTY's reads or the settling rule merge them, fix it, and give the frame-rate test its lower bound on every platform again.
  • APNG as a default output: a tape with no Output line now writes an APNG beside the GIF. Decide whether it stays a default (see decisions); the re-recorded tapes follow.
  • rs-rich-doom moves its pin to the merged 0.0.20 commit and onto pixel cells, held keys, fixed_step and the stats handle, which replace its own frame conversion, key timing and fps counter.

2. The gaps three clones share: intuituive

From the gap note's "Round 7" section, only those three or more clones asked for (the rest wait for a round 8 of the loop, if it runs):

  • Panel titles flush with the corner, ratatui's look, and plain-text titles (git, music, http).
  • A tree table, a table whose rows nest (top, tasks; bottom's and Taskwarrior's views).
  • App::min_size with a node of its own and shorter forms of the message (blocks, disk), with focus-scope cycling past hidden panes (http, top) folded in.

3. Parity: the rendering core: rich

segment, text, console, style, color, markup, measure, ansi, highlighter. For each partial row: a short list of what is missing (in PORTING itself), golden cases captured from rich 15.0.0 for each, then the port or a divergence entry. The rich crate's default build must keep matching upstream byte for byte.

4. Parity: widgets and layout: rich

panel, padding, align, table, layout, bar, screen, columns, rule, box, constrain, containers and the rest of PORTING's widget rows; the same method as workstream 3.

5. Parity: live display: rich

live, progress, status, spinner, live_render, file_proxy, including the alternate screen and the stdout/stderr redirect deferred in DIVERGENCES §17.

6. Parity: documents, scope.py, and the verdicts: rich, scripts

  • markdown, syntax, json, pretty, traceback, prompt.
  • Port scope.py (render_scope), the one module not started that 1.0 needs.
  • Every open divergence gets a verdict: fixed, or permanent with its reason, in DIVERGENCES.
  • The differential fuzzer grows to Markdown, Tree, Columns, Progress frames, Pretty and JSON, so parity is measured rather than sampled.

7. The marketplace's foundation: marketplace (new), plugin-api

Stage 2, track B of the plan to 1.0.0, first half.

  • The listing format: one file per package in buchochelliq-labs/rs-rich-marketplace: id, kind (Cargo crate, WASM plugin, micro pack, theme), versions, SHA-256 of each artifact, source repository, capabilities, declared permissions, and the plugin API and ABI versions it needs. A schema_version, a JSON Schema in the repository, and validation in its CI.
  • Trust: listings are signed with minisign and every download is checked against its hash; tiers official, reviewed and community; yanking. Only WASM plugins and asset packs install from the marketplace.
  • rs-rich-marketplace (new crate): reads and verifies the listings, resolves a version against the running host's plugin API and ABI (which rs-rich-plugin-api exposes as constants), downloads and checks artifacts, and keeps a lockfile. No terminal code.
  • Tests: a fixture marketplace (signed with a test key) in the crate's tests: a good install, a bad hash, a bad signature, a yanked version, an ABI the host cannot load.
  • Next release: rich plugin (search, info, install, update, remove, list, enable, disable, verify), rich plugin browse, publishing, and the compatibility job in CI.

8. DevTools over a pipe, on Unix: embed

0.0.19's workstream 5, on Linux and macOS only (decided 2026-10-19).

  • Chrome starts with --remote-debugging-pipe; CDP runs over descriptors 3 and 4 (NUL-separated JSON), passed with command-fds, so the crate keeps unsafe_code = "deny". No port is opened.
  • Windows keeps the port, still a known limit, until a maintained crate can pass two inheritable handles in one switch; the guide says which platforms get the pipe.
  • Tests: no listening socket while a view is open, on Linux and macOS; the CDP tests pass over the pipe there and over the port on Windows.

Order of work

  1. First, in parallel: workstream 1 (round 7's bugs, so every later clone run starts green), workstream 8 (small and self-contained) and workstream 7's listing format and schema (the crate builds on them).
  2. The bulk, in parallel: the four parity workstreams (3 to 6), one agent each, each in its own crate area so they rarely meet; then the marketplace crate.
  3. Then: workstream 2, the shared gaps, and a re-run of the eleven clones' suites and tapes against all of it.
  4. Release test: audits, validation, notes, the cohort.

Decisions

Answered on 2026-10-19:

  1. The marketplace starts in 0.0.21 (its foundation; the commands in 0.0.22), alongside parity.
  2. The DevTools pipe ships on Unix only; Windows keeps the documented port.

Still open:

  1. The minisign keys: a main and a backup pair, made offline by the maintainer; only the public halves enter the marketplace repository. Workstream 7's crate is tested with a test key and does not wait for them; the first real listing does. Answered 2026-10-21 in the 0.0.22 plan: the main key is a protected-environment secret, the backup key stays offline.
  2. APNG as a default tape output: keep it (every re-recorded tape gains an APNG, a few hundred kilobytes to a few megabytes each), or write it only when a tape's Output names it. The recommendation is the latter. Answered 2026-10-21: written only when asked (0.0.22 plan).

Added during the release

Work that came in after the workstreams above were set, from the demo clones' widget comparison, a consumer's review and the docs:

  • Widgets (#763): form controls, the log pane and tracing, pies, stacked charts, QR codes and gradient text, Huh-style forms and rich spin, effect presets, intuiTUIve's icons and mascots; then text editing (kill ring, search, wrap, Emacs and Vim presets) and the #[must_use] pass over every crate but the mirror.
  • For ODS (a consumer's review): rs-rich-ext's Markdown export for GitHub comments, plain-text table cells, and a SQL highlighter with no syntect; core's code feature (code blocks and Markdown without syntect; Divergences #39) and read-only getters on Table, Panel, Rule and Markdown.
  • Mermaid: sequence and ER diagrams drawn as text; line-end labels in rs-rich-diagram.
  • Docs: the playground (tiers 1 to 3: renderers, the CLI on WASI, apps), rs-rich's own identity and intuiTUIve as a sub-site.

Not in this release

  • rich plugin and rich plugin browse, publishing, and the marketplace's CI compatibility job: 0.0.22.
  • The DevTools pipe on Windows: after a crate can pass the handles; not before 1.0 unless one appears.
  • New demo-loop apps: the eleven clones stay as the framework's regression suite; a new round of apps waits until parity is done.
  • The gaps fewer than three clones asked for (round 7's list): a round 8 of the loop, if it runs.
  • API review and stability tooling: stage 3, 0.1.0.

Package impact

Against the 0.0.20 cohort's versions (published 2026-10-19). The versions are open: every package moved one patch past 0.0.20, as below, in a commit after 0.0.20's release notes (a release's versioned docs are cut where its versions move on); the new marketplace crate is added when it lands.

Package Proposed Reason
rs-rich 0.0.11 Parity: the partial rows ported, scope.py, divergence fixes
rs-rich-plugin-api 0.0.5 The plugin API and ABI versions as constants, for the marketplace; requires core 0.0.11
rs-rich-marketplace 0.0.1 (new) Listings, verification, resolution, downloads, the lockfile
rs-rich-ext 0.0.18 The compiled &str matcher; requires core 0.0.11
rs-rich-interact 0.0.9 Requires ext 0.0.18
rs-rich-intuituive 0.0.6 Round 7's bug fixes, TableSource bulk reads, the shared gaps
rs-rich-record 0.0.9 The macOS frame rate; the APNG default
rs-rich-embed 0.0.4 The DevTools pipe on Linux and macOS
rs-rich-cli 0.0.21 Requires the versions above
The rest one patch each Manifest only: their exact requirements on core and ext move. Opened as macros 0.0.5, art 0.0.14, diagram 0.0.4, Mermaid 0.0.7, lumis 0.0.5, micro 0.0.7, ratatui 0.0.6, web 0.0.4, data 0.0.5
rs-rich (PyPI) 0.0.9 Bindings for anything public that moves

Delivered

Tested SHA: c25f65e (main after #764; its tree is #764's head, 22718fd, where CI passed), with the release PR's prep commits on top (c25f65e..021-release: docs and the changelog only, no code or manifest). See the release notes.

Workstream PR Merged as
Tracker #758
Versions opened, 0.0.20's notes, docs per release #762: every package one patch past 0.0.20; docs-versions.toml pins a release's docs to a commit; a held key's repeats stop at its release (rs-rich-record) e14ac44
1. Round 7's bugs #763: the four bugs with their tests, the clones' workarounds out; csv's filter (TableSource::rows, transform::Pattern). Not done: the recorder on macOS, the APNG decision, rs-rich-doom 1683100
2. The gaps three clones share — Moved to 0.0.22
3 to 6. Parity — Moved to 0.0.22; core gained only the code feature and read-only getters (#764)
7. The marketplace's foundation #763: the listing format, schemas, validator and design note; the plugin API's version checks. The rs-rich-marketplace crate moves to 0.0.22 1683100
8. DevTools over a pipe on Unix #763 1683100
Added: widgets, first wave #763: form controls, the log pane and tracing, pies, stacked charts, QR codes and gradient text, Huh-style forms and rich spin, effect presets, icons and mascots, the no_std note 1683100
Added: second wave #764: text editing (kill ring, search, wrap, Emacs and Vim presets), the docs playground (tiers 1 to 3), #[must_use], the ODS items (Markdown export, plain-text cells, sql, core's code feature and getters), Mermaid sequence and ER diagrams, line-end labels, rs-rich's identity, the Python bindings c25f65e
Release test The release PR: validation on c25f65e, notes, the changelog heading Tested at c25f65e; the prep commits on it (524ec9e and the next) change only docs; merged as 29084d4 (#765), where the cohort was tagged