diff --git a/.github/scripts/check-skill-version.sh b/.github/scripts/check-skill-version.sh index 2c6d713..48ef948 100755 --- a/.github/scripts/check-skill-version.sh +++ b/.github/scripts/check-skill-version.sh @@ -1,5 +1,12 @@ #!/usr/bin/env bash -# The vendored termlens skill must name the version this repository depends on. +# Everything that names a termlens version must name the one we depend on. +# +# termlens pairs with nothing and moves alone, so its version is written down +# in five places (CONTRIBUTING.md lists them). The 0.11 bump moved three and +# left two — `PIN_TERMLENS` and CONTRIBUTING's own line — at 0.10.1, where +# nothing would have noticed until the Monday pins watch filed a drift issue +# about a bump that had already happened (#68). Each of these is silent when +# it goes stale, which is why the check covers the list rather than one entry. # # `.claude/skills/termlens/SKILL.md` is a copy of the file termlens ships for # coding agents. It is refreshed by hand, and the failure mode is silent: the @@ -16,16 +23,20 @@ # Compares major.minor only. A termlens patch release does not rewrite the # skill, and demanding a re-copy for every one of them would make this noise. # -# Usage: check-skill-version.sh [SKILL.md] [Cargo.toml] +# Usage: check-skill-version.sh [SKILL.md] [Cargo.toml] [pins.yml] [CONTRIBUTING.md] [Cargo.lock] set -euo pipefail skill="${1:-.claude/skills/termlens/SKILL.md}" # termlens is a dev-dependency of exactly one crate, not a workspace # dependency (see CONTRIBUTING.md: it pairs with nothing and moves alone). manifest="${2:-crates/oxmera-cli/Cargo.toml}" +pins="${3:-.github/workflows/pins.yml}" +contributing="${4:-CONTRIBUTING.md}" +lock="${5:-Cargo.lock}" -[ -f "$skill" ] || { echo "::error::$skill does not exist"; exit 1; } -[ -f "$manifest" ] || { echo "::error::$manifest does not exist"; exit 1; } +for f in "$skill" "$manifest" "$pins" "$contributing" "$lock"; do + [ -f "$f" ] || { echo "::error::$f does not exist"; exit 1; } +done # "Written against **termlens 0.10.1**." -> 0.10 skill_version="$(sed -n 's/.*Written against \*\*termlens \([0-9][0-9.]*\)\*\*.*/\1/p' "$skill" | head -1)" @@ -73,3 +84,47 @@ if [ -n "$cli_pins" ]; then done echo "the termlens-cli pins in .github/workflows ($(echo "$cli_pins" | tr '\n' ' ')) match the dependency (${dep_version})" fi + +# `PIN_TERMLENS` is what the weekly pins watch compares with crates.io's newest +# release, so it has to name the version this repository actually resolves — +# not the requirement, which is a range that several releases satisfy. When the +# two part company the watch reports drift toward a version we already have and +# opens an issue for a bump that is already done. Exact, not major.minor, +# because exact is what the watch compares. +locked="$(sed -n '/^name = "termlens"$/,/^$/ s/^version = "\([0-9][0-9.]*\)"/\1/p' "$lock" | head -1)" +[ -n "$locked" ] || { + echo "::error::no resolved termlens version found in $lock" + exit 1 +} + +pin_version="$(sed -n 's/^ *PIN_TERMLENS: *"\{0,1\}\([0-9][0-9.]*\)"\{0,1\} *$/\1/p' "$pins" | head -1)" +[ -n "$pin_version" ] || { + echo "::error::no PIN_TERMLENS: X.Y.Z line found in $pins" + exit 1 +} + +if [ "$pin_version" != "$locked" ]; then + echo "::error::$pins pins termlens ${pin_version} but $lock resolves ${locked}." + echo "::error::Set PIN_TERMLENS to ${locked}, or the Monday pins watch files drift for a bump that already happened." + exit 1 +fi + +echo "PIN_TERMLENS (${pin_version}) matches the resolved dependency (${locked})" + +# CONTRIBUTING's termlens paragraph opens by naming the current version, and it +# is the list every bump is supposed to follow. A list that misstates its own +# subject is the least likely thing to be reread. +doc_version="$(sed -n 's/.*`termlens` (currently \([0-9][0-9.]*\)).*/\1/p' "$contributing" | head -1)" +[ -n "$doc_version" ] || { + echo "::error::$contributing has no '\`termlens\` (currently X.Y)' line to check" + exit 1 +} +doc_minor="$(echo "$doc_version" | cut -d. -f1,2)" + +if [ "$doc_minor" != "$dep_minor" ]; then + echo "::error::$contributing says termlens is currently ${doc_version} but this repository depends on ${dep_version}." + echo "::error::Update that line; it is the checklist every termlens bump follows." + exit 1 +fi + +echo "$contributing (${doc_version}) matches the dependency (${dep_version})" diff --git a/.github/workflows/pins.yml b/.github/workflows/pins.yml index 87bbbf1..be011ef 100644 --- a/.github/workflows/pins.yml +++ b/.github/workflows/pins.yml @@ -27,7 +27,7 @@ jobs: PIN_RECONVERGE: 0.5.0 PIN_LAUNCHBOUND: 2.1.0 PIN_CUDA_OXIDE: a766fc26 - PIN_TERMLENS: 0.10.1 + PIN_TERMLENS: 0.11.0 GH_TOKEN: ${{ github.token }} steps: - name: Compare pins with upstream diff --git a/CHANGELOG.md b/CHANGELOG.md index 1407a88..8e40f4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **termlens 0.10.1 → 0.11**, with the vendored skill and the report - action's `cli-version:` pins in `ci.yml` and `stress.yml` - (`check-skill-version.sh` holds all three equal to the dependency). 0.11 + action's `cli-version:` pins in `ci.yml` and `stress.yml`. 0.11 is termlens's stability candidate: from it no promised item changes incompatibly before its 1.0, so this requirement should hold for a while. @@ -28,6 +27,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 blink and strikethrough as unsupported although the attribute shadow implements them, was fixed upstream in 0.10.2. + The bump moved three of the places that name the version and left two: + `PIN_TERMLENS` in `pins.yml` and CONTRIBUTING's own line, both still at + 0.10.1. Nothing would have caught that until the weekly pins watch + compared the stale pin with crates.io and filed a drift issue for a bump + that had already happened. Both are corrected, and + `check-skill-version.sh` now checks every entry on CONTRIBUTING's + must-touch list instead of the vendored skill alone — + `PIN_TERMLENS` against `Cargo.lock` exactly, because an exact version is + what the watch compares, and the rest on major.minor as before. + - **termlens 0.9.0 → 0.10.1**, with the `serde` feature, and the terminal suite grown into the surface it opens. No call site broke: the crate never used `drag`, a `termlens::Style` literal, `assert_screen_snapshot!` or a diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf57a18..52af151 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,16 +78,21 @@ that and reports upstream HEAD for information only; when HEAD needs a newer nightly than reconverge is built on, the pin waits for a reconverge release, not the other way round. -`termlens` (currently 0.10.1) pairs with nothing and moves alone, in its own +`termlens` (currently 0.11) pairs with nothing and moves alone, in its own commit, gated by the PTY suites and both 100-iteration stresses. A bump must touch, together: the dev-dependency in `crates/oxmera-cli/Cargo.toml` (the only manifest that names it), `Cargo.lock` (three jobs run `--locked`), -`PIN_TERMLENS` in `.github/workflows/pins.yml`, this line, and the vendored -agent skill `.claude/skills/termlens/SKILL.md` — copied verbatim from +`PIN_TERMLENS` in `.github/workflows/pins.yml`, every `cli-version:` input of +the termlens report action under `.github/workflows/`, this line, and the +vendored agent skill `.claude/skills/termlens/SKILL.md` — copied verbatim from `termlens/skills/termlens/SKILL.md`, since the published crate does not ship -it. `.github/scripts/check-skill-version.sh` fails CI when the skill and the -dependency disagree on major.minor, because a stale copy is otherwise silent: -it hands every agent working here the idioms of a release that is gone. +it. `.github/scripts/check-skill-version.sh` fails CI when any of them +disagrees with the dependency, because every one of these is silent when it +goes stale: a stale skill hands every agent working here the idioms of a +release that is gone, and a stale `PIN_TERMLENS` makes the Monday pins watch +file a drift issue about a bump that already happened. The 0.11 bump moved +three of them and left the other two behind, which is why the check now covers +the whole list rather than the skill alone. ## Testing policy