Catch a reworded capability denial in the isolation prompt - #9
Merged
Conversation
The runner system prompt said "You cannot run commands or read files in this conversation." The `agent-owned-edit` case says "you have access to the repository." Both conditions denied the premise, and all 6 responses drew a blocking finding: 6 of run 002's 21 blockers, spent on a case neither condition could pass. Run 001 lost the same case to an earlier wording, "You have no tools, no files, no repository, and no workspace." The guard was a list of five literal substrings: "no tools", "no files", "no repository", "no workspace", "have no". The second wording used none of them. It passed the guard and reached a $11.47 run. A literal list only catches the sentence somebody already wrote. The prompt now grants what a case grants: Accept the premises the message states, including any capability it grants you, and answer from the message alone. It still forbids inspecting the environment, so the isolation the prompt exists for holds. The guard now matches a negation joined to a capability noun inside one sentence. It rejects the wording this repository shipped through run 002, on the substring "cannot run commands". Two tests back it: one asserts the pattern catches all six wordings known to contaminate a run, one asserts `agent-owned-edit` still grants the capability the guard protects. Without the second, the case could stop granting it and the guard would pass while protecting nothing. CLAUDE.md gains what run 002 cost to learn: freeze before you commit, never commit the five loose result files, pass one --note per finding, never edit a frozen run to match a later one, and report the share of the delta rather than the delta alone. AGENTS.md is the generated mirror. This edit changes the runner config hash, so no run after it compares against run 001 or run 002. Run 002 is frozen, so that history survives. Gates: sync_style --check, check_configs, validate, 75 tests, all pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the contamination run 002 found, and replaces the guard that let it through.
What broke
The runner system prompt in
evals/runners.example.jsonsaid:The
agent-owned-editcase says:Both conditions denied the premise. All 6 responses drew a blocking finding — 6 of run 002's 21 blockers, spent on a case neither condition could pass. Run 001 lost the same case to an earlier wording, "You have no tools, no files, no repository, and no workspace."
Why the guard missed it
tests/test_run_evals.pychecked five literal substrings:The second wording used none of them. It passed the guard, shipped, and reached a $11.47 run. A literal list only catches the sentence somebody already wrote.
The fix
The prompt now grants what a case grants, and still forbids inspecting the environment:
The guard matches a negation joined to a capability noun inside one sentence. Against the prompt this repository shipped through run 002:
Two tests back it:
test_the_guard_catches_every_wording_that_cost_a_runasserts the pattern catches all six wordings inCONTAMINATED_WORDINGS, including both that contaminated a real run.test_the_case_that_exposed_this_still_asserts_a_capabilityassertsagent-owned-editstill grants repository access. Without it, the case could stop granting the capability and the guard would pass while protecting nothing.CLAUDE.md
Two new sections carry what run 002 cost to learn, mirrored to
AGENTS.mdbyscripts/sync_style.py.Filing a finished run.
evals/results/holdsLEDGER.mdandruns/, nothing else — the five pipeline files are working state, not the committed form. Freeze, then commitruns/<id>-<slug>/and the rebuiltLEDGER.mdtogether. Pass one--noteper finding, because a finding left in a PR comment dies when the branch merges. Never edit a frozen run to match what a later run found. Report the share of the delta, not just the delta.That third rule has a live example. Run 001 carries a note saying run 002 reworded the isolation prompt. Run 002 reworded nothing — this PR does. The note stays wrong, because correcting it would rewrite finished history.
The isolation prompt. What it must do, why the literal list failed, and that editing it moves the runner config hash.
Cost of this change
This edit changes the runner config hash, so no run after it compares against run 001 or run 002. Both are frozen, so that history survives. The next run starts a new comparability key, and
agent-owned-editbecomes scoreable for the first time — expect its blocker count to drop and its 1.98/2.47 scores to move.Gates