WIP: Pin the Rust toolchain and make CI report its resolved versions #537

Draft
toasterson wants to merge 6 commits from claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor into main
Owner

Anima work item 019fe0e9-92d6-7232-9fea-479211e19a14.

Supersedes WI-352/PR #385. Implement the small current-main delta: add rust-toolchain.toml pinning the channel plus rustfmt/clippy components to the version baked into the Solstice Rust image; make a bump an explicit reviewable change; decide and enforce fmt as a real gate alongside clippy; and print rustc, cargo, clippy, and rustfmt versions in each native CI verdict. Acceptance: local and CI fmt/clippy results match for one commit and an image rebuild cannot silently change the lint gate.

Anima work item `019fe0e9-92d6-7232-9fea-479211e19a14`. Supersedes WI-352/PR #385. Implement the small current-main delta: add `rust-toolchain.toml` pinning the channel plus rustfmt/clippy components to the version baked into the Solstice Rust image; make a bump an explicit reviewable change; decide and enforce fmt as a real gate alongside clippy; and print rustc, cargo, clippy, and rustfmt versions in each native CI verdict. Acceptance: local and CI fmt/clippy results match for one commit and an image rebuild cannot silently change the lint gate.
The previous commit enforced `cargo fmt --all -- --check` in CI, but
vendor/solstice-ci (a path dep of anima-solstice) was not formatted with
the pinned rustfmt version. This caused the CI fmt gate to fail.

Fix by updating scripts/fetch-solstice-common.sh to run `cargo fmt --all`
on the vendored code after checkout. This ensures the vendor dir is always
formatted consistently with Anima's pinned rust-toolchain.toml, so rustfmt
version drift between solstice upstream and Anima cannot break CI.

Acceptance: `cargo fmt --all -- --check` passes locally and in CI.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The previous commit used "1.97.1" which is not a valid channel format in
rust-toolchain.toml. Rust channels should use "1.XX" format (e.g., "1.97"),
not "1.XX.Y". When rustup encounters an invalid channel format, it fails to
install the toolchain, causing CI to fail with exit_code=1.

Additionally, removed the unnecessary `command -v rustfmt` check in
fetch-solstice-common.sh since formatting is done via `cargo fmt`, not the
`rustfmt` binary directly. This simplifies the conditional check.

Acceptance: rustup successfully installs the 1.97 toolchain, and CI passes
with the pinned toolchain components (rustfmt + clippy) working correctly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
toasterson force-pushed claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor from f65846bc3f to b8d9a234b0 2026-08-10 16:33:39 +00:00 Compare
toasterson force-pushed claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor from b8d9a234b0 to deee5e6749 2026-08-10 16:58:27 +00:00 Compare
toasterson force-pushed claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor from deee5e6749 to 3525ab9d79 2026-08-10 20:57:36 +00:00 Compare
toasterson force-pushed claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor from 3525ab9d79 to 264dac35ce
Some checks failed
CI / docker (pull_request) Has been skipped
CI / test (pull_request) Failing after 2h4m33s
CI / conflict-check (pull_request) Failing after 2h4m39s
2026-08-20 20:14:10 +00:00
Compare
WI-498 turns `cargo clippy --workspace -- -D warnings` into a real gate.
That makes a pre-existing, undocumented coupling load-bearing for the first
time, and it is genuinely surprising:

`vendor/solstice-ci/crates/common` is a `path` dependency. Cargo applies
`--cap-lints=allow` automatically to registry and git dependencies but NOT
to path deps -- it treats them as local, primary packages. So `-D warnings`
lints upstream solstice-ci code as if Anima had written it, and pristine
upstream currently trips 7 clippy lints (skip_while_next, 2x collapsible_if,
3x useless_conversion, drop_non_drop).

scripts/fetch-solstice-common.sh already caps this by injecting
`#![allow(clippy::all)]` after checkout, and job.sh runs that script (line
119) well before clippy (line 191), so the gate is green in CI. Two fixes
so it stays green and stops misleading readers:

1. Broaden the cap to `#![allow(warnings)]` as well. `clippy::all` covers
   only clippy lints; `-D warnings` also denies rustc's warn-by-default
   lints, so a SOLSTICE_COMMON_REV bump that added e.g. an unused import
   upstream would redden Anima's CI on code Anima does not own.

2. Comment the coupling at the gate site in .solstice/job.sh. Running the
   clippy line by hand against a pristine vendor checkout fails with
   upstream errors; that looks like a broken branch and is not. The fix
   belongs where the confusion happens.

