Suppress autogenerated module docstrings from rationale extraction (#882)

Alembic/Flask-Migrate revisions, Django migrations, and protobuf/OpenAPI
generated files produce hundreds of degree-1 rationale nodes labeled as
'possible documentation gaps'. Their module docstrings are revision
annotations or boilerplate, not architectural rationale.

- Add _is_autogenerated_python() in extract.py detecting Alembic, Django
  migrations, and generic DO-NOT-EDIT markers; skip module docstring only
- Function/class docstrings inside those files still extracted as normal
- report.py: exclude file_type=rationale nodes from isolated-node gaps
  section — rationale nodes are degree-1 by construction; flagging them
  as missing edges was always wrong
- 5 new tests covering Alembic, Django, protobuf, false-positive guard,
  and function-docstring passthrough
This commit is contained in:
Safi
2026-05-16 00:01:57 +01:00
parent 63926c5e39
commit fa70449d80
3 changed files with 117 additions and 5 deletions
+28 -4
View File
@@ -1866,6 +1866,27 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict:
_RATIONALE_PREFIXES = ("# NOTE:", "# IMPORTANT:", "# HACK:", "# WHY:", "# RATIONALE:", "# TODO:", "# FIXME:")
def _is_autogenerated_python(source: bytes) -> bool:
"""Return True if this Python file is auto-generated and its module docstring is noise.
Covers: Alembic/Flask-Migrate revisions, Django migrations, protobuf/gRPC/OpenAPI stubs.
Module docstrings in these files are change annotations or boilerplate, not rationale.
"""
head = source[:2048].decode("utf-8", errors="replace")
# Generic generated-file markers (protobuf, gRPC, OpenAPI codegen, etc.)
if any(m in head for m in ("DO NOT EDIT", "@generated", "Generated by the protocol buffer")):
return True
# Alembic / Flask-Migrate revision files
if (re.search(r"^revision\s*[:=]", head, re.MULTILINE)
and "def upgrade(" in head
and "down_revision" in head):
return True
# Django migrations
if "class Migration(migrations.Migration)" in head and "operations" in head:
return True
return False
def _extract_python_rationale(path: Path, result: dict) -> None:
"""Post-pass: extract docstrings and rationale comments from Python source.
Mutates result in-place by appending to result['nodes'] and result['edges'].
@@ -1924,10 +1945,13 @@ def _extract_python_rationale(path: Path, result: dict) -> None:
"weight": 1.0,
})
# Module-level docstring
ds = _get_docstring(root)
if ds:
_add_rationale(ds[0], ds[1], file_nid)
# Module-level docstring — skip for auto-generated files (Alembic, Django
# migrations, protobuf stubs, etc.) whose module docstrings are revision
# annotations, not architectural rationale.
if not _is_autogenerated_python(source):
ds = _get_docstring(root)
if ds:
_add_rationale(ds[0], ds[1], file_nid)
# Class and function docstrings
def walk_docstrings(node, parent_nid: str) -> None:
+4 -1
View File
@@ -164,7 +164,10 @@ def generate(
isolated = [
n for n in G.nodes()
if G.degree(n) <= 1 and not _is_file_node(G, n) and not _is_concept_node(G, n)
if G.degree(n) <= 1
and not _is_file_node(G, n)
and not _is_concept_node(G, n)
and G.nodes[n].get("file_type") != "rationale"
]
thin_communities = {
cid: nodes for cid, nodes in communities.items()