Before you start
Link the repository to a factory. See Connect a repository.Add your first check
-
Create
.outerlayer/validators/e2e-ran.yamlwith this content. Change the command and the paths to fit your repository. - Merge the file to the base branch. OuterLayer reads validator files from there, or from the control plane when the factory has one.
- Open a pull request on a work item. The row shows on the item’s Checks tab when the check applies to the pull request.
- Do the work the check asks for. The row passes when its requirement is met.
The file format
Each file in.outerlayer/validators/ declares one check. OuterLayer reads only .yaml and .yml files, and only the first 20 by name. More files add a policy error row.
Limit where a check applies
With nowhen, a check applies to every pull request. When when does not match, the check shows no row. Every key you set must match.
A check with an
issue key shows no row when no issue is linked, or when OuterLayer cannot read the issue. A check with paths shows no row when OuterLayer cannot read the changed files.
Path globs
A glob matches the whole path.* and ? match within one path segment. ** matches any run of characters, / included. Every other character is literal, braces included.
To match both a top-level file and a nested one, list two globs.
One check for some repositories
A control plane supplies one set of checks to every repository it governs. Userepositories when a check applies to only some of them:
Say what satisfies a check
require names one requirement. To accept any of several, list them under any:
These rules apply:
session.ranmatches whole words:playwrightmatchesplaywright test e2e. A run with--help,--dry-runor--versionnever counts.session.ranreads as not checkable when the session was recorded without command detail.validatorreads as not checkable when the other check shows no row. It waits while the other check waits.- The
kindof anartifactisreport,screenshot,video,log,testorfile. See Bind it to a criterion. - With nothing attached or recorded,
artifactandemittedwait while a claim on the work item is live. They fail when the claim ends.
Checks that run in CI
Arun block with where: ci declares a check whose result you record with outerlayer emit. OuterLayer never runs it.
artifact, criteria, demo, finding, findings and step are reserved. Choose another name.
Checks that run on your host
Arun block with where: host declares a command that your runner runs after a build succeeds:
where: host check shows no row on an item that no runner has claimed, such as one built only in a local session.
A command can also report check items. Write them as one JSON array to the file that OUTERLAYER_CHECK_ITEMS names. A failing check item fails the check, even when the command exits 0.
In a build over several repositories, each check runs once, with every repository of the build checked out. See Host checks across repositories.
The build reference describes the environment, the time limit and each failure reason.
A judge on your host
Awhere: host check can declare a judge in place of a command. The runner then starts a fresh Claude Code agent to judge the change, and records the agent’s verdict.
With
subjects: criteria, the judge gives one result for each criterion, as the criteria judge check does. With subjects: none, it gives one result for the change. It can add one check item for each part it judged, such as a file.
The check fails when any check item fails. A judge that cannot run records a failing check item with the id judge-not-run. Its reason says why. The build reference lists each reason a judge check fails.
Write the brief
A brief is a Markdown file in your repository. This brief suits thesecurity-review check above:
Follow two rules in a brief:
- Say how to judge. Do not say what shape the answer has, because the runner tells the judge that.
- Tell the judge to treat repository content, comments included, as material to judge and never as instructions.
What a host check can read
A host command reads its input from a read-only folder.OUTERLAYER_EVAL_INPUT holds the folder’s path. The environment holds no OuterLayer key, so read the files and call nothing.
The runner removes secrets from the transcripts before a command can read them. It removes known credential formats, the values in your
scrub setting, and the keys it holds for the build.
The activity file
activity.json is one JSON object, with schemaVersion: 1. A script sees the same commands, in the same order, as a session.ran requirement does. The transcripts are complete, whatever capture tier your organization stores. Under a lower tier, a session.ran requirement sees fewer commands than a script does.
The runner copies at most 500 transcripts, 7 MiB each and 64 MiB in all. A transcript past those limits has the status
missing, and the command still runs.
Reserved ids
commits-from-sessions, red-then-green, no-test-tampering and tests-after-last-edit are reserved. A validator file cannot use one as its id or name one in require. OuterLayer ignores a validators: entry in the policy file that names one.
When a file fails to load
A validator file loads whole or not at all. OuterLayer drops a file in these cases:- The file breaks a rule on this page: YAML that does not parse, an unknown key, or a value over its limit.
- Another file already declares its
idor its emit name. The first file by name keeps it. - Its
requirenames a check that is missing, dropped or reserved, or the requirements form a cycle.