Skip to content

feat(xtask): add cargo xtask bump-pins and a weekly bump workflow - #1829

Open
nathan-weinberg wants to merge 3 commits into
praxis-proxy:mainfrom
nathan-weinberg:pins/bump-pins
Open

nathan-weinberg wants to merge 3 commits into
praxis-proxy:mainfrom
nathan-weinberg:pins/bump-pins

Conversation

@nathan-weinberg

Copy link
Copy Markdown
Contributor

Summary

Third of three stacked PRs. Stacked on #1828 (which stacks on #1827). Review only the last commit, feat(xtask): add cargo xtask bump-pins and a weekly bump workflow.

cargo xtask bump-pins [--pin <pin>]... [--dry-run] [--report PATH] automates the mechanical half of a bump. The behavioral half stays human.

  • Discovery finds the newest release within each manifest's major_series:
    • Claude Code and OpenCode 1.x/2.x: npm dist-tags, falling back to the newest in-series version when latest crosses the major boundary.
    • pi, Codex and vLLM: the latest GitHub release.
    • vLLM image: the Docker Hub manifest-list digest for the release tag. If the tag isn't on Docker Hub yet, the pin is skipped, not failed.
  • Checksums come from upstream's own metadata where it publishes one (Claude Code manifest.json, GitHub asset digests). npm only publishes sha512 integrity, so the OpenCode tarballs are streamed through sha256 without buffering.
  • Rewrites are staged in memory through the same site table check-pins uses, with exact-count anchors that fail on drift. Checksum fixtures are swapped, and check-pins runs on the staged tree before anything is written.
  • Behavioral pins are never touched: tool lists, exit codes, xfails, replay recordings, "verified against" claims. The markdown report gives a per-client re-validation checklist plus every line that still names the old version.

The Bump Pins workflow runs it weekly (Mondays 05:23 UTC) and on dispatch. It opens or updates a draft PR from bot/bump-pins with the praxis-bot-app token, using the report as the body. It never auto-merges, and it never force-pushes over a bump PR that a person has committed to.

The client guide gains a "Pinned client versions" section, and the bump-instruction comments in integration.yaml now point at bump-pins.

Needs a maintainer before the workflow can work

  • praxis-bot-app needs Contents, Pull requests and Workflows write access on this repo. Workflows is required because bumps edit files under .github/workflows/, and GitHub rejects such pushes without it.
  • Bot commits carry the bot's own Signed-off-by.
  • If a draft bump PR is idle for 5 days, close-stale-drafts closes it, and the next weekly run opens a fresh one.

Open question

Claude Code follows npm latest (2.1.310 today), which is where the current pin came from. npm stable (2.1.308) lags latest and would have skipped the 2.1.265–2.1.267 regressions. Switching is a one-line change.

Related issue

Closes #1798

Validation

  • cargo test -p xtask --features openai-all,store-all pins::: 32 tests, covering site rewrites and canned npm, GitHub, Claude-manifest and Docker Hub JSON. No network access.

  • cargo clippy -p xtask --all-targets -- -D warnings (both feature sets), make fmt, make lint-license-headers, cargo xtask lint-markdown-links, cargo xtask check-pins.

  • Ran a live cargo xtask bump-pins --dry-run. It found Claude Code 2.1.310, OpenCode 1.19.4 and 2.1.4, and Codex 0.164.0; pi and vLLM were current.

  • Ran a real bump-pins on a scratch tree, then reverted it:

    • The OpenCode 1.x, OpenCode 2.x and Claude Code checksums it wrote match independent curl | sha256sum downloads.
    • I couldn't hash the Codex archive independently because GitHub release downloads were returning 504. Its checksum is GitHub's published asset digest, the same source that produced pi's checksum, which matches the committed fixture.
    • The only offline test that failed on the bumped tree was the intended gate, codex_pin::websocket_recording_matches_the_pinned_version.
  • Not run locally: actionlint. The workflow YAML parses.

  • Unit tests

  • Integration or functional tests

  • make lint

Checklist

  • I reviewed every changed line and can explain the change.
  • New capabilities include an example config and functional example test.
  • User-facing behavior and generated documentation are updated.
  • Performance-sensitive changes include appropriate benchmark or load-test evidence.
  • Commits are signed and include a Signed-off-by trailer.

Breaking changes

None.

🤖 Generated with Claude Code

First of three changes automating pinned-client bumps. This one cuts the
number of sites a bump must touch and closes the existing drift, with no
new tooling yet.

- Claude Code: move the CPU lane from 2.1.267 to the manifest's 2.1.278,
  which the GPU lane already runs, and make the CPU job assert the
  installed version. Drop the duplicate constant in claude_code_vllm.rs
  in favor of CLAUDE_CODE_PINNED_VERSION, add a major_series tripwire,
  and add offline tests tying the manifest, constant, URL, and CI env.
