Skip to content

Documentation

Tests and Graders

Configure fast review checks, landing checks, CI repair checks, coverage, and test insights.

Tests and Graders

Graders are repository-owned commands that Syrus runs to decide whether agent work is good enough to continue. Syrus does not rewrite the commands. Put parallelism, coverage, JSON/JUnit formatters, and CI-only behavior in wrapper scripts that live in the repository.

Phases

Each grader can declare the phases where it should run:

  • review: cheap checks before a human reviews the PR.
  • landing: checks that must pass immediately before merge.
  • ci: checks used when Syrus is repairing CI failures.

Example:

grade:
  - name: quick-ruby
    run: bin/rspec-focused
    phases: [review]
    junit_output: .syrus/grade-output/rspec-focused-junit.xml

  - name: rspec
    run: bin/rspec-fast
    phases: [landing]
    junit_output: .syrus/grade-output/rspec-junit.xml
    failures: allow_inherited

  - name: rspec-ci
    run: bin/rspec-ci
    phases: [ci]
    junit_output: .syrus/grade-output/rspec-ci-junit.xml
    failures: allow_inherited

The practical pattern is to keep review checks fast enough that iteration feels interactive, then run heavier checks at landing or during CI repair.

Required and Optional Checks

Graders are required by default. Optional graders still run and appear in the UI, but they do not fail the workflow by themselves.

grade:
  - name: lint-docs
    run: bin/lint-docs
    required: false

Use optional checks for early warning signals, not for correctness gates that must protect the branch.

Inherited Failures

Some projects allow a Job to pass when a grader failure is already present on the base revision and the Job did not introduce it. Set failures: allow_inherited for graders where Syrus can compare the branch result against known base results or structured test cases.

This works best for test runners that produce JUnit. Binary build checks can still benefit from inherited-failure policy, but they provide less detail than test-level results.

JUnit and Test Insights

When a grader writes JUnit output, Syrus ingests individual test cases. The repository Tests page groups repeated executions into durable test identities, so operators can find:

  • recently failing tests,
  • slow tests,
  • tests with changing outcomes,
  • test history with links back to specific runs.

Prefer stable test names and suites. If a test runner changes names on every run, Syrus cannot build a useful history.

Coverage

Coverage belongs in the repository's grader command. Syrus can read configured coverage artifacts, summarize deltas, and post a PR comment when requested, but the command itself should decide when coverage is collected.

For large suites, a common setup is:

  • no coverage for most review and repair iterations,
  • one coverage run for the final or landing path,
  • CI-only coverage checks for expensive policies.

File-Sensitive Graders

Use when_files_changed for expensive checks that only matter for certain paths:

grade:
  - name: website-build
    run: npm run build
    phases: [landing]
    when_files_changed:
      - "website/**/*"
      - "package.json"
      - "package-lock.json"

This keeps agents from burning time on unrelated checks while preserving the gate when relevant files change.

Good Wrapper Scripts

Good grader scripts are deterministic, reasonably quiet, and produce machine-readable output in a known location. For test suites, prefer a wrapper such as bin/rspec-fast or bin/rspec-ci over embedding a long formatter command directly in .syrus.yml.