perf(cpg): run the overlay pass in-session and verify it saved (M2 11.4)

The overlay was the last fixed cost bypassing the session: a whole JVM start,
15.8 s in the measured Node runs, while the census and query batches already route
through it.

`save` writes under the process working directory, which for a session is its own
private scratch rather than the build scratch, so the saved graph is now looked for
in both. Finding neither keeps the raw graph and records it rather than reporting
success, because a graph without its dataflow layer has that layer recomputed by
every later batch, 54 s each on a 637-file plugin, with nothing otherwise saying so.

The disposable invocation remains the fallback and runs unchanged whenever the
session is off or cannot answer.

Controls cover both new paths: an engine that reports success but saves no graph
keeps the raw one and notes it, and a graph saved under the session's workspace is
found and applied.

1,395 tests passed, nine skipped. The transport stays off by default; task 11.5
measures against the frozen profile. Rollout stays NO-GO.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-16 20:41:11 +02:00
co-authored by Claude Opus 5
parent d93dee9f1a
commit 87f7976a58
2 changed files with 74 additions and 11 deletions
+45
View File
@@ -218,3 +218,48 @@ def test_a_session_that_cannot_start_falls_back_rather_than_answering(tmp_path):
assert backend._session_payload(tmp_path / "cpg.bin", "census", {"cpgFile": "x"}) is None
assert any("session_unavailable" in note or "session" in note for note in backend._diagnostics) or backend._diagnostics == []
backend.close_session()
def test_an_overlay_that_saves_no_graph_keeps_the_raw_one(tmp_path, monkeypatch):
"""M2 11.4: reported success with no saved graph must not read as an applied overlay."""
from openultrasast.cpg.backend import JoernBackend
backend = JoernBackend(execution_budget=ExecutionBudget(time.monotonic() + 30, 1.0))
graph = tmp_path / "cpg.bin"
graph.write_bytes(b"raw")
scratch = tmp_path / "scratch"
scratch.mkdir()
# The engine answers, but nothing lands in any workspace.
monkeypatch.setattr("openultrasast.cpg.backend.shutil.which", lambda name: "/usr/bin/" + name)
monkeypatch.setattr(JoernBackend, "_run", lambda *a, **k: _completed('---OUSAST-CPG-BEGIN---\n{"files":"1"}\n---OUSAST-CPG-END---'))
assert backend._apply_overlays(graph, scratch) is False
assert graph.read_bytes() == b"raw"
assert "overlay_saved_graph_missing" in backend._diagnostics
def test_an_overlay_saved_under_the_session_workspace_is_found(tmp_path, monkeypatch):
from openultrasast.cpg.backend import JoernBackend
from openultrasast.cpg.session import EngineSession
backend = JoernBackend(session_transport=True, execution_budget=ExecutionBudget(time.monotonic() + 30, 1.0))
graph = tmp_path / "cpg.bin"
graph.write_bytes(b"raw")
scratch = tmp_path / "scratch"
scratch.mkdir()
session_scratch = tmp_path / "session"
saved = session_scratch / "workspace" / graph.name
saved.mkdir(parents=True)
(saved / "cpg.bin").write_bytes(b"overlaid")
live = EngineSession(session_scratch, ExecutionBudget(time.monotonic() + 30, 1.0), {})
monkeypatch.setattr(JoernBackend, "_session_for", lambda self, path: live)
monkeypatch.setattr(
JoernBackend, "_session_payload", lambda self, path, query, params: '---OUSAST-CPG-BEGIN---\n{"files":"1"}\n---OUSAST-CPG-END---'
)
assert backend._apply_overlays(graph, scratch) is True
assert graph.read_bytes() == b"overlaid"
def _completed(stdout):
import subprocess
return subprocess.CompletedProcess(["joern"], 0, stdout, "")