- Codex: add codex-cli/pin.toml and CODEX_PINNED_VERSION. Each Codex CI
  job now derives every path, URL, and version check from one job-level
  CODEX_VERSION, and the cache key hashes the checksum fixture instead of
  embedding it. The WebSocket replay fixture is tied to the pinned
  version, so a bump must recapture it. codex_pin.rs enforces it all.
- OpenCode 1.x: add the checksum fixture test 2.x and pi already have.
- vllm/Containerfile: pin the base image by tag@digest, matching every
  other vLLM reference.
- Reword compaction-reserve comments that claimed 2.1.267 was pinned to
  say where the value was measured.

Signed-off-by: Nathan Weinberg <nweinber@redhat.com>
…y#1798)

Second of three changes automating pinned-client bumps. The GPU workflow's
`pins` job validated the manifests in ~270 lines of inline Python that only
ran on schedule, dispatch, or the vllm-full-suite label. Port it to a Rust
xtask so it runs locally, in `make lint` on every PR, and later inside
bump-pins.

- New light `pins` xtask feature (`dev` includes it) depends only on
  `toml`, so the `pins` job builds check-pins without compiling the proxy.
- Every Python invariant is ported: Claude context and compaction
  arithmetic, OpenCode major/lane tripwires, provider/backend window
  agreement, the 2.x and pi shared-backend rules, models.json agreement,
  and explicit example-config routes.
- New: a site table records every file location that embeds a client
  version or the vLLM image (manifests, harness constants, workflow env,
  dev-endpoint image, Containerfile) with an exact expected count. Checksum
  fixtures must exist, name the downloaded artifact, and have no stale
  sibling. Both [vllm] blocks must pin one tag@sha256 image.
- `--github-output` exports the same keys the job emitted; a unit test
  holds them to the job's `outputs:` map, and the values were diffed
  identical against the Python script.
- Unit tests mutate one real file in memory per invariant.

Signed-off-by: Nathan Weinberg <nweinber@redhat.com>
…axis-proxy#1798)

Third of three changes automating pinned-client bumps. Closes praxis-proxy#1798.

`cargo xtask bump-pins [--pin <pin>]... [--dry-run] [--report PATH]`
automates the mechanical half of a bump:

- Discovers the newest release per pin within each manifest's
  major_series: npm dist-tags for Claude Code and OpenCode 1.x/2.x
  (falling back to the newest in-series version when `latest` crosses
  the boundary), GitHub releases for pi, Codex, and vLLM, and the Docker
  Hub manifest-list digest for the vLLM image tag.
- Fetches checksums from the release's own metadata where upstream
  publishes one (Claude Code manifest.json, GitHub asset digests) and
  streams the OpenCode npm tarballs through sha256 otherwise, without
  buffering them.
- Stages every rewrite in memory through the same site table check-pins
  uses, with exact-count anchored replacement that fails on drift, swaps
  the checksum fixtures, and runs check-pins on the staged tree before
  writing anything.
- Never touches behavioral pins. The markdown report is a per-client
  re-validation checklist plus every remaining line that still names the
  old version.

The Bump Pins workflow runs it weekly (and on dispatch) and opens or
updates a draft PR from `bot/bump-pins` with the praxis-bot-app token,
using the report as the body. It never auto-merges, and it never
force-pushes over a bump PR that a person has committed to.

Signed-off-by: Nathan Weinberg <nweinber@redhat.com>
@nathan-weinberg
nathan-weinberg requested review from a team and didierofrivia October 26, 2026 18:08
@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: praxis-proxy/ai
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 3a3704c
  • Layers: Repository YAML (base), Central YAML (inherited)
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 6af75ffd-8190-412b-97c1-c3680f42242f
Commits

Reviewing files that changed from the base of the PR and between 3a3704c and 9167377.

Files ignored due to path filters: 1
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
Files selected for processing: 26
  • .github/workflows/bump-pins.yaml
  • .github/workflows/integration.yaml
  • .github/workflows/vllm-integration.yaml
  • Cargo.toml
  • Makefile
  • docs/developing/cli-vllm-through-praxis.md
  • tests/integration/fixtures/claude-code-cli/pin.toml
  • tests/integration/fixtures/codex-cli/pin.toml
  • tests/integration/tests/suite/claude_code.rs
  • tests/integration/tests/suite/claude_code_vllm.rs
  • tests/integration/tests/suite/codex_http.rs
  • tests/integration/tests/suite/codex_pin.rs
  • tests/integration/tests/suite/codex_websocket.rs
  • tests/integration/tests/suite/harness.rs
  • tests/integration/tests/suite/main.rs
  • tests/integration/tests/suite/opencode.rs
  • vllm/Containerfile
  • xtask/Cargo.toml
  • xtask/src/main.rs
  • xtask/src/pins.rs
  • xtask/src/pins/bump.rs
  • xtask/src/pins/check.rs
  • xtask/src/pins/manifest.rs
  • xtask/src/pins/sites.rs
  • xtask/src/pins/tests.rs
  • xtask/src/pins/upstream.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automate the pinned-client and vLLM version bumps

3 participants