Skip to content

Commit b003346

Browse files
committed
feat(reachability): warn on silent library blackout across all parsers
The #75 zero-seed net only fires at EXACTLY 0 entry points. A library (e.g. tree-sitter) trips a handful of INCIDENTAL seeds (code merely containing an input-reading pattern), yielding a 96.6% reduction (712 -> 24, all wasm) that looks like a successful filter while the real public-API core was dropped. Add blackout_warning() in utilities/agentic_enhancer (shared by all 7 filter sites). Advisory ONLY -- never changes which units are kept. Warns on total blackout (0 kept) OR >=90% pruned with NO structural entry point (route/main/ CLI/handler) -- i.e. all seeds are incidental input-pattern matches. Suppressed under library_mode (high reduction is then the intended precise result). Suggests --library-mode in the message. Wired into core/parser_adapter.py + all 6 subprocess pipelines (c/js/go/ruby/php/zig). Calibration: silent on Arkime (63%/54% reductions, real route/main seeds), fires on tree-sitter. Tests: 7 new covering both triggers + structural-seed and library-mode suppression.
1 parent 6d5be3c commit b003346

10 files changed

Lines changed: 160 additions & 7 deletions

File tree

libs/openant-core/core/parser_adapter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ def _load_module(name, filename):
262262
_epd = _load_module("entry_point_detector", "entry_point_detector.py")
263263
_ra = _load_module("reachability_analyzer", "reachability_analyzer.py")
264264
EntryPointDetector = _epd.EntryPointDetector
265+
blackout_warning = _epd.blackout_warning
265266
ReachabilityAnalyzer = _ra.ReachabilityAnalyzer
266267

267268
call_graph_path = os.path.join(output_dir, "call_graph.json")
@@ -362,6 +363,12 @@ def _load_module(name, filename):
362363
file=sys.stderr,
363364
)
364365

366+
_blackout = blackout_warning(detector.entry_point_details, original_count,
367+
len(filtered_units), library_mode=library_mode)
368+
if _blackout:
369+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
370+
print(f" [Warning] {_blackout}", file=sys.stderr)
371+
365372
# Warn about unimplemented higher-level filters
366373
if processing_level == "codeql":
367374
print(

libs/openant-core/parsers/c/test_pipeline.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
4949
from utilities.file_io import open_utf8, read_json, run_utf8, write_json
5050
from utilities.context_enhancer import ContextEnhancer
51-
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer
51+
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer, blackout_warning
5252

5353
# Local imports
5454
from repository_scanner import RepositoryScanner
@@ -323,6 +323,13 @@ def apply_reachability_filter(self) -> bool:
323323
"reduction_percentage": round((1 - len(filtered_units) / original_count) * 100, 1) if original_count > 0 else 0
324324
}
325325

326+
_blackout = blackout_warning(detector.entry_point_details, original_count,
327+
len(filtered_units),
328+
library_mode=getattr(self, "library_mode", False))
329+
if _blackout:
330+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
331+
print(f" [Warning] {_blackout}", file=sys.stderr)
332+
326333
write_json(self.dataset_file, dataset)
327334

328335
elapsed = (datetime.now() - start_time).total_seconds()

libs/openant-core/parsers/go/test_pipeline.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def _stdout_supports_unicode() -> bool:
121121
# Add parent directory to path for utilities import
122122
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
123123
from utilities.context_enhancer import ContextEnhancer
124-
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer
124+
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer, blackout_warning
125125

126126

127127
class ProcessingLevel(Enum):
@@ -466,6 +466,13 @@ def apply_reachability_filter(self) -> bool:
466466
"reduction_percentage": round((1 - len(filtered_units) / original_count) * 100, 1) if original_count > 0 else 0
467467
}
468468

469+
_blackout = blackout_warning(detector.entry_point_details, original_count,
470+
len(filtered_units),
471+
library_mode=getattr(self, "library_mode", False))
472+
if _blackout:
473+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
474+
print(f" [Warning] {_blackout}", file=sys.stderr)
475+
469476
# Write filtered dataset
470477
write_json(self.dataset_file, dataset)
471478

libs/openant-core/parsers/javascript/test_pipeline.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def _stdout_supports_unicode() -> bool:
7878
# Add parent directory to path for utilities import
7979
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
8080
from utilities.context_enhancer import ContextEnhancer
81-
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer
81+
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer, blackout_warning
8282

8383

8484
class ProcessingLevel(Enum):
@@ -646,6 +646,13 @@ def apply_reachability_filter(self) -> bool:
646646
"reduction_percentage": round((1 - len(filtered_units) / original_count) * 100, 1) if original_count > 0 else 0
647647
}
648648