Why the injection and not a cleaner-looking alternative -- both were tested
against a pristine vendor and both still lint `common`, so both are dead
ends:
  cargo clippy --workspace --no-deps -- -D warnings      -> 7 errors
  cargo clippy -p <each of the 11 members> -- -D warnings -> 7 errors
Cargo offers no package-level lint exclusion for path deps; capping in the
crate source is the mechanism that works. The cap applies ONLY to the
vendored crate -- Anima's crates/* are never capped.

Verified with the pinned toolchain (1.97), vendor reset to pristine and
re-fetched via the script first, exactly as CI does:
  cargo clippy --workspace --exclude anima-desktop -- -D warnings -> 0
  cargo fmt --all -- --check                                      -> 0
  cargo check --workspace --exclude anima-desktop --tests          -> 0
Gate proven still real: a deliberate `ptr_arg` probe added to
crates/anima-solstice/src/logs.rs failed the gate (exit 101) and was
reverted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This pull request has changes conflicting with the target branch.
  • .solstice/job.sh
  • crates/anima-core/src/domain/next_action.rs
  • crates/anima-core/src/domain/progress_witness.rs
  • crates/anima-core/src/telemetry.rs
  • crates/anima-db/src/repo/mod.rs
  • crates/anima-db/src/repo/scheduling_clock.rs
  • crates/anima-db/src/repo/workflow.rs
  • crates/anima-db/src/repo/workitem_attempt_witness.rs
  • crates/anima-db/src/repo/workitem_dependency.rs
  • crates/anima-db/src/repo/workitem_phase_history.rs
  • crates/anima-db/tests/pinned_exit_bar_state.rs
  • crates/anima-db/tests/workitem_dependency_integration.rs
  • crates/anima-mq/examples/publish_dispatch.rs
  • crates/anima-mq/src/consumer.rs
  • crates/anima-mq/src/payload.rs
  • crates/anima-mq/src/publisher.rs
  • crates/anima-mq/tests/integration_test.rs
  • crates/anima-proto/src/envelope.rs
  • crates/anima-runner/src/attach.rs
  • crates/anima-runner/src/git.rs
  • crates/anima-runner/src/janitor.rs
  • crates/anima-runner/src/quota.rs
  • crates/anima-runner/src/slot.rs
  • crates/anima-runner/src/test_gate.rs
  • crates/anima-runner/src/vcs.rs
  • crates/anima-server/src/execution_fabric.rs
  • crates/anima-server/src/health.rs
  • crates/anima-server/src/lane_circuit_breaker.rs
  • crates/anima-server/src/mcp/handlers.rs
  • crates/anima-server/src/mcp/server.rs
  • crates/anima-server/src/scheduler.rs
  • crates/anima-server/src/services/agent.rs
  • crates/anima-server/src/services/dashboard.rs
  • crates/anima-server/src/services/plan.rs
  • crates/anima-server/src/services/pr_resync.rs
  • crates/anima-server/src/services/runner.rs
  • crates/anima-server/src/services/workflow.rs
  • crates/anima-server/src/services/workitem.rs
  • crates/anima-server/src/solstice.rs
  • crates/anima-server/tests/ai_gate_bypass_test.rs
  • crates/anima-server/tests/ai_gate_reject_handoff_test.rs
  • crates/anima-server/tests/burst_over_assignment_test.rs
  • crates/anima-server/tests/ci_failure_classification_test.rs
  • crates/anima-server/tests/ci_green_commit_binding_test.rs
  • crates/anima-server/tests/dispatch_rejection_test.rs
  • crates/anima-server/tests/document_deliverable_test.rs
  • crates/anima-server/tests/exit_bar_advancement_test.rs
  • crates/anima-server/tests/orphaned_ci_dispatch_test.rs
  • crates/anima-server/tests/park_race_test.rs
  • crates/anima-server/tests/scheduling_clock_test.rs
  • crates/anima-server/tests/session_leak_test.rs
  • crates/anima-server/tests/session_rebind_test.rs
  • crates/anima-server/tests/stale_gate_test.rs
  • crates/anima-server/tests/testing_ci_dispatch_test.rs
  • crates/anima-server/tests/turn_failure_test.rs
  • crates/anima-server/tests/workitem_dependency_test.rs
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor:claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git rebase main
git switch main
git merge --ff-only claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git rebase main
git switch main
git merge --no-ff claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch main
git merge --squash claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch main
git merge --ff-only claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git switch main
git merge claude/wi-019fe0e9-pin-the-rust-toolchain-and-make-ci-repor
git push origin main
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
toasterson/Anima!537
No description provided.