cross-check.yaml

Configure CrossCheck for a repo by committing cross-check.yaml (or .yml) at the repo root. The file can declare additional checks and override a subset of repo settings normally edited from the dashboard.

When the file is present, the dashboard locks the fields it manages and shows a banner linking back to the file on GitHub.

Minimal example

version: 1
checks:
  - name: new-tables-have-tests
    description: Every new SQL model under models/ has a matching test under tests/.

That's it. The check runs on every PR alongside whatever check groups you've attached in the dashboard.

Full example

version: 1

config:
  pass_behavior: approve_and_merge        # auto-merge when all checks pass
  general_review:
    mode: enabled
    required_for_approve: true
  instructions: |
    This is a Python service. Prefer asyncio idioms over threads.
  enabled_tools:
    - read_file
    - list_dir
    - glob
    - grep
    - read_diff
    - bash

checks:
  - name: no-print-in-prod
    description: |
      Production code under src/ must not contain print() statements.
      Use the logger from src/observability/logger.py instead.
    severity: high
    tier_hint: deep

  - name: migrations-have-down
    description: Every Alembic migration in alembic/versions/ has a non-trivial downgrade() body.
    severity: medium

Schema

Top level

FieldRequiredTypeNotes
versionyesinteger (1)Schema version. Only 1 is supported today.
confignoobjectSparse settings overrides. Omit fields to keep dashboard values.
checksnolist of checkRepo-local checks. Run alongside attached groups.

config

Every field is optional. A field present in the file overrides the dashboard value; a field omitted falls back to the dashboard.

FieldTypeDefault
pass_behaviorreport_only | approve | approve_and_mergereport_only
fail_behaviorreport_only | configurable_block | always_blockreport_only
report_modecomment_summary | comment_only | summary_onlycomment_summary
general_review.modeoff | enabledoff
general_review.required_for_approvebooleanfalse
general_review.prompt_overridestring (null/omit = built-in prompt)null
instructionsstringempty
enabled_toolslist of built-in tool names (see tools)dashboard default

checks

Each check is one natural-language assertion the reviewer agent evaluates per PR.

FieldRequiredTypeDefault
nameyesstring (unique within file, ≤240 chars)
descriptionyesstring (non-empty — write it like a code review note)
severitynolow | medium | highmedium
tier_hintnoauto | triage_only | deepauto

Enabled tools

If enabled_tools is set, it must be a subset of:

read_file, list_dir, glob, grep, read_diff, bash, write_file, apply_patch

Custom tools you've added in the dashboard cannot be enabled from the file (they may not exist when the file lands in a branch).

How statements are merged with dashboard groups

YAML checks run alongside dashboard-attached check groups. They never replace them. The PR comment lists them in a cross-check.yaml section, separate from your check groups.

This is intentional: if your org admin attaches a baseline "security" check group to every repo, a PR author can't drop those checks by adding a cross-check.yaml.

Where each part is read from

PartSourceWhy
checks:PR head commitLets a PR introduce a check alongside the change it guards.
config:Default branch HEADPrevents self-approval — a PR can't flip pass_behavior: approve_and_merge on itself.

Concretely: if you edit config.pass_behavior in a PR, the change does not take effect for that PR. It takes effect after the PR merges to your default branch.

When the dashboard re-reads the file

The dashboard's cached view of cross-check.yaml is refreshed:

  • Automatically, on the next push to your default branch that touches the file.
  • Manually, via the Refresh from GitHub button on the repo settings page.
  • On checks-page load, if the cache is older than 5 minutes.

Errors

If cross-check.yaml is malformed:

  • The PR review still runs, using your dashboard settings (the file is ignored for that run).
  • A single comment is posted on the PR with the parse error. The same error won't re-post on subsequent pushes — fix it and the next push gets the file applied.
  • A banner appears on the repo's Settings and Checks pages showing the error.

Common errors:

ErrorFix
unsupported version: NSet version: 1. Future versions will be documented here.
<field>: extra inputs are not permittedYou have a typo or unsupported key. Check the schema above.
<field>: input should be 'auto', 'manual' (etc.)Enum value isn't valid. Use one of the listed options.
enabled_tools contains unknown tool(s): XX isn't a built-in tool. See Enabled tools.
duplicate check name: 'X'Two checks[].name are the same. Rename one.
cross-check.yaml is larger than the 64 KB capSplit long description text or move it out of the file.

Limits

  • File size: 64 KB (after which the file is rejected with a parse error).
  • The file must be at the repo root, named exactly cross-check.yaml or cross-check.yml. Subdirectories are not searched.
  • cross-check.yaml wins over cross-check.yml if both exist.

YAML pitfalls

The file is parsed with YAML safe-load (no Python tag execution). A few things to watch:

  • Use block scalars (|) for multi-line descriptions. Plain folded strings collapse newlines into spaces.
  • Quote values that look like booleans. name: on is interpreted as name: true in YAML 1.1 dialects — write name: "on".
  • Use 2-space indentation. Tabs are not valid YAML.