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.pyis 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-marketplacecrate that resolves, downloads and locks; therich plugincommands 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 beforecx.modal(..)opens is where the focus returns when the modal closes, not the node focused before it (tasks). - A styled
layersnode covers the gaps its inset children leave (blocks). layout::squarifygives the largest item a tile when the rest's tile is narrower than the minimum (disk).- A
previews_keyscontainer leaves acommand_lineinside it its typed letters (csv). - csv's million-row filter (3.3 s to 15.4 s on
view_of): a bulk read onTableSourcefor passes, and a compiled matcher on&strin rs-rich-ext, so a regex runs on the row's text without building aText. 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
Outputline 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_stepand 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_sizewith 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. Aschema_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 withcommand-fds, so the crate keepsunsafe_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¶
- 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).
- 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.
- Then: workstream 2, the shared gaps, and a re-run of the eleven clones' suites and tapes against all of it.
- Release test: audits, validation, notes, the cohort.
Decisions¶
Answered on 2026-10-19:
- The marketplace starts in 0.0.21 (its foundation; the commands in 0.0.22), alongside parity.
- The DevTools pipe ships on Unix only; Windows keeps the documented port.
Still open:
- 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.
- 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
Outputnames 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 andrich 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'scodefeature (code blocks and Markdown without syntect; Divergences #39) and read-only getters onTable,Panel,RuleandMarkdown. - 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 pluginandrich 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 |