649+
_blackout = blackout_warning(detector.entry_point_details, original_count,
650+
len(filtered_units),
651+
library_mode=getattr(self, "library_mode", False))
652+
if _blackout:
653+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
654+
print(f" [Warning] {_blackout}", file=sys.stderr)
655+
649656
# Write filtered dataset
650657
write_json(self.dataset_file, dataset)
651658

libs/openant-core/parsers/php/test_pipeline.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
4949
from utilities.file_io import open_utf8, read_json, run_utf8, write_json
5050
from utilities.context_enhancer import ContextEnhancer
51-
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer
51+
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer, blackout_warning
5252

5353
# Local imports
5454
from repository_scanner import RepositoryScanner
@@ -314,6 +314,13 @@ def apply_reachability_filter(self) -> bool:
314314
"reduction_percentage": round((1 - len(filtered_units) / original_count) * 100, 1) if original_count > 0 else 0
315315
}
316316

317+
_blackout = blackout_warning(detector.entry_point_details, original_count,
318+
len(filtered_units),
319+
library_mode=getattr(self, "library_mode", False))
320+
if _blackout:
321+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
322+
print(f" [Warning] {_blackout}", file=sys.stderr)
323+
317324
write_json(self.dataset_file, dataset)
318325

319326
elapsed = (datetime.now() - start_time).total_seconds()

libs/openant-core/parsers/ruby/test_pipeline.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
4949
from utilities.file_io import open_utf8, read_json, run_utf8, write_json
5050
from utilities.context_enhancer import ContextEnhancer
51-
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer
51+
from utilities.agentic_enhancer import EntryPointDetector, ReachabilityAnalyzer, blackout_warning
5252

5353
# Local imports
5454
from repository_scanner import RepositoryScanner
@@ -314,6 +314,13 @@ def apply_reachability_filter(self) -> bool:
314314
"reduction_percentage": round((1 - len(filtered_units) / original_count) * 100, 1) if original_count > 0 else 0
315315
}
316316

317+
_blackout = blackout_warning(detector.entry_point_details, original_count,
318+
len(filtered_units),
319+
library_mode=getattr(self, "library_mode", False))
320+
if _blackout:
321+
dataset["metadata"]["reachability_filter"]["warning"] = _blackout
322+
print(f" [Warning] {_blackout}", file=sys.stderr)
323+
317324
write_json(self.dataset_file, dataset)
318325

319326
elapsed = (datetime.now() - start_time).total_seconds()

libs/openant-core/parsers/zig/test_pipeline.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def apply_reachability_filter(call_graph_output: dict, repo_path: str) -> dict:
201201
--processing-level reachable.
202202
"""
203203
try:
204-
from utilities.agentic_enhancer.entry_point_detector import EntryPointDetector
204+
from utilities.agentic_enhancer.entry_point_detector import EntryPointDetector, blackout_warning
205205
from utilities.agentic_enhancer.reachability_analyzer import ReachabilityAnalyzer
206206
except ImportError:
207207
print(
@@ -247,6 +247,11 @@ def apply_reachability_filter(call_graph_output: dict, repo_path: str) -> dict:
247247
if k in reachable
248248
}
249249

250+
_blackout = blackout_warning(detector.entry_point_details, len(functions),
251+
len(filtered_functions))
252+
if _blackout:
253+
print(f" [Warning] {_blackout}", file=sys.stderr)
254+
250255
return result
251256

252257

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Fix B — reachability blackout warning (advisory; never changes filtering).
2+
3+
The #75 zero-seed net only fires at EXACTLY 0 entry points. A library like
4+
tree-sitter trips a handful of INCIDENTAL seeds (code that merely contains an
5+
input-reading pattern), yielding a 96.6% reduction that looks like a successful
6+
filter while the real public-API core was dropped. `blackout_warning` catches
7+
both the total blackout and this partial-blackout-with-only-incidental-seeds case,
8+
and stays silent for a normal app (real route/main/CLI seeds, moderate reduction).
9+
"""
10+
import sys
11+
from pathlib import Path
12+
13+
sys.path.insert(0, str(Path(__file__).resolve().parents[1])) # libs/openant-core
14+
15+
from utilities.agentic_enhancer import blackout_warning # noqa: E402
16+
17+
18+
def _details(*reason_lists):
19+
"""Build an entry_point_details-shaped dict from per-seed reason lists."""
20+
return {f"f{i}": {"reasons": rs} for i, rs in enumerate(reason_lists)}
21+
22+
23+
def test_total_blackout_warns():
24+
assert blackout_warning(_details(), original_count=500, reachable_count=0) is not None
25+
26+
27+
def test_partial_blackout_incidental_seeds_warns():
28+
# tree-sitter shape: 4 incidental input_pattern seeds, 712 -> 24 (96.6% pruned).
29+
details = _details(["input_pattern:fopen"], ["input_pattern:read"],
30+
["input_pattern:getenv"], ["input_pattern:scanf"])
31+
assert blackout_warning(details, original_count=712, reachable_count=24) is not None
32+
33+
34+
def test_structural_seed_suppresses_even_high_reduction():
35+
# A real CLI/main seed means the high reduction is legitimate, not a blackout.
36+
details = _details(["unit_type:main"], ["input_pattern:read"])
37+
assert blackout_warning(details, original_count=712, reachable_count=24) is None
38+
39+
40+
def test_normal_app_reduction_is_silent():
41+
# Arkime C shape: route/main seeds, 1655 -> 608 (63% pruned). No warning.
42+
details = _details(["unit_type:cli_handler"], ["unit_type:main"], ["unit_type:http_handler"])
43+
assert blackout_warning(details, original_count=1655, reachable_count=608) is None
44+
45+
46+
def test_decorator_and_name_seeds_are_structural():
47+
assert blackout_warning(_details(["decorator:@app.route"]),
48+
original_count=712, reachable_count=24) is None
49+
assert blackout_warning(_details(["name:main"]),
50+
original_count=712, reachable_count=24) is None
51+
52+
53+
def test_library_mode_suppresses_warning():
54+
# With library-mode on, a high reduction is the intended precise result.
55+
details = _details(["input_pattern:read"])
56+
assert blackout_warning(details, original_count=712, reachable_count=24,
57+
library_mode=True) is None
58+
59+
60+
def test_empty_dataset_no_warning():
61+
assert blackout_warning(_details(), original_count=0, reachable_count=0) is None

