Skip to content

Declare the bench once and let everything read it - #388

Merged
HardMax71 merged 5 commits into
mainfrom
tools-single-source
Aug 12, 2026
Merged

HardMax71 merged 5 commits into
mainfrom
tools-single-source

Conversation

@HardMax71

@HardMax71 HardMax71 commented Aug 12, 2026 •

Copy link
Copy Markdown
Owner

Gate-tool versions lived in five places: the tools composite spelled every version three times over (cache key, prebuilt list, source list), the agent lanes and security.yml carried their own pins, and the ratchet hooks inlined the similarity version.

The workspace.metadata.tools tables in the root Cargo.toml are now the one authority, and cargo is the only thing that parses them. scripts/tools.sh serves the tables out of cargo metadata through jq (prebuilt list, source list, cache key, single version), the composite and both ratchet hooks call that one reader, and the cache key is a hash of the tables so it moves exactly when a tool does and dependency bumps cannot churn it. The three agent lanes and security.yml install through the composite, which gives the lanes the whole bench #383 asked for, with the lane prompts naming it. A documentation contract parses the manifest independently through the toml crate and holds a teeth test where the shell reader and that parser must agree on every tool; it also sweeps every workflow for a declared tool at another version, keeps the composite version-free, keeps the lanes on the composite, checks the prek floor, and pins the gh-aw dispatcher setup action to a sha, which caught the compiler regenerating the tag within the hour.

Platform-tests keeps its lone nextest install since compiling similarity-rs and cargo-fuzz on macOS and Windows buys nothing, and the sweep holds that pin to the declared version. Lane caches stay restore-only and hit the entries main CI saves under the same key. Bumping a tool is one edit in the manifest.

Summary by CodeRabbit

  • CI & Tooling

    • Centralized development and CI tool version management to keep checks consistent.
    • CI jobs now install the complete approved toolset automatically and reuse cached tools for faster runs.
    • Removed duplicated tool installation steps and hard-coded versions across automated workflows.
  • Documentation

    • Clarified how tool versions are managed and updated.
  • Tests

    • Added checks to detect inconsistent tool versions and workflow configurations before changes are merged.

Gate-tool versions lived in five places: the tools composite spelled
every version three times over, the agent lanes and security.yml carried
their own pins, and the ratchet hooks inlined the similarity version.
tools.toml at the root is now the one authority. The composite parses it
and keys its cache on the file's hash, the lanes and security.yml install
through the composite, the ratchet hooks read their pin out of it at run
time, and a documentation contract sweeps every workflow for a declared
tool spelled at another version. The same contract pins the gh-aw
dispatcher's setup action to a sha, which caught the compiler regenerating
the tag within the hour, and the lane prompts now name the whole bench.
Bumping a tool is one edit.
Copilot AI lite review requested due to automatic review settings August 12, 2026 18:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 33b999ef-0ecd-42c3-a0be-0614c30a1bcd

📥 Commits

Reviewing files that changed from the base of the PR and between 60418af and 594063a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • .github/actions/tools/action.yml
  • .github/workflows/agent-mention.lock.yml
  • .github/workflows/agent-mention.md
  • .github/workflows/agent-review.lock.yml
  • .github/workflows/agent-review.md
  • .github/workflows/agent-triage.lock.yml
  • .github/workflows/agent-triage.md
  • .github/workflows/ci.yml
  • .pre-commit-config.yaml
  • Cargo.toml
  • crates/amiss/Cargo.toml
  • crates/amiss/tests/documentation_contracts/tools.rs
  • docs/src/development.md
  • scripts/tools.sh
🚧 Files skipped from review as they are similar to previous changes (8)
  • docs/src/development.md
  • .pre-commit-config.yaml
  • .github/workflows/agent-triage.md
  • .github/workflows/agent-mention.md
  • .github/workflows/agent-review.lock.yml
  • .github/workflows/agent-triage.lock.yml
  • .github/workflows/agent-review.md
  • .github/workflows/agent-mention.lock.yml

