search-with-proof: split compressed verifier archives, isolated pip installs, verifier module paths

Archives are gzipped and uploaded in parts of at most 90 MB with per-part
digests (edge request limit); pip installs ignore the task venv so transitive
dependencies land in products; the verifier sets NODE_PATH and the Java
classpath from products when starting the app.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Marius Ciepluch
2026-10-06 11:15:09 +02:00
co-authored by Claude Fable 5.1
parent da804472b9
commit 0d3e6df31c
13 changed files with 437 additions and 44 deletions
+19 -1
View File
@@ -18,6 +18,7 @@ import stat
import subprocess
import tempfile
import time
import zipfile
from collections.abc import Callable
from concurrent.futures import ThreadPoolExecutor
from contextlib import suppress
@@ -380,6 +381,21 @@ def _side(side: Side, demo: Path, family: str, timeout: int, browser: BrowserExe
)
command = ("/usr/bin/python3", "-I", "-c", bootstrap, "/workspace/" + start_spec["path"], *start_spec["arguments"])
if start_spec["runtime"] == "java":
# -jar ignores CLASSPATH. Use the jar's declared main class
# with the verifier-owned product directories and jars.
with zipfile.ZipFile(entry) as jar, jar.open("META-INF/MANIFEST.MF") as jar_manifest:
metadata = jar_manifest.read(65537)
if len(metadata) > 65536:
return record("could_not_build", "oversized Java manifest")
metadata = metadata.replace(b"\r\n", b"\n").replace(b"\n ", b"")
main = re.search(rb"(?mi)^Main-Class: ([\w.$]+)\s*$", metadata.split(b"\n\n", 1)[0])
if main is None:
return record("could_not_build", "Java jar missing Main-Class")
classpath = ["/workspace/" + start_spec["path"], "/build/", "/build/classes"]
classpath.extend("/build/" + str(path.relative_to(products)) for path in sorted(products.rglob("*.jar")))
command = ("/usr/bin/java", "-cp", ":".join(classpath), main[1].decode(), *start_spec["arguments"])
oracle = oracle_for(family, browser)
assert oracle is not None
try:
@@ -393,6 +409,8 @@ def _side(side: Side, demo: Path, family: str, timeout: int, browser: BrowserExe
},
**oracle.prepare(canary),
}
if start_spec["runtime"] == "node":
app_env["NODE_PATH"] = "/build/node_modules"
app_scratch = canary.root if family == "command" else root / "app"
app_scratch.mkdir(exist_ok=True)
fixture = canary.root
@@ -483,7 +501,7 @@ def _side(side: Side, demo: Path, family: str, timeout: int, browser: BrowserExe
return record("could_not_run", str(exc), exc.phase, exc)
except task_storage.ScratchLimit as exc:
return record("could_not_build", exception_reason(exc))
except (OSError, ValueError, AssertionError, KeyError, IndexError, TypeError) as exc:
except (OSError, ValueError, AssertionError, KeyError, IndexError, TypeError, zipfile.BadZipFile) as exc:
return record("could_not_run", "verification unavailable or refused: " + exception_reason(exc))