Skip to content

Tooling excludes on the JavaScript corpus: measured, decision: do not build

Superseded in part (0.29.5): ESLint flat-config ignores plus .prettierignore, corroborated per directory, now ship. Re-measured on this same corpus they still exclude nothing; see 2026-10-19.

Date: 2026-08-11 Build under test: crimes 0.25.3 Question: 0.25.0 shipped honourToolingExcludes for pyproject.toml only. Sprint 0.26 S6 proposed the other three sources (.gitattributes linguist-vendored, tsconfig exclude, and .eslintignore) with the instruction to measure them on hono, cal.com, n8n and posthog first, and to close the entry with a measurement if nothing corroborates.

Decision: nothing corroborates, on any of the four. Do not build the three readers. One separate thing is worth reading, under a different mechanism, and is sized at the end.


repo.gitattributesroot tsconfig.json.eslintignore.prettierignore
honoabsentno exclude (solution-style, references only)absentabsent
cal.com4 linesabsent at rootabsentabsent
n8n1 line (*.sh text eol=lf)**/dist/**/*, **/node_modules/**/*absent19 patterns
posthog42 linesfrontend/dist/**/*, **/*.mdxabsentabsent

Three findings before any corroboration arithmetic runs.

.eslintignore does not exist on this corpus. ESLint 9 replaced it with an ignores key inside flat config, and all four repos have moved on. The plan named a dead format. hono has eslint.config.mjs with no ignores block at all.

Root tsconfig.exclude contributes nothing beyond crimes’ own defaults. Every pattern present names dist or node_modules, which are already excluded, or **/*.mdx, which is not scanned as source. The substance lives in the 12 / 28 / 85 / 86 nested tsconfigs each repo carries, and the root-only rule the pyproject.toml reader established deliberately does not follow those: a nested config governs its own tree, and following it is a separate decision with its own failure modes.

The plan named the wrong .gitattributes attribute. linguist-vendored appears exactly once across the four repos (/.yarn/** in cal.com). linguist-generated appears 30 times (29 in posthog, 1 in cal.com) and names real generated source: protobuf _pb2 modules, an ANTLR-emitted parser, posthog/schema.py, frontend/src/generated/**.

Applying the shipped rule: a pattern counts only when two independent tools name it, with two keys of one tool counting once:

repodistinct normalised patternscorroborated by ≥2 tools
hono00
cal.com20
n8n210
posthog290

The mechanism would exclude nothing, on any repo, however many readers were written. That is the measured answer to S6’s question, and it is cheaper than shipping something nothing triggers.

The corroboration rule is not a formality: it is load-bearing

Section titled “The corroboration rule is not a formality: it is load-bearing”

n8n’s .prettierignore ends:

# Handled by biome
**/*.ts
**/*.js
**/*.json
**/*.jsonc

A reader that treated a formatter’s ignore file as a maintenance claim would exclude 18,783 TypeScript files (the entire n8n codebase) on the strength of a line that means “a different formatter owns these”. The code is maximally maintained. Nothing in the file’s syntax distinguishes that from “this directory is dead”.

This is the general shape of the hazard, and it is why the answer to “decide what corroborates what” is not a table of weights:

.eslintignore, .prettierignore and tsconfig.exclude express a tool’s preferences. linguist-vendored is a display hint for GitHub’s language bar. None of them is a claim about whether the code is maintained — that is an inference the reader adds, and n8n shows what it costs when the inference is wrong.

Corroboration works on pyproject.toml because four tools read one file and agreeing on a path there is cheap evidence. It does not rescue a signal that never meant maintenance in the first place; it only makes a weak signal harder to trigger. On this corpus it makes it impossible.

The one thing worth reading, and why it is a different mechanism

Section titled “The one thing worth reading, and why it is a different mechanism”

linguist-generated is not a preference. It is a factual claim about provenance that the repository makes about its own file: the same kind of claim as an @generated banner or a Code generated by … DO NOT EDIT header, both of which util/scope-class.ts already trusts from a single source. Provenance does not need corroborating; maintenance does. That is the line.

So it belongs in the generated scope class, not in manifest/tooling-excludes.ts, and it needs no corroboration rule.

Sized against what the heuristics already catch: files carrying findings that posthog declares generated and GENERATED_RE misses:

posthog 4 files, 69 findings
52x frontend/src/queries/validators.js
14x frontend/src/products.tsx
2x services/mcp/src/api/generated.ts
1x frontend/src/lib/posthog-typed.ts
cal.com 0 files (its one entry, /.pnp.*, is not scanned)

None of the four matches the path heuristics: validators.js and products.tsx look like ordinary source, and api/generated.ts misses because the pattern wants generated as a directory segment or a .generated.ts suffix. 69 findings on four files a repo has explicitly labelled machine-written is a real result for a reader of about twenty lines.

Done in 0.25.10, as its own change with its own before/after rather than carried in on the back of this negative result. The reader lives in manifest/gitattributes.ts and feeds isNeverReportable: one policy, no new schema surface, and no coverage.warnings[] entry, matching the existing generated-code behaviour. The distinction that settles the warning question: a tooling-excluded path is never analysed, so silence about it is a gap the user cannot see past; a generated file is analysed and its findings simply are not the team’s to fix.

Measured on a clean paired scan, both runs clock-pinned:

posthog 14,250 → 14,181 −69 findings, 0 added, 0 surviving score moved
cal.com 4,633 → 4,633 unchanged (its one entry, /.pnp.*, is not scanned)
removed by detector: large_function 43, exact_duplicate_block 8,
negative_flag_maze 5, option_bag_junk_drawer 5,
large_file 4, boolean_naming_drift 2

Exactly the four files predicted, and the detector breakdown is the point: a machine-written validator accused of having a God Function and badly-named booleans. No eval fixture declares anything generated (04-monorepo has a .gitattributes, but only * text=auto), so evals:ranking is unchanged.

linguist-vendored is still not read: one occurrence across the four repos, and a display hint rather than a claim about authorship.

Implementation note, if anyone does return to tsconfig

Section titled “Implementation note, if anyone does return to tsconfig”

Its exclude is JSONC, and parsing it is not a one-liner. posthog’s root tsconfig.json defeated a comment-stripper that handled /* */ before //, and survived one that handled only //: by luck, since neither copes with // inside a string. A real reader needs a JSONC parser, not a regex. Cost worth knowing before quoting the entry as “small”.