Repository navigation
template: the verifier's diff shows every edited line, unsafe diffs are refused, and skipped tests count as regressions - #48
Merged
ArjunS07 merged 6 commits intoOct 8, 2026
Conversation
… base tree Before the agent-side run, pytest_runner.py puts test files the agent modified or deleted back to FC_BASE and removes test files it added. It writes the list to /logs/artifacts/test_edits.json (also under "test_edits" in test_results.json). Test selection still uses the changed source files, plus the restored test files. The base-side run no longer uses git stash. It copies every file that differs from FC_BASE (committed, uncommitted and untracked), checks out the FC_BASE versions, removes added files, runs, and copies the agent files and the git index back. It then compares file hashes with the state before the run. A mismatch or a failed patched rebuild sets regression.restore_ok to false and the runner exits 3.
… into fix/verifier-hardening # Conflicts: # tests/docker/test_pytest_runner_regression.py
… code, and count skipped tests as regressions The verifier's patch.diff uses --text --no-ext-diff --no-textconv with GIT_NO_REPLACE_OBJECTS, so a .gitattributes file in the agent's diff cannot hide edited benchmark lines from the tamper check; the collect command drops external diff drivers too. prepare.sh refuses a tree.diff that creates a symlink or adds *.pth, sitecustomize.py or usercustomize.py. A test that passes at base and is skipped, xfailed or not collected with the agent now counts as a regression.
…refused diffs, parse paths with -z Files under testing/ and _testing/ (numpy.testing, pandas._testing, xarray.testing) count as test code and are restored from base before pytest. The pytest sections of pyproject.toml, setup.cfg and tox.ini are put back to base while other settings stay, so addopts cannot load an agent plugin. parser.py records prepare.sh's tree_diff_refused or tree_diff_failed as patch.submission_rejected. The refusal check reads git apply --numstat -z, so a quoted non-ASCII path is matched.
…gin only the agent run loads is a regression Both pytest runs get -c with a copy of the base commit's pytest config file (pytest.ini, .pytest.ini, pyproject.toml, tox.ini or setup.cfg, in pytest's order) and --rootdir at the repo, so the agent's config files, dotted TOML keys and an added .pytest.ini are never read. The section editing of the previous commit is removed. Each run records its loaded plugins; one that only the agent run loads (a pytest11 entry point from the agent's package) adds plugin:<name> to regressed. prepare.sh also refuses dist-info and egg-info files in tree.diff.
Without the base config pytest may read the agent's config files, so a config_error adds config:unavailable to regressed.
ArjunS07
merged commit Oct 8, 2026
9bc8106
into
survey/phase1-template-shadow-conftest
0 of 3 checks passed
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.
Purpose
The audit of 2026-10-08 found three holes in the separate verifier (datasmith#45):
.gitattributesfile in the agent's diff can hide benchmark edits from the tamper check.This PR closes the three holes. It also counts a skipped or uncollected test as a regression.
Changes
fc_diffintest.shuses--text --no-ext-diff --no-textconvwithGIT_NO_REPLACE_OBJECTS=1. The collect command also uses--no-ext-diff --no-textconv.benchmarks/** -diffin the agent's.gitattributesdoes not turn a benchmark edit into "Binary files differ", so the tamper check sees the edited lines.patch.difffollowed the agent's.gitattributes.prepare.shrefuses atree.diffthat creates a symlink or adds*.pth,sitecustomize.pyorusercustomize.py. The verifier then uses the starting tree, so the trial has no patch, and it writesagent_tree.txt(tree_diff_refused) andtree_diff_refused.txt.git applyapplied such files.fix/restore-tests-before-pytest(ad45ffc):fc-baselinebefore the agent-side run, and the list is intest_edits.json.git stash. Afterwards it checks that the agent tree is back byte for byte.git stashmissed committed changes.testing/and_testing/(for examplenumpy/testing,pandas/_testing,xarray/testing) count as test code and are restored. Both pytest runs get-cwith a copy of the base commit's pytest config file, picked in pytest's order (pytest.ini,.pytest.ini,pyproject.toml,tox.ini,setup.cfg), and--rootdirat the repository. The agent's config edits are listed intest_edits.jsonasconfig_changed..pytest.ini, because pytest never reads the agent's config files. If the base config cannot be written, the check fails (config:unavailableinregressed).tests/,conftest.pyandpytest.iniwere restored.pytest11entry point from the agent's package metadata) addsplugin:<name>toregressed.prepare.shalso refuses*.dist-infoand*.egg-infofiles intree.diff.parser.pycopiesagent_tree.txtintoreward.jsonaspatch.submission_rejected. Such a trial already ends with the fail penalty, because the patch is empty andfailure_reasonreturnsno_patch. The new field gives the specific reason.pytest.skip()or breaks import cannot hide a failing test.Verification
pytest tests/docker/test_separate_verifier_tree.py tests/docker/test_pytest_runner_regression.py: 24 passed. New tests:.gitattributeswithbenchmarks/** -diff: the verifier'sfc_diffstill shows+def time_x(): return 0. With the old plaingit diffthe same test fails.evil.pthand a symlink is refused, and the verifier keeps the starting tree.pytest.skip(), and agent code that breaks import, each report the base-passing test as regressed.pkg/testing/helpers.pyis restored, and the broken change is reported as a regression.setup.cfg, an agentpyproject.tomlwith the dotted keypytest.ini_options.addopts, or an added.pytest.ini, is not read. Both tests fail without-c.pytest11entry point from adist-infofolder that the agent adds is reported asplugin:fcevil.tree.diffwith adist-infofile is refused.sitecustomize.pyunder a non-ASCII folder (é/) is refused. With the old parsing (without-z), the same test fails.pytest tests -k "template or adapter or parser or pytest_runner or separate or overrides": 120 passed.Notes
survey/phase1-template-shadow-conftest, which has template: run test.sh in Harbor's separate verifier, with the agent's tree diff as its only input #45. That template is not in use yet; all sessions switch together after the parity runs.__init__can change pytest hooks without any configuration. This is the same kind of hole as root in the verifier;