Skip to content

Go support

Radforge supports mutation analysis for production Go files in go.mod modules and go.work workspaces.

Dimension Planning and diagnosis Hosted execution
Go version Go 1.25.x and Go 1.26.x Pinned Go 1.25.x or Go 1.26.x profile
Project root Root go.mod or go.work Same project shape from the uploaded Git-tracked snapshot
Platform Linux or macOS on amd64 or arm64 Linux on amd64
CGo Uses the active local CGO_ENABLED value for dependencies Runs with CGO_ENABLED=0
Test runner go test go test

Radforge supports generics and evaluates build constraints for the active GOOS, GOARCH, CGo setting, and build tags. Run rad doctor --language go to check the local toolchain, project root, active environment, and clean test baseline before planning.

Radforge does not provide a native Windows CLI. Use a supported Linux environment approved by your organization.

Run Go commands from the repository root. Go planning is available through rad file, rad plan, rad changed, and rad scope:

Terminal window
rad file internal/billing/entitlement.go
rad plan --target internal/billing/entitlement.go --json > plan.json
rad changed --since-ref origin/main
rad scope --scope-file mutation-scope.txt

Use rad file for one file, rad plan to inspect or save a one-file plan, rad changed for a Git diff, and rad scope for an explicit file list. See Choose a workflow for command and submission details.

One run cannot combine Go with another language. Split mixed-language changes into separate runs or pull requests.

Radforge mutates active production .go files. It does not mutate:

  • *_test.go files;
  • generated files whose leading comment matches Go’s generated-code convention;
  • files under vendor/;
  • assembly files;
  • a Go file that imports C;
  • files excluded by the active build constraints; or
  • source shapes for which Radforge cannot produce a compiler-valid byte edit.

Assembly and CGo can remain package dependencies when the active environment supports them. Hosted execution uses CGO_ENABLED=0, so CGo-only packages are outside the hosted support boundary.

Radforge emits an operator only when the replacement is valid for the parsed Go syntax and type context.

  • arithmetic-replacement exchanges addition and subtraction, exchanges multiplication and division, and changes remainder to multiplication.
  • comparison-boundary changes strict comparisons to inclusive comparisons and vice versa.
  • comparison-negation replaces a comparison with its logical opposite.
  • logical-inversion exchanges logical AND and logical OR while preserving Go’s short-circuit evaluation rules.
  • logical-not-removal removes a logical NOT when that change does not duplicate a comparison mutation.
  • increment-decrement-replacement exchanges increment and decrement statements.
  • unary-negative-inversion changes unary negative to unary positive.
  • boolean-literal exchanges true and false in value expressions.
  • numeric-literal-delta changes a valid integer or floating-point literal by plus one and minus one.
  • compound-assignment-inversion exchanges arithmetic compound assignments.
  • bitwise-inversion changes bitwise, shift, and matching compound-assignment operators.
  • break-continue-replacement exchanges break and continue only when the replacement targets the same compiler-valid loop.

Radforge replaces only the candidate’s byte span. It does not format or rewrite the surrounding file.

Radforge first runs the unmodified Go package to verify the baseline. Each mutation then runs in a fresh process with one active mutation. Go overlay files apply mutation content without writing it to the tracked .go file.

When coverage data proves that an anchored test selector is complete, Radforge can run that narrower test set. If selection is missing, incomplete, or unsafe, it runs the full mutated package. The full mutated package is the correctness fallback.

A first-pass timeout is retried once with a larger isolated timeout. A persistent timeout remains a timeout and is not counted as a killed mutation.

Go mutation entries use these outcomes:

  • killed: a selected test failed;
  • survived: every selected test passed;
  • no coverage: no test covered the candidate;
  • timeout: the mutation exceeded its execution deadline;
  • not viable: the mutation did not compile; or
  • infrastructure failure: the runner or execution environment failed.

Compiler-invalid, not-viable mutations do not enter the mutation-score denominator. Review survivors and coverage gaps as findings, then add or strengthen tests when the changed behavior matters.