📝 Walkthrough

Walkthrough

The change centralizes repository tool versions in workspace metadata. A shared script and composite action install those tools. CI, agent workflows, hooks, documentation, and contract tests now consume or validate the centralized configuration.

Changes

Tool governance and CI installation

Layer / File(s) Summary
Tool metadata and composite installation
Cargo.toml, crates/amiss/Cargo.toml, scripts/tools.sh, .github/actions/tools/action.yml
Workspace metadata defines tool versions. scripts/tools.sh exposes tool lists, versions, and cache keys. The composite action installs tools into the shared runner cache and updates PATH.
Workflow adoption of centralized tools
.github/workflows/ci.yml, .github/workflows/security.yml, .github/workflows/agent-*.md, .github/workflows/agent-*.lock.yml
CI resolves cargo-nextest from the shared metadata. Security and agent workflows use the local tools action. Generated workflow metadata reflects the replacement.
Hook and development documentation alignment
.pre-commit-config.yaml, docs/src/development.md
Similarity hooks obtain their expected version through scripts/tools.sh. Development documentation describes the centralized tool-version process.
Tool governance contract validation
crates/amiss/tests/documentation_contracts/main.rs, crates/amiss/tests/documentation_contracts/tools.rs
Documentation-contract tests validate metadata parsing, script output, workflow pins, composite caching, agent workflow usage, hook configuration, and dispatcher action pinning.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Workflow
  participant ToolsAction
  participant ToolsScript
  participant WorkspaceMetadata
  Workflow->>ToolsAction: invoke tools action
  ToolsAction->>ToolsScript: request tool lists and cache key
  ToolsScript->>WorkspaceMetadata: read declared versions
  ToolsScript-->>ToolsAction: return parsed metadata
  ToolsAction-->>Workflow: install tools and update PATH
Loading

Possibly related PRs

  • HardMax71/amiss#65: Introduced the similarity-rs tooling and ratchet hook now governed by centralized metadata.
  • HardMax71/amiss#368: Introduced the agent workflows now migrated to the shared tools action.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: centralizing the tool bench so workflows and scripts read it from one source.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tools-single-source

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actions/tools/action.yml:
- Around line 16-20: Change the cache step identified by id “cache” to use
actions/cache/restore so agent lanes only restore existing ~/.cargo-tools
entries. Add a separate actions/cache/save step after the successful tools
installation, guarded by github.ref == 'refs/heads/main', while preserving the
existing cache path and key.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ee719ec-23e7-4145-a8f7-71186e705ce7

📥 Commits

Reviewing files that changed from the base of the PR and between 79448e7 and 60418af.

📒 Files selected for processing (13)
  • .github/actions/tools/action.yml
  • .github/workflows/agent-mention.lock.yml
  • .github/workflows/agent-mention.md
  • .github/workflows/agent-review.lock.yml
  • .github/workflows/agent-review.md
  • .github/workflows/agent-triage.lock.yml
  • .github/workflows/agent-triage.md
  • .github/workflows/security.yml
  • .pre-commit-config.yaml
  • crates/amiss/tests/documentation_contracts/main.rs
  • crates/amiss/tests/documentation_contracts/tools.rs
  • docs/src/development.md
  • tools.toml

Comment thread .github/actions/tools/action.yml Outdated
The maintainer's call: the tool tables live under
workspace.metadata.tools in the root Cargo.toml rather than a separate
tools.toml. The composite extracts the two tables and keys its cache on
the hash of the extracted lists, so the key still moves exactly when a
tool does and dependency bumps cannot churn it. The ratchet hooks, the
contract test, the lane prompts, and the book follow the manifest.
The seds were three hand parsers for one TOML table and the review was
right to call them unreadable. scripts/tools.sh now serves the tables out
of cargo metadata through jq, the composite and both ratchet hooks call
that one reader, and the contract test parses the manifest independently
through the toml crate, with a teeth test making the two parsers agree on
every tool. The manifest comment shrank to a line and the composite keeps
only the constraint notes.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 8 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .github/actions/tools/action.yml
Comment thread scripts/tools.sh Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

