Plan to 1.0.0¶
Status: proposed on 2026-10-11, after the 0.0.18 cohort and rs-rich
0.0.6 on PyPI were published. The maintainer decided all eight
decisions on 2026-10-11, including the
package split below and a plugin marketplace as part of 1.0. Tracked in
#730. On
2026-10-27, with 0.0.23 in release, the maintainer widened the stable set
to sixteen packages, put three apps and Textual parity before 1.0, and
added a last stage, maintenance mode (decisions 9 to 14).
Goal: 1.0.0 is a promise, not a feature set. It tells someone choosing
this project that the crates they depend on will not break under them, that
the core renders what Python rich renders, and that there is a written
policy for what can and cannot change. Features keep landing after 1.0; what
changes is that breaking them costs a major version.
Where we are¶
Measured on 2026-11-02, on the 0.0.24 wave-2 integration branch (stage 0's
snapshot, taken on main at 3cd1bce on 2026-10-11, is in this file's
history):
- Releases. 0.0.23 was published on 2026-10-27: 19 crates on
crates.io and
rs-rich0.0.11 on PyPI (release notes). 0.0.24, the first release of the two tracks, runs in four waves (its plan): - wave 0, merged: the plan, then edition 2024 for every crate (#829);
- wave 1, merged
(#830):
Cornacai's foundations (rs-rich-acp, the new ACP client, and the
intuiTUIve items #797, #798, #800 and #804),
inspectfor Rust values (#796), Noctiluca's fixes, mouse, video and start page with the animated banner, the signer's GitHub App, the threat model withSECURITY.md, and the docs on Zensical; - wave 2, in flight: on its integration branch so far, a hardening round (six of the threat model's gaps mitigated), Noctiluca's #817, #819 and #820, and intuiTUIve's #799, #801, #802 and #806; the rest of Textual parity's independent gaps, the call for a community plugin and this bookkeeping are on their way;
- wave 3, next: Cornacai itself (#794's phases 3 and 4), then the release.
- 20 packages, all at 0.0.x: 19 crates published and the Python
package, with rs-rich-acp (0.0.1) new in 0.0.24 and Cornacai not yet a
crate. About 670,000 lines of Rust under
crates/, tests included. - Core parity:
rs-richmirrorsrich15.0.0, and the CLIrich-cli1.8.1 (withrich-rst2.2.0), all three still upstream's latest releases on PyPI. Since 0.0.23 every library row of PORTING is complete (49) or a recorded divergence (5). Of the CLI's twelve rows that were partial, eleven are complete; the twelfth accepts every rich-cli 1.8.1 option but gives three of them a different meaning that DIVERGENCES does not yet record. The stable crates outside core have status tables there too. - Divergences: DIVERGENCES has 51 entries, 14 of them resolved, so 37 open; the gaps that read like bugs listed at stage 0 (§7, §12, §28, §29, §32, §33) are among them.
- Stability tooling that exists now: besides the goldens, the fuzzer,
the release tests and the tapes, every published crate's public API is
snapshotted in
api/and checked withcargo-semver-checksagainst its last release, with each 0.0.x break listed inapi/semver-breaks.toml(CI's "public API and SemVer" job). Edition 2024 everywhere; the MSRV is 1.90 (1.91 for rs-rich-lumis). - Still missing: a
missing_docslint, and the API review itself (stage 3). Core, ext and the plugin API carry 41#[non_exhaustive]markers. - Security: a written threat model and a
root
SECURITY.md(wave 1), the starting point of stage 4's review. - The marketplace has been live since 2026-10-26, signed, listing only
official packages. The community-plugin call
(decision 12) has its guide page,
Write a plugin, and a template,
templates/wasm-plugin/; the issue and the template repository are the maintainer's. - Public dependencies: as at stage 0 (not measured again): core's
default features expose
syntectandpulldown-cmark,rs-rich-artre-exportsimage,rs-rich-ratatuire-exportsratatui_core, andrs-rich-interactbuilds oncrosstermandtermwiz. - Issues: 209 open, among them the apps track (#784 to #821, #794, #796) and the 1.0 tracker, #730.
- Python: abi3 wheels for CPython 3.9 and later; 3.9 reached end of life in October 2025.
What 1.0.0 covers¶
Decided (2026-10-11): a stable set of packages goes to 1.0.0 together; every other package moves to 0.1.0 and graduates on its own evidence later. Widened (2026-10-27) from seven packages to sixteen: intuiTUIve and what it is built on, the recorder, the web view, Noctiluca and two new crates, rs-rich-acp and Cornacai, all go to 1.0.0 (decision 9).
| Package | At 1.0 | Why |
|---|---|---|
rs-rich |
1.0.0 | The faithful core; the reason the project exists |
rs-rich-plugin-api |
1.0.0 | Third-party plugins need a contract that holds; its native/WASM ABI already has ABI_MAJOR |
rs-rich-macros |
1.0.0 | Small, and rs-rich-ext exposes it |
rs-rich-ext |
1.0.0 | Most users' second dependency; depends only on the three above |
rs-rich-cli |
1.0.0 | Its contract is the command line: flags, exit codes and the JSON report envelope, not a Rust API, and rich plugin. Commands newer than one release are listed as experimental and outside the promise |
rs-rich (PyPI) |
1.0.0 | The Python surface of the stable set; rs_rich.tui and other wrappers of 0.x crates stay provisional |
rs-rich-marketplace (new) |
1.0.0 | The marketplace client: the listing format, verification and the install lockfile, which rich plugin and third-party tools share |
rs-rich-art, rs-rich-micro, rs-rich-record |
1.0.0 | Pictures, micro assets and recordings: what intuiTUIve, Noctiluca and the CLI's stable commands are built on (2026-10-27) |
rs-rich-interact, rs-rich-intuituive |
1.0.0 | The interactive components and the TUI framework, with Textual's widgets at parity before 1.0 (2026-10-27) |
rs-rich-embed, noctiluca |
1.0.0 | The terminal pane and web view, and the terminal web browser built on them, with its improvements (#784 to #792, #816 to #821) before 1.0 (2026-10-27) |
rs-rich-acp (new), cornacai (new) |
1.0.0 | The Agent Client Protocol for intuiTUIve apps, and Cornacai, a Toad-inspired agent app built on it (#794) (2026-10-27) |
rs-rich-diagram, -mermaid, -lumis, -data, -ratatui, -web |
0.1.0 | Not reviewed for 1.0; CLI commands built on them are experimental, outside the CLI's promise |
The libraries in the stable set depend on no 0.x crate of ours, so their
promise does not depend on theirs (intuiTUIve's use of rs-rich-ratatui is a
test-only dev-dependency). The CLI and the Python package are different: the CLI
depends on rs-rich-data and rs-rich-diagram unconditionally and enables
more 0.x crates by default, and the Python package bundles nearly all of
them. Their promise is therefore drawn around what they expose, not around
what they link:
- Every CLI command and every Python module is classed in stage 3 as
stable or experimental, by the crate behind it. A stable one is
covered whatever crate implements it; an experimental one is marked in
--helpand the Python docs and is outside the promise. - A 0.x crate's breaking release that reaches a stable command or module is absorbed inside the CLI or binding without changing what users see; if it cannot be, the change waits for the next CLI or Python major.
- The CLI and the Python package pin each 0.x dependency to one minor
(
0.1), so Cargo never pulls a breaking release into a 1.0 build.
Moving the rest from 0.0.x to 0.1.0 matters on its own: from 0.1.0, Cargo treats 0.1.1 as compatible with 0.1.0, so those crates can ship fixes without forcing every dependent to bump.
The path¶
Six stages, each a release or a short run of releases; stage 2 runs two
tracks side by side. The issue backlog
(about 180 feature issues across data, observability, reports, art, diagrams
and interactive components) is not a 1.0 prerequisite: it continues in
the 0.x crates and in rs-rich-ext minor releases throughout, except during
the release-candidate freeze.
Stage 0 — housekeeping (done 2026-10-11)¶
- Close every open issue a release already delivered, after checking it against the CHANGELOG; move any undelivered remainder into a new issue.
- Rename milestones by theme instead of by version ("Observability & operations", "Reports & publishing", …), since releases did not follow them. Create "0.1.0 – API review" and "Plugin marketplace" (#232, #463, #582), and keep "1.0.0" for the stability work; move #380 and #670 to a "Post-1.0" milestone (see decisions).
- Update ROADMAP (0.0.17 and 0.0.18 published; this plan as the way forward) and the roadmap epic #16.
- Open a tracker issue for this plan.
Done on 2026-10-11: 75 of the 213 open issues closed (35 delivered, 30 partly delivered with the rest filed as 30 new issues, 9 duplicates, and
12), every open issue in a theme milestone, the milestones above created,¶
16 updated, and the tracker opened as¶
#730.
Stage 1 — 0.0.19, the scope already decided¶
Planned in detail in the 0.0.19 plan, with a docs workstream added on 2026-10-12.
As recorded in the 0.0.18 plan on
2026-10-08: flex alignment in layout and the stylesheet, a text-area widget,
one process per browser session in rs-rich-web, and a Surface drawing
handle in rs-rich-ext. Add the one 0.0.18 known limit with a security
edge: the Chrome web view's DevTools port, moved to a pipe. That one moved
on to 0.0.20 on 2026-10-13, as decided, because Windows cannot pass Chrome
the pipe's handles without unsafe (see the
0.0.19 plan).
Stage 2 — parity complete, and the marketplace (0.0.20 to 0.0.22)¶
Both tracks are planned in 0.0.22: 0.0.20 became the demo loop's release and 0.0.21 a widgets and docs release, which laid the marketplace's listing format.
Track A: parity¶
The core's promise at 1.0 is "renders what rich renders". Make it true,
or write down exactly where it is not.
- Every partial row in PORTING gets a short list of what is missing,
then is ported or recorded as a divergence. 41 rows, grouped into four
workstreams: rendering core (
segment,text,console,style,color,markup,measure,ansi,highlighter), widgets and layout (panel,padding,align,table,layout,bar,screen, …), live display (live,progress,status,spinner, including §17's deferred alternate screen and redirect), and documents (markdown,syntax,json,pretty,traceback,prompt). - Port
scope.py(render_scope), the one small module not started. - Each open divergence gets a verdict: fixed, or permanent with its reason. The bug-like ones listed above are fixed unless a fix is impossible.
- Widen the differential fuzzer to Markdown, Tree, Columns, Progress frames, Pretty and JSON, so parity is measured rather than sampled.
- Sync any upstream release that appeared meanwhile, and the
rich-rstpin to 2.x. - Windows legacy console (#12): settle per the decision below.
Track B: the plugin marketplace (#232, #463)¶
Plugins already work three ways (PLUGINS.md): as a Cargo dependency, as a
native library loaded from a path, and as a WASM module loaded from a path,
behind off-by-default features, with --plugin and a user-only plugins
list. What is missing is a way to find, trust, install and update one.
Micro asset packs (#582) have the same gap, so they share the design.
- The listings: a Git repository,
buchochelliq-labs/rs-rich-marketplace(named on 2026-10-11), with one file per package: 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. The format has aschema_versionand is part of the 1.0 promise. Crates stay on crates.io and WASM modules on GitHub releases; the marketplace stores where they are and what they hash to, not the files. - Trust: the listings are signed (minisign key held by the maintainer), every download is checked against its hash, and entries carry a tier: official (this repository's plugins), reviewed and community. A package can be yanked. Only WASM plugins and asset packs are installable from the marketplace; a native library still has to be named by path, because it runs with the user's full rights.
rs-rich-marketplace(new crate): reads and verifies the listings, resolves a version against the running host's plugin API and ABI, downloads and checks artifacts, and keeps a lockfile of what is installed. No terminal code: the CLI and other tools build on it.rich plugin:search,info,install,update,remove,list,enable,disableandverify; an installed plugin is loaded 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 an interactive browser built onrs-rich-interact's selector and preview, with provenance shown for each entry.- Publishing:
rich plugin publishchecks a package locally and writes the listing; it is submitted as a pull request to the marketplace repository, whose CI builds or downloads the artifact, checks the hash and the ABI, and runs the plugin against the current host. - Compatibility tests: every official plugin (Mermaid, DOT, lumis) and a fixture WASM plugin are installed from a test marketplace in CI against each host version, so a host change that breaks installed plugins fails a PR.
- Maintainer actions: the
rs-rich-marketplacerepository exists (2026-10-11). The signing keys are a main and a backup minisign pair made by the maintainer: the main key a secret of a protected environment in the marketplace repository, so CI signs each index, and the backup kept offline for rotations (decided 2026-10-21, 0.0.22 plan); only their public halves enter the repositories. - The signer pushes with a GitHub App before 1.0 (decided 2026-10-26;
done in 0.0.24, the 0.0.24 plan, item 8).
For 0.0.23 the signing workflow pushed the signed index to the
marketplace's
mainwith a deploy key, which the maintainer had set up. A deploy key never expires and can write to the whole repository; an App's installation token is short-lived and scoped to what the App is granted. The move is part of 1.0.0, and the marketplace's security review (Stage 4) covers it.
Before 0.1.0 — the apps and the wider stable set (0.0.24 to 0.0.28)¶
Decided on 2026-10-27, after the stable set grew. About five releases in two tracks, side by side, then stage 3 reviews all sixteen packages. Shortened on 2026-11-03 (decision 15): 0.0.24 carried almost all of both tracks, so 0.0.25 finishes them and the release after it is 0.1.0.
- Track 1, the apps: Cornacai (#794)
and rs-rich-acp; Textual parity for intuiTUIve, from
the audit (#797 to #815), with
rich inspect(#796); Noctiluca's improvements (#784 to #792, #816 to #821). They land as features of 0.0.x crates and are reviewed in stage 3 with the rest. - Track 2, the stable set's preparation: the rows of PORTING still partial for the new stable crates, edition 2024, the signer's move to a GitHub App, the written threat model (stage 4's review starts from it), and the call for a community plugin (decision 12).
Stage 3 — API review and stability tooling (0.1.0)¶
This is the release that makes 1.0 possible. Every package moves to 0.1.0; the stable set's public API is reviewed item by item.
- Snapshots of the public API per crate (
cargo public-api), checked into the repository and diffed in CI, so every API change is visible in review. cargo-semver-checksin CI against each crate's last published version, and inscripts/release.py plan, which refuses a version bump smaller than the change.- Brought forward to 0.0.23, and done there (the maintainer's call on
2026-10-26): the snapshots,
cargo-semver-checksin CI and in the plan, and the Python stubs below. See the 0.0.23 plan. - Snapshots:
api/<crate>.txt,scripts/public_api.py, CI'spublic API and SemVerjob. - SemVer: for 0.0.x, where Cargo counts every bump as breaking, CI
checks each crate as if its bump were a minor one and holds every
breaking change to
api/semver-breaks.toml. - What stays for this stage: the review itself, and the move to CPython 3.10 with the provisional modules marked.
- The review itself, against the Rust API guidelines:
#[non_exhaustive]on every public enum and option struct that may grow, constructors or builders instead of public fields where a field may be added, sealed traits where only we implement them, error types that implementstd::error::Errorand can grow,Send/Syncstated and tested, names consistent across crates. - Public dependencies: for each stable crate, list every foreign type in
its API. Hide it behind our own type, or keep it only behind a feature
documented as "follows
<dependency>'s major version".syntectandpulldown-cmarkin core are the main cases. - Features: audit names and defaults; after 1.0, removing a feature or changing a default is breaking.
- Documentation:
missing_docsset to deny on the stable set, an example on each main type,doc_cfgbadges for feature-gated items on docs.rs. - The CLI and Python contracts: freeze and document the exit-code
classes and give the JSON report envelope a schema version; class every
CLI command and Python module as stable or experimental by the crate
behind it (see What 1.0.0 covers) and mark the
experimental ones in
--helpand the Python docs. - Toolchain: move to edition 2024 before the freeze (it can change behavior, so it belongs before the review, not after), and write down the MSRV policy (proposed: the latest stable minus six releases; raising it is a minor release).
- Python: complete
.pyistubs (done in 0.0.23, checked against the wheel bystubtestin CI), raise the minimum to CPython 3.10, and mark the provisional modules. - Core's own types, made cheap: brought forward to 0.0.23 by the maintainer on 2026-10-25 ("make the strings lighter"), and done there.
- What changed:
Segment.textandColor.namearerich::CompactStrings, with output byte-identical. See the 0.0.23 plan. - What the review does: check the result as part of the public API.
Stage 4 — hardening (0.1.x)¶
- Fuzzing:
cargo-fuzztargets, run in nightly CI, for every parser that takes outside input: markup, the ANSI decoder, Markdown, DOT, Mermaid, CSV/JSONL, stylesheets, the VT emulator, WebSocket frames and the plugin ABI's inputs. - Brought forward to 0.0.23 by the maintainer on 2026-10-26: the
targets exist (
fuzz/, 19 of them, including the tape parser and the marketplace's documents and signatures) and run nightly (fuzz.yml). The exit criterion's four-week clock starts with the first nightly run onmain; the fuzzing design records its date and any open finding. See the 0.0.23 plan. - A threat model for the parts that run other code or serve a network:
dylib and WASM plugins, the marketplace's listings, signatures and
downloads,
rich serve, the embedded web view. - A structured security review against that threat model before the
release candidate (decided 2026-10-27, decision 13):
the marketplace and its signing (key handling, the GitHub App), the WASM
sandbox,
rich serveand rs-rich-web, Noctiluca and Chrome, the embed PTY, TLS and redirects, and Cornacai's ACP agents. Each threat is checked against the code and its tests, and each finding fixed or recorded. No paid audit. - Benchmarks with thresholds enforced in CI (the open half of the ROADMAP item), so a slowdown fails a PR the way a parity break does.
- The real-terminal and screen-reader passes become a recorded checklist run on every stable-set release, not only when protocols change.
- Dogfood outside this repository: #564 proposes rs-rich as the shared CLI layer for other BuchochelliQ Labs tools. Building one of them on the 0.1 API is the best test that the API is usable by someone who did not write it.
Stage 5 — release candidates (1.0.0-rc.N)¶
- Tag
1.0.0-rc.1for the stable set. The release tooling already handles prereleases. - Freeze: no feature merges into the stable set until 1.0.0; fixes only, each with a regression test. The 0.x crates keep moving.
- At least two weeks between the last rc and 1.0.0, with the dogfood project on the rc.
- The full release test: three independent audits,
validate_release.py, parity, tapes, the real-terminal and screen-reader checklist. - Publish the stability policy and a 0.0.x → 1.0 migration guide.
Stage 6 — 1.0.0¶
Publish the stable set and the Python package, then retarget the issue backlog at post-1.0 minor releases.
Stage 7 — maintenance mode¶
Decided on 2026-10-27: after 1.0.0 the project goes into maintenance mode for a while. Before 1.0.0 ships:
- The marketplace keeps working unattended. The signed index expires; decide how its expiry and re-signing work when no maintainer approves each signing run, and write it down.
- Dependencies: Dependabot's cadence for maintenance (security updates at once, the grouped weekly pull requests less often), and who merges them.
- A handoff note for whoever picks the work up: what is in flight, how a release is cut, where the keys and secrets are.
- A notice in the README and CONTRIBUTING: maintained, not developed; what kind of pull request is accepted and how fast to expect a reply.
Exit criteria for 1.0.0¶
For each package in the stable set:
- [ ] Every PORTING row (core) is complete or has a DIVERGENCES entry marked permanent; no open divergence reads as a bug.
- [ ] The public API snapshot has been reviewed and is unchanged across the last release candidate.
- [ ]
cargo-semver-checksand the API snapshot diff run in CI and the release tooling. - [ ] Every public item is documented;
missing_docsis denied. - [ ] No foreign type in the public API outside a documented feature.
- [ ] Fuzz targets for its parsers have run in nightly CI for at least four weeks without an open finding.
- [ ] The stability policy, MSRV policy and migration guide are published.
- [ ] One project outside this repository builds on it (the maintainer's own tool, decision 16).
For the marketplace:
- [x] The marketplace is live, signed, and lists every official plugin and the built-in micro packs. Live since 2026-10-26, when its first index (serial 1) was signed (0.0.23, item 17).
- [ ] (Moved to 1.x by decision 16; not a 1.0.0 blocker.) A third-party
WASM plugin has gone through
rich plugin publish, the marketplace's CI andrich plugin installend to end. The officialtextcasehas gone throughpublishandinstall(0.0.23), and the marketplace's pull request check installs every new WASM version; a third party's is still to come. The maintainer knows no one to ask, so the project puts out a call (decision 12). - [x] The compatibility tests run in CI for every official plugin (0.0.23:
the crates,
textcaseand the micro packs, from a fixture marketplace that lists them as the real one does).
Decisions for the maintainer¶
Each is marked decided, with the date, or open with a recommendation.
- Which packages go to 1.0? Decided (2026-10-11): the stable set above, with everything else at 0.1.0.
- Is a change in rendered output a breaking change? Decided
(2026-10-11): no, with exceptions. Bytes that move towards upstream
richare fixes and ship in minor or patch releases. What is covered: the Rust API, the CLI's flags, exit codes and JSON reports, and the export formats' structure. Otherwise every parity fix after 1.0 would need 2.0. - Byte-parity as the north star after 1.0 (the ROADMAP's open
question). Decided (2026-10-11): yes for output; no for API shape. §3 (byte
offsets in
Textspans where upstream counts code points) stays: it is the right Rust API and does not change what is rendered. - Upstream's next major (
rich16). Decided (2026-10-11): sync it like any release. Output changes follow decision 2; only an API change we cannot absorb compatibly makesrs-rich2.0. - Splitting the monorepo (#380). Decided (2026-10-11): after 1.0, not as part of it. The issue's own preconditions (a proven plugin API, a marketplace underway, the workspace measurably slowing work) are not met, and moving repositories during an API freeze adds risk for no user benefit.
- The plugin marketplace (#232, #463). Decided (2026-10-11): part of
1.0, contract and marketplace both: the listings repository,
rs-rich-marketplace,rich pluginand the browser (stage 2, track B). - Windows legacy console (#12). Decided (2026-10-11): declare it unsupported
(Windows 10 and later only, as every supported Windows release is), close
#12, and record it in DIVERGENCES. Implementing it needs
unsafein core for terminals almost nobody runs. - A stop at 0.1.0. Decided (2026-10-11): yes, as described in stage 3, so the API review and its tooling get a release of real use before the freeze.
- The stable set grows to sixteen packages. Decided (2026-10-27): the seven above, plus rs-rich-interact, rs-rich-intuituive, rs-rich-art, rs-rich-micro, rs-rich-record, rs-rich-embed, noctiluca, and two new crates, rs-rich-acp and cornacai. rs-rich-diagram, -mermaid, -lumis, -data, -ratatui and -web stay 0.x.
- The apps come before 1.0, as stable crates. Decided (2026-10-27): Cornacai (#794), the Textual-parity work (#797 to #815) and Noctiluca's improvements (#784 to #792, #816 to #821) all land before 1.0.0.
- Two tracks from 0.0.24 to 0.0.28, then 0.1.0's review of all sixteen. Decided (2026-10-27); see Before 0.1.0.
- The third-party plugin criterion stays, with a call. Decided (2026-10-27): the maintainer knows no one to ask, so the project puts out a call: a "write the first community plugin" issue, a plugin template repository (which the maintainer creates) and a docs page.
- Security: a structured review against a written threat model, not a paid audit. Decided (2026-10-27); see stage 4.
- Maintenance mode after 1.0.0. Decided (2026-10-27): stage 7.
- 0.0.25, then 0.1.0. Decided (2026-11-03): 0.0.24 carried 34 of the apps track's 36 issues and most of track 2, so 0.0.25 finishes both tracks and 0.0.26 to 0.0.28 are not planned. What is not ready by 0.0.25 is named in its notes and moves on rather than holding up the review. Releases run on release-kit from 0.0.25.
-
1.0.0 at the beginning of December. Decided (2026-11-03). The dates, each a target:
- 0.0.25 about 7 November;
- 0.1.0 (stage 3) about 14 November;
- 0.1.1 (stage 4's hardening) and
1.0.0-rc.1about 19 November; - 1.0.0 about 3 December, two weeks after the rc.
With it: - 0.1.0's real use is the rc's two weeks. Decision 8's "a release of real use before the freeze" is compressed to about five days of 0.1.0, and the release candidate's two weeks count as the rest. - The maintainer dogfoods. The maintainer builds one of their own tools on the stable set between 0.1.0 and the rc (#564); that meets the outside-project criterion. - The third-party plugin moves to 1.x. It no longer blocks 1.0.0. The call (#831) stays open, and the criterion stays as a goal after 1.0. - What can still move the date: the fuzz clock. Four clean weeks from the first nightly run after the 2026-11-03
stylesheetfix ends about 3 December only if that fix merges on 4 November and no new finding opens; any finding moves 1.0.0 by the time to fix it.
Sizing¶
No dates: in stage releases, 0.0.19, three releases for parity and the marketplace, 0.1.0, one or two 0.1.x hardening releases, at least one release candidate, then 1.0.0. That is eight or nine releases. With the stable set widened (2026-10-27), 0.0.23 and about five releases for the apps and the wider set came before 0.1.0; on 2026-11-03 that became two, 0.0.24 and 0.0.25 (decision 15). From 0.0.25: 0.1.0, one or two 0.1.x hardening releases, at least one release candidate, then 1.0.0, about six releases. At the recent pace of a cohort every few days to a week, with three-audit release tests, it is a matter of weeks, not months. The longest poles are stage 2's 41 partial rows, the marketplace, and stage 3's API review; all three split into parallel workstreams.