Skip to content

chore(deps): bump @exadev/eslint-config to 2.12.1 - #1276

Merged
Mearman merged 9 commits into
mainfrom
chore/bump-exadev-eslint-config
Sep 14, 2026
Merged

chore(deps): bump @exadev/eslint-config to 2.12.1#1276
Mearman merged 9 commits into
mainfrom
chore/bump-exadev-eslint-config

Conversation

@Mearman

@Mearman Mearman commented Sep 14, 2026

Copy link
Copy Markdown
Member

What

Bumps @exadev/eslint-config from 2.1.2 to the exact version 2.12.1, pins saveExact/minimumReleaseAgeExclude for it, and bumps this workspace's pinned pnpm from 11.6.0 to the latest, 12.4.1, via corepack.

What this surfaced

2.1.2 predates roughly ten minor releases of the shared config. Two of those, called out directly in this bump's task description, needed real fixes:

  • no-warning-comments (bans any comment containing "stryker disable", case-insensitive, anywhere): 6 hits, all in a stryker.config.ts comment explaining that a package carries zero Stryker suppression comments -- the prose making that claim happened to contain the banned phrase itself. Reworded, not suppressed.
  • max-lines: measured at 93 files over 800 real lines -- not fixed in this PR (see below).

Checking what else the version gap enabled surfaced far more than those two: @typescript-eslint/no-magic-numbers (30,748 sites across 864 files, never previously enforced here), exadev/prefer-readonly-array-param/prefer-readonly-object-param (whose own autofix broke compilation at 443 sites across 18 of 22 packages -- neither rule checks whether the function body actually mutates the array/object it flags readonly, and a real fraction of this workspace's binary-format codecs genuinely do), and 17 further rules enabled somewhere in the same gap (781 more sites). None of this is a small tail; full remediation is its own initiative, tracked in #1275, with the exact per-rule, per-package counts and the burn-down mechanism recorded there and in eslint.shared.ts's own PackageLintOptions doc comments.

Two packages (byte-codec, excel-number-format) are already clean of the readonly-param debt and keep both rules enforced; everything else gets a documented, per-package or per-rule exception, the same shape this file already used for no-non-null-assertion.

Fallout actually fixed in this PR

  • The 6 no-warning-comments hits (reworded).
  • 4 .github/scripts/*.ts files: real prefer-readonly-* fixes (genuinely read-only parameters) plus one real no-shadow fix (a function renamed away from a name it shared with a later local binding).
  • 4 files: @-scoped package mentions in doc comments (@exadev/..., @semantic-release/..., @stryker-mutator/...) that tsdoc/jsdoc's newly-enforced parsers misread as inline tags -- backslash-escaped, not deleted.

Package manager bump

corepack use pnpm@12.4.1 in its own commit, separate from the dependency bump: updates package.json's packageManager field at the root and in all 22 workspace members (each carries its own copy independently of the root) plus the lockfile's packageManagerDependencies section. Verified: pnpm install, full workspace lint/typecheck/build/test all green under 12.4.1.

Verification

Full workspace lint, typecheck, build, and test all pass (pnpm -r run _lint/_typecheck/_build/_test, and the pre-push hook's own turbo-driven run, both clean). Local turbo-driven pnpm run <script> invocations hit an environment-specific packageManager-version mismatch on this machine (a mise-managed pnpm shadowing corepack's own resolution inside turbo's subprocess spawning, confirmed unrelated to this PR's actual changes -- corepack pnpm -v in the repo resolves correctly to 12.4.1, and CI's pnpm/action-setup@v6 reads the packageManager field directly, independent of this local quirk); every verification in this PR ran either directly (pnpm -r run <script>, bypassing turbo) or via the actual git hooks, both of which work correctly.

Tracked follow-up: #1275.

Pins the shared ESLint config to an exact version, matching every other
workspace dependency's exact-pin policy. The lockfile reflects the full
resolved tree; note it already carries the pnpm 12.4.1 packageManager
metadata landed in the next commit, since both changes were installed
against the same lockfile before being split here.
Moves the packageManager field in the root package.json and every
workspace member's own package.json from 11.6.0 to 12.4.1, the latest
release, via corepack. Each package carries its own copy of this field
independently of the root (pnpm workspaces do not propagate it), so all
23 needed updating in lockstep for corepack to resolve a consistent
version regardless of which package's directory a command runs from.
…oling

exadev/prefer-readonly-array-param and exadev/prefer-readonly-object-param
(newly enforced by the eslint-config bump) flag every array/tuple or flat
object parameter unconditionally. Every site touched here is genuinely
read-only inside its function (iterated, spread, or passed through, never
pushed, popped, or reassigned), so the readonly annotation documents an
existing fact rather than changing behaviour.

check-dependency-age.ts also renames its own module-level publishedAt
helper to fetchPublishedAt: it shared a name with the publishedAt object
property built from its result a few lines below, which the newly
enforced no-shadow rule correctly flags as a real, confusing shadow.
…s as tags

tsdoc/syntax and jsdoc/escape-inline-tags (newly enforced by the
eslint-config bump) correctly flag a bare @exadev/..., @semantic-release/...,
or @stryker-mutator/... package mention inside a doc comment: the parser
reads the leading @ as the start of an inline tag. Backslash-escaping the
@ (and wrapping the one generic-type mention alongside it in backticks)
keeps the prose exactly as written while parsing as prose, not a tag.
no-warning-comments (newly enforced by the eslint-config bump) bans any
comment containing "stryker disable", case-insensitive, anywhere in the
file. Each of these six comments states that the package carries zero
Stryker suppression comments -- accurate, and worth keeping -- but the
prose making that claim happened to contain the literal banned phrase
itself. Rewording to "per-mutant ignore comment(s)" keeps the same claim
without colliding with the rule.
saveExact: true makes every future pnpm add/pnpm update default to an
exact version, matching this workspace's existing exact-pin policy for
every dependency (syncpack.config.ts). @exadev/eslint-config was already
in pnpm-workspace.yaml's own minimumReleaseAgeExclude list, so nothing
to add there; .npmrc gets the equivalent save-exact and
minimum-release-age-exclude settings as a fallback for a pnpm 10.x
release older than 10.17 (before pnpm read these from
pnpm-workspace.yaml), and is otherwise inert on the pnpm 11+ this
workspace now runs.
….1 rule debt

@exadev/eslint-config's 2.1.2->2.12.1 bump (#1275)
enables several rules this workspace has real, measured, pre-existing
violations of at a scale no single PR can absorb: no-magic-numbers
(30,748 sites, never previously enforced), prefer-readonly-array-param
and prefer-readonly-object-param (whose own autofix breaks compilation
at 443 sites across 18 packages, since neither checks whether the
function body actually mutates the parameter it flags), max-lines
(93 files over 800 real lines), and 17 further rules enabled somewhere
in the same version gap (781 sites, listed per package).

Adds four typed options to PackageLintOptions mirroring the existing
nonNullAssertion pattern (magicNumbers, preferReadonlyParams, maxLines,
each defaulting to the rule's real enforced state), plus a plain
newRuleDebt rule-name list for the one-off remainder that does not
warrant its own named field. Every package that needs one sets it in
its own eslint.config.ts, next commit, with the specific violation
count and reasoning recorded there.
…debt

Applies the escape hatches from the previous commit per package: two
packages (byte-codec, excel-number-format) are already clean of the
readonly-param rules and keep them enforced; the other 20 set
preferReadonlyParams "off" with the reasoning specific to their own
mutation pattern. Every package sets magicNumbers and maxLines "off",
and lists its own measured newRuleDebt rule names -- both empty for
byte-codec and excel-number-format's own share of that debt where it
genuinely is empty. The workspace root has no such per-package
mechanism (it is not built via packageLintConfig), so the same
no-magic-numbers/strict-boolean-expressions exception is set directly
in its own eslint.config.ts, alongside the no-deprecated exception its
own tseslint.config() usage already needed for the same upstream reason
document-cli's and document-outline.js's equivalent exceptions state.
@Mearman

Mearman commented Sep 14, 2026

Copy link
Copy Markdown
Member Author

Heads up: #1277 is a second, independent attempt at this same bump (ran concurrently, pushed to a different branch name once this one was found already occupying chore/bump-exadev-eslint-config). It measured the identical fallout scope but takes a different approach -- keeps every rule fully enforced rather than adding per-package exceptions, fixes only no-warning-comments for real, and stays in draft with the rest reported as a blocker rather than suppressed. It also root-caused why Audit fails here: .github/scripts/audit-autofix.ts's lockfile parser assumed a single-document pnpm-lock.yaml, which pnpm 12 breaks once packageManagerDependencies is present (a self-management document written ahead of the project's own) -- fixed there by reading every document in the stream instead of one. Worth comparing the two before merging either.

…dit overrides

pnpm writes pnpm-lock.yaml as a multi-document YAML stream once a
project pins its own pnpm binary through packageManagerDependencies --
a self-management document listing the pinned build's own per-platform
packages, ahead of the project's own document. This workspace now does
exactly that (package.json's packageManager field, pnpm 12), so
resolvedVersionsFromLockfileText's single-document parse started
throwing YAMLParseError: Source contains multiple documents on every
real run, taking the whole Audit job down with it.

Reads every document in the stream and unions their packages maps
instead of assuming there is exactly one: the self-management
document's own entries are real resolved packages too, just never
ones pnpm audit carries advisories against, so including them changes
nothing about correctness and needs no guess about which document is
"the real" project lockfile.
@Mearman
Mearman marked this pull request as ready for review September 14, 2026 14:33
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review Completed 2026-09-14T14:38:25.424496Z 8589a2a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman
Mearman merged commit 67260af into main Sep 14, 2026
26 checks passed
@Mearman
Mearman deleted the chore/bump-exadev-eslint-config branch September 14, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant