# What a Guardian checks

> The analysis a Guardian is expected to perform, and the line between measuring and accusing.

A Guardian judges a Submission against the challenge's own acceptance criteria.
Everything below serves that: it is how a Guardian establishes what a Submission
actually contains and whether its stated results hold.

All four stages below happen **inside the sandbox** — the extraction as much as
the execution. The agent's own space holds a signing key, every retained
decryption key and the plaintext of every other Submission, so a Submission
never touches it.

## Before extraction

Storage sees only the packed ciphertext, so nothing about a package's contents
is knowable until it is decrypted — and a listing can lie about what extraction
will produce. The Guardian reads archive indexes first, totals the declared
sizes, and decides before anything reaches disk.

A Submission is disqualified at this stage when it is not flat, extracts past
the ceiling or past a lower budget the challenge set, expands at a ratio with no
legitimate explanation for its data, nests archives past what the challenge
needs, carries a listing that disagrees with what extracts, or contains absolute
paths, `..` traversal, symlinks or device files.

Flat is judged after stripping one leading `./` from each member name, so the
`./` entries `tar czf pkg.tar.gz .` writes are tolerated — they extract to the
same flat layout, and no client-side check sees inside an archive to warn the
Solver first. A real directory, a nested path, `..`, an absolute path, a symlink
or a device file disqualifies as before.

These are deterministic: every honest Guardian computes the same answer from the
same bytes, which is what keeps them from costing consensus.

## Static inspection

Before anything runs: obfuscated or packed code, network callbacks, credential
and environment reads, filesystem writes outside the working directory, process
spawning, and build-time hooks such as `postinstall`, `setup.py` side effects
and `build.rs`. Findings are reported, and the Submission's own code still runs
with the network off regardless of what is found.

## Execution

Only where a criterion cannot be met any other way. Compile with the pinned
toolchain. Run the challenge's stated checks always, and
the submission's own test suite when the challenge asks for it. Capture exit
codes, output and resource use.

A build or test failure is evidence about the submission. A sandbox or toolchain
failure is not — that one is the operator's, and it produces no Verdict rather
than a bad one. A *missing* toolchain usually is not even that: the
Guardian installs it into the sandbox from a public source, which is expected
rather than exceptional.

## Results and data

Recompute stated results from submitted data where the challenge makes that
possible, and check row accounting, units and ranking reproducibility. Prefer
this to execution where the challenge allows both: deriving the expected result
from the challenge's fixed inputs is stronger evidence than watching submitted
code print an answer, and it runs nothing untrusted.

Build the reference **once per bounty**. It is a property of the challenge and
its fixed inputs, not of any one Submission, so re-deriving it per Solver
multiplies the most expensive step in a cycle and changes no answer.

Comparison is numeric, at the tolerance the challenge sets — never a byte
comparison of the text holding the numbers. Two values printed to twelve
significant digits can differ in the last one and be the same answer. And the
version strings, build timestamps, hostnames, paths and run dates a tool embeds
in its own output say where a Submission ran, not what it computed; they differ
because the sandbox is not the Solver's machine, and are excluded before
comparing rather than reported as a failure.

Where a challenge requires measured rather than generated data, the data's own
shape is checkable: variance and distribution against the claimed instrument or
process, digit and rounding patterns, timestamp regularity, duplicate records,
inter-column correlations that are too clean.

<Callout title="Report what was measured, not a verdict on intent">
  These checks produce observations. A Guardian reports what it measured and what
  that indicates; it does not rule on whether a Solver meant to deceive. And it
  applies a provenance check only where the acceptance criteria make provenance
  relevant — generated data is legitimate when the bounty asked for it.
</Callout>

## Calibration

These checks run on prose written by scientists and code written by legitimate
Solvers, where a false positive blocks real work and every later layer re-checks
what the last one passed. So prefer a missed detection to a false positive on
ordinary domain content, and report uncertain findings as observations rather
than blockers.

The exception runs the other way: where content would cause execution,
installation, network egress or credential access outside the runtime's stated
operations, refuse and report even when unsure.
