Context test: a run passes only having looked nowhere outside its export, and is judged in a tree of its own (#511)

Merged
DO
7d ago
+633-75

The two gaps in the context test's judge that Argon found reading #509 (The context's task is held by its sentence's sha256), which the Builder ruled real. Both close before #8's three runs.

1. A run that looked outside its export does not pass, and the answer is not there to look at. The agent's shell at the Maintainer's terminal has no sandbox (P-26).

  • passed now needs outside_reads == 0 and no unreadable command, and the pending test of #8 holds it for the newest three runs.
  • A read counts when it names a path outside the export through any of three routes: a tool's path input; an absolute path, ~, $HOME or .. in a command; or a glob's pattern. /dev/null and an absolute path inside the export don't count.
  • A run whose agent writes a command the record cannot read, such as PYTHONPATH=. python3 …, also fails, as ruled.
  • The runner refuses to start while HELD_OUT exists. Once the agent stops, it waits for the Maintainer to fetch the test from the private home and place it, so no copy of the answer is on the machine while the agent runs.
  • The runner also refuses to start unless CONTEXT_EVAL_AWAY names each place a clone of the private home was, and none of them exists. Its instructions say to move every clone out of reach first. The repo names no such place.
  • The residual, which record 0133 states: a shell with no sandbox cannot be shown not to have read something on the machine. The answer's absence and the count narrow that; they do not close it.

2. The judge runs in a tree of its own, with the export's mutation runner.

  • python3 -m tools.context_eval judge PRISTINE WORK JUDGE makes a fresh tree holding:
    • the export as made;
    • the agent's own text files under kernel/ and tests/, read without following a link, with any file it removed gone;
    • tools/mutants.py as the export made it, with each entry the agent added to a list MUTANTS is made of (ISSUE among them), in that list, and each entry it changed in place of the one of its name.
  • Everything else the agent changed is left out of that tree and recorded as put back, by where: a tools/mutants/ package, a root module that would shadow the standard library, a link, the Makefile. Nothing is written through anything the agent left.
  • An entry is data alone: constants; names the export's file binds; tuples and lists; strings joined; a star; the file's own helpers; a string's replace. Its target is never absolute or through ... An entry that is code, one the agent took out, or a change outside the lists is put back and recorded. Every entry of main's own file reads as data.
  • The mutation runner reads whether a named test exists in a process of its own (_missing_apart), so an agent's test module that patches the runner on import patches another process.

Tests and mutants.

  • The fixtures gain a clean stream for a run that may pass, beside the stream that names paths outside the export.
  • The record test holds the guard both ways, on reads, commands and globs.
  • test_the_judge_runs_the_exports_mutation_runner_with_the_agents_entries holds the merge: entries kept wherever they stand, and in either list; a runner edit; the file's own style; code; an unbound name; targets outside; an update by name; a deletion; no last comma before a comment.
  • test_the_judge_runs_in_a_tree_of_its_own holds the tree.
  • test_a_test_module_is_read_in_a_process_of_its_own holds the runner's name check.
  • The runner tests place the held-out test only at the prompt, and show the agent ran with no HELD_OUT. They also show a rigged runner beaten, a rigged runner with nothing to survive still killing, a run that looked outside failing, and the refusals.
  • Every mutant of these rules is killed.

Record. Record 0133 replaces 0129: when the held-out test is placed, how a run is judged and when it passes, and the residual. The other rows are restated. It follows 0130, 0131 and 0132, so the context check reports a gap until they merge. I'll bring this branch up to main then, and queue it only after asking the Builder.

Nothing here reads, names or guesses the held-out rule. Nothing in kernel/ is touched.

Closes #511

Reviews

Four reads at 1fc69eda, applied in 69b008d8 and 3b38af62:

ReadFindingsDisposition
Claude reviewmajor: outside reads through a command or a glob are not counted; major: a tools/mutants/ package or root module shadows the runner; major: an updated mutant is kept beside its original; major: an entry added to ISSUE is dropped; minor: entries in the file's own style are dropped; minor: a deleted mutant is not recorded; minor: the judge's unlink is untested; info: the docstring omits the judgeFixed, each with a test and a mutant; the outside-read gap as the Builder ruled (option a)
Security passmajor: the runner imports the agent's test modules in its own process, so a test can patch the verdict; and a new package under tools/ shadows a module the runner importsFixed: names are read in a process of their own; the judge's tree holds no file of the agent's outside kernel/ and tests/
Museblocking: commands read outside and the run passes; major: ISSUE entries dropped; major: a dropped or edited mutant restored silently; major: the judge writes through a linked tools/Fixed as above; the judge never writes in the agent's tree
Argon (gemini-4-argon-high), 11 findingsblocking: writes through a linked tools/; major: entries naming a target outside or an unbound name; major (two): ISSUE entries dropped; major: a deleted entry kept silently; major: a shadowing package; minor: no test of a deleted entry; minor: no runner case with an unclean stream; minor: the rigged case only with a survivor; minor: byte against character offsets; minor: a comma placed inside a commentFixed: names held to what the export binds and targets inside the tree; offsets in bytes; the comma placed after the last entry; runner cases for an unclean stream and a rigged runner with nothing to survive

šŸ¤– Generated with Claude Code