From db608e985c22bb7faccf2b5d54fbe3e3ba00cb3d Mon Sep 17 00:00:00 2001 From: Vyncint Ng <115854244+vyncint@users.noreply.github.com> Date: Sun, 13 Sep 2026 21:45:33 +0700 Subject: [PATCH] ci: termlens 0.11's two stale pins, and the check that missed them The 0.11 bump moved the dev-dependency, the lockfile, the vendored skill and both `cli-version:` inputs, and left `PIN_TERMLENS` in pins.yml and CONTRIBUTING's own line at 0.10.1. Nothing would have caught that: the skill-version check compared the skill and the workflow pins with the dependency and nothing else, so the first report would have been Monday's pins watch comparing 0.10.1 with crates.io and filing a drift issue for a bump that had already happened. Both are corrected, and the check now covers every entry on CONTRIBUTING's must-touch list instead of the skill alone. `PIN_TERMLENS` is compared with `Cargo.lock` exactly rather than on major.minor, because an exact version is what the watch compares: a lockfile moved to a patch release with the pin left behind produces the same false drift report, and major.minor would not see it. CONTRIBUTING gains the `cli-version:` inputs it never listed, so the list a bump follows is the list CI enforces. Verified by mutating each value in a copy of the tree: a stale PIN_TERMLENS, a lockfile ahead of the pin, a stale CONTRIBUTING line, a bumped dependency with nothing else moved, and a deleted PIN_TERMLENS line each exit 1 with the error naming the file; the unmodified tree exits 0. `just ci` is green (165 tests, 0 failed; deny ok; research green once rustup's proxy precedes Homebrew's cargo on PATH). Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com> --- .github/scripts/check-skill-version.sh | 63 ++++++++++++++++++++++++-- .github/workflows/pins.yml | 2 +- CHANGELOG.md | 13 +++++- CONTRIBUTING.md | 17 ++++--- 4 files changed, 82 insertions(+), 13 deletions(-) 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