0.0.22 plan: parity, the marketplace, and round 7's last items¶
Status: published on 2026-10-25, every crate from main at
6e8e82e by one release run, with rs-rich 0.0.10 on PyPI
(release notes). The plan (#767), the
first wave (#768: parity, the marketplace crate, the recorder) and the
second wave (#770: rich plugin, workstream 2, Noctiluca, the crate spots)
are merged, and the release PR (#771) prepared the cohort from 9f8ea4b;
console.py's remaining rows and one fuzzer case (#769) stay open, and
rs-rich-doom's core gaps and rich-rst 2.2.0 move to 0.0.23
(see Delivered). Proposed on 2026-10-21, while the 0.0.21 cohort
waited to be tagged from main at 29084d4
(release notes); 0.0.21 was published the same
day. The versions were opened after 0.0.21's publication notes.
It finishes stage 2 of the plan to 1.0.0: 0.0.21 grew into a
widgets, text editing and docs release, so its parity workstreams, the
marketplace crate, the gaps three clones share and the rest of round 7's
list move here (0.0.21's Delivered table). The two
decisions it needed were answered on 2026-10-21. The tracker
is #766.
Goal: make the core's 1.0 promise, "renders what rich renders", true
or written down; ship the marketplace end to end, from listing to
rich plugin install; and close round 7's list.
- Parity: every partial (🟡) row in PORTING 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: the
rs-rich-marketplacecrate,rich pluginandrich plugin browse, publishing, the signing workflow and the compatibility job in CI. - Round 7's last items: the recorder on macOS, APNG made opt-in, and rs-rich-doom on the current crates.
- The gaps three clones share: flush panel titles, a tree table and
App::min_size's own node.
Versions¶
The 0.0.21 versions stay on main until that cohort is tagged: a
release tags the commit it is run from, and release_cohort.py tag reads
the manifests there. The commit that moves every package one patch past
0.0.21 (and adds rs-rich-marketplace at 0.0.1) lands after the tags are
pushed, with 0.0.21's publication date in the changelog and notes. The
workstreams below change no manifest version until then.
Done on 2026-10-25: every package moved one patch past 0.0.21 in the
commit after 0.0.21's publication notes (the commit docs-versions.toml
names for 0.0.21's docs). rs-rich-marketplace is added at 0.0.1 by its own
branch, when it lands.
Workstreams¶
1. Round 7's last items: record, intuituive¶
- The recorder on macOS: CI kept 7 frames over 0.8 s where Linux keeps about 30 a second (known issues). 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 is written only when asked (decision 2): a tape writes an APNG
only when an
Outputline names it or--formatincludesapng. The default outputs go back to what they were before 0.0.20; the docs, the CLI help and the tape reference say so. - rs-rich-doom moves its pin to the current crates and onto pixel
cells, held keys,
fixed_stepand the stats handle, which replace its own frame conversion, key timing and fps counter. The saved review comes with it: check whether 0.0.20's image nodes cover a live in-memory frame source, design the public indices-plus-palette Sixel encoder in rs-rich-art, and measure that the style table settles over a long run. Doom's own repository joins the work only if it is attached; the rich-side findings do not wait for it. Done on 2026-10-25 in Doom's repository: it builds on the 0.0.21 crates, uses those four features and plays sound through intuiTUIve's audio output. Its core gaps list 13 generic pieces, the Sixel encoder among them. The maintainer moved them to 0.0.23, except gap 4 (made-up releases with a first-press hold and a repeat hold), which is small and lands here with workstream 2.
2. The gaps three clones share: intuituive¶
From the gap note's "Round 7" section, only those three or more clones asked for:
- 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.- Made-up releases with a first-press hold and a repeat hold
(
App::synthesize_releases_with(Holds)), gap 4 of rs-rich-doom's core gaps: landed.
Each clone's workaround comes out as its gap closes.
Added on 2026-10-25, from the Noctiluca design: four generic controls the browser's web widgets need, each useful to any app:
- Button and checkbox labels that change in place (
button_of), so a label such as Play/Pause updates without rebuilding the node. - A three-state checkbox (
CheckState { Off, On, Mixed }), with the accessible "mixed" state. - Keyed select and radio options (
SelectOption<K>), each with its own enabled flag and reason, so reordering keeps the selection. - A live action list: help and the palette update while open, a binding can carry a reason it is disabled, and running one re-checks it.
3. Parity: the rendering core: rich¶
segment, text, console, style, color, markup, measure,
ansi, highlighter, errors, containers, terminal_theme,
protocol. 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 keeps
matching upstream byte for byte.
4. Parity: widgets and layout: rich¶
panel, padding, align, constrain, table, layout, screen,
bar, box's substitution, _ratio, columns, rule 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,emoji,filesize,pager,_log_render, export.- 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.
- Sync any upstream release that appeared meanwhile. The
rich-rstpin's move from 1.3.2 to 2.2.0 went to 0.0.23 on 2026-10-25.
7. The marketplace crate: marketplace (new), plugin-api¶
On 0.0.21's listing format, schemas and version checks (design):
rs-rich-marketplace(new crate): reads the index and verifies its minisign signature, the key chain, the serial and the expiry; reads and checks listings against the index; resolves a version against the running host's plugin API and ABI; downloads over HTTPS within the declared size, checks the SHA-256, checks the artifact by kind, then moves it into place and writes the lockfile. No terminal code.- Tests: a fixture marketplace signed with a test key: a good install, a bad hash, a bad signature, a wrong key id, a rolled-back serial, an expired index, a yanked version, an ABI the host cannot load.
8. rich plugin and publishing: cli, marketplace¶
rich plugin:search,info,install,update,remove,list,enable,disableandverify; an installed plugin loads on the next run without--plugin.installshows the permissions and tier and asks before it writes anything;--yesfor scripts.rich plugin browse(#463): the same operations in rs-rich-interact's selector and preview, with provenance for each entry.rich plugin publish: checks a package locally and writes its listing, to be submitted as a pull request to the marketplace repository.- The signing workflow (decision 1), in
rs-rich-marketplace's repository: when a listing pull request merges, CI rebuildsindex.json, bumps the serial and signs it with the main key, held as a secret of a protected environment (marketplace-signing) that needs the maintainer's approval and runs only frommain. - Compatibility tests: every official plugin (Mermaid, DOT, lumis) and a fixture WASM plugin are installed from a test marketplace in CI against the current host, so a host change that breaks installed plugins fails a pull request.
9. Noctiluca, a terminal web browser: noctiluca (new), embed¶
A new crate, noctiluca (no rs-rich prefix), built on intuiTUIve and
rs-rich-embed's Chrome engine: page text stays terminal text, images, GIFs
and video play in media regions, and controls come from the page's
accessibility tree as stock intuiTUIve widgets. The
design note holds the architecture, the phases and
the decisions; the user's own proof of concept supplies its rules and its
fixtures.
- 0.0.1, the spike (done on its branch): a local page read with one
DevTools snapshot and printed as rich
Text; embed'sDevTools::calland a navigation fix. - In this release: the reader phase (0.1 in the note): text, links, forms with web widgets over the controls of workstream 2, images, history, the live F1 action overlay, link hints, and a PTY end-to-end test; embed's switches for audio and downloads (off by default).
- Reserved early:
noctilucajoinsRELEASES.toml, and its 0.0.1 may be published on its own crate tag once it is onmain. - Later releases: forms and tables, layout projection and GIFs, then video, then the automation API.
- Status: the reader phase is done on
022-browser, with sound (asked for in this release:--audio, media controls, verified through an ALSA sink) and the web widgets on workstream 2's controls;noctilucais inRELEASES.tomlwithpublish = falseremoved. The design note's "Where things stand" has the detail.
Order of work¶
- First, in parallel: workstream 1's APNG change and macOS recorder (small, self-contained), workstream 7 (the crate the commands need), and the four parity workstreams (3 to 6), one agent each, each in its own module area so they rarely meet.
- Then: workstream 8 on the crate, workstream 2 (with the four controls Noctiluca needs), workstream 9, and rs-rich-doom.
- Then: the eleven clones' suites and tapes re-run against all of it.
- Release test: audits, validation, notes, the cohort.
Decisions¶
Answered on 2026-10-21:
- Where the marketplace keys live: the main key is a GitHub secret,
with its password, in a protected
marketplace-signingenvironment ofrs-rich-marketplacethat needs the maintainer's approval and runs only frommain, so CI signs each index. The backup key never enters GitHub: it stays offline and signs only key rotations, so a leaked main key can be rotated out. Both pairs are made by the maintainer withminisign -G; only the public halves enter either repository. This replaces the offline main key of 0.0.21's decision 3 (see the design note). - APNG as a default tape output: no. A tape writes an APNG only when
its
Outputor--formatnames it.
Answered on 2026-10-25, for Noctiluca (workstream 9): the engine trait in
noctiluca; C1 to C4 into intuiTUIve core; embed's audio and download
switches, off by default; an opt-in kept profile; the system Chrome
first; a browser in CI with live tests as a normal user; the PoC's code
may be copied where it fits intuiTUIve's architecture; noctiluca
reserved soon. See the design note's decisions.
Answered on 2026-10-25: rich-rst 2.2.0 moves to 0.0.23, and so do
rs-rich-doom's core gaps, except gap 4 (workstream 1).
Still open: none.
Not in this release¶
- API review and stability tooling: stage 3, 0.1.0.
- The DevTools pipe on Windows: after a crate can pass the handles; not before 1.0 unless one appears.
- New demo-loop apps and the gaps fewer than three clones asked for: a round 8 of the loop, if it runs, after parity.
- Python bindings for 0.0.21's new intuiTUIve widgets: with 0.1.0's Python contract, unless one is asked for sooner.
- rs-rich-doom's core gaps (except gap 4) and the
rich-rst2.2.0 pin: 0.0.23.
Package impact¶
Against the 0.0.21 cohort's versions (published 2026-10-21). The versions are open: every package moved one patch past 0.0.21, as below, in a commit after 0.0.21's publication notes (see Versions); the new marketplace crate is added when it lands.
| Package | Proposed | Reason |
|---|---|---|
rs-rich |
0.0.12 | Parity: the partial rows ported, scope.py, divergence fixes |
rs-rich-marketplace |
0.0.1 (new) | Index and listings, verification, resolution, downloads, the lockfile |
noctiluca |
0.0.1 (new) | The terminal browser's reader phase |
rs-rich-plugin-api |
0.0.6 | Requires core 0.0.12 |
rs-rich-ext |
0.0.19 | Requires core 0.0.12 |
rs-rich-art |
0.0.15 | Manifest only (the public indexed Sixel encoder moved to 0.0.23) |
rs-rich-record |
0.0.10 | APNG opt-in; the macOS frame rate |
rs-rich-intuituive |
0.0.7 | Flush titles, the tree table, min_size's node; live labels, the three-state checkbox, keyed options, the live action list |
rs-rich-cli |
0.0.22 | rich plugin; requires the versions above |
| The rest | one patch each | Manifest only: their exact requirements on core and ext move. Opened as macros 0.0.6, diagram 0.0.5, Mermaid 0.0.8, lumis 0.0.6, micro 0.0.8, interact 0.0.10, ratatui 0.0.7, embed 0.0.5, web 0.0.5, data 0.0.6 |
rs-rich (PyPI) |
0.0.10 | Bindings for anything public that moves |
Delivered¶
Tested SHA: 9f8ea4b (main after #770; its tree is #770's head,
531b9ba, where CI passed), with the release PR's prep
commits on top (9f8ea4b..022-release: docs and the changelog only, no
code or manifest). See the release notes.
| Workstream | PR | Merged as |
|---|---|---|
| Tracker | #766 | |
| Plan, versions opened, 0.0.21's publication notes | #767: the plan and its decisions, Noctiluca's workstream, every package one patch past 0.0.21 | 0eaae1b |
| 1. Round 7's last items | #768: APNG only when asked; a late read split into its updates. Not done: macOS still keeps fewer frames (known issue). rs-rich-doom on the 0.0.21 crates, in its own repository; its core gaps but gap 4 move to 0.0.23 | a010f93 |
| 2. The gaps three clones share, and C1 to C4 | #770: flush and plain-text titles, tree_table, min_size_with and min_size_forms, focus_scope_reveal, synthesize_releases_with (Doom's gap 4); live labels, CheckState, keyed options, the live action list |
9f8ea4b |
| 3. Parity: the rendering core | #768: twelve rows complete, parity_core.tsv, §41 to §45. console.py stays partial (PORTING lists what it lacks) |
a010f93 |
| 4. Parity: widgets and layout | #768: ten rows complete, parity_widgets.tsv, §7, §12 and §29 resolved |
a010f93 |
| 5. Parity: live display | #768: the alternate screen, FileProxy, Status and Progress, parity_live.tsv, §16 and §17 settled |
a010f93 |
6. Parity: documents, scope.py, verdicts |
#768: scope.py and pretty.py's layout, parity_docs.tsv, a verdict for every divergence, the fuzzer on the document renderers. One case is a known divergence, #769. rich-rst 2.2.0 moves to 0.0.23 |
a010f93 |
| 7. The marketplace crate | #768: rs-rich-marketplace 0.0.1, tested on a fixture marketplace. The official keys are not compiled in yet |
a010f93 |
8. rich plugin and publishing |
#770: the nine commands, browse, publish, wasm-plugins on by default, the signing workflow in docs/marketplace-repo/, the compatibility job |
9f8ea4b |
| 9. Noctiluca | #770: noctiluca 0.0.1, the reader phase with sound, its docs page and iconography; embed's DevTools calls and switches; CI's live browser job |
9f8ea4b |
| Added: Memo's crate spots | #770: the cartoon look and a spot per crate. Revisiting the art moves to 0.0.23 | 9f8ea4b |
| The clones re-run | The clones are intuiTUIve's examples: their suites run in cargo test --all and their tapes in the tape check, both in the release test |
|
| Release test | The release PR: validation on 9f8ea4b, notes, the changelog heading; then Noctiluca's guide and three fixes (the profile left behind, the stale projection, none in [keys]), re-checked for the crates they touch |
Tested at 9f8ea4b, and the fixes at 66689219; CI runs the whole PR; merged as 6e8e82e (#771), where the cohort was tagged |