Skip to content

Stability candidate and 1.0 readiness criteria #335

Description

@vyncint

0.11 is the stability candidate. It is the release after which no promised public item of termlens changes incompatibly before 1.0. This issue holds the criteria 1.0 must meet, in one place, so they can be argued about here and then pinned. Proposed wording — finalise it in this issue, then pin.

What 0.11 ships

Everything else in the tracker is welcome and unaffected by the freeze: additive flags, fixture hygiene, docs polish.

What "frozen" means

From 0.11.0, the items docs/STABILITY.md names as promised do not change incompatibly. A change that must break one ships as a new candidate (0.12.0) with a migration table, and restarts the observation window below. A patch release does not restart it. The _for wait methods, wait_idle, Recording, frame_timings and the renderers stay as they are.

1.0 readiness criteria

1.0 is tagged when all of the following hold, and not before. No calendar date is a criterion.

  1. Contract published — STABILITY.md states the promised API, feature configurations, formats, CLI contract, platform limits and MSRV policy, and every statement names the job or test that checks it.
  2. Enforcement proven — the PR gate has been seen to fail on a deliberate break and on an item hidden behind a feature (the self-test), and has been green on every PR since the candidate.
  3. Consumers migrated — every maintained downstream repository depends on the candidate from crates.io (no path or patch overrides) and has been green on it for the whole observation window.
  4. An external pilot — at least one repository the maintainer does not own has tests on a published release candidate (1.0.0-rc.N) covering one real user flow, has caught at least one regression with them, and has run them in its own CI repeatedly. Internal green runs do not count.
  5. No known correctness blocker in the promised scope.
  6. Eight weeks of stable pilot usage, counted from the external pilot's first green run on the candidate — not from the candidate's publication date. Recorded here: pilot start, installed version, consumer SHA, runs, blockers, upgrades.
  7. Fresh-install evidence — the daily install.yml (library and CLI) green throughout the window.

If a criterion cannot be met, this issue records why, and 0.11 stays the current release. A candidate that is never promoted is a smaller failure than a 1.0 that is broken by 1.1.