The single-source refactor itself reads well, but the lane prompt now promises a full pinned bench that never reaches the agent container.

The lane claims the full pinned bench is installed, but this lane runs with none of it.

The composite installs the bench on the host runner under $HOME/.cargo-tools and appends that dir to the host job's PATH (action.yml#L41), while the agent runs inside the awf firewall container, which mounts the workspace and tool cache but not the host ~/.cargo-tools; the container's own /home/runner/.cargo-tools does not exist. Empirically, in this lane (the agent run on the PR head, which uses the new composite): none of prek, typos, cargo-nextest, cargo-deny, cargo-shear, cargo-llvm-cov, cargo-mutants, cargo-fuzz, similarity-rs, or zizmor is on PATH or on disk, and cargo nextest run --workspace --locked fails with error: no such command: nextest. The same claim sits in agent-mention.md (#L61). Every cold lane run also spends the composite's full bench install on the host, where the agent cannot see it.

Confidence: High.

Nit: "Bumping a tool is one edit" is not true for cargo-nextest, whose pin is still hardcoded in the platform-tests job.

The new paragraph promises single-edit bumps, but the platform-tests job keeps tool: cargo-nextest@0.9.140 (ci.yml#L173), and the new sweep test workflow_tool_pins_match_the_bench (tools.rs#L68) forces that pin to equal the manifest, so a nextest bump edits both files together. The doc should name the exception, or the platform-tests install should move onto the composite.

Confidence: High.

Session details

Run: 31631839210

Reviewed head fb13636: ran scripts/tools.sh prebuilt/source/key/version against the head tree, traced the sweep logic in crates/amiss/tests/documentation_contracts/tools.rs against every workflow, and probed the agent lane environment directly (command -v over the ten bench tools, cargo nextest run --workspace --locked).

Comment thread .github/workflows/agent-review.md
Comment thread docs/src/development.md
The review round proved the prompt lied: the composite installed onto the
host under HOME and exported the host PATH, while the agent runs inside
the awf container, which sees neither, so the lane held none of the bench
it named. The bench now lives under the runner tool cache, the one
directory the sandbox assembles onto its own PATH, and host jobs reach it
through the same GITHUB_PATH line. The reader captures cargo metadata
before piping, so a metadata failure kills the run instead of caching an
empty bench under a fixed key, jq -e refuses null tables, and the digest
falls back to shasum where sha256sum is absent. Platform-tests reads its
nextest pin through the reader, which makes the one-edit sentence true,
and the sweep learns that an expression version is a runtime read.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/tools.sh">

<violation number="1" location="scripts/tools.sh:21">
P2: Adding `-e` to this jq call breaks the unknown-tool guard. When a name isn't in the bench, `.metadata.tools | .prebuilt + .source | .[$name] // empty` produces no output and jq `-e` exits 4; under `set -e` the `result=$(...)` assignment aborts the script with rc 4 before the `[ -n "$result" ]` check runs, so the friendly `unknown tool: $2` message never prints and the error is silent. Drop `-e` (back to `-r`) so jq returns 0 on empty and the existing guard handles it.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/tools.sh Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

One defect: the version reader's unknown-tool guard is dead code and fails silently.

  1. scripts/tools.sh

Problem: jq -e in the version mode defeats the unknown-tool guard, so an unrecognized tool name aborts the script with a silent exit 4 instead of the intended diagnostic.

Explanation: under set -eu, the result=$(...) substitution propagates jq's exit 4 on an empty last value, so line 23's [ -n "$result" ] check and its unknown tool: $2 message are unreachable; the fail-closed -e is only right on the prebuilt/source/key modes. Verified against the head tree.

Confidence: High.

Evidence:

result=$(printf '%s' "$json" | jq -re --arg name "${2:?usage: tools.sh version <name>}" \

Session details

run — reviewed the head diff against 79448e7; ran cargo test -p amiss --test documentation_contracts tools:: --locked (6 passed) and a direct repro of scripts/tools.sh's version mode.

Comment thread scripts/tools.sh Outdated
Both reviewers reproduced it: jq -e exits 4 on the empty result the
version arm uses to detect an unknown name, and set -e killed the script
before the diagnostic printed. The version arm goes back to -r so the
guard answers, while the three table modes keep -e where a null table
must abort.
@HardMax71
HardMax71 merged commit 1d80ef3 into main Aug 12, 2026
32 of 33 checks passed
@HardMax71
HardMax71 deleted the tools-single-source branch August 12, 2026 20:13

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

One defect: the bench composite masks reader failures, so the run does not fail when scripts/tools.sh does.

The composite bench step swallows reader failures

Problem: The three printf lines wrap each scripts/tools.sh call in a command substitution, so a failing reader still leaves the step green with empty prebuilt/source/key outputs and a fixed degenerate cache key.

The step runs under the Actions default bash --noprofile --norc -eo pipefail. A failing command substitution does not fail the enclosing command: printf 'nextest=%s\n' "$(false)" exits 0 with nextest= written to $GITHUB_OUTPUT (reproduced). So a cargo metadata failure or missing jq makes tools.sh exit nonzero while the step succeeds, the cache key collapses to tools-ubuntu-, and install-action either errors with a misleading message or is skipped on a cache hit of the degenerate key — the "empty bench under a fixed key" that commit 16c70fc claims to prevent. Capturing each value in an assignment first (prebuilt="$(scripts/tools.sh prebuilt)") fails under -e when the substitution fails (verified rc 1), which is the fix. See

printf 'prebuilt=%s\n' "$(scripts/tools.sh prebuilt)"
printf 'source=%s\n' "$(scripts/tools.sh source)"
printf 'key=%s\n' "$(scripts/tools.sh key)"
.

Confidence: high.

Session details
  • run
  • Ran: cargo nextest run -p amiss --test documentation_contracts tools --locked (6/6), full documentation_contracts suite (31/31), scripts/tools.sh subcommand probes, and bash reproductions of the Actions default shell behavior.

Comment on lines +11 to +13
printf 'prebuilt=%s\n' "$(scripts/tools.sh prebuilt)"
printf 'source=%s\n' "$(scripts/tools.sh source)"
printf 'key=%s\n' "$(scripts/tools.sh key)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The three printf lines swallow a scripts/tools.sh failure, so a reader failure does not kill the run — it leaves the step green with empty outputs and a fixed degenerate cache key.

The step's shell is the Actions default bash --noprofile --norc -eo pipefail. A failing command substitution does not fail the enclosing command: I reproduced printf 'nextest=%s\n' "$(false)" under that exact shell and it exits 0 with nextest= in $GITHUB_OUTPUT. So when cargo metadata fails or jq is absent, tools.sh exits nonzero but the step still succeeds, emitting prebuilt=, source=, key=, and the cache key collapses to the fixed tools-ubuntu- string — the "empty bench under a fixed key" that commit 16c70fc says a metadata failure kills the run to avoid. The reader's diagnostic survives only as a stderr line inside a green step; downstream, install-action either errors with a misleading message or, on a cache hit of the degenerate key, is skipped entirely.

Fix: capture each value in an assignment before printing. Under -e, prebuilt="$(scripts/tools.sh prebuilt)" exits nonzero when the substitution fails (verified: bash -e -c 'x="$(false)"' → rc 1), so the step fails at the reader. The same pattern repeats at

run: printf 'nextest=%s\n' "$(sh scripts/tools.sh version cargo-nextest)" >> "$GITHUB_OUTPUT"
.

Confidence: high.

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.

2 participants