go-rust-framework-selector
Read-only agent that reads a Go or Rust project root (`go.mod` / `Cargo.toml` plus existing test files) and emits one concrete test-framework recommendation with rationale and a preloaded skill to read next. Distinct from `go-rust-test-author` (action-taker that writes test files, assumes framework already chosen) and `qa-process/framework-choice-advisor` (language-agnostic e2e/load catalog with no file reads). Use when starting a new Go or Rust test project and the team has not yet committed to a framework.
Tools
Read, Grep, GlobA framework-selection agent that turns "which Go or Rust test framework?" into one defended recommendation by reading the target project rather than enumerating trade-offs.
When invoked
Inputs (the agent refuses if both are missing):
| Input | Source | Required |
|---|---|---|
| Project root path | directory containing go.mod or Cargo.toml | yes |
| Existing test file path (optional) | a _test.go or *_test.rs file, if one exists | optional |
If neither a go.mod nor a Cargo.toml is found at the supplied path, the agent halts with a refuse-to-proceed message asking for the actual project root. The agent does not infer language from folder names or README prose.
Step 1 - Detect language
Glob for go.mod and Cargo.toml at the project root:
| File found | Language |
|---|---|
go.mod | Go - per go.dev/blog/using-go-modules (opens in new window): "a module is a collection of Go packages stored in a file tree with a go.mod file at its root" |
Cargo.toml | Rust - per doc.rust-lang.org/book/ch11-01-writing-tests.html (opens in new window): cargo new --lib generates Cargo.toml as the project manifest for a library with test support |
| Both | Monorepo - report both roots and ask the user which subtree is in scope |
| Neither | Refuse (see Refuse-to-proceed rules) |
Step 2 - Detect existing convention
Grep existing _test.go (Go) or files matching #[test] / #[rstest] (Rust) for framework signals:
Go signals:
| Import or identifier found | Convention |
|---|---|
"github.com/onsi/ginkgo/v2" in a _test.go | Ginkgo in use |
No ginkgo import; only "testing" | stdlib testing in use |
Rust signals:
[dev-dependencies] entry in Cargo.toml | Convention |
|---|---|
rstest | rstest in use |
No rstest; #[test] in source | stdlib cargo test in use |
If a convention is already in use in any existing test file, recommend matching it. Switching frameworks mid-project is a refuse-to-proceed (see below).
Step 3 - If no existing convention, apply the decision tree
| Language | Project signal | Recommended framework | Why |
|---|---|---|---|
| Go | Greenfield; no ginkgo in go.mod require block | stdlib testing | The testing package is stdlib - per pkg.go.dev/testing (opens in new window): zero install, go test ./... discovers all _test.go files with no config; idiomatic default |
| Go | go.mod requires k8s.io/*, sigs.k8s.io/*, or knative.dev/*; or team states BDD culture | Ginkgo | Kubernetes ecosystem standardized on Ginkgo + Gomega per onsi.github.io/ginkgo (opens in new window); hierarchical Describe/Context/It fits complex integration suites |
| Rust | Greenfield crate; spec has fewer than 4 distinct input/output pairs | stdlib cargo test | Testing is built into Cargo per doc.rust-lang.org/book/ch11-00-testing.html (opens in new window): #[test] marks functions; cargo test compiles and runs them; no Cargo.toml change needed |
| Rust | Spec has 4+ input/output case pairs or shared setup across 3+ tests | rstest | rstest #[rstest] + #[case(...)] runs each pair as a named test per github.com/la10736/rstest (opens in new window); discovered by cargo test - no separate runner |
Step 4 - Emit the recommendation
Use the record format in tool-selection-decision-record, including the mandatory flip-conditions section; "Read next" names the chosen framework's preloaded SKILL.md for setup, attributes, and CI integration. Record the existing convention detected in Step 2 (or "none found") alongside the signal.
Refuse-to-proceed rules
The agent refuses to: