Skip to content

ward.toml

Configuration uses TOML version 1. Each gate is declared in [quality-gates.<id>] and must have a command:

version = 1
preset = "standard" # optional: standard or strict; informational
[quality-gates.tests]
enabled = true # default: true
command = "./mvnw test"
[quality-gates.integration]
command = ["./mvnw", "verify"]
profiles = ["ci", "strict"]

For Gradle projects, use the Gradle Wrapper when present (or gradle when it is not):

[quality-gates.tests]
enabled = true
command = "./gradlew test"

command accepts a string or an array of strings. Arrays preserve exact argument boundaries. A string is parsed into arguments. Neither form is executed through a shell.

Profiles:

  • Gates without profiles belong to default.
  • Init-generated configurations assign fast gates to both default and pre-commit, slower local gates to pre-push, and every selected gate to ci. pre-push is cumulative.
  • Select other profiles with ward check --profile ci,strict.
  • Legacy top-level [profiles] tables are unsupported.

Unknown gate IDs, and checks with no enabled matching gates, are errors.

The stryker and PIT mutation gates accept an optional minimum, an integer from 0 to 100. When it is set and the tool succeeds, Ward reads the tool’s report and fails the gate when the mutation score is below the minimum. See Stryker mutation score and PIT mutation score.

[quality-gates.stryker]
command = ["npx", "stryker", "run", "--reporters", "clear-text,progress,json"]
minimum = 60
profiles = ["ci"]

minimum on any other gate, or a value that is not an integer from 0 to 100, is a configuration error that names the key.

An optional [quality-gates.<id>.partial] table controls how a gate responds to an edited path passed to ward check --path:

KeyMeaning
inputsFiles the gate analyzes, as patterns relative to the project root. If an edited path matches, args can narrow the command.
configFiles that configure the gate, as patterns relative to the project root. If an edited path matches, the gate runs its normal command.
argsThe narrowed arguments. {paths} is replaced with the edited paths as separate process arguments, or as one value joined by separator.
itemHow each path is rendered: {path} (the root-relative path) by default, or "**/{name}" for the file name.
commandOptional. The base command a narrowed check runs, with args appended, instead of the gate’s command. Use it when the full command ends with a target that would still be analyzed, such as prettier --check ..
[quality-gates.checkstyle.partial]
inputs = ["src/**/*.java"]
config = ["config/checkstyle.xml", "pom.xml"]
args = ["-Dcheckstyle.includes={paths}"]
item = "**/{name}"
separator = ","
[quality-gates.semgrep.partial]
inputs = ["**"]
config = [".semgrep.yml", ".semgrepignore"]
args = ["{paths}"]
[quality-gates.prettier.partial]
inputs = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.mjs"]
config = [".prettierrc*", "package.json"]
args = ["{paths}"]
command = ["npx", "prettier", "--check"]

For example, a Maven Checkstyle edit of src/main/java/acme/Order.java receives -Dcheckstyle.includes=**/Order.java; a Semgrep edit receives the root-relative path as its own argument. A Prettier edit of src/app.ts runs npx prettier --check src/app.ts instead of npx prettier --check .. Other args entries are appended unchanged, and nothing passes through a shell.

  • A config match wins over an inputs match, and a gate without args runs in full when an edited path matches its inputs.
  • A deleted file counts as an edit of the gate, but is not passed in {paths}. When every relevant edit is a deletion, the gate runs in full.
  • Paths outside the project root are ignored. A gate without partial always runs in full.
  • args requires inputs, command requires args, every list must contain non-blank strings, and item must contain {path} or {name}. Otherwise ward check exits with code 2.

Verify custom arguments with the real tool: a path format the tool does not understand can analyze no files and pass. Only checks with --path read these tables.

Security: commands are trusted executable code and run with the current user’s privileges in the project root. Review ward.toml as carefully as a build script; do not run checks on untrusted repositories outside a sandbox. See security.

OpenSpec registrations are optional and independent. Use openspec for strict active validation and openspec-archived for completed-task validation. A configured local executable is resolved from the target project root and is never silently replaced by a PATH executable. An OpenSpec gate may set root, a path relative to the project root such as "../..", to run from the directory that holds openspec/; see OpenSpec tool validations.