From 1726a74fd9255a7d32698621533b0d5b9e80049d Mon Sep 17 00:00:00 2001 From: "Moises Lopez - https://www.vauxoo.com/" Date: Tue, 1 Sep 2026 19:25:10 -0600 Subject: [PATCH] [IMP] Stop indexing module prose: drop .rst, .md and .css Every extension should earn its place by how much of the graph it builds. Measured on a real Odoo instance (188 modules, 77935 DEFINES edges): .py 2755 files 55603 definitions 20.2 per file 71.3% of the graph .xml 1883 files 14844 definitions 7.9 per file 19.0% .js 890 files 6368 definitions 7.2 per file 8.2% .scss 232 files 912 definitions 3.9 per file 1.2% .csv 86 files 86 definitions 1.0 per file 0.1% .sql 20 files 35 definitions 1.8 per file 0.0% .rst 73 files 73 definitions 1.0 per file 0.1% <- dropped .css 8 files 8 definitions 1.0 per file 0.0% <- dropped .md 2 files 6 definitions 3.0 per file 0.0% <- dropped ".rst" and ".css" build exactly one node each -- the File node itself and nothing inside it. ".md" only adds the headings of a README: every Section node in that graph came from its two markdown files. All three are module prose, so the graph gains a path and no structure. ".csv" scores the same 1.0 and stays anyway. An indexed file is also greppable through search_code, and ir.model.access.csv is a file people really do search: searching the indexed graph for "access_" returns 52 hits inside csv files, with line numbers. Structure is not the only thing an indexed file is good for. This is about keeping the graph free of prose, not about making a scope fit: the three dropped extensions are 1.4% of the files of an instance, where .js alone is 15%. Anyone who wants them back has --extensions. --- README.md | 6 +++--- src/codebase_memory_deployv/indexer.py | 23 ++++++++++++++++++++++- tests/test_indexer.py | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9a7f111..7c72db9 100644 --- a/README.md +++ b/README.md @@ -58,17 +58,17 @@ That single command: one-shot indexing is never a problem. 5. Validates the graph scope: no `test_*` addon modules indexed, no missing and no extra module roots compared to the expected module list, and **every indexed file carrying one of the - configured extensions** (`SOURCE_GLOBS`: `.py .xml .js .rst .md .css .scss .csv`) — anything + configured extensions** (`SOURCE_GLOBS`: `.py .xml .js .scss .csv .sql`) — anything else means `.cbmignore` did not apply. Counts per extension are logged, unexpected ones marked `(!)`: ```text - extensions_configured=.css,.csv,.js,.md,.py,.rst,.scss,.xml + extensions_configured=.csv,.js,.py,.scss,.sql,.xml extensions_indexed=5 files=12057 extension .py files=4949 extension .xml files=3276 extension .json files=39 (!) - unexpected_extensions=1 files=39 (not in SOURCE_GLOBS: .json) + unexpected_extensions=1 files=39 (not in the configured extensions: .json) ``` Both checks read the graph with `query_graph` over its `File` nodes, not with `search_code`: diff --git a/src/codebase_memory_deployv/indexer.py b/src/codebase_memory_deployv/indexer.py index 3449564..9f25a52 100644 --- a/src/codebase_memory_deployv/indexer.py +++ b/src/codebase_memory_deployv/indexer.py @@ -39,7 +39,28 @@ DEFAULT_PROJECT = "odoo_instance" CORE_DIRS = ("odoo/odoo",) CORE_PREFIX = "odoo/odoo/" -SOURCE_GLOBS = ("*.py", "*.xml", "*.js", "*.rst", "*.md", "*.css", "*.scss", "*.csv", "*.sql") +# Prose formats are deliberately absent. Measured on a real Odoo instance (188 modules, +# 77935 DEFINES edges), every extension earns its place by how much of the graph it builds: +# +# .py 2755 files 55603 definitions 20.2 per file 71.3% of the graph +# .xml 1883 files 14844 definitions 7.9 per file 19.0% +# .js 890 files 6368 definitions 7.2 per file 8.2% +# .scss 232 files 912 definitions 3.9 per file 1.2% +# .csv 86 files 86 definitions 1.0 per file 0.1% +# .sql 20 files 35 definitions 1.8 per file 0.0% +# .rst 73 files 73 definitions 1.0 per file 0.1% <- dropped +# .css 8 files 8 definitions 1.0 per file 0.0% <- dropped +# .md 2 files 6 definitions 3.0 per file 0.0% <- dropped +# +# ".rst" and ".css" build exactly one node each — the File node itself, nothing inside it — +# and ".md" only adds the headings of a README (every Section node in that graph came from +# two markdown files). They are module prose, so the graph gains a path and no structure. +# +# ".csv" scores the same 1.0 and stays anyway: an indexed file is also greppable through +# search_code, and ir.model.access.csv is a file people really do search. Extensions are a +# weak lever on memory in any case (these three are 1.4% of the files, where .js is 15%), +# so this is about keeping the graph free of prose, not about making a scope fit. +SOURCE_GLOBS = ("*.py", "*.xml", "*.js", "*.scss", "*.csv", "*.sql") # What .cbmignore lets through, so what the graph is expected to hold: ".py", ".xml", ... SOURCE_EXTENSIONS = tuple(sorted(pattern[1:] for pattern in SOURCE_GLOBS)) MANIFEST_NAMES = ("__manifest__.py", "__openerp__.py") diff --git a/tests/test_indexer.py b/tests/test_indexer.py index 82f88dc..5dc72e9 100644 --- a/tests/test_indexer.py +++ b/tests/test_indexer.py @@ -480,3 +480,26 @@ def test_check_layout_requires_odoo_bin(tmp_path): odoo_dir.mkdir() (odoo_dir / "odoo-bin").write_text("") assert indexer.check_layout(str(tmp_path)) == os.path.join(str(tmp_path), "odoo", "odoo-bin") + + +def test_source_globs_exclude_module_prose(): + """.rst/.md/.css build a File node and nothing inside it; the graph gains no structure.""" + assert ".rst" not in indexer.SOURCE_EXTENSIONS + assert ".md" not in indexer.SOURCE_EXTENSIONS + assert ".css" not in indexer.SOURCE_EXTENSIONS + + +def test_source_globs_keep_csv_for_text_search(): + """ir.model.access.csv builds no structure either, but an indexed file stays greppable.""" + assert ".csv" in indexer.SOURCE_EXTENSIONS + + +def test_render_cbmignore_stops_letting_prose_through(): + content = indexer.render_cbmignore(["extra_addons/vauxoo/sale_extended"]) + assert "!extra_addons/vauxoo/sale_extended/**/*.py" in content + assert "!extra_addons/vauxoo/sale_extended/**/*.csv" in content + assert "*.rst" not in content + assert "*.md" not in content + assert "*.css" not in content + # ".scss" must survive a naive "*.css" removal: it ends with the same three letters. + assert "!extra_addons/vauxoo/sale_extended/**/*.scss" in content