Skip to main content
An artifact is a file that proves something about a change. It appears on the work item’s page and in the pull request’s evidence comment.

Emit an artifact

Capture the state first, then emit it:
Write the caption as one present-tense sentence with no secrets. The file’s extension sets its kind; you cannot set it yourself: Keep files small: video is the kind most likely to hit the size cap. The caps and every flag rule are in outerlayer emit artifact.

Where it lands

Inside a recorded session, the file is queued, and the next outerlayer sync uploads it with the session. A session not launched with OUTERLAYER_WORK refuses the emit, because nothing it produces may leave the machine. Outside a session, it uploads at once. It attaches to the first of these that exists:
  1. The pull request --pr names.
  2. In GitHub Actions, the pull request the run is for.
  3. The current git checkout.
With nothing to attach to, the command refuses. On other CI systems, pass --pr.

Bind it to a criterion

First record the item’s criteria with outerlayer emit criteria. Then pass one of their ids to --for, and the Criteria tab shows the artifact on that row:
The artifact’s kind must match the proof the criterion declares. A screenshot never satisfies a criterion that asks for a video.

Prove a criterion with test results

A criterion can declare "proof": "test". Bind JUnit XML results to it with --for. Vitest, Jest, pytest, Go (through gotestsum), JUnit and RSpec can all write that format.
Every test in the file is bound. To bind only some, name each one with --test. Add =<path>:<line> to say where a test is written:
The rules for --test, and for which XML files are accepted, are in outerlayer emit artifact. A test’s location comes from the testcase’s own file and line attributes first, then from --test. A test with neither shows by name, with no link. Vitest and jest-junit write file only with their addFileAttribute option. pytest writes it only under junit_family=xunit1. The criterion is proven when every bound test passed, at least one passed, and no test you named with --test was skipped. A failed or errored test leaves it unproven. A skipped test you did not name neither proves nor fails it. When you emit again after a fix, retire the old results with --replaces, or the old failure still counts. Results prove a criterion only at the head commit of a pull request linked to the item. In GitHub Actions, the command records the pull request’s head commit, not the merge commit the checkout holds. On other CI, check out the pull request’s head commit before you run the tests. Results from an earlier commit show as out of date on the Criteria tab and prove nothing until you emit again at the head. To require that results came from CI, set criteria.test_proof: ci in the policy file. On the Criteria tab, each bound test links to its file and line at the commit that ran it. A failed test is marked as failed.

Replace an earlier artifact

The command prints an id. Pass it to --replaces to correct that artifact:
A retired artifact that had uploaded is hidden as superseded, but keeps its file and link. One still queued never uploads. A failed emit retires nothing. To retire several at once, see --replaces.

Find the artifact afterwards

Once it uploads, the artifact appears on the work item’s page:
  • on its criterion’s row on Criteria, when it is bound to one;
  • beside the check that names it on Checks;
  • otherwise under Other artifacts on Checks.
Its link also appears in the pull request’s evidence comment, if there is one. Copy the link from either. The printed id is not part of the link.

Permissions

The caller needs Emit evidence. See API keys.