libs/openant-core/utilities/agentic_enhancer/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121
from .repository_index import RepositoryIndex, load_index_from_file
2222
from .tools import TOOL_DEFINITIONS, ToolExecutor
23-
from .entry_point_detector import EntryPointDetector
23+
from .entry_point_detector import EntryPointDetector, blackout_warning
2424
from .reachability_analyzer import ReachabilityAnalyzer
2525

2626
__all__ = [
@@ -33,5 +33,6 @@
3333
"TOOL_DEFINITIONS",
3434
"ToolExecutor",
3535
"EntryPointDetector",
36+
"blackout_warning",
3637
"ReachabilityAnalyzer"
3738
]

libs/openant-core/utilities/agentic_enhancer/entry_point_detector.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,47 @@ def get_statistics(self) -> Dict:
284284
'by_unit_type': by_type,
285285
'by_reason_category': by_reason,
286286
}
287+
288+
289+
# Reason categories that indicate a STRUCTURAL entry point — a real route, program
290+
# main, CLI command, framework handler, or decorator-marked endpoint — as opposed
291+
# to an INCIDENTAL match (code merely contains an input-reading pattern). A result
292+
# seeded ONLY by incidental matches is the library-blackout signature: the public
293+
# API was never a seed, so the BFS dropped the core.
294+
_STRUCTURAL_REASON_CATEGORIES = {"unit_type", "decorator", "name"}
295+
296+
297+
def blackout_warning(entry_point_details, original_count, reachable_count,
298+
library_mode=False, reduction_threshold=0.90):
299+
"""Advisory string when a reachability result looks like a silent library
300+
blackout, else None. This is ADVISORY ONLY — it never changes which units
301+
are kept.
302+
303+
Two triggers (both off when ``library_mode`` is set, since then the public
304+
API was deliberately seeded and a high reduction is the intended result):
305+
* total blackout — 0 of N units kept (no seedable frontier); or
306+
* partial blackout — >= ``reduction_threshold`` pruned AND no STRUCTURAL
307+
entry point was found (every seed is an incidental ``input_pattern``
308+
match). This is the case that slips past the zero-seed net: a handful of
309+
incidental seeds yield a 96%+ reduction that looks like success while the
310+
real public API surface was never analysed (e.g. a C/JS parser library).
311+
"""
312+
if original_count <= 0 or library_mode:
313+
return None
314+
if reachable_count == 0:
315+
return (f"Reachability kept 0 of {original_count} units — total blackout "
316+
f"(no entry point could seed the frontier). If this is a library, "
317+
f"re-run with --library-mode to seed the exported public API surface.")
318+
reduction = 1.0 - (reachable_count / original_count)
319+
structural = sum(
320+
1 for d in (entry_point_details or {}).values()
321+
if any(r.split(":", 1)[0] in _STRUCTURAL_REASON_CATEGORIES
322+
for r in d.get("reasons", []))
323+
)
324+
if reduction >= reduction_threshold and structural == 0:
325+
return (f"Reachability kept {reachable_count} of {original_count} units "
326+
f"({reduction * 100:.0f}% pruned) but found NO structural entry point "
327+
f"(route/main/CLI/handler) — only incidental code-pattern seeds. This is "
328+
f"the library-blackout pattern: the public API was not seeded, so the core "
329+
f"was dropped. Re-run with --library-mode to seed the exported public API.")
330+
return None

0 commit comments

Comments
 (0)