mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(plane): the improvement loop as a plane Run (harnessx-removal task 4)
`ousast plane workspaces --validation-set ... --loop` appends the loop to a Run:
per case `alerts` (plane/tasks/alerts.py: the quick-mode scan on the vulnerable
and the fixed pin, a fixed-pin Workspace per case, alerts attributed to their
enclosing function by the repo-facts patterns, `in_fix_range` from the fix's
old-side and new-side ranges, failing on an unread tree) feeding `remember`,
then `memory-snapshot` -> `loop-measure` -> `loop-propose` -> `loop-improve`
(plane/tasks/loop.py). Every new task binds no Model and has budget
{usd: 0, calls: 0}. The snapshot is the store's rows after the train-on-test
guard, written on the host by memory.seed (a sandboxed run of it fails loudly);
propose runs M1/M2 against this repository at the commit under test; improve
runs one unchanged evolve.run_round and delivers gate.json, journal.json, the
sidecar, rule_policy.json only when accepted, and proposal_outcome rows that
the host ingests. Adoption stays a maintainer commit.
`remember` is now a Run entry per case (the image contains it), with the facts
row keyed by the image the facts were computed on (repo-facts records it in
its summary; unknown -> the row is omitted, never guessed). Alert rows carry
their own pin; improve/memory.py counts a repeated alert once.
Runner image rebuilt (+0.39 MB: only the new modules; the quick scan needs no
extra and the rulesets were already in the package), pushed, plane/ re-pinned
and regenerated (validation-46: 105 entries). Fixture test runs the whole loop
graph through the fake ax, whose new `exec` mode runs the real task modules.
Live: one loop Run over three validation-46 cases on the local ax, recorded in
benchmarks/measurements/2026-09-30-harnessx-removal-loop/ (all done, $0 new
spend, 0 proposals, gate verdict no_proposals).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d104166697
commit
b68fe27c74
@@ -91,6 +91,26 @@ def gone():
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def run_task(rec, task, env, spec):
|
||||
"""``python -m openultrasast.plane.tasks.<command>`` with the rendered env, ``AX_TASK_YAML``/``AX_WORKSPACES_YAML``,
|
||||
each fetched input at its ``OUSAST_INPUT_<NAME>``, and ``spec["env"]`` (local checkouts for bound Workspaces)."""
|
||||
import os, subprocess
|
||||
doc = next(d for d in rec["docs"] if d["kind"] == "Task")
|
||||
run_env = {{**os.environ, **env, "AX_TASK_YAML": yaml.safe_dump(doc)}}
|
||||
run_env["AX_WORKSPACES_YAML"] = yaml.safe_dump_all([d for d in rec["docs"] if d["kind"] == "Workspace"])
|
||||
for name, ref in json.loads(env.get("OUSAST_INPUTS", "{{}}")).items():
|
||||
run_env["OUSAST_INPUT_" + name] = str(HERE / "fetched" / task / ref)
|
||||
out = HERE / "out" / task
|
||||
run_env.update(spec.get("env", {{}}), OUSAST_OUTPUT_DIR=str(out))
|
||||
command = doc["spec"]["command"]
|
||||
argv = [sys.executable, "-m", "openultrasast.plane.tasks." + command[0].replace("-", "_"), *command[1:]]
|
||||
proc = subprocess.run(argv, env=run_env, capture_output=True, text=True)
|
||||
(HERE / "ax.log").open("a").write(f"{{time.monotonic():.4f}} exec {{task}} {{proc.returncode}}\\n")
|
||||
(HERE / "stderr").mkdir(exist_ok=True)
|
||||
(HERE / "stderr" / task).write_text(proc.stderr)
|
||||
return {{p.relative_to(out).as_posix(): p.read_text() for p in sorted(out.rglob("*")) if p.is_file()}}
|
||||
|
||||
|
||||
if argv[:2] == ["apply", "-f"]:
|
||||
docs = list(yaml.safe_load_all(Path(argv[2]).read_text()))
|
||||
for doc in docs:
|
||||
@@ -139,6 +159,8 @@ elif argv[:2] == ["get", "task"]:
|
||||
except urllib.error.HTTPError as exc: # the runner delivers a failed summary naming the input
|
||||
(HERE / "ax.log").open("a").write(f"{{time.monotonic():.4f}} unfetched {{task}} {{name}} {{exc.code}}\\n")
|
||||
files = {{"summary.json": {{"status": "failed", "reason": f"input {{name}} ({{ref}}) not fetched: HTTP {{exc.code}}"}}}}
|
||||
if "exec" in script and "summary.json" not in files: # the real task module, as the runner runs it
|
||||
files = run_task(rec, task, env, script["exec"])
|
||||
buf = io.BytesIO()
|
||||
with tarfile.open(fileobj=buf, mode="w") as tar:
|
||||
for path, content in files.items():
|
||||
|
||||
Reference in New Issue
Block a user