From fa824a2f20c01b403a9fe7beaabad64acb828a41 Mon Sep 17 00:00:00 2001 From: Matthew Charles Busel Date: Fri, 25 Sep 2026 15:15:50 -0400 Subject: [PATCH 1/2] Release 4.2.0: binary release workflow, changelog, install docs - .github/workflows/release.yml builds Linux x86_64, macOS arm64/x86_64 and Windows x86_64 binaries on a vX.Y.Z tag and attaches them with SHA-256 checksums to a GitHub Release. No crates.io publish step. - CHANGELOG: 4.2.0 section covering the fixes since 4.1.2. - README install section points at the prebuilt binaries. - CONTRIBUTING: real commands (cargo test is what CI runs; clippy -D warnings is not enforced because the codebase has existing warnings), no-key demo, release steps. --- .github/workflows/release.yml | 103 ++++++++++++++++++++++++++++++++++ CHANGELOG.md | 39 ++++++++++++- CONTRIBUTING.md | 33 ++++++++--- README.md | 17 +++++- 4 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..698933b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,103 @@ +name: Release + +# Push a tag like v4.2.0 to build binaries for Linux, macOS and Windows and +# attach them to a GitHub Release. Publishing to crates.io stays manual. +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + workflow_dispatch: + inputs: + tag: + description: "Existing tag to (re)build, e.g. v4.2.0" + required: true + +permissions: + contents: write + +env: + CARGO_TERM_COLOR: always + TAG: ${{ github.event.inputs.tag || github.ref_name }} + +jobs: + build: + name: Build ${{ matrix.target }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + - os: macos-latest + target: aarch64-apple-darwin + - os: macos-latest + target: x86_64-apple-darwin + - os: windows-latest + target: x86_64-pc-windows-msvc + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ env.TAG }} + + - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + + - name: Build + run: cargo build --release --locked --target ${{ matrix.target }} + + - name: Package (Unix) + if: runner.os != 'Windows' + shell: bash + run: | + name="every-other-token-${TAG}-${{ matrix.target }}" + mkdir "$name" + cp "target/${{ matrix.target }}/release/every-other-token" README.md LICENSE "$name/" + tar czf "$name.tar.gz" "$name" + shasum -a 256 "$name.tar.gz" > "$name.tar.gz.sha256" + + - name: Package (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + $name = "every-other-token-$env:TAG-${{ matrix.target }}" + New-Item -ItemType Directory $name | Out-Null + Copy-Item "target/${{ matrix.target }}/release/every-other-token.exe", README.md, LICENSE $name + Compress-Archive -Path $name -DestinationPath "$name.zip" + $hash = (Get-FileHash "$name.zip" -Algorithm SHA256).Hash.ToLower() + "$hash $name.zip" | Out-File -Encoding ascii "$name.zip.sha256" + + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: | + every-other-token-*.tar.gz* + every-other-token-*.zip* + + release: + name: Publish GitHub Release + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + + - name: Create or update release + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + ls -l dist + if gh release view "$TAG" >/dev/null 2>&1; then + gh release upload "$TAG" dist/* --clobber + else + gh release create "$TAG" dist/* --title "every-other-token $TAG" \ + --notes "Prebuilt binaries are attached below. See CHANGELOG.md for what changed." + fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 4254de0..31f2869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [4.2.0] - 2026-09-25 + +First release since 4.1.2. It carries the library modules added since then +(divergence detection, logit lens, activation patching, circuit discovery, +Thompson-sampling bandit, checkpointing, SSE backpressure, batch research mode +and the many analysis modules added in rounds 3 to 32; see `git log v4.1.2..v4.2.0`), +plus the fixes below. + +### Added + +- `examples/mock_stream.rs`: `cargo run --example mock_stream` runs the real + interceptor against the mock provider (no API key) and prints a per-token + table of original and intercepted text, confidence and perplexity. +- `.github/workflows/release.yml`: pushing a `vX.Y.Z` tag builds binaries for + Linux x86_64, macOS arm64 and x86_64, and Windows x86_64 and attaches them, + with SHA-256 checksums, to a GitHub Release. crates.io publishing is manual. + +### Fixed + +- Mock provider no longer panics on prompts whose 20th byte falls inside a + multi-byte UTF-8 character. +- Mock provider in terminal mode counted every token twice, so the CLI + transformed every token instead of every other one. +- Terminal output now keeps the spaces between words (whitespace tokens were + dropped, so words ran together). +- `StanceClassifier` matched keywords as substrings, so "disagree" counted as + support; it now matches words. +- `NgramModel::generate` is reproducible for a given seed and no longer stops + early at a context with no observed continuation. +- `SimilarityEngine` uses smoothed IDF, so terms present in every document + (including any term of a one-document corpus) no longer get zero weight. +- Test suite compiles and passes again (stale `cli::Args` literals, doctests + referencing APIs that did not exist, wrong expectations in two tests). + +## Earlier unreleased notes (included in 4.2.0) + ### Added - Module-level `//!` doc comments on all previously undocumented public modules @@ -29,9 +65,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Async unit tests for `run_research_headless` using the Mock provider (no API key required): empty-prompt error path, multi-run accumulation, vocab diversity bounds, and citation string format. -- `.github/workflows/release.yml`: release workflow that triggers on `v*.*.*` - tags, builds release binaries for Linux (musl), macOS, and Windows, publishes - a GitHub Release with attached binaries, and publishes to crates.io. - `EotConfig` struct and all its fields now carry `///` doc comments explaining each configuration option and its valid range. - `make_test_interceptor` helper added to the `research_tests` module so diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54c0284..0654c2d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,11 @@ This project is primarily a research tool for token-level LLM analysis. Contribu ## What we want -- **New providers** — Mistral, Gemini, local Ollama with logprob support -- **New transforms** — semantically interesting token mutation strategies -- **Research features** — new metrics, export formats, comparison modes -- **Web UI improvements** — new visualization modes, better diff views -- **Bug fixes** — especially anything that breaks the token confidence pipeline +- **New providers**: Mistral, Gemini, local Ollama with logprob support +- **New transforms**: semantically interesting token mutation strategies +- **Research features**: new metrics, export formats, comparison modes +- **Web UI improvements**: new visualization modes, better diff views +- **Bug fixes**: especially anything that breaks the token confidence pipeline ## What we don't want @@ -18,10 +18,25 @@ This project is primarily a research tool for token-level LLM analysis. Contribu ## How to contribute -1. Fork and clone -2. `cargo test --all-features` — must pass -3. `cargo clippy -- -D warnings` — zero warnings -4. Open a PR with a clear description of the research motivation +1. Fork and clone. +2. Try it without an API key: `cargo run --example mock_stream`, or + `cargo run -- "hello" --provider mock --visual`. +3. `cargo test` must pass (this is what CI runs). If you touch a feature-gated + module, also run `cargo check --no-default-features --features self-improving` + (or the feature you changed). +4. `cargo clippy` should not report new warnings in the code you changed. The + codebase has existing warnings, so `-D warnings` is not enforced yet; + cleaning some up is a welcome first PR. +5. New behaviour needs a test; bug fixes need a regression test. +6. Open a PR with a clear description of what changed and why. + +Issues labelled [good first issue](https://github.com/Mattbusel/Every-Other-Token/labels/good%20first%20issue) are small, self-contained starting points. + +## Releases + +Maintainers bump `version` in `Cargo.toml`, add a `CHANGELOG.md` entry, merge, +then push a tag such as `v4.2.0`. `.github/workflows/release.yml` builds the +Linux, macOS and Windows binaries and attaches them to the GitHub Release. ## Research ideas diff --git a/README.md b/README.md index ecf0fcb..c271734 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,25 @@ You normally see a model's answer only as finished text. `every-other-token` sit ## Install +**Prebuilt binaries** (no Rust toolchain needed): download the archive for your platform from the [latest release](https://github.com/Mattbusel/Every-Other-Token/releases/latest). Builds are provided for Linux x86_64, macOS (Apple Silicon and Intel) and Windows x86_64. + +```bash +# Linux example; adjust the file name for your platform and version +curl -LO https://github.com/Mattbusel/Every-Other-Token/releases/download/v4.2.0/every-other-token-v4.2.0-x86_64-unknown-linux-gnu.tar.gz +tar xzf every-other-token-v4.2.0-x86_64-unknown-linux-gnu.tar.gz +./every-other-token-v4.2.0-x86_64-unknown-linux-gnu/every-other-token "hello" --provider mock +``` + +**With Cargo:** + ```bash -cargo install every-other-token # crates.io release (4.1.2) -# or the latest code (4.2.0) +cargo install every-other-token +# or the latest unreleased code cargo install --git https://github.com/Mattbusel/Every-Other-Token ``` +The Linux binary links the system OpenSSL (libssl3, present on Ubuntu 22.04+ and most current distros). + ## Unique capabilities vs. standard LLM clients | Capability | Standard clients | every-other-token | From 1c65106a6f3fdacc5c5364f12baadfa750cf8a7d Mon Sep 17 00:00:00 2001 From: Matthew Charles Busel Date: Fri, 25 Sep 2026 15:16:54 -0400 Subject: [PATCH 2/2] release.yml: build-only dry run on PRs that change it --- .github/workflows/release.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 698933b..adf4215 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,10 @@ on: push: tags: - "v[0-9]+.[0-9]+.[0-9]+" + # Build-only dry run when this workflow itself changes (nothing is released). + pull_request: + paths: + - ".github/workflows/release.yml" workflow_dispatch: inputs: tag: @@ -17,7 +21,7 @@ permissions: env: CARGO_TERM_COLOR: always - TAG: ${{ github.event.inputs.tag || github.ref_name }} + TAG: ${{ github.event_name == 'pull_request' && 'pr-test' || github.event.inputs.tag || github.ref_name }} jobs: build: @@ -38,7 +42,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ env.TAG }} + ref: ${{ github.event_name == 'pull_request' && github.sha || env.TAG }} - uses: dtolnay/rust-toolchain@stable with: @@ -82,6 +86,7 @@ jobs: release: name: Publish GitHub Release needs: build + if: github.event_name != 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4