search-with-proof: one interpreter for pip and apps; checkout root on sys.path; real node_modules path

The pip recipe ran under the system Python 3.13 while apps started under the
venv 3.12, so compiled extensions never loaded. Both now use sys.executable.
Package-style starts see the checkout root; NODE_PATH lists the project
node_modules under the checkout before the products mount.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Marius Ciepluch
2026-10-06 14:37:58 +02:00
co-authored by Claude Fable 5.1
parent 7a91cc1482
commit 630603ee28
5 changed files with 134 additions and 5 deletions
+6
View File
@@ -16,6 +16,7 @@ import resource
import signal
import struct
import subprocess
import sys
import tempfile
from contextlib import suppress
from pathlib import Path
@@ -140,6 +141,11 @@ def run(
for path in ("/usr", "/lib", "/lib64", "/bin"):
if Path(path).exists():
argv += ["--ro-bind", path, path]
# The verifier's Python can live in /venv or a host venv backed by
# an interpreter outside /usr. Keep that same ABI available in this lane.
for path in dict.fromkeys((sys.base_prefix, sys.prefix)):
if not any(Path(path).is_relative_to(base) for base in ("/usr", "/lib", "/lib64", "/bin")):
argv += ["--ro-bind", path, path]
argv += ["--bind" if writable_checkout else "--ro-bind", str(job.repo_root), "/workspace"]
if scratch_bytes is None:
writable_directory(scratch)
+2 -2
View File
@@ -61,7 +61,7 @@ MAX_VALUE_BYTES = 16384
BUILD_RECIPES = {
"none": (),
"pip": (
"/usr/bin/python3",
sys.executable,
"-I",
"-m",
"pip",
@@ -258,7 +258,7 @@ def preparation_command(recipe: str, path: Path, checkout: Path, products: Path)
if not target.resolve().is_relative_to(checkout.resolve()):
raise ValueError("recipe input outside checkout")
return [
"python3",
sys.executable,
"-I",
"-m",
"pip",
+13 -3
View File
@@ -373,10 +373,10 @@ def _side(side: Side, demo: Path, family: str, timeout: int, browser: BrowserExe
# recipe's offline packages without trusting PYTHONPATH.
bootstrap = (
"import os,runpy,sys; sys.dont_write_bytecode=True; p=sys.argv.pop(1); "
"sys.path[:0]=['/build/packages',os.path.dirname(p)]; sys.argv[0]=p; "
"sys.path[:0]=['/build/packages','/workspace',os.path.dirname(p)]; sys.argv[0]=p; "
"runpy.run_path(p,run_name='__main__')"
)
command = ("/usr/bin/python3", "-I", "-c", bootstrap, "/workspace/" + start_spec["path"], *start_spec["arguments"])
command = (*RUNTIMES["python"], "-c", bootstrap, "/workspace/" + start_spec["path"], *start_spec["arguments"])
if start_spec["runtime"] == "java":
# -jar ignores CLASSPATH. Use the jar's declared main class
@@ -427,7 +427,17 @@ def _side(side: Side, demo: Path, family: str, timeout: int, browser: BrowserExe
**oracle_env,
}
if start_spec["runtime"] == "node":
app_env["NODE_PATH"] = "/build/node_modules"
# Executor npm runs in its selected project. That project
# may be separate from the launcher (e.g. .demo/), and the
# exported spec no longer carries a build recipe. Discover
# project installs, pruning dependency-internal installs.
node_paths = []
for parent, dirs, _ in os.walk(checkout):
dirs.sort()
if "node_modules" in dirs:
node_paths.append("/workspace/" + (Path(parent) / "node_modules").relative_to(checkout).as_posix())
dirs.remove("node_modules")
app_env["NODE_PATH"] = ":".join([*node_paths, "/build/node_modules"])
app_scratch = canary.root if family == "command" else root / "app"
app_scratch.mkdir(exist_ok=True)
fixture = canary.root