Why this matters
nodejs/node is the canonical mature C++/JS hybrid mega-repo — 15 years of accumulated convention discipline, with structural validation scattered across the broadest surface alint has linted in any case study: a 1,700-line Makefile, 25 GitHub Actions workflows, 27 in-tree custom eslint rules, 7 per-tier eslint partials, a vendored Google cpplint fork, a remark-lint pipeline, ruff, yamllint, lint-md, lint-pr-url, lint-readme-lists, lint-sh, find-inactive-collaborators — and an unwritten test/parallel/test-*.{js,mjs,cjs} discovery filename grammar enforced statically by exactly nothing.
This is the canonical “conventions without checks” repo. The discipline is real; the enforcement is institutional knowledge.
Headline catch
The two most alint-shaped surfaces in node’s 15-year-old structural-validation surface are enforced statically by nothing.
test/parallel/test-*.{js,mjs,cjs}discovery grammar.tools/test.pyglobs fortest-*.{js,mjs,cjs}to discover regression tests. A misnamed file (tst-foo.js,text-foo.js,Test-Foo.js) silently drops out of the test run. The only feedback today is a missing test failing to fire when an intentionally-broken regression test goes silent. alint encodes the grammar as a 6-linefilename_regexrule.
doc/changelogs/CHANGELOG_V<MAJOR>.mdper-major-version convention. 27 changelog files at clone time. Editorial review of the release-prep PR catches typos today; a hand-editedCHANGELOG_v27.md(lowercase) orCHANGELOG_V27(no extension) could merge accidentally without alint’sfilename_regexrule.Maturity is the hard test. node has every conceivable convention pinned somewhere — and alint expresses the 43% that’s structural cleanly without overstepping.
Where alint earns its keep here
- The orchestration layer is one declarative file. A new node contributor today reads the 1,700-line Makefile, 25 workflows, 27 custom eslint rules, 7 per-tier eslint partials, the
.gitattributestable, the.editorconfig, thetools/lint-*.mjshelpers, the vendoredtools/cpplint.py+tools/checkimports.py, thetools/lint-md/remark pipeline, andpyproject.tomlto understand what rules apply where. The alint config covers the structural 43% of that in one file. - The boundary is honest at every layer. All 27 in-tree custom eslint rules under
tools/eslint-rules/are TSESTree visitors — alint deliberately doesn’t compete. cpplint, clang-format, ruff, yamllint, lint-md, shellcheck — each stays where it is, shelled out viacommand:. node’s 15-year-old institutional choices are respected; alint sits beneath them as the structural-orchestration layer. - Net-new enforcement on conventions the existing pipeline assumes but doesn’t verify. Beyond the test-discovery + per-major-changelog headlines:
src/node_version.hmacro types (NODE_MAJOR_VERSION 27not27.0— a typo today breaksnode --versionsilently);tools/lint-md/package.jsondeps pinning (a missingremark-preset-lint-nodepin silently drops most of the markdown-lint rules); per-tiereslint.config_partial.mjspresence (catches silent-coverage-drop on tier deletion). - The maturity narrative. Repos so old that the conventions have always worked, but where a new contributor has no single place to read them. node sits at the intersection of all four positioning narratives — script-sprawl, conventions-without-checks, structural-floor, and maturity — and the alint pitch lands as: “we sit beneath your existing linters as the structural-orchestration layer, we collapse the hand-rolled scripts you’ve outgrown, we surface the conventions your tooling assumes but never checks, AND we make 15 years of institutional discipline legible to a contributor reading the repo for the first time.”
Future story angles
- node’s
tools/eslint-rules/*↔eslint.config.mjscross-file registration is one of the densest demand signals forcross_file_value_equalsin the v0.10 candidate list — 27 source files all referenced by string-literal paths in the registry. Now a v0.10 ship-target with 10 sources past saturation; node is one of the most adopter-visible instances. - node’s
tools/dep_updaters/update-<libname>.{sh,mjs}↔deps/<libname>/is one of the canonical sources forregistry_paths_resolve— every key in a registry directory must resolve to an on-disk artefact in a partner directory. Now a v0.10 ship-target at 8 sources. - A NEW v0.10+ candidate surfaced uniquely by node:
file_header_consistency(or, equivalently,file_header.alt_pattern). The historical Joyent BSD/MIT banner insrc/**/*.{cc,h}has drifted — 56 of 268 files still carry it; the rest have moved to a “no banner, just#includeand#ifndefguard” convention. Niche; the cleaner outcome is a one-time editorial sweep.