From f08e50534d240907d1dfb25f1669dffd767a02bd Mon Sep 17 00:00:00 2001 From: ayushcodes10 Date: Sat, 12 Sep 2026 18:58:46 +0530 Subject: [PATCH] Surface unclassified files in GRAPH_REPORT.md detect() already returns every file it saw but could not classify, no supported extension or shebang, but nothing read it: a corpus mostly in an unsupported language got the same well covered verdict as one that was actually extracted, silently. Adds an Unclassified line to the Corpus Check section naming the count and the biggest offending extensions. Toward #3511. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh --- graphify/report.py | 15 +++++++++++++++ tests/test_report.py | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/graphify/report.py b/graphify/report.py index 673c2f2bb..0f1c5e709 100644 --- a/graphify/report.py +++ b/graphify/report.py @@ -137,6 +137,21 @@ def generate( f"- {detection_result['total_files']} files ยท ~{detection_result['total_words']:,} words", "- Verdict: corpus is large enough that graph structure adds value.", ] + # #3511: files detect() saw but could not classify (no supported + # extension/shebang) were counted nowhere -- a corpus that is mostly + # an unsupported language reported the same "well covered" verdict as + # one that was actually extracted. Surface the count and its biggest + # extensions so a near-total miss (e.g. a Lean/Zig/whatever repo with + # no matching extractor) is visible here instead of silent. + unclassified = detection_result.get("unclassified") or [] + if unclassified: + from collections import Counter as _Counter + ext_counts = _Counter(Path(p).suffix or "(none)" for p in unclassified) + top = ", ".join(f"{ext} {n}" for ext, n in ext_counts.most_common(3)) + lines.append( + f"- Unclassified: {len(unclassified)} file(s) not represented in " + f"the graph (top: {top})" + ) from .analyze import _is_file_node as _ifn diff --git a/tests/test_report.py b/tests/test_report.py index 03bc67acb..98f256907 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -29,6 +29,29 @@ def test_report_contains_corpus_check(): report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, "./project") assert "## Corpus Check" in report + +def test_report_surfaces_unclassified_files(): + """#3511: detect() already tracks files it saw but could not classify + (no supported extension), but nothing surfaced them -- a corpus that is + mostly an unsupported language got the same "well covered" verdict as + one that was actually extracted.""" + G, communities, cohesion, labels, gods, surprises, detection, tokens = make_inputs() + detection = { + **detection, + "unclassified": ["Main.lean", "Util.lean", "a.toml", "b.toml", "c.toml", "readme"], + } + report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, "./project") + assert "Unclassified: 6 file(s)" in report + assert ".lean 2" in report + assert ".toml 3" in report + + +def test_report_omits_unclassified_line_when_none(): + """Backward compatible: no unclassified files, no new line.""" + G, communities, cohesion, labels, gods, surprises, detection, tokens = make_inputs() + report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, "./project") + assert "Unclassified:" not in report + def test_report_contains_god_nodes(): G, communities, cohesion, labels, gods, surprises, detection, tokens = make_inputs() report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, "./project")