From 09dc45cefddfabeb99292f18c8d5dfd27b44d2d8 Mon Sep 17 00:00:00 2001
From: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
Date: Wed, 9 Sep 2026 17:45:26 +0700
Subject: [PATCH 1/2] docs: correct four claims a deep read found false
Checked every markdown file against the code before cutting 2.2.0. Links and
anchors are sound -- a script walked all 22 files and found 0 broken relative
links and 0 broken anchors -- and the measured numbers hold: the five
Spearman correlations match model-calibration.toml exactly, the documented
`cargo reconverge check --strict --message-format json --cc` invocation
matches runner.rs verbatim, and `--cc 86` / `sm_86` / `8.6` all resolve as
the README claims.
Four things did not hold.
**`--allow-unsafe` is on `stage`, not on `tune`.** The README put it in a
paragraph immediately after `tune`'s exit codes, so a reader would try
`launchbound tune --allow-unsafe` and get "unexpected argument". Verified.
Now stated where it lives and what it requires.
**The README's CLI block omitted `stage` entirely** -- a real subcommand,
listed in docs/ARCHITECTURE.md's crate table but nowhere a user would look.
Added, along with `space --list` and `model --results`, both of which exist
and neither of which was mentioned.
**`just ci` was described with a recipe list two releases stale**, in three
places that each name it: AGENTS.md, CONTRIBUTING.md and ci.yml's own header
comment. None mentioned `docs`, `versions` or `skill`. A contributor reading
any of them would not know what CI runs.
**docs/research-baseline.md said "the gate now pins 0.3.0"** in the present
tense. It pins 0.6.0. The row records the conditions of the S0 measurements
and should not be updated to match the gate -- so it now says which versions
followed and points at the two comparison sections, and says explicitly that
the row is deliberately frozen.
Also: the mermaid diagram used `\n` for line breaks. `
` is the form
verified to render on GitHub (termlens's diagram, which was checked
visually); `\n` in mermaid *edge* labels is not reliably supported. Switched.
Deep test at this commit, all green: `just ci`, `just gate` 3/3 against real
reconverge 0.6.0 and cuda-oxide 26754ae5, MSRV 1.88, `just termlens-cli` 4/4,
cargo-semver-checks 8/8 crates clean against 2.1.0, corpus prune 93 clean /
8 refused / 0 tool errors, all six kernels lowering to PTX, and the stress
hunt 12/12 across both OSes at 1/2/4/8/16 threads.
Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
---
.github/workflows/ci.yml | 5 +++--
AGENTS.md | 3 ++-
CONTRIBUTING.md | 3 ++-
README.md | 24 +++++++++++++++++-------
docs/research-baseline.md | 2 +-
5 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5f52b74..ebdac9b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,5 +1,6 @@
-# The main gate: fmt, clippy -D warnings, tests, cargo-deny, schema
-# validation — identical to `just ci` locally, on runners with NO GPU. That a
+# The main gate: fmt, clippy -D warnings, tests, rustdoc with warnings denied,
+# cargo-deny, schema validation, and the pin/version/skill consistency
+# scripts — identical to `just ci` locally, on runners with NO GPU. That a
# plain runner stays green is itself the no-GPU path's regression test.
name: ci
diff --git a/AGENTS.md b/AGENTS.md
index 5e151a9..4ae4819 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -19,7 +19,8 @@ is the full contributor document and wins wherever the two disagree.
## Build and test
```sh
-just ci # fmt, clippy, test, deny, schemas, pins
+just ci # fmt, clippy, test, docs, deny, schemas, pins,
+ # versions, skill
cargo test --workspace # no GPU, no network, no checkout needed
just pins # the recorded pin sites agree — no network
just gate # the gate tests — needs cargo-reconverge + cuda-oxide
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 79fda52..6a789e6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,7 +19,8 @@ runners.
```bash
rustup show # installs the pinned nightly from rust-toolchain.toml
cargo install just # or: brew install just
-just ci # fmt, clippy -D warnings, tests, cargo-deny, schemas
+just ci # fmt, clippy -D warnings, tests, rustdoc, cargo-deny,
+ # schemas, pins, versions, skill
```
`cargo reconverge check` also needs no GPU: it runs over Stable MIR as a
diff --git a/README.md b/README.md
index ee31087..de43080 100644
--- a/README.md
+++ b/README.md
@@ -86,11 +86,11 @@ reader arriving from cuda-oxide's docs will assume otherwise; see
```mermaid
flowchart LR
- A[enumerate] --> B["PRUNE\n(reconverge, MIR — no GPU)"]
- B --> C["compile\n(cuda-oxide → PTX)"]
+ A[enumerate] --> B["PRUNE
reconverge · MIR · no GPU"]
+ B --> C["compile
cuda-oxide → PTX"]
C --> D[benchmark]
D --> E[rank]
- B -. "disqualified configs\n+ rule ID + source span" .-> F[rejection report]
+ B -. "disqualified configs
+ rule ID + source span" .-> F[rejection report]
D -. "faster but refused" .-> F
```
@@ -140,9 +140,14 @@ Two asymmetries, published rather than buried:
## CLI
```
-launchbound space [--json] # enumerate the space, print its size
+launchbound space [--json] [--list] # enumerate the space, print its size
launchbound prune --cc 8.6 [--json] # reconverge pass only — NO GPU NEEDED
-launchbound model --cc 8.6 # analytical ranking — NOT GATED
+launchbound model --cc 8.6 [--results R] # analytical ranking — NOT GATED;
+ # --results prints Spearman vs measured
+launchbound stage --cc 8.6 [--allow-unsafe --reason "…"]
+ # prune + compile every admitted
+ # specialization, emit a bench plan
+ # directory to ship to a GPU box
launchbound tune --cc 8.6 --backend cuda|metal|model [--budget 30m]
launchbound report [--json] [--rejected] # includes refused-but-faster configs
launchbound apply [--no-verify] # emit the cuda-oxide policy specialization
@@ -174,8 +179,13 @@ re-verify against — and the output carries a notice saying so.
Exit codes: `0` a safe configuration was found; `1` the fastest candidates
were refused and the chosen one is slower than a rejected candidate — notable,
-not an error; `2` tool error. `--allow-unsafe` exists, requires an explicit
-reason string recorded in the report, and is never the default.
+not an error; `2` tool error.
+
+`--allow-unsafe` is **on `stage`, not on `tune`**: measuring a configuration
+the gate refused is a deliberate act with its own command, and it requires
+`--reason` with a non-empty string, recorded verbatim in the report. A
+missing reason is a usage error, not a warning. It is never the default, and
+`tune` has no such flag.
`prune` needing no GPU is the reason it exists as its own verb: it is the only
part of the pipeline a developer on a laptop can run, and it is the part that
diff --git a/docs/research-baseline.md b/docs/research-baseline.md
index 674e01f..270b2c0 100644
--- a/docs/research-baseline.md
+++ b/docs/research-baseline.md
@@ -15,7 +15,7 @@ Measured 2026-08-20.
| tier-1 guest | Apple `container` 1.2.0, **native arm64** Ubuntu 24.04 (no Docker, no Rosetta — operator requirement), CUDA toolkit 13.2 (sbsa), LLVM 21.1.8, container `cuda-oxide-dev` |
| tier-2 box | AWS `g5.xlarge` spot @ **$0.364/hr**, us-east-2c, **NVIDIA A10G** (`sm_86`, cc 8.6), driver 595.71.05, CUDA 13.2 (V13.2.51), LLVM 21.1.8 — chosen over the T4 by the operator; barely above T4 spot ($0.335/hr) |
| pinned toolchain | `nightly-2026-04-03` (`rustc 1.96.0-nightly (55e86c996 2026-04-02)`) |
-| reconverge | `cargo-reconverge 0.1.11` (built at `~/Projects/reconverge/target/release`) — **the version these measurements were taken with**; the gate now pins 0.3.0, which was verified to admit the identical set (see below) |
+| reconverge | `cargo-reconverge 0.1.11` (built at `~/Projects/reconverge/target/release`) — **the version these measurements were taken with**. The gate has since moved to 0.3.0, 0.4.0, 0.5.0 and (in 2.2.0) 0.6.0; each move was verified to admit the identical set — see the two comparison sections below. This row records the conditions of *these* measurements and is deliberately not updated. |
| cuda-oxide | checkout `50d07314eb8b7d5ec821ba02b0048a753c20dd4e` — the tree synced to the box (the box AMI's own stale clone reports `e28248c1`, but `./gpu sync` replaces the working tree and excludes `.git`, so the synced tree is what compiled) |
| subject kernels | `s0-reduce` (device-only lib crate, dep `cuda-device` only, containing the README's known-flip reduction); cuda-oxide examples `vecadd` (small) and `tiled_gemm` (large) |
| evidence logs | `~/Projects/cuda-oxide/.gpu-evidence/20260820T{071248,071807,071959}Z.log` |
From f6bd80d40aa8a21f0caee950a7bb7993a16e2e36 Mon Sep 17 00:00:00 2001
From: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
Date: Wed, 9 Sep 2026 17:47:38 +0700
Subject: [PATCH 2/2] release: v2.2.0
Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
---
CHANGELOG.md | 179 ++++++++++++++++++++++++++++++++++++++++++++++
Cargo.lock | 22 +++---
Cargo.toml | 18 ++---
action/action.yml | 2 +-
4 files changed, 200 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8650309..e614aed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,8 +9,67 @@ change measured timings are marked `bench:`.
## [Unreleased]
+## [2.2.0] - 2026-09-09
+
+The cuda-oxide pin was 133 commits and one toolchain behind, and the watch
+that would have said so had its schedule commented out. 2.2.0 catches up,
+turns the watch back on, widens the device model past Ampere, and closes the
+panic and arithmetic gaps user input could reach — plus the semver and
+documentation gates a published 2.x line should have had from the start.
+
+Ten issues (#50–#59). **Four of them were wrong when filed**, and measuring
+before implementing caught each one; the corrections are recorded on the
+issues and repeated below, because an audit that miscounts is worth less
+than no audit and the shape of the miscount is the useful part.
+
### Changed
+- **The lockstep pins move to the current upstream**, at every recorded
+ site: `nightly-2026-04-03` → **`nightly-2026-08-28`**, cuda-oxide
+ `50d07314` → **`26754ae5`** (upstream `main` on the day), reconverge
+ `0.5.0` → **`0.6.0`**. The prune leg never needed this — it is analysis
+ only, which is why the staleness stayed invisible — but the compile leg
+ shells out to `cargo oxide inspect` from the checkout the pin names, so a
+ kernel written against a current `cuda-device` could not be built by the
+ gate at all.
+
+ Verified rather than assumed: the corpus ran under both pin sets and the
+ outputs were diffed **byte for byte** — 93 clean, 8 refused, the same
+ eight `REFUSED RC001` lines on `reduce-flip` above one warp, the same
+ candidate hashes. All six corpus kernels lower to PTX at the new pin
+ (`.target sm_80`, one `.visible .entry` each). Recorded in
+ `docs/research-baseline.md` in the shape the 0.1.11 → 0.3.0 comparison
+ established. (#50)
+
+- **The README toolchain badge is a checked pin site.** It was not one, and
+ it had drifted to a nightly nothing installed — the first pin a reader
+ sees. `check-pins.sh` reports three nightly sites now and fails on badge
+ drift, which was verified by drifting it on purpose. (#50)
+
+- **The device model reaches Blackwell.** `DEVICES` held two rows, A10G
+ (8.6) and T4 (7.5), so `--cc 9.0` on a Hopper part — the architecture a
+ reader arriving from cuda-oxide is most likely to be holding — was a model
+ error. Added 8.0 (A100), 8.9 (L4/L40), 9.0 (H100) and 10.0 (B200).
+
+ Every field but `sm_count` is a compute-capability fact from the CUDA C++
+ Programming Guide; `sm_count` is a product fact and each row names the
+ part it came from. The new rows' shared-memory figures were cross-checked
+ against reconverge 0.6.0's independent `cc.rs` table and agree exactly,
+ allowing for the 1 KiB the driver reserves per SM on Ampere and later. An
+ unknown capability now lists the known ones, sorted numerically — `"10.0"`
+ precedes `"8.6"` as a string, which is the trap. (#52)
+
+- **`launchbound_bench::Summary` is re-exported from `launchbound-report`.**
+ It appears in the public fields of `CandidateReport`, `ChosenInfo` and
+ `RejectedFaster`, so it was reachable and unnameable unless you also
+ depended on the bench crate. (#55)
+
+- **`launchbound-space` refuses an impossible block at load.** A block axis
+ above CUDA's per-axis limit (x, y: 1024; z: 64) is now rejected by
+ `KernelSpec` with a message naming the value and the limit, so an operator
+ hears about a typo when the spec loads rather than as a launch failure ten
+ minutes into a sweep. (#53)
+
- **The PTY test harness moves to termlens 0.10.1** (from 0.9). The upgrade
itself is small — `drag` takes four column-first arguments now instead of
two coordinate pairs — but it brings the accessor this suite was missing.
@@ -38,6 +97,126 @@ change measured timings are marked `bench:`.
summary** via termlens's `report` action, so a red PTY test arrives as a
picture rather than a grid in a log.
+### Fixed
+
+- **Six `partial_cmp(..).expect("no NaN")` sorts became `f64::total_cmp`.**
+ The issue said five; there are seven `partial_cmp` sites and six carried
+ an `expect`, because the audit grepped the *message string* rather than
+ the construct and the two with different message text fell out of the
+ count. Those two were the ones that mattered: `bench/stats.rs` sorts the
+ **raw measured timings**, and `model/lib.rs` sits under **`spearman`, a
+ `pub fn`** — so `spearman(&xs, &ys)` with a single NaN in either column
+ aborted the process from safe code, with no unsafe input path required.
+ That is a reachable panic, not a latent one.
+
+ `total_cmp` is total, free, and identical to `partial_cmp` on every pair
+ of non-NaN floats. NaN ordering is documented where it changes an outcome.
+ In `summarize` it has a consequence worth stating: a NaN fails both Tukey
+ fence comparisons and is **rejected as an outlier**; poison the quantiles
+ badly enough and the answer is `None`, the honest summary of a sample that
+ has none. (#54)
+
+- **`Config::block_threads()` saturates instead of overflowing.** It was
+ `.product()` over three `u64`s read straight from `kernel.toml`: a panic
+ in a debug build, a wrapped value in release — and a wrapped value does
+ not stop there, it feeds `estimate` and the gate's `threads > WARP_SIZE`
+ test, so a block of 2^64 + 32 threads reads as a legal 32-thread block.
+
+ The issue proposed `checked_mul` folding to `Result`, which is a break to
+ a `pub fn` on a crate published at 2.1.0 and could not ship in a minor
+ bump. It was also unnecessary, and the issue said why without noticing:
+ `grid_blocks` is the sibling doing the same job with `saturating_mul`.
+ A proptest over three arbitrary `u64` axes holds the line. (#53)
+
+- **The summary invariant lives in the type.** `measured_fastest_first`
+ filtered on `summary.is_some()` and returned bare candidates, so both
+ callers re-`unwrap()`ed on the strength of a filter performed in another
+ function. It returns `(&CandidateReport, &Summary)` pairs; the four
+ unwraps are gone because they no longer compile. Same shape in
+ `report::build`. Remaining `expect`s in functions that already return
+ `Result` became `?`. (#55)
+
+### Added
+
+- **A semver gate, with the release type forced.** No workflow ran
+ `cargo-semver-checks`, so removing a `pub fn` shipped without a signal.
+ The gate forces `--release-type patch` and the reason is measured, not
+ assumed: remove `Config::kernel` while bumping the manifest to 3.0.0 in
+ the same PR and the *inferred* run prints `0 checks: 0 pass, 254 skip` and
+ exits **0**, while forced `patch` prints `1 major and 0 minor checks
+ failed` and exits **100**. cargo-semver-checks runs only the lints the
+ declared bump does not already excuse, so a PR that declares its own break
+ silences the gate. `patch` excuses nothing — and does not forbid
+ additions, since only breaking changes are reported.
+
+ A deliberate break carries the new `breaking` label, which switches the
+ job to `major`. Three of the eleven published crates are binary-only; the
+ eight with a library API are all covered. (#56)
+
+- **`scripts/check-versions.sh`, in `just ci`.** `[workspace.dependencies]`
+ pinned the path crates at 2.0.0 while the workspace was 2.1.0 — harmless
+ for a path build, which is why it survived a whole minor line. Not
+ harmless for the next major: with the pins stale, bumping to 3.0.0 makes
+ `cargo metadata` refuse to resolve the workspace at all. **The drift
+ breaks the release after next.** (#56)
+
+- **A rustdoc gate, and 237 documented public items.** The issue said "about
+ 42". It is 237 — I counted items and never counted *fields*, and 144 of
+ the 237 are public struct fields. In a crate family whose structs are the
+ JSON wire formats, the fields are the part a consumer actually reads.
+
+ The gate cost nothing to turn on (`cargo doc` was already at zero
+ warnings) and earned its keep immediately by failing on two broken
+ intra-doc links in the commit that added it — one naming a function that
+ does not exist. (#57)
+
+- **The pin watch runs weekly again, and reports a toolchain move on its own
+ line.** The schedule had been commented out, so it spoke only when
+ dispatched. The two kinds of drift are not alike: commit churn is a bump
+ you can schedule, a channel move means our rustc can no longer build
+ upstream's kernels and reconverge must be rebuilt. An extractor that reads
+ nothing now fails the job instead of reporting "Pins current." forever.
+ Exercised against a stubbed upstream across five scenarios. (#51)
+
+- **The TUI's freedom from colour is now an invariant.** #58 expected a
+ colour-only cue to vanish under `NO_COLOR`; measuring found there is no
+ such cue — every style is `BOLD` or `BOLD | REVERSED` and `Color::`
+ appears nowhere. So the tests assert the stronger claim: every cell of all
+ four views has the terminal's default foreground and background, the metal
+ banner keeps its emphasis under `NO_COLOR=1`, and a `NO_COLOR` frame is
+ byte-identical to one without it. The first fires the day someone marks a
+ refusal red. (#58)
+
+ (The issue's other half — "the suite runs at one geometry" — was already
+ false when filed: 2.1.0's suite runs nine tests at 80×24 and two at 60×30.)
+
+### Documentation
+
+- **`#[launch_bounds]` and register budgeting are not validated**, and the
+ README and LIMITATIONS now say so and link to each other. launchbound
+ never reads a register count and does not check `#[launch_contract]`
+ against grid limits. The confusion is earned: `stencil-1d/kernel.toml`
+ opens by narrating register pressure, `lb_max` is a real tuning dimension,
+ and the tool is called *launchbound*. The one `.maxntid` relationship the
+ corpus enforces holds because the kernel author wrote it as a constraint —
+ launchbound attaches no meaning to `lb_max`. (#59)
+
+- **The model's device table is narrower than the gate's**, recorded in
+ LIMITATIONS: reconverge covers 7.0–12.0, so `prune --cc 12.0` can succeed
+ where `tune --backend model --cc 12.0` refuses. Only 8.6 and 7.5 have ever
+ had a kernel measured on them here; the other four rows are documented
+ capacity, not experience.
+
+- **Four false claims found by a deep read before the release.**
+ `--allow-unsafe` was documented as if it were on `tune`; it is on `stage`,
+ and `tune --allow-unsafe` is an "unexpected argument" error. The README's
+ CLI block omitted `stage` entirely. `just ci` was described with a
+ two-release-stale recipe list in three separate places. And
+ research-baseline said "the gate now pins 0.3.0" in the present tense.
+
+- `docs/RELEASING.md` gains the internal pin bump in step 1 and the
+ post-publish `baseline-version` move as its own step.
+
## [2.1.0] - 2026-09-05
Thirteen findings, all reported against 2.0.0 with a measured reproduction.
diff --git a/Cargo.lock b/Cargo.lock
index 5e227fc..926c944 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1121,7 +1121,7 @@ checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f"
[[package]]
name = "launchbound-bench"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"anyhow",
"launchbound-space",
@@ -1135,7 +1135,7 @@ dependencies = [
[[package]]
name = "launchbound-build"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-space",
"serde",
@@ -1146,7 +1146,7 @@ dependencies = [
[[package]]
name = "launchbound-cli"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"anyhow",
"clap",
@@ -1164,7 +1164,7 @@ dependencies = [
[[package]]
name = "launchbound-metal"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-bench",
"launchbound-space",
@@ -1175,7 +1175,7 @@ dependencies = [
[[package]]
name = "launchbound-model"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-space",
"serde",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "launchbound-prune"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-build",
"launchbound-space",
@@ -1198,7 +1198,7 @@ dependencies = [
[[package]]
name = "launchbound-report"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"insta",
"jsonschema",
@@ -1210,7 +1210,7 @@ dependencies = [
[[package]]
name = "launchbound-runner"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-bench",
"launchbound-search",
@@ -1218,7 +1218,7 @@ dependencies = [
[[package]]
name = "launchbound-search"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"launchbound-bench",
"proptest",
@@ -1226,7 +1226,7 @@ dependencies = [
[[package]]
name = "launchbound-space"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"proptest",
"serde",
@@ -1237,7 +1237,7 @@ dependencies = [
[[package]]
name = "launchbound-tui"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"anyhow",
"crossterm",
diff --git a/Cargo.toml b/Cargo.toml
index 3ac490b..b42932e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,7 +20,7 @@ members = [
exclude = ["corpus"]
[workspace.package]
-version = "2.1.0"
+version = "2.2.0"
edition = "2024"
# MSRV for crates that do not require the pinned nightly (CONTRIBUTING.md);
# set by ratatui 0.30. The analysis and compile paths require
@@ -38,14 +38,14 @@ categories = ["development-tools", "development-tools::profiling"]
# published crate is compatible with a release it was never built against --
# harmless for a path build, wrong as a record. They sat at 2.0.0 through the
# whole 2.1.0 line; `just versions` (and a test) now refuse the drift.
-launchbound-space = { path = "crates/launchbound-space", version = "2.1.0" }
-launchbound-prune = { path = "crates/launchbound-prune", version = "2.1.0" }
-launchbound-build = { path = "crates/launchbound-build", version = "2.1.0" }
-launchbound-bench = { path = "crates/launchbound-bench", version = "2.1.0" }
-launchbound-report = { path = "crates/launchbound-report", version = "2.1.0" }
-launchbound-search = { path = "crates/launchbound-search", version = "2.1.0" }
-launchbound-model = { path = "crates/launchbound-model", version = "2.1.0" }
-launchbound-metal = { path = "crates/launchbound-metal", version = "2.1.0" }
+launchbound-space = { path = "crates/launchbound-space", version = "2.2.0" }
+launchbound-prune = { path = "crates/launchbound-prune", version = "2.2.0" }
+launchbound-build = { path = "crates/launchbound-build", version = "2.2.0" }
+launchbound-bench = { path = "crates/launchbound-bench", version = "2.2.0" }
+launchbound-report = { path = "crates/launchbound-report", version = "2.2.0" }
+launchbound-search = { path = "crates/launchbound-search", version = "2.2.0" }
+launchbound-model = { path = "crates/launchbound-model", version = "2.2.0" }
+launchbound-metal = { path = "crates/launchbound-metal", version = "2.2.0" }
anyhow = "1"
clap = { version = "4", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
diff --git a/action/action.yml b/action/action.yml
index 0c57031..e829e9f 100644
--- a/action/action.yml
+++ b/action/action.yml
@@ -40,7 +40,7 @@ inputs:
default: tool-error
version:
description: >-
- Which launchbound release runs the gate, e.g. "2.1.0". The default,
+ Which launchbound release runs the gate, e.g. "2.2.0". The default,
`latest`, installs the newest release on crates.io each run. Pin a
number if you want the gate to change only when you say so.
required: false