Activity

  1. added this to the v0.11 milestone on Sep 9, 2026
  2. pinned this issue on Sep 10, 2026
  3. vyncint commented on Sep 10, 2026

    @vyncint
    OwnerAuthor

    The candidate is published. termlens 0.11.0 and termlens-cli 0.11.0 went to crates.io on 2026-09-10T21:35Z from tag v0.11.0 = b8af0fa, through Trusted Publishing (release run 34532570645: tag check, full CI, semver gate, publish, GitHub Release, and the registry-consumer check — library in both feature shapes and the installed CLI — all green on Linux and macOS). The stress workflow ran on that exact commit first: 100 iterations per OS across five --test-threads shards, Linux, macOS and Windows, all green (34530320216).

    What 0.11 shipped, against the list above. Correctness: #320 (in 0.10.2). The contract: #328, #329. Enforcement that can fail: #323 (with its self-test, and seen to fail on a real removal), #324, #325, #326, #327 (a 0.10.1 corpus written by the published 0.10.1, and a 0.11.0 one frozen from the release tree). The one breaking change: #330, landed alone under the breaking label with the diagnostics pasted and the migration table in the CHANGELOG. Additive API: #331, #332, #306, #308, #315. Documentation and process: #333, #334. Plus #340, found while writing the CLI contract: inspect's stdout is now a saved screen. The docs carry the criteria above in docs/STABILITY.md, and the README, CHANGELOG header and STABILITY state the candidate in the same words, checked by CI.

    What the freeze now means in practice. Every pull request is compared against the published 0.11.0 (once #350 moves the baseline) with the release type forced to patch in three feature views; the gate has been seen to fail on a removed item and on a gated one. One known blind spot, recorded in STABILITY.md: a method re-typed under the same name is not a lint cargo-semver-checks 0.50.0 has — it reported only the removed unsupported_overflow() beside #330's return-type change.

    For the criteria. 1 (contract published) and 2 (enforcement proven to fail; green on every PR since — from now) hold as of this release. 3 (consumers migrated) starts now: six maintained repositories move to termlens = "0.11" from crates.io, never a path. 4–7 begin when an external pilot's first green run is recorded here; nothing here sets a date.

  4. vyncint commented on Sep 11, 2026

    @vyncint
    OwnerAuthor

    Criterion 3 — consumers migrated — is met. All six maintained repositories now depend on termlens = "0.11" from crates.io (never a path or [patch.crates-io]), each merged with its own CI green:

    Repository PR Notes
    reconverge #139 two manifests, moved together
    mossaic #106
    launchbound #69
    oxmera #43
    oxidelake #20 two PTY suites
    termlens-demo #19 plus a new survey_0_11.rs

    The observation window for criterion 6 does not start here — it starts at an external pilot's first green run, and there is no pilot yet.

    What the migration measured, which is the point of doing it rather than asserting the table was right.

    The unsupported() break was mechanical everywhere, and in every repository it made the suite stricter rather than merely different: the pinned list and "the record is not truncated" collapse into one assertion, because the view is equal to a slice only when the retained shapes match and nothing overflowed. Five repositories deleted a Vec<String> helper that existed only to make the old comparison typecheck.

    Two things were found by a test failing, both in termlens-demo, which is what that tier is for. Its unsupported() probe pinned #320 as a defect and said in the test body that it should invert once fixed — against 0.11.0 it does, so the fix is now confirmed from outside against a real ratatui application. And its CLI test asserted inspect's trailer was in stdout, which #340 moved to stderr; it now asserts the split and the round trip.

    One gap in my own verification, worth recording. Five repositories keep their termlens-cli tests #[ignore]d because they install from crates.io, so a local cargo test — and reconverge's just ci, which says so explicitly — skips them. All five asserted the trailer from stdout and all five went red on CI after a locally green run. The #[ignore] is right (a local gate should not reach the network), but it means "green locally" is not evidence about the CLI contract in these repositories, and the next termlens CLI change will meet the same shape.

    A follow-up available but not taken: cursor().2 still appears at ten call sites across five repositories where cursor_visible() would read better. It compiles identically, so mixing that sweep into a dependency bump would only have made the diffs harder to review.

  5. vyncint commented on Sep 16, 2026

    @vyncint
    OwnerAuthor

    Criteria checked against main, 2026-09-16

    A status pass over the seven criteria, since this issue is where the
    evidence is supposed to live. Nothing here changes the criteria — the
    wording above is unchanged and the issue stays open, which is what it says
    it should do until criterion 4 is met.

    # criterion state evidence
    1 Contract published met docs/STABILITY.md §§1–3 each carry a decision and the measurement behind it (Windows #149, backend #150, styled history #146); "What the promise covers" splits Promised / Third-party boundaries / Not promised
    2 Enforcement proven met tools/semver-gate-selftest/run.sh passes today, 7/7, asserting both holes as holes — including "forced minor still fails on 0.x", which is why the gate uses major. It runs in ci.yml's semver job, and ci.yml on main is green on every run since the candidate
    3 Consumers migrated met All six on termlens = "0.11" from crates.io, no path or patch override anywhere: reconverge (×2 manifests), mossaic, launchbound, oxmera, oxidelake, termlens-demo
    4 An external pilot NOT met — the blocker No repository outside the maintainer's own has tests on a 1.0.0-rc.N. Nothing else is waiting on anything
    5 No known correctness blocker met No open issue in the promised scope. The twelve issues open when this pass started were eleven enhancements/docs and this tracker
    6 Eight weeks of stable pilot not started Counts from criterion 4's first green run, which has not happened. Not a calendar item and not startable yet
    7 Fresh-install evidence met so far install.yml green every day 2026-09-11 → 2026-09-16. The one failure in the window, 2026-09-10, predates the candidate's publication later that day

    So: six of seven hold, and the seventh has not been started. Criterion 6
    cannot begin until criterion 4 does, so the distance to 1.0 is measured
    entirely by finding a pilot — at least eight weeks after that, and no
    sooner. Worth saying plainly because five green boxes can read like
    progress toward a date, and criterion 6 explicitly is not one.

    The honest reading of criterion 4 is that it is the one criterion this
    repository cannot satisfy by working harder on itself. It may be worth its
    own issue: who the candidate pilots are, what "one real user flow" means for
    them, and what termlens offers in return for the trouble.

  6. unpinned this issue on Sep 16, 2026
  7. vyncint commented on Sep 16, 2026

    @vyncint
    OwnerAuthor

    Closing this as the discussion it was opened for, which has concluded:
    the criteria were argued, finalised and pinned, and the status pass above
    records each one against main.

    Closed does not mean met. Reading it that way would be wrong, so for
    anyone who arrives here from the README, CHANGELOG.md, docs/STABILITY.md
    or docs/RELEASING.md:

    • Criterion 4 — an external pilot — has not started. No repository
      outside the maintainer's own has tests on a 1.0.0-rc.N. It is the one
      criterion this project cannot satisfy by working harder on itself.
    • Criterion 6 — eight weeks of stable pilot usage — cannot begin until
      criterion 4 does.
      It counts from the pilot's first green run, not from
      a calendar date and not from the candidate's publication.
    • The other five held as of 2026-09-16, with the evidence in the comment
      above.

    So termlens is not 1.0-ready, and the distance to 1.0 is still measured
    entirely by finding a pilot plus at least eight weeks after that.

    The criteria themselves are unchanged and remain readable here. 0.11.0 stays
    the current release and the freeze it declares is unaffected: from 0.11.0 no
    promised item changes incompatibly before 1.0, and a change that must break
    one ships as a new candidate.

    docs/RELEASING.md still names this issue as the gate for a v1.0.0 tag —
    "every criterion in #335 to be recorded as met, with its evidence". That
    remains the rule; this issue is where the evidence is, closed or not.

  8. vyncint commented on Sep 23, 2026

    @vyncint
    OwnerAuthor

    The seven criteria in this issue are now a section of docs/STABILITY.md: The 1.0 readiness criteria (#472, landed in #492). They are copied word for word, except that "this issue" now reads "this section". The candidate statement in the README, the CHANGELOG and STABILITY.md, and docs/RELEASING.md's v1.0.0 gate now link that section instead of this closed issue. That section is the live record, and a criterion is recorded as met there. Nothing about the criteria themselves changed: criterion 4, the external pilot, has still not started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions