Add proof-from-scratch evaluator contract - #71
Conversation
884ce5b to
d4a3905
Compare
|
@sukanya1426 Can you also review this PR when you get a chance? Since #80 depends on it, we should make sure both PRs stay in sync. |
|
Sure. |
| context_paths.append(context_path) | ||
|
|
||
| resolved_paths = tuple(context_paths) | ||
| _validate_module_files(task_key, ((task_key, task_path), *context_entries)) |
There was a problem hiding this comment.
The validator checks paths, symlinks, duplicate basenames, and module names, but it never verifies that the context covers the task's full EXTENDS/INSTANCE closure. I tested this by removing a context module, and the run ended up as [SANY-INVALID] / GATES-FAILED: A, identity, so a generator bug gets scored as agent tampering. Since the manifest is now the only source of context, it should validate the closure here and raise ManifestError instead.
|
|
||
| resolved_paths = tuple(context_paths) | ||
| _validate_module_files(task_key, ((task_key, task_path), *context_entries)) | ||
| boundaries[task_key] = TaskBoundary( |
There was a problem hiding this comment.
Another small improvement: call parse_editable_regions while loading tasks. Missing markers currently slip through loading and only surface as an exit-3 ERROR during grading. Better to catch them early.
| if not cut_short: | ||
| grading_canonical_dir = run.canonical_dir | ||
| if getattr(mode, "canonical_replay_required", False): | ||
| grading_canonical_dir = _make_canonical_dir( |
There was a problem hiding this comment.
This snapshot is taken after the agent finishes and reads from item.benchmark_path in the repo. In --no-container mode the agent has host write access, so it can edit the source and the "fresh" snapshot picks up the tampered bytes, which also feeds get_baseline_text, so nothing independently catches it. Take it once before _run_backend_with_retries and reuse it for grading.
There was a problem hiding this comment.
Good catch. Fixed. In --no-container mode, we now save the original target and context files in memory before starting the agents. I
| return staged_file | ||
|
|
||
|
|
||
| def check_editable_region_integrity(filepath, benchmark_dir): |
There was a problem hiding this comment.
Byte exact comparison means even a trailing newline at EOF or a CRLF rewrite gets flagged as CHEAT-DETECTED, scaffold_unchanged (gate A). I confirmed both cases. _reconstruct_marked_solution already treats these as harmless retyping for one-shot, but agentic backends don't. We should either normalize line endings and trailing newlines before comparing, or give these their own non-cheat reason code. Otherwise, editor noise will inflate the reported cheating rate.
| return False | ||
| return resolved in self._boundaries_by_path | ||
|
|
||
| def get_benchmark_files(self, filter_pattern: str | None = None) -> list[str]: |
There was a problem hiding this comment.
main() calls this at runner.py:1721 with no try/except, so a missing or malformed manifest escapes as a raw ManifestError traceback and never reaches the parser.exit(2, ...) handling on the next line. Catch it in main() or handle it here, so the user gets an error message instead of a stack trace.
71792cd to
31874c9
Compare
|
|
||
| if submitted_regions.fixed_segments != canonical_regions.fixed_segments: | ||
|
|
||
| def normalize_format(regions): |
There was a problem hiding this comment.
One thing I noticed is that this only handles a single trailing newline, so the common case of an editor adding a newline still gets reported as SCAFFOLD_MODIFIED/CHEAT-DETECTED. Switching to suffix = suffix.rstrip("\n") fixes that without affecting real scaffold modifications.
There was a problem hiding this comment.
Fixed. Extra newlines at EOF are now ignored.
sukanya1426
left a comment
There was a problem hiding this comment.
Seems alright now. Thanks for addressing the issues. Over to @Qian-Cheng-nju , can you please take a look and validate ?
|
LGTM! |
Important
This remains a draft until the proof-from-scratch generator emits
manifest.jsonand the editable-region markers. Runs fail closed without that producer-side contract.What changed