From 9372fa2c4ef09d5a8aa02c34979127fc742b5ace Mon Sep 17 00:00:00 2001 From: melbinjp Date: Wed, 19 Aug 2026 16:14:20 +0530 Subject: [PATCH 1/2] The line telling you what to widen to should name your documentation, not your biggest folder Measured over sweep batch 10, twenty-three repositories, 4,819 unread documentation files. The largest unread segments across all of them: skills/ 429, tools/ 176, docs.feldera.com/ 131, datafusion/ 123, .changeset/ 108, .claude/ 108, src/ 97, backends/ 77, crates/ 69 One of those nine is documentation. The rest are source-tree READMEs, agent skill definitions and changelog fragments, which is to say find_docs is RIGHT to leave them out and its docstring already argues so. The scope was never the defect. The defect was that the line telling a reader how to widen picked the biggest directory, so immich was told to read mobile/ while its readme_i18n/ tree went unmentioned, executorch was told examples/ over .wiki/, and deepagents libs/ over openwiki/. And where nothing is named like documentation, it now says that instead of naming the biggest. superset has 276 unread across apps/, plans/ and packages/; suggesting apps/ would tell the reader to widen into exactly the package-internal READMEs the scope excludes on purpose. Both widening routes are still printed for a project whose docs live somewhere odd. Three of twenty-three suggestions change. The other twenty already pointed at the right place or had nothing better to point at. 199 tests. --- src/docproof/cli.py | 27 ++++++++++++++++++++----- src/docproof/docs.py | 36 +++++++++++++++++++++++++++++++++ tests/test_coverage.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/src/docproof/cli.py b/src/docproof/cli.py index f972005..a1c6c53 100644 --- a/src/docproof/cli.py +++ b/src/docproof/cli.py @@ -18,7 +18,13 @@ superseded_lines, suppressed_lines, ) -from .docs import by_directory, find_docs, read, unread_documents +from .docs import ( + by_directory, + find_docs, + likeliest_docs_directory, + read, + unread_documents, +) from .history import classify, vanished_documents from .project import Project, find_root from .report import Report @@ -149,10 +155,21 @@ def report_coverage(project: Project, unread: list[Path]) -> None: f"default scope is top-level files plus doc/ and docs/" ) print(f" {where}") - print( - f" read them too with --docs '{groups[0][0]}/**/*.md' or " - f'[tool.docproof] docs = ["{groups[0][0]}/**/*.md"]' - ) + # The directory to widen TO is not the biggest one. Measured over sweep batch 10: + # the largest unread segments across twenty-three repositories are `skills/`, `tools/`, + # `src/`, `crates/` and `.changeset/`, and one entry in the top nine is documentation. + # See `likeliest_docs_directory`. + widen = likeliest_docs_directory(groups) + if widen: + print( + f" read them too with --docs '{widen}/**/*.md' or " + f'[tool.docproof] docs = ["{widen}/**/*.md"]' + ) + else: + print( + " none of them is named like a documentation tree; if one is, widen with " + "--docs 'DIR/**/*.md' or [tool.docproof] docs = [\"DIR/**/*.md\"]" + ) def report_set_aside(historical: list[str], disclaimed: dict[tuple[str, str], list[str]]) -> None: diff --git a/src/docproof/docs.py b/src/docproof/docs.py index ecb6fe2..6983cb2 100644 --- a/src/docproof/docs.py +++ b/src/docproof/docs.py @@ -194,6 +194,42 @@ def by_directory(root: Path, paths: Iterable[Path]) -> list[tuple[str, int]]: return sorted(counts.items(), key=lambda item: (-item[1], item[0])) +# A directory whose NAME says it holds documentation, for the one line that tells the reader +# what to widen to. Everything here is a naming convention rather than a guess about contents. +DOCS_DIRECTORY = re.compile( + r"(?i)^(docs?([.\-_].*)?|.*\.wiki|.*wiki.*|handbooks?|guides?|manuals?|books?|" + r"readme_i18n|website|content|reference)$" +) + + +def likeliest_docs_directory(groups: list[tuple[str, int]]) -> str: + """Which unread directory to SUGGEST widening to, given (name, count) biggest first. + + **Measured across the twenty-three repositories of sweep batch 10, 2026-08-19.** They hold + 4,819 unread documentation files, and ranking the suggestion by count points at the wrong + directory most of the time, because the biggest unread directory in a monorepo is almost + never its documentation. The top segments were `skills/` 429, `tools/` 176, + `docs.feldera.com/` 131, `datafusion/` 123, `.changeset/` 108, `.claude/` 108, `src/` 97, + `backends/` 77, `crates/` 69. + + One of those nine is documentation. The rest are source-tree READMEs, agent skill + definitions and changelog fragments - which is to say `find_docs` is RIGHT to leave them + out, and its docstring already argues so. The defect was never the scope. It was that the + line telling a reader how to widen said `--docs 'ts/**/*.md'` at a project whose real + documentation site sat two entries below. + + Returns None when nothing in the unread tree is named like documentation, and the caller + says so rather than naming the biggest. Suggesting `--docs 'apps/**/*.md'` at a monorepo, + which is what ranking by count did to `superset-sh/superset`, tells the reader to widen + into exactly the package-internal READMEs `find_docs` excludes on purpose. Advice that + produces findings nobody wants is worse than no advice. + """ + for name, _ in groups: + if DOCS_DIRECTORY.match(name): + return name + return None + + def read(path: Path) -> str: """UTF-8 with universal newlines, so a CRLF checkout reads the same as a LF one.""" return path.read_text(encoding="utf-8", errors="replace").replace("\r\n", "\n") diff --git a/tests/test_coverage.py b/tests/test_coverage.py index 1e56e77..9f3eba9 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -205,3 +205,48 @@ def test_full_coverage_adds_no_sentence(make_repo: Callable[..., Path], capsys) main([str(repo)]) out = capsys.readouterr().out assert "were never read" not in out + + +def test_the_widen_suggestion_names_the_documentation_tree( + make_repo: Callable[..., Path], capsys +) -> None: + """**Measured over sweep batch 10, twenty-three repositories, 4,819 unread files.** The + biggest unread directory in a real project is almost never its documentation: the top + segments were `skills/` 429, `tools/` 176, `docs.feldera.com/` 131, `datafusion/` 123, + `.changeset/` 108, `.claude/` 108, `src/` 97. One of the top nine is documentation. + + So ranking the suggestion by count told `immich` to read `mobile/`, `executorch` to read + `examples/` and `deepagents` to read `libs/`, while each of them keeps a wiki or an i18n + README tree the line never mentioned. + """ + files = {"README.md": README, "src/thing.py": "x = 1\n", "project.wiki/page.md": "# W\n"} + for n in range(6): + files[f"crates/pkg{n}/README.md"] = "# Crate\n" + repo = make_repo(files) + main([str(repo)]) + out = capsys.readouterr().out + assert "crates/ 6" in out, "the LIST still ranks by count, which shows the shape" + assert "--docs 'project.wiki/**/*.md'" in out + assert "--docs 'crates/**/*.md'" not in out + + +def test_no_documentation_tree_means_no_confident_suggestion( + make_repo: Callable[..., Path], capsys +) -> None: + """`superset-sh/superset` has 276 unread files and not one directory named like + documentation - `apps/ 116`, `plans/ 100`, `packages/ 21`. Naming the biggest would tell + the reader to widen into exactly the package-internal READMEs `find_docs` excludes on + purpose, so the advice would manufacture the findings the scope exists to avoid. + + Both widening routes are still printed, because a reader whose documentation genuinely + lives in an oddly named directory still needs to know how to say so. + """ + files = {"README.md": README, "src/thing.py": "x = 1\n"} + for n in range(4): + files[f"apps/app{n}/README.md"] = "# App\n" + repo = make_repo(files) + main([str(repo)]) + out = capsys.readouterr().out + assert "none of them is named like a documentation tree" in out + assert "--docs 'apps/**/*.md'" not in out + assert "--docs" in out and "[tool.docproof] docs" in out From d29b4694aa2939bdb670c07cc3f44eb57f2ca136 Mon Sep 17 00:00:00 2001 From: melbinjp Date: Wed, 19 Aug 2026 16:16:38 +0530 Subject: [PATCH 2/2] mypy: the suggestion can be absent, so say so in the type --- src/docproof/docs.py | 2 +- tests/test_coverage.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/docproof/docs.py b/src/docproof/docs.py index 6983cb2..a938a61 100644 --- a/src/docproof/docs.py +++ b/src/docproof/docs.py @@ -202,7 +202,7 @@ def by_directory(root: Path, paths: Iterable[Path]) -> list[tuple[str, int]]: ) -def likeliest_docs_directory(groups: list[tuple[str, int]]) -> str: +def likeliest_docs_directory(groups: list[tuple[str, int]]) -> str | None: """Which unread directory to SUGGEST widening to, given (name, count) biggest first. **Measured across the twenty-three repositories of sweep batch 10, 2026-08-19.** They hold diff --git a/tests/test_coverage.py b/tests/test_coverage.py index 9f3eba9..a8b867f 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -207,9 +207,7 @@ def test_full_coverage_adds_no_sentence(make_repo: Callable[..., Path], capsys) assert "were never read" not in out -def test_the_widen_suggestion_names_the_documentation_tree( - make_repo: Callable[..., Path], capsys -) -> None: +def test_the_widen_suggestion_names_the_documentation_tree(make_repo: Callable[..., Path], capsys) -> None: """**Measured over sweep batch 10, twenty-three repositories, 4,819 unread files.** The biggest unread directory in a real project is almost never its documentation: the top segments were `skills/` 429, `tools/` 176, `docs.feldera.com/` 131, `datafusion/` 123, @@ -230,9 +228,7 @@ def test_the_widen_suggestion_names_the_documentation_tree( assert "--docs 'crates/**/*.md'" not in out -def test_no_documentation_tree_means_no_confident_suggestion( - make_repo: Callable[..., Path], capsys -) -> None: +def test_no_documentation_tree_means_no_confident_suggestion(make_repo: Callable[..., Path], capsys) -> None: """`superset-sh/superset` has 276 unread files and not one directory named like documentation - `apps/ 116`, `plans/ 100`, `packages/ 21`. Naming the biggest would tell the reader to widen into exactly the package-internal READMEs `find_docs` excludes on