fix(scan): itemise change context only in the files a change touched

The PHP transfer replay (pre-push 13.3) spent its whole 7,200 s case in the
head side's evidence pass. A probe on one PMPro graph named the cause: not
compute -- context adds ~20% engine time -- but OUTPUT. Each evidence request
listed every method its scope reached, up to 1,845 rows; 200 requests into
the bundled Braintree SDK returned 52,831 rows, 9.4 MB, against 211 rows
without context, over 22,125 requests in a 3 GB container.

`affected_context` only ever attaches a location in a changed file, and
every other row was checked (real file under the root, usable extent) and
discarded. The scan now sends the changed files; the engine itemises those
and folds the rest into one `context_elsewhere` row carrying exactly what
that check reads. With no safe file list the engine itemises everything,
as before.

Equivalence: unit controls over valid, missing-file, no-extent and
outside-root cases, with and without a changed-file row; a real-Joern
control; and on PMPro itself, 2,440 relationships and zero gaps decided
identically from both forms, 52,831 rows down to 3,241 with the most
referenced file as the change. Probe: benchmarks/push/context_cost_probe.py.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-23 12:19:35 +02:00
co-authored by Claude Opus 5.5
parent cda679cb3b
commit 3c195c9369
7 changed files with 351 additions and 13 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ FRONTEND_BUILD_ATTEMPTS = 4
# across 2,500 requests made a 42.5MB request file of which 41.7MB was the same string over and over. Joern
# parsed that with ujson inside a 2GB heap and the whole batch died in ForkJoinPool, which the driver
# correctly reported as `query_failed` for all 2,500 regions -- a whole-repository scan that decided nothing.
_SHARED_REQUEST_FIELDS = ("hookCallbacks", "dispatchApply")
_SHARED_REQUEST_FIELDS = ("hookCallbacks", "dispatchApply", "contextFilter", "contextPaths")
Runner = Callable[..., subprocess.CompletedProcess[str]]