Expand description
Did the patch touch anything it had no business touching?
The sandbox answers “was the agent able to write that file”. This answers
a different and more useful question: “was that file in scope for this
task”. An agent asked to fix a parser, holding fs:write:/src/**, that also
edits /src/auth.rs has done nothing the sandbox forbids and something
nobody asked for.
§It reads the raw patch, never the condensate payload
A Condensate is lossy on purpose — the diff slicer (US-0704) drops
whole hunks to fit a token cap, and a file whose every hunk was dropped
keeps only a summary line. Scope-checking that would under-report the change
set, and under-reporting is the one error this checker must not make: it
would produce a Pass that says “nothing out of scope” about a patch it
only partly saw.
So this fetches Condensate::raw from the content store and parses the
complete original. That is exactly what raw exists for, and it is the
criterion “the check runs on the actual diff, not on the model’s description
of it” made structural rather than aspirational.
§The parser is strict, unlike the slicer’s
DiffSlicer::parse is deliberately tolerant: a patch with one header line
it does not recognise is still mostly a patch, and refusing to summarise a
build’s diff over it would be worse than ignoring the line. The trade goes
the other way here. A line this parser does not understand might be the one
introducing the file that should not have been touched, so an unrecognised
construct is Verdict::Inconclusive and
nothing commits.
Hunks are consumed by the line counts in their own @@ headers rather than
by scanning for the next header, so patch content that looks like a header
cannot end a hunk early and hide the files that follow.
§What counts as touching a file
Content edits, additions, deletions, both halves of a rename, and mode
changes. The last is easy to leave out and worth having: chmod +x on a
script in a deployment directory changes what runs, without changing a byte
of content.
§Which grant it checks against
The one the step was granted, handed to the checker when it is built —
never WorkOrder::requests, which is what the model asked for. A checker
that scoped a patch against the proposer’s own request would let the
proposer define the scope it is being held to, which is not a check.
Structs§
- Change
- One file a patch touched.
- Diff
Scope - Confirms that a patch only touched files the step was granted.
Enums§
- Change
Kind - What happened to a file.
- Patch
Error - The patch could not be understood, so no scope claim can be made about it.
Constants§
- MAX_
NAMED - How many offending paths are named before the rest are counted.
Functions§
- parse_
patch - Parse a unified diff into the set of files it touches.