From 5aef703669b4521f431fe74f6ef8326c828211a2 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sat, 10 Oct 2026 07:14:48 +0100 Subject: [PATCH 1/3] fix: list every commit type in the release notes and CHANGELOG.md The angular preset's transform returns undefined for every type except feat, fix, perf and revert, so a release made of refactor, docs, test, build, ci, style or chore commits published a version header and nothing under it. The notes now keep the preset's templates and replace its transform: each type in commitTypes gets a section titled from the same table, in the table's order, and chore(release) commits are left out. The header pattern accepts a `!` after the type, as the commit analyser's does, so a breaking `feat!:` commit is read the same way in both. The conventionalcommits preset stays rejected: its templates are functions, which the conventional-changelog-writer bundled with the release-notes generator does not call, so its output has section titles with no commits under them. The release-notes generator becomes a direct devDependency so tests can run it. --- README.md | 4 +- package.json | 1 + pnpm-lock.yaml | 3 + release.config.ts | 165 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 156 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index acd9c54d..81177d9c 100644 --- a/README.md +++ b/README.md @@ -1825,7 +1825,7 @@ pnpm build - [`eslint.config.ts`](eslint.config.ts) dogfoods this package's own factory export on itself (`import { exadevConfig } from './src/index'`), spreading `exadevConfig({ react: false, nextjs: false, ... })`, with the [tooling wiring](#tooling-wiring) preset on for the sections it uses. React and Next.js are forced off explicitly, not left to the plain auto-detecting default, since `eslint-plugin-react`/`@next/eslint-plugin-next` are real devDependencies of *this* repo (needed to test [`src/react.ts`](src/react.ts)/[`src/nextjs.ts`](src/nextjs.ts)'s own "package is resolvable" branch) even though this repo is neither a React nor a Next.js project. `no-side-effects-in-index` and `no-non-barrel-reexport` self-scope to [`src/index.ts`](src/index.ts) internally, so no `files`/`ignores` wiring is needed here. Plugin construction lives in [`src/plugin.ts`](src/plugin.ts) specifically so `src/index.ts` stays a pure re-export point. - [`tsconfig.json`](tsconfig.json) enables [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) (`import type`/`export type` required for type-only imports — also enforced by `consistent-type-imports`) and [`noUncheckedIndexedAccess`](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess) (narrow indexed access before use rather than asserting). -- Conventional commits are enforced by [commitlint](https://commitlint.js.org), restricted to the type-enum defined once in [`release.config.ts`](release.config.ts)'s `commitTypes` — both commitlint and semantic-release derive from that single list. +- Conventional commits are enforced by [commitlint](https://commitlint.js.org), restricted to the type-enum defined once in [`release.config.ts`](release.config.ts)'s `commitTypes` — commitlint, the release rules and the release notes' section titles all derive from that single list. ### Gotchas and quirks @@ -1842,7 +1842,7 @@ Conventional commits are enforced by a husky `commit-msg` hook and re-checked in ### Release -Conventional commits drive [semantic-release](https://semantic-release.gitbook.io/semantic-release) on every push to `main`: version bump, `CHANGELOG.md`, GitHub Release, and npm publish via [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers) (no stored token). The release commit and tag are pushed over SSH with a repository deploy key that bypasses the `main` ruleset; the key is written to the runner's temporary directory only by the step directly before semantic-release (checkout does not receive it and persists no credentials) and removed afterwards, and the job's actions are pinned to commit SHAs. This narrows the key's exposure without isolating it: code run by an earlier step, or by semantic-release and its plugins from `node_modules`, can still reach it, so a credential that does not outlive the job (a short-lived GitHub App installation token) remains the complete fix. A second CI job republishes the identical build under the unscoped alias `exadev-eslint-config`. +Conventional commits drive [semantic-release](https://semantic-release.gitbook.io/semantic-release) on every push to `main`: version bump, `CHANGELOG.md`, GitHub Release, and npm publish via [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers) (no stored token). The release commit and tag are pushed over SSH with a repository deploy key that bypasses the `main` ruleset; the key is written to the runner's temporary directory only by the step directly before semantic-release (checkout does not receive it and persists no credentials) and removed afterwards, and the job's actions are pinned to commit SHAs. This narrows the key's exposure without isolating it: code run by an earlier step, or by semantic-release and its plugins from `node_modules`, can still reach it, so a credential that does not outlive the job (a short-lived GitHub App installation token) remains the complete fix. A second CI job republishes the identical build under the unscoped alias `exadev-eslint-config`. The release notes and `CHANGELOG.md` list every commit under the section titled for its type in `commitTypes` ([`release.config.ts`](release.config.ts)), in that list's order, so a release made only of `refactor`, `docs`, `test` or `chore` commits still has a body; the `chore(release)` commits are the one exclusion. The notes use the `angular` preset's layout with its commit transform replaced, because that preset hides every type but `feat`, `fix`, `perf` and `revert`; the `conventionalcommits` preset is not used, because the writer bundled with the release-notes generator does not render its templates. ## License diff --git a/package.json b/package.json index ce4a64b3..9c9c04dd 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@next/eslint-plugin-next": "^16.3.2", "@semantic-release/changelog": "^7.0.0", "@semantic-release/git": "^11.0.1", + "@semantic-release/release-notes-generator": "14.1.1", "@stryker-mutator/api": "10.0.0", "@stryker-mutator/core": "10.0.0", "@stryker-mutator/typescript-checker": "10.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e07439db..f212fa1a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -233,6 +233,9 @@ importers: '@semantic-release/git': specifier: ^11.0.1 version: 11.0.1(semantic-release@25.0.9(supports-color@7.2.0)(typescript@6.0.3))(supports-color@7.2.0) + '@semantic-release/release-notes-generator': + specifier: 14.1.1 + version: 14.1.1(semantic-release@25.0.9(supports-color@7.2.0)(typescript@6.0.3))(supports-color@7.2.0) '@stryker-mutator/api': specifier: 10.0.0 version: 10.0.0 diff --git a/release.config.ts b/release.config.ts index 2a3de894..3cef7c72 100644 --- a/release.config.ts +++ b/release.config.ts @@ -5,27 +5,155 @@ type ReleaseLevel = 'major' | 'minor' | 'patch' | false; interface CommitType { readonly type: string; readonly release: ReleaseLevel; + /** Heading of the section that lists this type's commits in the release notes and CHANGELOG.md. */ + readonly title: string; } /** - * Single source of truth for the conventional-commit types this project uses. commitlint's allowed type-enum (commitlint.config.ts imports this) and commit-analyzer's releaseRules below both derive from it, so a type can't trigger a release without also being accepted by commit-msg validation, or the reverse. Mirrors the identical pattern in documents.js/ooxml.js/etc. + * Single source of truth for the conventional-commit types this project uses. commitlint's allowed type-enum (commitlint.config.ts imports this), commit-analyzer's releaseRules and the release notes' sections below all derive from it, so a type can't trigger a release without also being accepted by commit-msg validation, or appear in a release without a section in its notes. The order is the order of the sections in the notes. Mirrors the identical pattern in documents.js/ooxml.js/etc. */ export const commitTypes: readonly CommitType[] = [ - { type: 'feat', release: 'minor' }, - { type: 'fix', release: 'patch' }, - { type: 'perf', release: 'patch' }, - { type: 'revert', release: 'patch' }, - { type: 'refactor', release: 'patch' }, - { type: 'docs', release: 'patch' }, - { type: 'style', release: 'patch' }, - { type: 'test', release: 'patch' }, - { type: 'build', release: 'patch' }, - { type: 'ci', release: 'patch' }, - { type: 'chore', release: 'patch' }, + { type: 'feat', release: 'minor', title: 'Features' }, + { type: 'fix', release: 'patch', title: 'Bug Fixes' }, + { type: 'perf', release: 'patch', title: 'Performance Improvements' }, + { type: 'revert', release: 'patch', title: 'Reverts' }, + { type: 'refactor', release: 'patch', title: 'Code Refactoring' }, + { type: 'docs', release: 'patch', title: 'Documentation' }, + { type: 'style', release: 'patch', title: 'Styles' }, + { type: 'test', release: 'patch', title: 'Tests' }, + { type: 'build', release: 'patch', title: 'Build System' }, + { type: 'ci', release: 'patch', title: 'Continuous Integration' }, + { type: 'chore', release: 'patch', title: 'Chores' }, ]; /** - * Runs on `main`. Analyses commits since the last tag, bumps the version, publishes to npmjs.org (trusted OIDC publishing, no stored token -- see .github/workflows/ci.yml), creates a versioned tag and GitHub Release with generated notes, and commits CHANGELOG.md + package.json back to main. + * Type and scope of the commit semantic-release makes to publish CHANGELOG.md and package.json. It is a release artefact, not a change, so the notes leave it out; a range read by hand (a backfill, a re-run) contains the commits of earlier releases. + */ +export const releaseCommit = { type: 'chore', scope: 'release' } as const; + +const sectionTitles = commitTypes.map((t) => t.title); +const revertTitle = commitTypes.find((t) => t.type === 'revert')?.title; + +/** The fields of a commit parsed by conventional-commits-parser (plus the hash semantic-release adds) that the notes' transform reads. */ +interface ParsedCommit { + readonly type?: string | null | undefined; + readonly scope?: string | null | undefined; + readonly subject?: string | null | undefined; + readonly hash?: string | null | undefined; + readonly revert: object | null; + readonly notes: readonly { readonly title: string; readonly text: string }[]; + readonly references: readonly { readonly issue: string }[]; +} + +/** The part of the changelog context that links in a commit subject are built from. */ +interface NotesContext { + readonly host?: string; + readonly owner?: string; + readonly repository?: string; + readonly repoUrl?: string; +} + +/** A commit in the shape the angular preset's templates render. */ +interface ListedCommit { + readonly notes: readonly { readonly title: string; readonly text: string }[]; + readonly type: string; + readonly scope: string | null | undefined; + readonly shortHash: string | undefined; + readonly subject: string | undefined; + readonly references: readonly { readonly issue: string }[]; +} + +/** A group of commits under one section title, as the writer sorts them. */ +interface CommitGroup { + readonly title: string; +} + +const SHORT_HASH_LENGTH = 7; + +/** + * Turns a subject's `#123` references into issue links. Returns the new subject and the issue numbers it linked, so the caller can drop them from the references printed after the subject. + * @param subject - The commit subject. + * @param context - The changelog context that names the repository. + * @returns The subject with issue links, and the linked issue numbers. + */ +function linkIssues(subject: string, context: NotesContext): { readonly subject: string; readonly issues: readonly string[] } { + const repositoryUrl = context.repository === undefined ? context.repoUrl : `${context.host ?? ''}/${context.owner ?? ''}/${context.repository}`; + if (repositoryUrl === undefined || repositoryUrl === '') { + return { subject, issues: [] }; + } + const issues: string[] = []; + const linked = subject.replace(/#([0-9]+)/g, (_match, issue: string) => { + issues.push(issue); + + return `[#${issue}](${repositoryUrl}/issues/${issue})`; + }); + + return { subject: linked, issues }; +} + +/** + * Turns a subject's `@user` mentions into profile links, leaving code spans and `@scope/name` package names alone. + * @param subject - The commit subject. + * @param host - The repository host, such as `https://github.com`. + * @returns The subject with mention links. + */ +function linkUsers(subject: string, host: string): string { + return subject.replace(/`[^`]*`|\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (match, username: string | undefined) => { + if (username === undefined) { + return match; + } + + return username.includes('/') ? `@${username}` : `[@${username}](${host}/${username})`; + }); +} + +/** + * Decides which commits reach the release notes and under which section. It replaces the transform of the `angular` preset, which returns `undefined` for every type but feat, fix, perf and revert (and for any commit without a breaking change), so a release made of other types had an empty body. Here every type in `commitTypes` is listed under its title, and only release commits and commits that are not conventional commits are left out. The returned shape, the issue and user links and the short hash follow the preset's own transform (conventional-changelog-angular, src/writer.js), because the preset's templates render them. + * @param commit - The commit as parsed by conventional-commits-parser. + * @param context - The changelog context built by the release-notes generator. + * @returns The commit as the preset's templates expect it, or `undefined` when it is not listed. + */ +export function transformCommit(commit: ParsedCommit, context: NotesContext): ListedCommit | undefined { + if (commit.type === releaseCommit.type && commit.scope === releaseCommit.scope) { + return undefined; + } + const title = commit.revert === null ? commitTypes.find((t) => t.type === commit.type)?.title : revertTitle; + if (title === undefined) { + return undefined; + } + + let subject: string | undefined; + let issues: readonly string[] = []; + if (typeof commit.subject === 'string') { + ({ subject, issues } = linkIssues(commit.subject, context)); + if (context.host !== undefined) { + subject = linkUsers(subject, context.host); + } + } + + return { + notes: commit.notes.map((note) => ({ ...note, title: 'BREAKING CHANGES' })), + type: title, + scope: commit.scope === '*' ? '' : commit.scope, + shortHash: commit.hash?.substring(0, SHORT_HASH_LENGTH), + subject, + // References that already appear as a link in the subject are not repeated after it. + references: commit.references.filter((reference) => !issues.includes(reference.issue)), + }; +} + +/** + * Orders the sections of a release's notes as `commitTypes` does, instead of alphabetically as the angular preset does. + * @param a - A commit group titled with one of the `commitTypes` titles. + * @param b - The group compared with it. + * @returns Negative when `a` is listed before `b`. + */ +export function compareSections(a: CommitGroup, b: CommitGroup): number { + return sectionTitles.indexOf(a.title) - sectionTitles.indexOf(b.title); +} + +/** + * Runs on `main`. Analyses commits since the last tag, bumps the version, publishes to npmjs.org (trusted OIDC publishing, no stored token; see .github/workflows/ci.yml), creates a versioned tag and GitHub Release with generated notes, and commits CHANGELOG.md + package.json back to main. */ const config: Options = { branches: ['main'], @@ -42,8 +170,15 @@ const config: Options = { [ '@semantic-release/release-notes-generator', { - // Deliberately angular, not conventionalcommits -- see documents.js's identical note: conventional-changelog-writer's bundled commit partial doesn't match the conventionalcommits preset's function-based partial signature, producing a changelog with a version header and nothing under it. + // The angular preset's layout (templates, heading levels, link style) with its transform replaced, so every type in commitTypes is listed. Not the conventionalcommits preset: its templates are functions, which the conventional-changelog-writer that @semantic-release/release-notes-generator bundles does not call, so a changelog built from it has a version header and section titles with no commits under them (checked against the installed releases of both). preset: 'angular', + // The header patterns of the conventionalcommits preset that commit-analyzer above uses, so a commit the analyser reads as breaking (`feat!:`) is read the same here. The angular preset's own pattern does not accept `!`, which would drop such a commit from the notes. + parserOpts: { + headerPattern: /^(\w*)(?:\((.*)\))?!?: (.*)$/, + breakingHeaderPattern: /^(\w*)(?:\((.*)\))?!: (.*)$/, + noteKeywords: ['BREAKING CHANGE', 'BREAKING-CHANGE'], + }, + writerOpts: { transform: transformCommit, commitGroupsSort: compareSections }, }, ], '@semantic-release/changelog', @@ -53,7 +188,7 @@ const config: Options = { '@semantic-release/git', { assets: ['CHANGELOG.md', 'package.json'], - message: 'chore(release): ${nextRelease.version} [skip ci]', + message: `${releaseCommit.type}(${releaseCommit.scope}): \${nextRelease.version} [skip ci]`, }, ], ], From d809c822697ee9a5092461959edb83db136c7234 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sat, 10 Oct 2026 07:15:05 +0100 Subject: [PATCH 2/3] test: run the real release-notes generator over every commit type The test builds the notes through @semantic-release/release-notes-generator with the options in release.config.ts, and asserts the exact notes for one commit of every type, a release made of types the angular preset hides, a breaking change, issue and mention links, a release commit in the range, and commits that are not conventional commits. tsconfig.json now includes root test files and declaration files so the test is type-checked and linted beside release.config.ts. --- release-notes-generator.d.ts | 15 ++++ release.config.unit.test.ts | 154 +++++++++++++++++++++++++++++++++++ tsconfig.json | 2 +- 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 release-notes-generator.d.ts create mode 100644 release.config.unit.test.ts diff --git a/release-notes-generator.d.ts b/release-notes-generator.d.ts new file mode 100644 index 00000000..c69dbe39 --- /dev/null +++ b/release-notes-generator.d.ts @@ -0,0 +1,15 @@ +/** + * The release-notes generator plugin ships no type declarations. This declares the one function release.config.unit.test.ts calls, with the context fields that function reads. + */ +declare module '@semantic-release/release-notes-generator' { + export function generateNotes( + pluginConfig: Readonly>, + context: { + readonly cwd: string; + readonly commits: readonly { readonly hash: string; readonly message: string }[]; + readonly options: { readonly repositoryUrl: string }; + readonly lastRelease: { readonly gitTag: string }; + readonly nextRelease: { readonly gitTag: string; readonly version: string }; + }, + ): Promise; +} diff --git a/release.config.unit.test.ts b/release.config.unit.test.ts new file mode 100644 index 00000000..d49f676a --- /dev/null +++ b/release.config.unit.test.ts @@ -0,0 +1,154 @@ +import { generateNotes } from '@semantic-release/release-notes-generator'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { isRecord } from './src/is-record'; +import config, { commitTypes, releaseCommit } from './release.config'; + +const NOTES_PLUGIN = '@semantic-release/release-notes-generator'; + +/** The hash of a synthetic commit is its two digit position in the list followed by this tail, which makes a full 40 character hash. */ +const HASH_TAIL = 'abcdef0123456789abcdef0123456789abcdef'; + +/** The options release.config.ts hands to the release-notes generator, read out of the plugin list the way semantic-release reads it. */ +function notesPluginConfig(): Readonly> { + for (const plugin of config.plugins ?? []) { + if (Array.isArray(plugin) && plugin[0] === NOTES_PLUGIN && isRecord(plugin[1])) { + return plugin[1]; + } + } + throw new Error(`${NOTES_PLUGIN} is not configured in release.config.ts`); +} + +/** Notes for `messages`, one commit each (the first is the newest, as `git log` lists them), through the real generator. */ +async function notesFor(messages: readonly string[]): Promise { + return await generateNotes(notesPluginConfig(), { + cwd: process.cwd(), + commits: messages.map((message, index) => ({ hash: `${String(index + 1).padStart(2, '0')}${HASH_TAIL}`, message })), + options: { repositoryUrl: 'git@github.com:ExaDev/eslint-config.git' }, + lastRelease: { gitTag: 'v1.0.0' }, + nextRelease: { gitTag: 'v1.0.1', version: '1.0.1' }, + }); +} + +describe('release notes', () => { + beforeEach(() => { + vi.useFakeTimers({ toFake: ['Date'] }); + vi.setSystemTime(new Date('2026-01-02T12:00:00Z')); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('lists every commit type under its own section, in the order of commitTypes', async () => { + const messages = commitTypes.map((t) => `${t.type}: ${t.title} change`); + const notes = await notesFor(messages); + + expect(notes).toBe(`## [1.0.1](https://github.com/ExaDev/eslint-config/compare/v1.0.0...v1.0.1) (2026-01-02) + + +### Features + +* Features change ([01abcde](https://github.com/ExaDev/eslint-config/commit/01abcdef0123456789abcdef0123456789abcdef)) + + +### Bug Fixes + +* Bug Fixes change ([02abcde](https://github.com/ExaDev/eslint-config/commit/02abcdef0123456789abcdef0123456789abcdef)) + + +### Performance Improvements + +* Performance Improvements change ([03abcde](https://github.com/ExaDev/eslint-config/commit/03abcdef0123456789abcdef0123456789abcdef)) + + +### Reverts + +* Reverts change ([04abcde](https://github.com/ExaDev/eslint-config/commit/04abcdef0123456789abcdef0123456789abcdef)) + + +### Code Refactoring + +* Code Refactoring change ([05abcde](https://github.com/ExaDev/eslint-config/commit/05abcdef0123456789abcdef0123456789abcdef)) + + +### Documentation + +* Documentation change ([06abcde](https://github.com/ExaDev/eslint-config/commit/06abcdef0123456789abcdef0123456789abcdef)) + + +### Styles + +* Styles change ([07abcde](https://github.com/ExaDev/eslint-config/commit/07abcdef0123456789abcdef0123456789abcdef)) + + +### Tests + +* Tests change ([08abcde](https://github.com/ExaDev/eslint-config/commit/08abcdef0123456789abcdef0123456789abcdef)) + + +### Build System + +* Build System change ([09abcde](https://github.com/ExaDev/eslint-config/commit/09abcdef0123456789abcdef0123456789abcdef)) + + +### Continuous Integration + +* Continuous Integration change ([10abcde](https://github.com/ExaDev/eslint-config/commit/10abcdef0123456789abcdef0123456789abcdef)) + + +### Chores + +* Chores change ([11abcde](https://github.com/ExaDev/eslint-config/commit/11abcdef0123456789abcdef0123456789abcdef)) +`); + }); + + it('gives a release made only of types the angular preset hides a body', async () => { + const notes = await notesFor(['refactor: split the parser', 'test: cover the splitter', 'docs: describe the split']); + + expect(notes).toContain('### Code Refactoring\n\n* split the parser ('); + expect(notes).toContain('### Documentation\n\n* describe the split ('); + expect(notes).toContain('### Tests\n\n* cover the splitter ('); + }); + + it('leaves the release commit out, even in a range that contains earlier release commits', async () => { + const releaseMessage = `${releaseCommit.type}(${releaseCommit.scope}): 1.0.0 [skip ci]`; + const notes = await notesFor([releaseMessage, 'chore(deps): bump left-pad from 1.0.0 to 1.1.0', 'fix: handle an empty list']); + + expect(notes).not.toContain('1.0.0 [skip ci]'); + expect(notes).not.toContain('release'); + expect(notes).toContain('### Chores\n\n* **deps:** bump left-pad from 1.0.0 to 1.1.0 ('); + expect(notes).toContain('### Bug Fixes\n\n* handle an empty list ('); + }); + + it('keeps dependabot build(deps) commits', async () => { + const notes = await notesFor(['build(deps): bump vite from 7.0.0 to 7.0.1']); + + expect(notes).toContain('### Build System\n\n* **deps:** bump vite from 7.0.0 to 7.0.1 ('); + }); + + it('lists a breaking change under its type and in a BREAKING CHANGES section', async () => { + const notes = await notesFor(['refactor!: drop the legacy entry point\n\nBREAKING CHANGE: the legacy entry point is gone']); + + expect(notes).toContain('### Code Refactoring\n\n* drop the legacy entry point ('); + expect(notes).toContain('### BREAKING CHANGES\n\n* the legacy entry point is gone'); + }); + + it('links an issue number in a subject and a mention of a user', async () => { + const notes = await notesFor(['fix: handle the case from #12 reported by @someone']); + + expect(notes).toContain('* handle the case from [#12](https://github.com/ExaDev/eslint-config/issues/12) reported by [@someone](https://github.com/someone) ('); + }); + + it('leaves out a commit that is not a conventional commit', async () => { + const notes = await notesFor(['Merge branch main into feature', 'fix: keep the merge target']); + + expect(notes).not.toContain('Merge branch'); + expect(notes).toContain('### Bug Fixes\n\n* keep the merge target ('); + }); + + it('puts a revert commit under Reverts', async () => { + const notes = await notesFor(['Revert "feat: add the flag"\n\nThis reverts commit 1234567890abcdef1234567890abcdef12345678.']); + + expect(notes).toContain('### Reverts\n\n* '); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index ba588c9f..e41bfd49 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,5 +26,5 @@ "types": ["node"], "verbatimModuleSyntax": true }, - "include": ["src", "*.config.ts", "vitest.setup.ts"] + "include": ["src", "*.config.ts", "*.test.ts", "*.d.ts", "vitest.setup.ts"] } From acce1bdc7158089add22d7855ca73fafc1bb2c8a Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sat, 10 Oct 2026 07:15:34 +0100 Subject: [PATCH 3/3] docs: regenerate CHANGELOG.md with every commit of each release Each version's entry is rebuilt from its tag range by the release-notes configuration in release.config.ts, so releases whose commits were all of a type the angular preset hid now list them, and every earlier commit is carried over. Sections follow the order of commitTypes. --- CHANGELOG.md | 883 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 798 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b7a7b6..8113db38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,32 @@ ## [2.36.4](https://github.com/ExaDev/eslint-config/compare/v2.36.3...v2.36.4) (2026-10-10) + +### Code Refactoring + +* validate patterns with a RegExp call instead of voiding a construction ([6ef84c1](https://github.com/ExaDev/eslint-config/commit/6ef84c1f55d7544cc398aa97b3dab8011fccf314)) + + +### Tests + +* assert what the plugin configs getters return instead of voiding them ([fcb9c89](https://github.com/ExaDev/eslint-config/commit/fcb9c8934efc98b9dddd93f3c172e97fad9752f6)) + + +### Chores + +* **deps:** bump the minor-and-patch group across 1 directory with 16 updates ([5f0bb78](https://github.com/ExaDev/eslint-config/commit/5f0bb78e986403c07cc4bc27d48eabec0e0cc217)) + ## [2.36.3](https://github.com/ExaDev/eslint-config/compare/v2.36.2...v2.36.3) (2026-10-10) + +### Documentation + +* read the shared layout from the value of loadSection's result ([f9f3ecc](https://github.com/ExaDev/eslint-config/commit/f9f3ecc509ddb41860e31805e80e7d6fa4253487)) + + +### Chores + +* **deps-dev:** bump @exadev/config from 1.1.3 to 2.1.2 ([ca8db42](https://github.com/ExaDev/eslint-config/commit/ca8db42a0b01257ed88b4adcf50b8dd0c4006db4)) + ## [2.36.2](https://github.com/ExaDev/eslint-config/compare/v2.36.1...v2.36.2) (2026-10-09) @@ -11,11 +36,27 @@ * scope tsdoc/syntax and jsdoc/no-types to TypeScript files ([dc107a4](https://github.com/ExaDev/eslint-config/commit/dc107a41aba0722ddfae9b5c76245faba3038673)) * strip trailing whitespace from comment-style fixes and keep content markers standalone ([f67807b](https://github.com/ExaDev/eslint-config/commit/f67807b76e5f4485d0fa1c38fc96f60402592f20)) + +### Tests + +* write every fixture before ESLint reads the TypeScript project ([fdc30f7](https://github.com/ExaDev/eslint-config/commit/fdc30f764981eefc894521c219ed5d87f2ac7495)) + ## [2.36.1](https://github.com/ExaDev/eslint-config/compare/v2.36.0...v2.36.1) (2026-10-09) + +### Chores + +* **deps-dev:** bump @types/node from 24.13.3 to 26.6.4 ([8a69550](https://github.com/ExaDev/eslint-config/commit/8a695507de8da26d274b44de1fc5b12c5ba9bf2e)) + # [2.36.0](https://github.com/ExaDev/eslint-config/compare/v2.35.4...v2.36.0) (2026-10-09) +### Features + +* add rules for agent SKILL.md files and Claude Code plugin manifests ([b9aba88](https://github.com/ExaDev/eslint-config/commit/b9aba88c7a4fddfd346830c9046ad7afb782d01b)) +* add the agentSkills option and agentSkillsConfig preset ([31f25fd](https://github.com/ExaDev/eslint-config/commit/31f25fd491c2c29a239fae4ceb55f92c9b308b24)) + + ### Bug Fixes * accept skill names the specification's reference validator accepts ([b8a3d60](https://github.com/ExaDev/eslint-config/commit/b8a3d6050a99562c865459b1d9a0138f60e6ae4e)) @@ -56,10 +97,43 @@ * validate the skill-name-unique files option once, not per linted file ([9f521f7](https://github.com/ExaDev/eslint-config/commit/9f521f7fac53a1cb79de5e7cbf54dbc1199a37a5)) -### Features +### Code Refactoring -* add rules for agent SKILL.md files and Claude Code plugin manifests ([b9aba88](https://github.com/ExaDev/eslint-config/commit/b9aba88c7a4fddfd346830c9046ad7afb782d01b)) -* add the agentSkills option and agentSkillsConfig preset ([31f25fd](https://github.com/ExaDev/eslint-config/commit/31f25fd491c2c29a239fae4ceb55f92c9b308b24)) +* drop the outside-the-directory guard from the ignore matcher ([daf1685](https://github.com/ExaDev/eslint-config/commit/daf1685b0673bbc918be2844f5e1664ae590167b)) +* keep hasExtglob private to the glob scope module ([3ef0c5d](https://github.com/ExaDev/eslint-config/commit/3ef0c5df357acd82920d6a3edc3b722d46aba956)) +* match every file glob with minimatch, as ESLint does ([f94f37f](https://github.com/ExaDev/eslint-config/commit/f94f37f369a8c21466a82d0084e66f8a42bfa076)) +* restore the pnpm packages glob reader to its own rules ([699fa24](https://github.com/ExaDev/eslint-config/commit/699fa249e8f08b87a8a4731e3861a5f4df486b77)) + + +### Documentation + +* carry the agent skills option descriptions in the published declarations ([8a732a3](https://github.com/ExaDev/eslint-config/commit/8a732a30a272252234c9c2c705b29e022645a42e)) +* describe agent skills auto-detection and the scan cache as they behave ([3989b63](https://github.com/ExaDev/eslint-config/commit/3989b631f9e79924cb1a8e04f22e2f69a2cea74e)) +* describe agentSkills auto-detection in its option comment without a dash ([d1eaf99](https://github.com/ExaDev/eslint-config/commit/d1eaf99568f54ab019500c7166ae66fdedfebec1)) +* describe the agent skills defaults in words the published types can use ([f248975](https://github.com/ExaDev/eslint-config/commit/f2489758e7be4574f9247eb51c5196ad7b6db328)) +* document agent skills and plugin marketplace linting ([7c2188e](https://github.com/ExaDev/eslint-config/commit/7c2188e36a28aee35caf5ac5e911f3331bf3d784)) +* list the file glob forms that follow minimatch and the ones rejected on read ([feeb436](https://github.com/ExaDev/eslint-config/commit/feeb436e228744437885089724454674ccdc9bac)) +* say that a skill linked into a plugin is not a duplicate of its target ([0776d6e](https://github.com/ExaDev/eslint-config/commit/0776d6ec0bd8b3922f84610cbdb85ecb82d49d61)) +* say that ESLint's --cache hides changes to the set of skills ([ae524ec](https://github.com/ExaDev/eslint-config/commit/ae524ec099d943ef5bad0fecd70f82905cbfceea)) +* scope the ignore matcher contract to paths below the working directory ([a6e1846](https://github.com/ExaDev/eslint-config/commit/a6e18467e2c349fad7c9f259d3098415e55db648)) +* state that the skill-name-unique scan cache is shared by every ESLint instance ([9ab4a00](https://github.com/ExaDev/eslint-config/commit/9ab4a007b9baa8f8ef936a04fdbbaffac2b0fcbc)) +* stop describing a glob dialect that file globs no longer have ([e1da8d5](https://github.com/ExaDev/eslint-config/commit/e1da8d5b8301a059ca8a0f6de8fc30d76e27e462)) +* turn off agentSkills detection in the standalone agent skills example ([8cb6f8d](https://github.com/ExaDev/eslint-config/commit/8cb6f8dab859a2216e3e174b58b4b7bb7442393d)) +* word the plugin-manifest rule row as it behaves ([993dcf2](https://github.com/ExaDev/eslint-config/commit/993dcf281a859081fcb675a47894360b8acd4d37)) + + +### Tests + +* accept the readonly config arrays of the README example builders ([67a8cc4](https://github.com/ExaDev/eslint-config/commit/67a8cc4d8d0b7893ff4478e4913a6be10b87f177)) +* assert the rendered duplicate marketplace entry message again ([e852c4f](https://github.com/ExaDev/eslint-config/commit/e852c4f759a1c8b379055006018dcafea7d56ae5)) +* lint a root plugin through ESLint without tying its name to the checkout folder ([3b49dae](https://github.com/ExaDev/eslint-config/commit/3b49dae9b4a12caf457fd053717d4b6968f738d1)) +* lint the text of a skill that is not on disk against the ones that are ([c152e97](https://github.com/ExaDev/eslint-config/commit/c152e97cea3ed3e40ecddd116a01f684360561af)) +* pin escaped backslashes inside a glob class against minimatch ([c2395b1](https://github.com/ExaDev/eslint-config/commit/c2395b143d46aa1239fd54b3593c12ee30ac0ef0)) +* pin that skill-name-unique validates each distinct files list ([1dadb9d](https://github.com/ExaDev/eslint-config/commit/1dadb9d53f9d8ac9bc63d57224afccf72b23c9ff)) +* pin that the ignore matcher matches a path outside the working directory ([59c93a1](https://github.com/ExaDev/eslint-config/commit/59c93a1b82e885ebacae494ef65e74f1858d56d0)) +* pin the extglob and permission checks on every entry and error code ([20e2c52](https://github.com/ExaDev/eslint-config/commit/20e2c52c18266ac48ba0a52788b2943d62ec66e3)) +* pin the extglob error text and the location of an empty entry name ([c044f79](https://github.com/ExaDev/eslint-config/commit/c044f79d395290eeaaa4fe9fb9bb68ab2d9d96ae)) +* pin the rejection of a glob that has no valid form in minimatch ([467a3da](https://github.com/ExaDev/eslint-config/commit/467a3dae983401204a2e37bc5491113ca4bd8ea6)) ## [2.35.4](https://github.com/ExaDev/eslint-config/compare/v2.35.3...v2.35.4) (2026-10-09) @@ -75,10 +149,38 @@ * keep agentGuidance in turbo.json in the key order json/sort-keys requires ([5bde537](https://github.com/ExaDev/eslint-config/commit/5bde53763bffe51990bc62d184dccf305f0b1da6)) + +### Documentation + +* describe the commit and push hooks as they now run ([b532070](https://github.com/ExaDev/eslint-config/commit/b5320700a0d5cc3b9a23ebfc7570987098926929)) + + +### Continuous Integration + +* lint JSON on commit and run the full lint on push ([de1723e](https://github.com/ExaDev/eslint-config/commit/de1723e520a349d2eec59de9a5933dbeb27f30d1)) +* lint Markdown with @eslint/markdown and fix the table it flagged ([648d65b](https://github.com/ExaDev/eslint-config/commit/648d65b8aa1101e8559e7082b70b904444bed01c)) + + +### Chores + +* upgrade turbo to 2.11.5 and disable agentGuidance ([d9954ed](https://github.com/ExaDev/eslint-config/commit/d9954edf49e988f55da93cfc5c5fe054e8dd51fa)) + ## [2.35.2](https://github.com/ExaDev/eslint-config/compare/v2.35.1...v2.35.2) (2026-10-03) + +### Continuous Integration + +* let Dependabot propose npm updates after a week's cooldown ([f495875](https://github.com/ExaDev/eslint-config/commit/f49587552707a8a3ede2996d1000db4361548c74)) +* lint workflows with actionlint and zizmor ([7a72767](https://github.com/ExaDev/eslint-config/commit/7a727677fafa120c47cf10f0d3c3a3f7708cb763)) +* stop persisting checkout credentials and expanding needs into shell ([5f6cfe7](https://github.com/ExaDev/eslint-config/commit/5f6cfe71f5644451335a302586c397b23f3441d9)) + ## [2.35.1](https://github.com/ExaDev/eslint-config/compare/v2.35.0...v2.35.1) (2026-10-03) + +### Continuous Integration + +* pin third-party actions by commit SHA ([9994c75](https://github.com/ExaDev/eslint-config/commit/9994c75fe9b0cbb9d6d6a4f2743ca839c3d6fe90)) + # [2.35.0](https://github.com/ExaDev/eslint-config/compare/v2.34.1...v2.35.0) (2026-10-02) @@ -86,8 +188,18 @@ * **import-policy:** allow-list of import names on a deny entry ([bc388cf](https://github.com/ExaDev/eslint-config/commit/bc388cf82152ed51a39e61ae8caca297b82ab4e2)) + +### Documentation + +* **import-policy:** tested recipes for repository conventions ([a6d77a5](https://github.com/ExaDev/eslint-config/commit/a6d77a576f7edd724266594e1f693a923cdd1cd5)) + ## [2.34.1](https://github.com/ExaDev/eslint-config/compare/v2.34.0...v2.34.1) (2026-10-02) + +### Documentation + +* add live usage charts to the readme ([04fd7d0](https://github.com/ExaDev/eslint-config/commit/04fd7d0bd55a720f133c5db3ad1b95fb77fa7b1f)) + # [2.34.0](https://github.com/ExaDev/eslint-config/compare/v2.33.1...v2.34.0) (2026-10-02) @@ -96,6 +208,11 @@ * add multiline-comment-style wrapper that keeps directives standalone ([f48ba38](https://github.com/ExaDev/eslint-config/commit/f48ba3810be601c17e64d03ae5ffb433d6048b1a)), closes [eslint-stylistic/eslint-stylistic#1287](https://github.com/eslint-stylistic/eslint-stylistic/issues/1287) [#region](https://github.com/ExaDev/eslint-config/issues/region) [#45](https://github.com/ExaDev/eslint-config/issues/45) * enable multiline-comment-style at bare-block through the wrapper ([966a97c](https://github.com/ExaDev/eslint-config/commit/966a97cc636c5c0eaf80f6226ba027fd0b779353)), closes [#region](https://github.com/ExaDev/eslint-config/issues/region) [eslint-stylistic/eslint-stylistic#1287](https://github.com/eslint-stylistic/eslint-stylistic/issues/1287) [#45](https://github.com/ExaDev/eslint-config/issues/45) + +### Styles + +* apply multiline-comment-style bare-block fixes to own source ([07f40cd](https://github.com/ExaDev/eslint-config/commit/07f40cde9e56919498de82d2372291c377dfc40d)), closes [#45](https://github.com/ExaDev/eslint-config/issues/45) + ## [2.33.1](https://github.com/ExaDev/eslint-config/compare/v2.33.0...v2.33.1) (2026-10-02) @@ -103,6 +220,11 @@ * **deps:** upgrade @stylistic/eslint-plugin to 6.0.0-beta.6 ([3fffbc7](https://github.com/ExaDev/eslint-config/commit/3fffbc7e0ef6c7f138a900ee5cbc6958cb786ad2)) + +### Tests + +* pin multiline-comment-style bare-block behaviour on the bundled config ([cd7a8ea](https://github.com/ExaDev/eslint-config/commit/cd7a8ea667353b2cea9d828622d4fa7a9f4dec78)) + # [2.33.0](https://github.com/ExaDev/eslint-config/compare/v2.32.1...v2.33.0) (2026-10-02) @@ -110,6 +232,11 @@ * **import-policy:** optionally report computed import specifiers ([efdcf29](https://github.com/ExaDev/eslint-config/commit/efdcf2913ddf8cd61c8fda4e326c316c39bc40d4)), closes [#88](https://github.com/ExaDev/eslint-config/issues/88) + +### Documentation + +* **react:** allow eslint-plugin-react in ban-dependencies ([37cc2c2](https://github.com/ExaDev/eslint-config/commit/37cc2c2ad8f0c57ec17752ce6f879fae151236c9)), closes [#30](https://github.com/ExaDev/eslint-config/issues/30) + ## [2.32.1](https://github.com/ExaDev/eslint-config/compare/v2.32.0...v2.32.1) (2026-10-02) @@ -117,6 +244,11 @@ * **jsdoc:** validate doc comment tags against TSDoc's vocabulary ([34f5f00](https://github.com/ExaDev/eslint-config/commit/34f5f0072ac494847d94b7e62d52c906f2f536a6)), closes [#49](https://github.com/ExaDev/eslint-config/issues/49) + +### Documentation + +* **prefer-doc-comment:** update tag-line withholding rationale ([808946b](https://github.com/ExaDev/eslint-config/commit/808946bb7d691bf3fa0b313f4eb6426ee510b911)), closes [#49](https://github.com/ExaDev/eslint-config/issues/49) + # [2.32.0](https://github.com/ExaDev/eslint-config/compare/v2.31.2...v2.32.0) (2026-10-02) @@ -124,13 +256,55 @@ * **workspace:** add selector-based dependency constraints ([1ed6664](https://github.com/ExaDev/eslint-config/commit/1ed6664ec9a24ca360277f0b743ed6f9ca17b7f2)), closes [#36](https://github.com/ExaDev/eslint-config/issues/36) + +### Documentation + +* **readme:** document dependency constraints ([2913aec](https://github.com/ExaDev/eslint-config/commit/2913aec4268564d8fd5baec4293d2fdaab0f4158)), closes [#36](https://github.com/ExaDev/eslint-config/issues/36) +* **readme:** list every src/index.ts export in the architecture notes ([c37ca5a](https://github.com/ExaDev/eslint-config/commit/c37ca5ac656bef0316221f32fd21ed28a775223e)) + ## [2.31.2](https://github.com/ExaDev/eslint-config/compare/v2.31.1...v2.31.2) (2026-10-02) + +### Documentation + +* document reading the shared layout into workspaceArchitecture ([f21b81f](https://github.com/ExaDev/eslint-config/commit/f21b81f68c6f4442a8ec9061fce5b29a4c696b78)) + + +### Tests + +* cover policy options added beside a spread shared layout ([8fbdd7b](https://github.com/ExaDev/eslint-config/commit/8fbdd7b2048d42e0529661db3c040fa3ecac7b14)) +* prove a layout loaded from @exadev/config maps into workspaceArchitecture ([eb7e6dd](https://github.com/ExaDev/eslint-config/commit/eb7e6dd2e3d54d01b223c9530f7835cfd51b829a)) + + +### Chores + +* add @exadev/config and cosmiconfig as dev dependencies ([e80d802](https://github.com/ExaDev/eslint-config/commit/e80d802f48864602a58b724971642f667649e1c9)) + ## [2.31.1](https://github.com/ExaDev/eslint-config/compare/v2.31.0...v2.31.1) (2026-10-02) + +### Continuous Integration + +* correct the checkout persist-credentials comment ([c2643f1](https://github.com/ExaDev/eslint-config/commit/c2643f1a1f1fabdbdd470c36b9b5d1df861e296c)) +* correct the host-key rotation comment on the provision step ([0a7d8c1](https://github.com/ExaDev/eslint-config/commit/0a7d8c13bba0acb15e72678c737ebbede07cdea2)) +* correct the release preflight comment on push ordering ([713009e](https://github.com/ExaDev/eslint-config/commit/713009e8a8a32dc67ba294b8c8547d91afe748ba)) +* drop the chmod that umask already makes redundant ([0ced514](https://github.com/ExaDev/eslint-config/commit/0ced514a6c16f426a4703701bc38eeb2b65c4f40)) +* fail the release push at once when the deploy key is unusable ([ff5a564](https://github.com/ExaDev/eslint-config/commit/ff5a5644ac385ee1ee8ec828fd418cea1e55c622)) +* note that key cleanup relies on an ephemeral runner ([b2b9da8](https://github.com/ExaDev/eslint-config/commit/b2b9da8a05ce91083b9703e7f15b4c0567ee8784)) +* pin release job actions to commit SHAs and blank shell startup hooks ([a04bad7](https://github.com/ExaDev/eslint-config/commit/a04bad70b122503064e684968ff74c2c0bdb363e)) +* pin the release job to the newest week-old npm 12.x ([901926b](https://github.com/ExaDev/eslint-config/commit/901926b21f27332705709b05d773a3d35162f954)) +* provision the release deploy key only for the semantic-release step ([52653db](https://github.com/ExaDev/eslint-config/commit/52653db25186cf189b618c253673850896a4be94)) + # [2.31.0](https://github.com/ExaDev/eslint-config/compare/v2.30.0...v2.31.0) (2026-10-02) +### Features + +* add package-requirements rule for conditional manifest fields, files and scripts ([2213c41](https://github.com/ExaDev/eslint-config/commit/2213c41db3abf51ac2ec73e36fc2f67c73245a8c)) +* add the tooling wiring preset for publish checks, root tooling, hooks and tool configs ([022b4f6](https://github.com/ExaDev/eslint-config/commit/022b4f60243ab4739610d60fa86bb66c490ba031)) +* verify through ESLint's Node API that the config is applied to sample files ([e28562b](https://github.com/ExaDev/eslint-config/commit/e28562b91da9aaae428dd6f1d6d3fedf9c12f26c)) + + ### Bug Fixes * accept syncpack configured under config.syncpack in package.json ([c5c96b0](https://github.com/ExaDev/eslint-config/commit/c5c96b008a8eef51ddcf1070c43e1b991c0955fb)) @@ -140,15 +314,35 @@ * require the root tool scripts to run the tool, not merely exist ([4053223](https://github.com/ExaDev/eslint-config/commit/40532237a2d443fbf289cc1ab07d292e611db832)) -### Features +### Code Refactoring + +* share script requirement reading and checking beyond workspace selectors ([bd15e6d](https://github.com/ExaDev/eslint-config/commit/bd15e6d52bc08e314ac45a5cf97e7a3c150ddf81)) -* add package-requirements rule for conditional manifest fields, files and scripts ([2213c41](https://github.com/ExaDev/eslint-config/commit/2213c41db3abf51ac2ec73e36fc2f67c73245a8c)) -* add the tooling wiring preset for publish checks, root tooling, hooks and tool configs ([022b4f6](https://github.com/ExaDev/eslint-config/commit/022b4f60243ab4739610d60fa86bb66c490ba031)) -* verify through ESLint's Node API that the config is applied to sample files ([e28562b](https://github.com/ExaDev/eslint-config/commit/e28562b91da9aaae428dd6f1d6d3fedf9c12f26c)) + +### Documentation + +* document the tooling wiring preset and the ESLint verifier and export them ([36272d5](https://github.com/ExaDev/eslint-config/commit/36272d5a93efea662137af50e29d64366b8f45aa)) +* fix the punctuation of the fixture ignore comment ([45997fa](https://github.com/ExaDev/eslint-config/commit/45997fa1bb2037d63bcb1957269a57ba1df5a1dc)) +* state that the smoke project check covers presence only ([81a462e](https://github.com/ExaDev/eslint-config/commit/81a462e2423565bb76fe9125b300521ca856c141)) + + +### Tests + +* exercise every dependency field the declares condition reads ([bc70b57](https://github.com/ExaDev/eslint-config/commit/bc70b57c6128faf04dba35493e71c2616ab4f68d)) # [2.30.0](https://github.com/ExaDev/eslint-config/compare/v2.29.0...v2.30.0) (2026-10-01) +### Features + +* add playwright-config rule ([625d287](https://github.com/ExaDev/eslint-config/commit/625d28788b3078959e7c6dc6c325c1eb630b1174)) +* add require-compiler-options rule ([5849719](https://github.com/ExaDev/eslint-config/commit/5849719e3a0fca31638e03ac58ea76252a000126)) +* add stryker-break-threshold and stryker-thresholds-order rules ([e3c82cd](https://github.com/ExaDev/eslint-config/commit/e3c82cdf490c0f7719db4a94d053cb5dfc085d0a)) +* add vitest-config and vitest-coverage-config rules ([e60fc1d](https://github.com/ExaDev/eslint-config/commit/e60fc1d61ce68b5825ea5590bb5347c01ee94e92)) +* read the literal structure of a tool config file ([cb450e7](https://github.com/ExaDev/eslint-config/commit/cb450e74e48a9b2b4574be6ed82e6bd0143f9c5d)) +* register the tool config rules in the plugin ([78f3710](https://github.com/ExaDev/eslint-config/commit/78f3710c4936ae964dabc67b0fd25dd73de8fac3)) + + ### Bug Fixes * accept a root file name as a vitest coverage threshold key ([798e0b5](https://github.com/ExaDev/eslint-config/commit/798e0b5252644173483b5915be8ef361d0a570cb)) @@ -160,18 +354,46 @@ * tell require-compiler-options runs apart by tsconfig and lint order ([3e6380e](https://github.com/ExaDev/eslint-config/commit/3e6380e9e2381a9b7ee110a55a2525c7629a9fe6)) -### Features +### Code Refactoring -* add playwright-config rule ([625d287](https://github.com/ExaDev/eslint-config/commit/625d28788b3078959e7c6dc6c325c1eb630b1174)) -* add require-compiler-options rule ([5849719](https://github.com/ExaDev/eslint-config/commit/5849719e3a0fca31638e03ac58ea76252a000126)) -* add stryker-break-threshold and stryker-thresholds-order rules ([e3c82cd](https://github.com/ExaDev/eslint-config/commit/e3c82cdf490c0f7719db4a94d053cb5dfc085d0a)) -* add vitest-config and vitest-coverage-config rules ([e60fc1d](https://github.com/ExaDev/eslint-config/commit/e60fc1d61ce68b5825ea5590bb5347c01ee94e92)) -* read the literal structure of a tool config file ([cb450e7](https://github.com/ExaDev/eslint-config/commit/cb450e74e48a9b2b4574be6ed82e6bd0143f9c5d)) -* register the tool config rules in the plugin ([78f3710](https://github.com/ExaDev/eslint-config/commit/78f3710c4936ae964dabc67b0fd25dd73de8fac3)) +* read a tsconfig by path, apart from finding a program's tsconfig ([f5892b1](https://github.com/ExaDev/eslint-config/commit/f5892b13b023830bfea737b40d7afac2c0775a7b)) +* share one property key name reader between static-config and vitest-config ([48ae4ba](https://github.com/ExaDev/eslint-config/commit/48ae4baabd97d33c561ec96ba3f198ce9357012c)) +* share one scalar compiler option value guard ([0c02e33](https://github.com/ExaDev/eslint-config/commit/0c02e3384b98d52cb4620e0b4fc40e3e0122905f)) + + +### Documentation + +* document the compiler option and tool config rules ([d8099f2](https://github.com/ExaDev/eslint-config/commit/d8099f2817b1b43b0443d6bba828890986c052a4)) + + +### Styles + +* split the joined config blocks in eslint.config.ts ([547ecbb](https://github.com/ExaDev/eslint-config/commit/547ecbb80c102bd1409ad5560b73f2bd5a8885e1)) + + +### Tests + +* run the long-lived require-compiler-options tests with persistent programs ([4665a54](https://github.com/ExaDev/eslint-config/commit/4665a5439003ae6a6b60d87e339ad4e269565a1d)) + + +### Build System + +* depend on typescript-estree and type the file reference schema ([b441f54](https://github.com/ExaDev/eslint-config/commit/b441f54ad4cb8fd10389a9d996f319bfd681a8ba)) + + +### Chores + +* hold this repo's own configs to the new rules ([d35a8d8](https://github.com/ExaDev/eslint-config/commit/d35a8d80d8066937a94471320180b3eb258b8642)) # [2.29.0](https://github.com/ExaDev/eslint-config/compare/v2.28.0...v2.29.0) (2026-10-01) +### Features + +* add no-defensive-fallback rule ([1cee130](https://github.com/ExaDev/eslint-config/commit/1cee13002e69e662eabe6cdc443b62453808456b)) +* enable core robustness rules and stricter switch exhaustiveness ([758c55a](https://github.com/ExaDev/eslint-config/commit/758c55a19a6868c9e63441d4b6bc57685bb706ad)) + + ### Bug Fixes * match a bare allow filename at any depth in no-defensive-fallback ([6efefae](https://github.com/ExaDev/eslint-config/commit/6efefae3a0f32429ed7d3a0a075cf07e48c48249)) @@ -179,14 +401,37 @@ * report void, 0n and continue swallows in no-defensive-fallback ([72dcd42](https://github.com/ExaDev/eslint-config/commit/72dcd427560b2f0b8a9f43684c2ebc13b1bb0f16)) -### Features +### Code Refactoring + +* reuse entryFilesSchema for the no-defensive-fallback allow files ([746ee5b](https://github.com/ExaDev/eslint-config/commit/746ee5b1fa6effac28bf157590dbd24e0e4b7154)) +* share the type-only wrapper check across rules ([606f433](https://github.com/ExaDev/eslint-config/commit/606f4332523b363cfdbbdfb9c107a01664c28f08)) +* write out exported return types and compare to null strictly ([83f528e](https://github.com/ExaDev/eslint-config/commit/83f528ec803ce0a0dd5b2dd0f440c5852fb4085d)) -* add no-defensive-fallback rule ([1cee130](https://github.com/ExaDev/eslint-config/commit/1cee13002e69e662eabe6cdc443b62453808456b)) -* enable core robustness rules and stricter switch exhaustiveness ([758c55a](https://github.com/ExaDev/eslint-config/commit/758c55a19a6868c9e63441d4b6bc57685bb706ad)) + +### Documentation + +* describe the shared robustness rule set in the architecture notes ([fb9d083](https://github.com/ExaDev/eslint-config/commit/fb9d083ee8830f6a6327ea68269f1dc211ca5926)) +* document no-defensive-fallback and the sequential await override ([7b8b1e3](https://github.com/ExaDev/eslint-config/commit/7b8b1e3458f05a5d2b068c49a26c9f8cca4acd21)) +* drop em-dashes from the new rule-tuning bullets ([f7b58d9](https://github.com/ExaDev/eslint-config/commit/f7b58d947265f1501cc1efdee08ee9c9489b3d6b)) +* keep the rule-tuning bullets in one list ([5feb645](https://github.com/ExaDev/eslint-config/commit/5feb6457f69f0f1668540f9db1e36208dca5f554)) +* name the predicate and schema false positives and the bare-filename allow depth ([1cc33fe](https://github.com/ExaDev/eslint-config/commit/1cc33fe8e56f6c12d1d0bb9afbe60c074eb0c93d)) + + +### Tests + +* cover hole and unreachable-statement returns in no-defensive-fallback ([003e8b9](https://github.com/ExaDev/eslint-config/commit/003e8b97bc6e6dcafc663d89147271e3dd9c53e6)) # [2.28.0](https://github.com/ExaDev/eslint-config/compare/v2.27.0...v2.28.0) (2026-09-30) +### Features + +* add markdown-required-heading rule and markdownHeadingsConfig preset ([c290ed9](https://github.com/ExaDev/eslint-config/commit/c290ed95b2758e8c3011acc8c119400ed6dbd877)), closes [#80](https://github.com/ExaDev/eslint-config/issues/80) +* add no-multiline-template-literal rule with a string-preserving fix ([3c459ba](https://github.com/ExaDev/eslint-config/commit/3c459badaa80bb16e56815e7de7f88fd339287a9)), closes [#79](https://github.com/ExaDev/eslint-config/issues/79) +* add server component boundary rules to the Next.js preset ([095ebb0](https://github.com/ExaDev/eslint-config/commit/095ebb08195dbe8263e2754b4379ce7c8fa0c6cb)), closes [#82](https://github.com/ExaDev/eslint-config/issues/82) +* add timeout-aborts-request rule for Promise.race timeouts ([9e7b163](https://github.com/ExaDev/eslint-config/commit/9e7b1636c98ec6a96a8973a897c029fc99bd1a77)), closes [#81](https://github.com/ExaDev/eslint-config/issues/81) + + ### Bug Fixes * accept any unary expression as data and word the prop rule as data, not literal ([ae28306](https://github.com/ExaDev/eslint-config/commit/ae2830649c2a5a017b97c69eb7bd5be5199356d3)) @@ -197,16 +442,35 @@ * treat only dot-slash paths as relative in no-external-member-jsx-tag ([e8eb328](https://github.com/ExaDev/eslint-config/commit/e8eb328990f367d9719765af8680db5eb2cec125)) -### Features +### Code Refactoring -* add markdown-required-heading rule and markdownHeadingsConfig preset ([c290ed9](https://github.com/ExaDev/eslint-config/commit/c290ed95b2758e8c3011acc8c119400ed6dbd877)), closes [#80](https://github.com/ExaDev/eslint-config/issues/80) -* add no-multiline-template-literal rule with a string-preserving fix ([3c459ba](https://github.com/ExaDev/eslint-config/commit/3c459badaa80bb16e56815e7de7f88fd339287a9)), closes [#79](https://github.com/ExaDev/eslint-config/issues/79) -* add server component boundary rules to the Next.js preset ([095ebb0](https://github.com/ExaDev/eslint-config/commit/095ebb08195dbe8263e2754b4379ce7c8fa0c6cb)), closes [#82](https://github.com/ExaDev/eslint-config/issues/82) -* add timeout-aborts-request rule for Promise.race timeouts ([9e7b163](https://github.com/ExaDev/eslint-config/commit/9e7b1636c98ec6a96a8973a897c029fc99bd1a77)), closes [#81](https://github.com/ExaDev/eslint-config/issues/81) +* let the cooked line-feed count alone refuse escapes spelling a line feed ([f3fd74d](https://github.com/ExaDev/eslint-config/commit/f3fd74d1db8d7899dd4fcc507edb459374d9ba02)) +* throw on a missing source line in the template indentation lookup ([bbae429](https://github.com/ExaDev/eslint-config/commit/bbae429baf89e180e5e80903ff30d7c11d1edf6d)) +* throw on missing visitor keys in the timeout-aborts-request traversal ([f0fc449](https://github.com/ExaDev/eslint-config/commit/f0fc4498d03f92d0708b534f537756e56d9bd32c)) + + +### Documentation + +* describe the awaited-race, abort-test and controller checks of timeout-aborts-request ([ba415e5](https://github.com/ExaDev/eslint-config/commit/ba415e53236aae7ccf2aaae515bd28f62e712a8a)) + + +### Chores + +* add @eslint/markdown as an optional peer and dev dependency ([7bc3da0](https://github.com/ExaDev/eslint-config/commit/7bc3da00521c29286d27c7d72e7d38d94f7f46f7)) # [2.27.0](https://github.com/ExaDev/eslint-config/compare/v2.26.0...v2.27.0) (2026-09-30) +### Features + +* add non-vacuous-guard rule requiring guard tests to show they can fail ([5d412b1](https://github.com/ExaDev/eslint-config/commit/5d412b12ba7e3272f7b8e7254161d9d66a36f1f3)) +* add pure-module rule banning I/O, ambient state and async in configured files ([1d3b4a9](https://github.com/ExaDev/eslint-config/commit/1d3b4a9948133a4bc0f8381846b9acf831c2a19d)) +* add pureModules option and pureModulesConfig for functional-core files ([5d5b715](https://github.com/ExaDev/eslint-config/commit/5d5b7156475c6bf7f3f52943ca7f8b6f381097d7)) +* add scoped-first-parameter rule for repository interface methods ([e7ac227](https://github.com/ExaDev/eslint-config/commit/e7ac227c0e6dbcb13ed64bbce820075cc244d868)) +* add testHygiene option for guard and conformance test files ([fc6d707](https://github.com/ExaDev/eslint-config/commit/fc6d70787824164550d05a886bcc48be70689a35)) +* check test functions a conformance kit receives as parameters ([459607e](https://github.com/ExaDev/eslint-config/commit/459607e6cd1e39a3ab7b656bb8c07a516b096249)) + + ### Bug Fixes * ban console, worker and sqlite in pure modules and see through globalThis ([b9131ca](https://github.com/ExaDev/eslint-config/commit/b9131caf96a3bac03be0c4c4e00f6a05a1b290a1)) @@ -219,25 +483,21 @@ * treat the Array.from mapper as running per element in non-vacuous-guard ([856615f](https://github.com/ExaDev/eslint-config/commit/856615f5e63ae91e7df679ccd746d6134a16556d)) -### Features +### Documentation -* add non-vacuous-guard rule requiring guard tests to show they can fail ([5d412b1](https://github.com/ExaDev/eslint-config/commit/5d412b12ba7e3272f7b8e7254161d9d66a36f1f3)) -* add pure-module rule banning I/O, ambient state and async in configured files ([1d3b4a9](https://github.com/ExaDev/eslint-config/commit/1d3b4a9948133a4bc0f8381846b9acf831c2a19d)) -* add pureModules option and pureModulesConfig for functional-core files ([5d5b715](https://github.com/ExaDev/eslint-config/commit/5d5b7156475c6bf7f3f52943ca7f8b6f381097d7)) -* add scoped-first-parameter rule for repository interface methods ([e7ac227](https://github.com/ExaDev/eslint-config/commit/e7ac227c0e6dbcb13ed64bbce820075cc244d868)) -* add testHygiene option for guard and conformance test files ([fc6d707](https://github.com/ExaDev/eslint-config/commit/fc6d70787824164550d05a886bcc48be70689a35)) -* check test functions a conformance kit receives as parameters ([459607e](https://github.com/ExaDev/eslint-config/commit/459607e6cd1e39a3ab7b656bb8c07a516b096249)) +* document a scoped complexity ceiling for logic-free modules ([3b4279a](https://github.com/ExaDev/eslint-config/commit/3b4279a18ef00096d6a43ea08cb3522b355adddb)) -# [2.26.0](https://github.com/ExaDev/eslint-config/compare/v2.25.0...v2.26.0) (2026-09-30) +### Tests -### Bug Fixes +* type the directly configured pure-module rule in the option-name test ([0027cf3](https://github.com/ExaDev/eslint-config/commit/0027cf32e40b61e750cd174af467363c7eb13811)) -* count constructions, non-null callees and tagged templates in required-imports call ([1880afe](https://github.com/ExaDev/eslint-config/commit/1880afef5be4bc3edf25c0f7b908eaccac20ae4f)) -* name the pattern field when a filename-pattern regex is invalid ([bead7a3](https://github.com/ExaDev/eslint-config/commit/bead7a384295b70a3730cc8fc20eb1f1a98db421)) -* normalise the file of an import-policy exception edge ([5c3970c](https://github.com/ExaDev/eslint-config/commit/5c3970cadd6e1a13a11ec7fb3f75d8a294c5b807)) -* reject an import-policy exception edge in a file a confine entry allows ([53152e3](https://github.com/ExaDev/eslint-config/commit/53152e3a31010e974e6cfe3c4e4af66bd5481c24)) -* reject duplicate and misspelt filename-pattern sibling templates ([25abb79](https://github.com/ExaDev/eslint-config/commit/25abb79c3f2d788f00b5b5e4e5d68233696200c5)) + +### Chores + +* range the @vitest/eslint-plugin devDependency like the others ([0271660](https://github.com/ExaDev/eslint-config/commit/027166053d1961bacc757f8cae4a8b5b2cda7421)) + +# [2.26.0](https://github.com/ExaDev/eslint-config/compare/v2.25.0...v2.26.0) (2026-09-30) ### Features @@ -249,16 +509,31 @@ * add shared entry-option helpers and a specifier pattern matcher ([eedfb1f](https://github.com/ExaDev/eslint-config/commit/eedfb1f9f51aeccd4f6dc2136c5f2ed27a856769)) * register the file-level rules and wire importPolicyConfig ([de7a614](https://github.com/ExaDev/eslint-config/commit/de7a614feccf4a4c3bfd88c08f6d93711eb118e8)) -# [2.25.0](https://github.com/ExaDev/eslint-config/compare/v2.24.0...v2.25.0) (2026-09-30) - ### Bug Fixes -* accept eslint-plugin-turbo from the first release with a flat recommended config ([9037761](https://github.com/ExaDev/eslint-config/commit/90377614b216f0f2d02127ce23453854d3671f1c)) -* accept the local and versioned turbo $schema forms turbo documents ([58b7f01](https://github.com/ExaDev/eslint-config/commit/58b7f01932c8bb8d85ca2f3c797a19548c5e2a6a)) -* develop against an eslint-plugin-turbo release that passes the minimum release age ([f940ced](https://github.com/ExaDev/eslint-config/commit/f940cedd474a2b16242573eb4b0b71b0c51d821b)) -* name the excluding inputs glob when a tool config is dropped from a task cache key ([6e013b9](https://github.com/ExaDev/eslint-config/commit/6e013b9c1675c23c32e2dd28850861a5434834fe)) -* reject an empty tool name in the toolConfigs option ([cae7df3](https://github.com/ExaDev/eslint-config/commit/cae7df3027d64d74e96bc012d1beb95a34ce0d0a)) +* count constructions, non-null callees and tagged templates in required-imports call ([1880afe](https://github.com/ExaDev/eslint-config/commit/1880afef5be4bc3edf25c0f7b908eaccac20ae4f)) +* name the pattern field when a filename-pattern regex is invalid ([bead7a3](https://github.com/ExaDev/eslint-config/commit/bead7a384295b70a3730cc8fc20eb1f1a98db421)) +* normalise the file of an import-policy exception edge ([5c3970c](https://github.com/ExaDev/eslint-config/commit/5c3970cadd6e1a13a11ec7fb3f75d8a294c5b807)) +* reject an import-policy exception edge in a file a confine entry allows ([53152e3](https://github.com/ExaDev/eslint-config/commit/53152e3a31010e974e6cfe3c4e4af66bd5481c24)) +* reject duplicate and misspelt filename-pattern sibling templates ([25abb79](https://github.com/ExaDev/eslint-config/commit/25abb79c3f2d788f00b5b5e4e5d68233696200c5)) + + +### Code Refactoring + +* expose the glob path matcher and relative-path spelling behind createFileScope ([876a74f](https://github.com/ExaDev/eslint-config/commit/876a74f539026c2f0c2ca7e87120d816361ab34f)) + + +### Documentation + +* document exception edge normalisation and confine liveness ([f79cbeb](https://github.com/ExaDev/eslint-config/commit/f79cbeb862cf51f09bd32db94adc3f30478b3f70)) +* document filename-pattern regex and sibling template validation ([ba70b4e](https://github.com/ExaDev/eslint-config/commit/ba70b4e635e20e25a545b9e82fe168dd49053d49)) +* document the file-level rules, import policy and filename patterns ([0cd3ea8](https://github.com/ExaDev/eslint-config/commit/0cd3ea80724b9d775f499da3a462d90af6ae9579)) +* list importPolicies and the new exports in the README ([a529bb3](https://github.com/ExaDev/eslint-config/commit/a529bb3e9d1efa7309c07fd3526758570955a839)) +* note that export = contributes no name to required-exports ([b344379](https://github.com/ExaDev/eslint-config/commit/b344379b3795d36f8c59ca83b59394263d300b37)) +* state that export = contributes no name in collectExportedNames ([5f5e536](https://github.com/ExaDev/eslint-config/commit/5f5e53605b8f0c3e1199966c46b04fd761d2ffed)) + +# [2.25.0](https://github.com/ExaDev/eslint-config/compare/v2.24.0...v2.25.0) (2026-09-30) ### Features @@ -270,9 +545,52 @@ * read inputs, globalDependencies, $schema and pass-through env from turbo.json ([03c1bc0](https://github.com/ExaDev/eslint-config/commit/03c1bc01f7a233ad2a9a3f1173239c063f4f83f1)) * report a taskGraph requirement that matches no task entry ([c4dcc52](https://github.com/ExaDev/eslint-config/commit/c4dcc527c28c800d1bd6ec238885dde9cffe418d)) + +### Bug Fixes + +* accept eslint-plugin-turbo from the first release with a flat recommended config ([9037761](https://github.com/ExaDev/eslint-config/commit/90377614b216f0f2d02127ce23453854d3671f1c)) +* accept the local and versioned turbo $schema forms turbo documents ([58b7f01](https://github.com/ExaDev/eslint-config/commit/58b7f01932c8bb8d85ca2f3c797a19548c5e2a6a)) +* develop against an eslint-plugin-turbo release that passes the minimum release age ([f940ced](https://github.com/ExaDev/eslint-config/commit/f940cedd474a2b16242573eb4b0b71b0c51d821b)) +* name the excluding inputs glob when a tool config is dropped from a task cache key ([6e013b9](https://github.com/ExaDev/eslint-config/commit/6e013b9c1675c23c32e2dd28850861a5434834fe)) +* reject an empty tool name in the toolConfigs option ([cae7df3](https://github.com/ExaDev/eslint-config/commit/cae7df3027d64d74e96bc012d1beb95a34ce0d0a)) + + +### Code Refactoring + +* reuse the package qualifier when grouping config input problems ([7467fb5](https://github.com/ExaDev/eslint-config/commit/7467fb52a9e74e0db0c452d1beea47e5f142951a)) +* share the single-plugin preset builder between nextjs and turboEnv ([e62a8e5](https://github.com/ExaDev/eslint-config/commit/e62a8e59f680243e459aa03becd4ac510dc13669)) + + +### Documentation + +* describe the config inputs, task graph, hygiene and turboEnv options ([f846ea1](https://github.com/ExaDev/eslint-config/commit/f846ea1c5308f7441fc14781dc4fb7ddc553fb17)) +* describe turbo default inputs as the package's source-controlled files ([550f14f](https://github.com/ExaDev/eslint-config/commit/550f14f08321584369f1d74cbb4df5bd394e470b)) +* name the root task key for an aggregate task backed by a root script ([3ec788a](https://github.com/ExaDev/eslint-config/commit/3ec788a9ae13e4059cbb153624e0afea458f809a)) +* replace spaced double hyphens in the turboEnv option comments ([6750930](https://github.com/ExaDev/eslint-config/commit/67509300f6c1e3f572010ed2cd1687fa6c12c012)) +* state the eslint-plugin-turbo checks without dating them ([6fcfc04](https://github.com/ExaDev/eslint-config/commit/6fcfc04462fa598e65724623f2a4cc96e55ac3bd)) + + +### Tests + +* pin option list validation, package name handling and joined package names in the turbo rules ([15dc965](https://github.com/ExaDev/eslint-config/commit/15dc9652bfaf01d3e3c07ece5e4a40687e2f5201)) + # [2.24.0](https://github.com/ExaDev/eslint-config/compare/v2.23.3...v2.24.0) (2026-09-30) +### Features + +* add a file-reference option for reading a sibling or root file ([9d26018](https://github.com/ExaDev/eslint-config/commit/9d26018b01a37a517186566d08755a7c3c3b0402)) +* add filename glob scoping and a JSONC parser for JSON rules ([e37e761](https://github.com/ExaDev/eslint-config/commit/e37e7618d52e8de6944bb23823456adf9c26181f)) +* add package-has-files, dev-dependency-only and required-scripts workspace rules ([5fa720b](https://github.com/ExaDev/eslint-config/commit/5fa720bb8a2f64aa86318a034c641f3b04d70457)) +* add turbo boundaries opt-in, package tag, script and ignore-comment rules ([8f11ed9](https://github.com/ExaDev/eslint-config/commit/8f11ed93f861e1923e9b80ee935590890b2b3bf1)) +* add turbo script convention, task and script cross-check, outputs and no-fix rules ([3f94c75](https://github.com/ExaDev/eslint-config/commit/3f94c75bc7d762776700e5b3852179ebecaa3699)) +* let no-uphill-dependency allow documented edges and exempt whole target groups ([e41fb8a](https://github.com/ExaDev/eslint-config/commit/e41fb8a7867b1fecbc67074b5b8ae5ee148cf72b)) +* match a glob against files as well as directories inside a package directory ([381ac23](https://github.com/ExaDev/eslint-config/commit/381ac23f40ce1fdf81505ff532b7de4a6b115ca8)) +* read allow, exemptTargetGroups, requiredFiles, devOnly and requiredScripts workspace options ([da54d26](https://github.com/ExaDev/eslint-config/commit/da54d263e594b3276f77c761224a6785dc29ad14)) +* share the JSON language block builder and json/jsonc file globs ([73d66e0](https://github.com/ExaDev/eslint-config/commit/73d66e01dd5534d1e09e15e5e21b15a3c4502288)) +* wire the turbo rules through turboConfig and exadevConfig ([71d943e](https://github.com/ExaDev/eslint-config/commit/71d943ea362de8c0261031a84b91a3df10993509)) + + ### Bug Fixes * build the surrounding-quote pattern per call so a mutation of it is testable ([fd2c92e](https://github.com/ExaDev/eslint-config/commit/fd2c92e74d532d0960f13a1c08a4dfa9303131e3)) @@ -288,23 +606,55 @@ * treat a // task run or depended on by its bare name as reachable ([620f0e1](https://github.com/ExaDev/eslint-config/commit/620f0e1d580aefc9f91ca0eac52fa2135337cabd)) -### Features +### Code Refactoring -* add a file-reference option for reading a sibling or root file ([9d26018](https://github.com/ExaDev/eslint-config/commit/9d26018b01a37a517186566d08755a7c3c3b0402)) -* add filename glob scoping and a JSONC parser for JSON rules ([e37e761](https://github.com/ExaDev/eslint-config/commit/e37e7618d52e8de6944bb23823456adf9c26181f)) -* add package-has-files, dev-dependency-only and required-scripts workspace rules ([5fa720b](https://github.com/ExaDev/eslint-config/commit/5fa720bb8a2f64aa86318a034c641f3b04d70457)) -* add turbo boundaries opt-in, package tag, script and ignore-comment rules ([8f11ed9](https://github.com/ExaDev/eslint-config/commit/8f11ed93f861e1923e9b80ee935590890b2b3bf1)) -* add turbo script convention, task and script cross-check, outputs and no-fix rules ([3f94c75](https://github.com/ExaDev/eslint-config/commit/3f94c75bc7d762776700e5b3852179ebecaa3699)) -* let no-uphill-dependency allow documented edges and exempt whole target groups ([e41fb8a](https://github.com/ExaDev/eslint-config/commit/e41fb8a7867b1fecbc67074b5b8ae5ee148cf72b)) -* match a glob against files as well as directories inside a package directory ([381ac23](https://github.com/ExaDev/eslint-config/commit/381ac23f40ce1fdf81505ff532b7de4a6b115ca8)) -* read allow, exemptTargetGroups, requiredFiles, devOnly and requiredScripts workspace options ([da54d26](https://github.com/ExaDev/eslint-config/commit/da54d263e594b3276f77c761224a6785dc29ad14)) -* share the JSON language block builder and json/jsonc file globs ([73d66e0](https://github.com/ExaDev/eslint-config/commit/73d66e01dd5534d1e09e15e5e21b15a3c4502288)) -* wire the turbo rules through turboConfig and exadevConfig ([71d943e](https://github.com/ExaDev/eslint-config/commit/71d943ea362de8c0261031a84b91a3df10993509)) +* build the JSONC string-literal pattern per call so mutants attribute to tests ([9d54cec](https://github.com/ExaDev/eslint-config/commit/9d54cec88077db863d91508f7c91ea5e340dc8cd)) +* scan JSONC escapes without a whitespace-equivalent character class ([6f13040](https://github.com/ExaDev/eslint-config/commit/6f130404c9eaf38b6731949b25c5e5c65bdd6d86)) +* scan JSONC string literals with a sticky pattern and pin edge cases in tests ([4bc5647](https://github.com/ExaDev/eslint-config/commit/4bc56472baa5ad59012d07d61903cbbe372756a4)) +* share script reading between the script rules ([2f520fe](https://github.com/ExaDev/eslint-config/commit/2f520fe5ad06a158400a5b75eb68a984dd4947b8)) + + +### Documentation + +* describe file scope outside cwd, glob uniqueness and BOM handling ([187599f](https://github.com/ExaDev/eslint-config/commit/187599fae1521a10caa11f394b3423f76cd31b97)) +* describe the allow list, exempt groups and the three opt-in workspace rules ([be19f7d](https://github.com/ExaDev/eslint-config/commit/be19f7d6c2650066e702f1bdab0356d74063452e)) +* describe the turbo rules without counting them ([60b6c7c](https://github.com/ExaDev/eslint-config/commit/60b6c7c02fd3a3b8a1e393b20bf70bc6bd41453e)) +* describe the turbo rules, their options and the boundaries limits ([26ef076](https://github.com/ExaDev/eslint-config/commit/26ef076a9fcf3976be28ff81e116ebe727665f91)) +* **readme:** describe the shared JSON-language, file-scope and file-reference helpers ([0dc1059](https://github.com/ExaDev/eslint-config/commit/0dc1059d49cf770a9ae4c1e27bf5c97df07f4933)) +* state which scripts exemptTasks covers and why fixFlags omits short forms ([94d2a99](https://github.com/ExaDev/eslint-config/commit/94d2a99a8298cd14c5d5fbb7a3df1751caed32f0)) + + +### Tests + +* add an in-memory workspace filesystem for rules that read sibling files ([6388b16](https://github.com/ExaDev/eslint-config/commit/6388b16b08a0b6a1dc954fa3df5ad8998794f5b5)) +* build the valueless flag list per call so its entries are mutable ([840d6ab](https://github.com/ExaDev/eslint-config/commit/840d6abc86af9261cee14bab1c115dd3336550b2)) +* cover a comma at the very start of JSONC text ([22da6d7](https://github.com/ExaDev/eslint-config/commit/22da6d71d7370d56a23f56630189ccc7a06baad7)) +* cover a root turbo configuration at the filesystem root ([695aa5c](https://github.com/ExaDev/eslint-config/commit/695aa5c925b83bd193cd24ec25bec3e63ea67718)) +* pin JSONC dangling escapes, escaped whitespace and leading whitespace ([27470d8](https://github.com/ExaDev/eslint-config/commit/27470d80009781da3331f55052721819a79d56b3)) +* pin option names, nested-object guards and file glob edge cases in the workspace rules ([e4c351d](https://github.com/ExaDev/eslint-config/commit/e4c351d252a79dd8805e92b88614641b4fe07984)) +* pin the bare-name and valueless-flag cases of the turbo command readers ([474558b](https://github.com/ExaDev/eslint-config/commit/474558b94c628bb7581e94acb5ecf3242b542d21)) + + +### Chores + +* lint this repo's scripts with the turbo rules and split the fixing lint task ([e8b267b](https://github.com/ExaDev/eslint-config/commit/e8b267bbc617bdb7f0a7cac7a33122d1170934e7)) ## [2.23.3](https://github.com/ExaDev/eslint-config/compare/v2.23.2...v2.23.3) (2026-09-29) + +### Continuous Integration + +* run mutation testing on manual dispatch only ([8ad4019](https://github.com/ExaDev/eslint-config/commit/8ad401933a75fcc6ccb7141604af24a0b7400be5)) + ## [2.23.2](https://github.com/ExaDev/eslint-config/compare/v2.23.1...v2.23.2) (2026-09-29) + +### Continuous Integration + +* lint commits with the repo's own commitlint instead of a Docker action ([3c9852a](https://github.com/ExaDev/eslint-config/commit/3c9852a0378790445e5206831e0bd62701767edb)) +* resolve the runner once and prefer the self-hosted fleet ([d1c6955](https://github.com/ExaDev/eslint-config/commit/d1c6955eacbac652232913bdeb851c7b5747099d)) +* run the mutation job on a 4-vCPU Blacksmith runner ([b059468](https://github.com/ExaDev/eslint-config/commit/b059468a230ba8c2b01cbd9f86f296201d803953)) + ## [2.23.1](https://github.com/ExaDev/eslint-config/compare/v2.23.0...v2.23.1) (2026-09-29) @@ -315,6 +665,16 @@ # [2.23.0](https://github.com/ExaDev/eslint-config/compare/v2.22.2...v2.23.0) (2026-09-28) +### Features + +* add prefer-doc-comment rule ([aa3d937](https://github.com/ExaDev/eslint-config/commit/aa3d9370c8a60b7028880342cd2c14727955db12)) +* **deps:** add @stylistic/eslint-plugin ([37e38de](https://github.com/ExaDev/eslint-config/commit/37e38de72afadcb1a9f853429b808f1054e8dcfa)) +* **prefer-doc-comment:** cover exported enums, namespaces, value consts, default expressions ([3f658d5](https://github.com/ExaDev/eslint-config/commit/3f658d5f14d29d7ca46042ef64c533c65f11d447)) +* **prefer-doc-comment:** cover public abstract methods and function-valued class properties ([349d96a](https://github.com/ExaDev/eslint-config/commit/349d96a26b3a2d6758c442b5bd2b22669f624f5d)) +* **prefer-doc-comment:** report an exported function's own overload signature ([cb4be1e](https://github.com/ExaDev/eslint-config/commit/cb4be1e603d41c91830e6d58ad17e06d67919da1)) +* wire stylistic comment, class-member and JSX rules into config ([950de79](https://github.com/ExaDev/eslint-config/commit/950de796de61f0304454a5f3ea002a7344cbe475)) + + ### Bug Fixes * exempt a /*! license or banner block from both comment rules ([7758fa8](https://github.com/ExaDev/eslint-config/commit/7758fa83ee06b78eecdbb3800ed55b05e6e7f973)) @@ -355,14 +715,59 @@ * **stylistic-comments:** stop spaced-comment breaking source-map and #region markers ([a511051](https://github.com/ExaDev/eslint-config/commit/a511051d7c50348d41d3b6e261fe4b8d429a5fc6)), closes [#region](https://github.com/ExaDev/eslint-config/issues/region) [region/#endregion](https://github.com/ExaDev/eslint-config/issues/endregion) -### Features +### Code Refactoring -* add prefer-doc-comment rule ([aa3d937](https://github.com/ExaDev/eslint-config/commit/aa3d9370c8a60b7028880342cd2c14727955db12)) -* **deps:** add @stylistic/eslint-plugin ([37e38de](https://github.com/ExaDev/eslint-config/commit/37e38de72afadcb1a9f853429b808f1054e8dcfa)) -* **prefer-doc-comment:** cover exported enums, namespaces, value consts, default expressions ([3f658d5](https://github.com/ExaDev/eslint-config/commit/3f658d5f14d29d7ca46042ef64c533c65f11d447)) -* **prefer-doc-comment:** cover public abstract methods and function-valued class properties ([349d96a](https://github.com/ExaDev/eslint-config/commit/349d96a26b3a2d6758c442b5bd2b22669f624f5d)) -* **prefer-doc-comment:** report an exported function's own overload signature ([cb4be1e](https://github.com/ExaDev/eslint-config/commit/cb4be1e603d41c91830e6d58ad17e06d67919da1)) -* wire stylistic comment, class-member and JSX rules into config ([950de79](https://github.com/ExaDev/eslint-config/commit/950de796de61f0304454a5f3ea002a7344cbe475)) +* **prefer-doc-comment:** drop the redundant -1 branch from the segment slice ([e480610](https://github.com/ExaDev/eslint-config/commit/e480610311def4d42c702af6b26de833dcb7c5a0)) +* **prefer-doc-comment:** remove defensive fallbacks for unreachable cases ([e583048](https://github.com/ExaDev/eslint-config/commit/e58304840438dac2ee2784649878276121d45ee1)) +* **stylistic-comments:** share the real-Linter test config across describe blocks ([7093d5e](https://github.com/ExaDev/eslint-config/commit/7093d5e0593ebf2d20049fffbc5398f331ac54b2)) + + +### Documentation + +* correct the triple-slash issue wording to a plain upstream link ([f54606f](https://github.com/ExaDev/eslint-config/commit/f54606f41eb29ae8f0cc36102d84230d1617b557)) +* document prefer-doc-comment and the new stylistic rules ([30882e9](https://github.com/ExaDev/eslint-config/commit/30882e928aa551d21b8f4d8a243ad988b290896b)) +* make version and process references evergreen ([9c4812e](https://github.com/ExaDev/eslint-config/commit/9c4812ecd339f2b63a1708fb9e6f44c15f232128)) +* **prefer-doc-comment:** correct the indent comment's column-zero claim ([499d8ef](https://github.com/ExaDev/eslint-config/commit/499d8efe605183b2f9a8064b5c8991d037fe6d5b)) +* **prefer-doc-comment:** fix a garbled sentence in the rules table ([0e08fa4](https://github.com/ExaDev/eslint-config/commit/0e08fa4a1aafc1c537343a88f73f478efafa6f38)) +* **prefer-doc-comment:** sync the README directive list with the widened pattern ([9abd9f0](https://github.com/ExaDev/eslint-config/commit/9abd9f09fd837b62f671e5a51c826a89982f7caa)), closes [region/#endregion](https://github.com/ExaDev/eslint-config/issues/endregion) +* **readme:** cover a directive seated directly above the declaration ([2581b55](https://github.com/ExaDev/eslint-config/commit/2581b558b7f384f39411489a566a0ead0d899ad7)) +* **readme:** describe prefer-doc-comment's generalised tag-line withholding ([a6609e6](https://github.com/ExaDev/eslint-config/commit/a6609e62c87a383fe704c49706a5c738dccb66bf)) +* **readme:** document the [@stylistic](https://github.com/stylistic) plugin registration migration ([6b39472](https://github.com/ExaDev/eslint-config/commit/6b39472e101c2a21bcac2df1b4485bf11f132209)) +* **readme:** fix the dangling clause in the prefer-doc-comment row ([e01aa20](https://github.com/ExaDev/eslint-config/commit/e01aa2027912cc5bbeee75d30445a0048dea130b)) +* **readme:** state which config wires prefer-doc-comment, correct its stale mechanism note ([7fb4526](https://github.com/ExaDev/eslint-config/commit/7fb45267e276188f8d3b49d41b79f87bc8b19041)) +* **stylistic-comments:** correct jsx-pascal-case comment on what it enforces ([827e21d](https://github.com/ExaDev/eslint-config/commit/827e21dd4f84cf247fe53fd0823ecd218a989946)) +* **stylistic-comments:** correct the block.markers explanation for spaced-comment ([d0260ba](https://github.com/ExaDev/eslint-config/commit/d0260baf01c01fdd6de53812b0f54f9e349b35d6)) +* **stylistic-comments:** document the no-space triple-slash spaced-comment gap ([18950cb](https://github.com/ExaDev/eslint-config/commit/18950cb60e0bb452637d39dbea0aed79baaa6917)), closes [ExaDev/eslint-config#47](https://github.com/ExaDev/eslint-config/issues/47) +* **stylistic-comments:** remove variant rule counts from header comment ([b489c19](https://github.com/ExaDev/eslint-config/commit/b489c19fa60db015d5c752811fa409b845f70fd3)) +* track the multiline-comment-style re-enable with a real issue ([c860ff9](https://github.com/ExaDev/eslint-config/commit/c860ff9c7089f72fed1a8ded61f561d6f1aeb9db)) + + +### Styles + +* apply stylistic comment and class-member rules across the codebase ([4ceb1c0](https://github.com/ExaDev/eslint-config/commit/4ceb1c0f72e3a4b96c792b0cf4d1739dd7f589be)) +* finish reverting bare-block churn left behind by 7966e15 ([8930f4a](https://github.com/ExaDev/eslint-config/commit/8930f4addea5756aca81dc9f99ac1ad4023d63c0)) +* revert bare-block churn from the disabled multiline-comment-style rule ([8238223](https://github.com/ExaDev/eslint-config/commit/8238223c7091e0d7a2242bafd55bfa48c3974130)) +* trim whitespace-only paragraph-separator lines in bare comment blocks ([0b20cf8](https://github.com/ExaDev/eslint-config/commit/0b20cf86a27c6515c4b3774f36059fc7732852c9)) + + +### Tests + +* close remaining mutation gaps in prefer-doc-comment and stylistic-comments ([baeb627](https://github.com/ExaDev/eslint-config/commit/baeb627ae30965c8faa4b6b9bf6a51a3c53c4824)) +* cover explicit public modifier and non-function const init ([625532a](https://github.com/ExaDev/eslint-config/commit/625532ae2eb467141635c6829248b4973d425675)) +* **prefer-doc-comment:** close mutation gaps found by the full Stryker gate ([8e6bd37](https://github.com/ExaDev/eslint-config/commit/8e6bd37b6df53497dc288bb5121f80655c6f2935)) +* **prefer-doc-comment:** close mutation gaps the full Stryker gate found ([5bd2a65](https://github.com/ExaDev/eslint-config/commit/5bd2a655922bf0f6dadde60617e744b775aa0f22)) +* **prefer-doc-comment:** close mutation gaps the full Stryker gate found ([49b7003](https://github.com/ExaDev/eslint-config/commit/49b700308f8172c7bcc2cdea1535dc83a1d94678)) +* **prefer-doc-comment:** close the mutation gaps in isDirectiveComment ([f7b11a3](https://github.com/ExaDev/eslint-config/commit/f7b11a3e054369c0249370951d3e2d9f3569fffe)) +* **prefer-doc-comment:** cover both decorator placements around export ([802084a](https://github.com/ExaDev/eslint-config/commit/802084a5c8055ce67884a516c3b00b97cfda7850)) +* **prefer-doc-comment:** cover multi-line ESLint config Block comments ([5e4e9ba](https://github.com/ExaDev/eslint-config/commit/5e4e9babc22e9cb207692590f9e7228e1b6bb95b)) +* **prefer-doc-comment:** kill the same-key-regardless-of-name mutant ([0d6b3bf](https://github.com/ExaDev/eslint-config/commit/0d6b3bf7c6020d9d9d42a81e640cee52f0dc5671)) +* **prefer-doc-comment:** kill the sibling-value-type mutant on isOverloadImplementationMethod ([bbdd330](https://github.com/ExaDev/eslint-config/commit/bbdd330809be5b6550da37596de01236e6340981)) + + +### Continuous Integration + +* cache Stryker's incremental result file across mutation runs ([5d93825](https://github.com/ExaDev/eslint-config/commit/5d9382520295492e3ddbb2f1431670f725a728aa)) +* cancel a branch's superseded runs instead of letting them finish ([81a53c0](https://github.com/ExaDev/eslint-config/commit/81a53c038a1dbe4b3996223c08bd00cbc52eb89b)) ## [2.22.2](https://github.com/ExaDev/eslint-config/compare/v2.22.1...v2.22.2) (2026-09-27) @@ -397,6 +802,44 @@ * **workspace-path:** credit the right helper for the doc comment shape ([c0a0092](https://github.com/ExaDev/eslint-config/commit/c0a0092a8a57abbee3b5c7544d29156554203ac2)) * **workspace-path:** drop history narration from doc comments ([82935ec](https://github.com/ExaDev/eslint-config/commit/82935ec6d24f415d8dc26fc06615d09412146aad)) + +### Code Refactoring + +* **rules:** extract the duplicated getMemberKeyName into json-member-key ([8927f83](https://github.com/ExaDev/eslint-config/commit/8927f833897c6b5763ae61002d7d2a7bbcf0b78e)) +* **workspace:** extract shared isRecord and requireChar helpers ([44b9f77](https://github.com/ExaDev/eslint-config/commit/44b9f772d2009f1a52432ca08df5ffe4053ec4f8)) + + +### Documentation + +* **cast-boundary:** drop the leftover compile-verification claim ([fed8468](https://github.com/ExaDev/eslint-config/commit/fed8468cb2f7334fb375743de4102579f9ff4fe4)) +* **readme:** correct CI trigger and job-casing description in Contributing ([7b85a02](https://github.com/ExaDev/eslint-config/commit/7b85a026d329b5cd5297740b324902a96bb24b8a)) +* **readme:** drop the redundant plugin registration from the group-ranked example ([00bea28](https://github.com/ExaDev/eslint-config/commit/00bea288266028d856c2013a01a93f2cc407ecbf)) +* **readme:** fix keep-group example text to match the Options table ([540fcb1](https://github.com/ExaDev/eslint-config/commit/540fcb141d67aaa4ac0bf3dff512a5ca0373e60a)) +* **readme:** mention the Mutation CI job and pnpm test:mutation ([81014f2](https://github.com/ExaDev/eslint-config/commit/81014f2ea2015d09ceaebfb19b81a66c6ed2694b)) +* **readme:** quote src/index.ts's real barrel line and name the PublicPlugin boundary ([506352f](https://github.com/ExaDev/eslint-config/commit/506352fcf21b2147187744d59e3c2c3ece416814)) +* **readme:** quote the barrel in full and list every concatenated builder ([0a5bf4e](https://github.com/ExaDev/eslint-config/commit/0a5bf4e220a57e81656222152bdd36766c43ef7a)) +* **readme:** use a keep-group example where name and path segment differ ([acebe92](https://github.com/ExaDev/eslint-config/commit/acebe927b52552fa304afab8d25a506dcc70f8ce)) +* **workspace-architecture:** correct the cast-boundary comment ([485d555](https://github.com/ExaDev/eslint-config/commit/485d555ac8ccdf9e6f048eb96dc22c32b306586e)) + + +### Tests + +* **barrel-auto-detect:** cover caching and the filesystem-root walk ([1bd6cb6](https://github.com/ExaDev/eslint-config/commit/1bd6cb60ea8541eefc5f07ce735d77c6f18dcea9)) +* kill the three remaining mutation survivors ([225523f](https://github.com/ExaDev/eslint-config/commit/225523f9bf1def4f404f9d0d18c157b36bc90fde)) +* **prefer-options-object-param:** cover describeFunctionKind's abstract-method branch ([b90a93b](https://github.com/ExaDev/eslint-config/commit/b90a93b174eceaa82f01919e61b32c14f4ef5617)) +* **readme:** assert each flattened extends entry's own fields, not just aggregate plugin keys ([a5b962f](https://github.com/ExaDev/eslint-config/commit/a5b962f2652a09a135496a3f63456e2607f563f0)) +* **readme:** typecheck and verify defineConfig examples that wire plugin directly ([059dbf9](https://github.com/ExaDev/eslint-config/commit/059dbf9744e65a94fb19e6056fea03106746d7a2)) +* **recommended-type-checked:** cover the max-params boundary ([c9bdb1e](https://github.com/ExaDev/eslint-config/commit/c9bdb1ed249101978d51c3da3ff743842349e4c2)) +* **test-file-kind:** cover the rule's own schema and message metadata ([2517c64](https://github.com/ExaDev/eslint-config/commit/2517c640a29ed922b2f05dbfd8167ff222801bbb)) +* **workspace-graph:** cover array and null manifests in readDeclaredManifest ([f8fd137](https://github.com/ExaDev/eslint-config/commit/f8fd1372a6d34eacb439d724c9fb7421629c8ab1)) +* **workspace-yaml:** assert the "@exadev/eslint-config: " error prefix ([3791a70](https://github.com/ExaDev/eslint-config/commit/3791a70ffd8e5e1f7a32cdaf5871dcf3aea06d80)) + + +### Continuous Integration + +* raise the Mutation job's timeout to 60 minutes ([314ca48](https://github.com/ExaDev/eslint-config/commit/314ca48c2e157cf6eeb1e9eb1d56b0737825fd3f)) +* run the mutation gate in CI ([9aa15b4](https://github.com/ExaDev/eslint-config/commit/9aa15b44dd55cb819f99c54f9ec91056acd8b68d)) + ## [2.22.1](https://github.com/ExaDev/eslint-config/compare/v2.22.0...v2.22.1) (2026-09-27) @@ -405,9 +848,19 @@ * **workspace-checks:** keep-group uses the group's own name, not its path ([68df33c](https://github.com/ExaDev/eslint-config/commit/68df33c73b50bff845ab5c94320781474b8da043)) * **workspace-yaml:** prefix packages: parse errors like the other workspace-architecture modules ([0820a56](https://github.com/ExaDev/eslint-config/commit/0820a56ee14f0b35c4a3534ef390422b8e914205)) + +### Documentation + +* **readme:** stop naming a specific pnpm version in the install line ([0d7d82b](https://github.com/ExaDev/eslint-config/commit/0d7d82b7400be8f6e4a41a08f7116b2621907026)) + # [2.22.0](https://github.com/ExaDev/eslint-config/compare/v2.21.1...v2.22.0) (2026-09-26) +### Features + +* **workspace:** add assertIsError, a shared non-Error-throw guard ([1ec4277](https://github.com/ExaDev/eslint-config/commit/1ec427773b4bc99f14854d8347c15cb62105b286)) + + ### Bug Fixes * **workspace rules:** report a nameless package under package-name-mirrors-path ([e47ea1c](https://github.com/ExaDev/eslint-config/commit/e47ea1c9aac60fc61354da86f394cfbdb2b17693)) @@ -422,9 +875,9 @@ * **workspace:** make the two assertIsError call-site contexts directly testable ([20f4af7](https://github.com/ExaDev/eslint-config/commit/20f4af7cd90dbc66260c1d077a1aa020c5ab52e9)) -### Features +### Documentation -* **workspace:** add assertIsError, a shared non-Error-throw guard ([1ec4277](https://github.com/ExaDev/eslint-config/commit/1ec427773b4bc99f14854d8347c15cb62105b286)) +* **readme:** document keep-group derivation and nameless-package handling ([2bea512](https://github.com/ExaDev/eslint-config/commit/2bea512115332bc27a4329303070c330e1caaded)) ## [2.21.1](https://github.com/ExaDev/eslint-config/compare/v2.21.0...v2.21.1) (2026-09-26) @@ -441,16 +894,24 @@ * **workspace-yaml:** correct the double-quote doubling-escape test's own input ([101e318](https://github.com/ExaDev/eslint-config/commit/101e318be80b44271fdc580a4a05fe2766ce4af5)) * **workspace-yaml:** eliminate equivalent boundary mutants; export helpers for direct testing ([cd50839](https://github.com/ExaDev/eslint-config/commit/cd508394cfe71b7c362d9e64a81fd4c161648de7)) -# [2.21.0](https://github.com/ExaDev/eslint-config/compare/v2.20.2...v2.21.0) (2026-09-26) +### Code Refactoring -### Bug Fixes +* **workspace-options:** remove isSliceSpec's dead "namePrefix" guard ([4b03e6a](https://github.com/ExaDev/eslint-config/commit/4b03e6ad4c6bab150ad45ca9f52080c34cf16d1c)) -* **workspace:** accept zero-indent pnpm-workspace.yaml sequence items ([800483c](https://github.com/ExaDev/eslint-config/commit/800483cf9ae6d1f6643a1586c9cdde5d224a4ebe)) -* **workspace:** de-duplicate dependency names before checking uphill rules ([50f752d](https://github.com/ExaDev/eslint-config/commit/50f752d1e08ae07f1b33349576ac49d5ee0dd283)) -* **workspace:** namePrefix slice picks the longest match and strips scope ([d20ee82](https://github.com/ExaDev/eslint-config/commit/d20ee82a5ffe099962c4e4e29d9acdec3ef2c83d)) -* **workspace:** reject unknown option keys and validate isolatedGroups ([73deb85](https://github.com/ExaDev/eslint-config/commit/73deb850684d700b84395debed310ff0ab1713c0)) -* **workspace:** support in-segment glob wildcards and skip node_modules ([456e77f](https://github.com/ExaDev/eslint-config/commit/456e77fa2e72a05e7ae2b02eedbd7c718191a1ae)) + +### Documentation + +* **workspace-options:** list "slice" among the levels this reader validates ([7b9d7ba](https://github.com/ExaDev/eslint-config/commit/7b9d7ba4f298612165793494d271e3a13de29bb9)) + + +### Tests + +* **workspace-checks:** distinguish isIsolatedPair's .some from .every ([12df113](https://github.com/ExaDev/eslint-config/commit/12df113a51608f68688904997fe17cb758d0a8b5)) +* **workspace-glob:** distinguish a real depth counter from an inverted or dead one ([1148a78](https://github.com/ExaDev/eslint-config/commit/1148a782507d45bc6c492c6d9ed70a1665fbbfa8)) +* **workspace-yaml:** assert the doubling escape never applies to a double-quoted scalar ([8846566](https://github.com/ExaDev/eslint-config/commit/8846566de545a4a0576130f79eedf3af13ffc978)) + +# [2.21.0](https://github.com/ExaDev/eslint-config/compare/v2.20.2...v2.21.0) (2026-09-26) ### Features @@ -465,6 +926,35 @@ * **workspace:** add shared workspace architecture options schema and reader ([9db2cc2](https://github.com/ExaDev/eslint-config/commit/9db2cc2659d70067e44a306f651701bf53dd28b3)) * **workspace:** add workspace dependency graph construction ([67b7d30](https://github.com/ExaDev/eslint-config/commit/67b7d30f931fc947bfacdfe980ecaaf786a19c79)) + +### Bug Fixes + +* **workspace:** accept zero-indent pnpm-workspace.yaml sequence items ([800483c](https://github.com/ExaDev/eslint-config/commit/800483cf9ae6d1f6643a1586c9cdde5d224a4ebe)) +* **workspace:** de-duplicate dependency names before checking uphill rules ([50f752d](https://github.com/ExaDev/eslint-config/commit/50f752d1e08ae07f1b33349576ac49d5ee0dd283)) +* **workspace:** namePrefix slice picks the longest match and strips scope ([d20ee82](https://github.com/ExaDev/eslint-config/commit/d20ee82a5ffe099962c4e4e29d9acdec3ef2c83d)) +* **workspace:** reject unknown option keys and validate isolatedGroups ([73deb85](https://github.com/ExaDev/eslint-config/commit/73deb850684d700b84395debed310ff0ab1713c0)) +* **workspace:** support in-segment glob wildcards and skip node_modules ([456e77f](https://github.com/ExaDev/eslint-config/commit/456e77fa2e72a05e7ae2b02eedbd7c718191a1ae)) + + +### Code Refactoring + +* **workspace:** close mutation-testing survivors in the workspace rules ([41cd8d9](https://github.com/ExaDev/eslint-config/commit/41cd8d9761ffa5eb769899b81034dc663548ec72)) +* **workspace:** pick the longest namePrefix slice by sorting, not a running max ([5020761](https://github.com/ExaDev/eslint-config/commit/50207615e2dadfd34daa8541a8acafa7b64299aa)) + + +### Documentation + +* document the workspace architecture rules ([09f1fd7](https://github.com/ExaDev/eslint-config/commit/09f1fd7515b7bbedaa3331bb6c4d583099c31c6a)) +* **workspace:** correct the three workspace-architecture examples ([1f15718](https://github.com/ExaDev/eslint-config/commit/1f15718c99ab14bd1b158b82390f835420db7550)) + + +### Tests + +* **workspace:** assert segmentToRegExp carries the unicode regex flag ([76b33e1](https://github.com/ExaDev/eslint-config/commit/76b33e1e84e7a0af4fd80462511f4729a4ec4fa4)) +* **workspace:** assert the block-sequence error trims its own line content ([2aaaf84](https://github.com/ExaDev/eslint-config/commit/2aaaf84523c53c4e118aaeb3777be351a7345376)) +* **workspace:** close remaining mutation-testing survivors ([98bc538](https://github.com/ExaDev/eslint-config/commit/98bc5383c83d17009e6609b0e03a078171e7ec43)) +* **workspace:** distinguish OR from AND in the isolatedGroups group-check ([ae5e0df](https://github.com/ExaDev/eslint-config/commit/ae5e0df73082e5e599a9fd9f0b8031746f114b38)) + ## [2.20.2](https://github.com/ExaDev/eslint-config/compare/v2.20.1...v2.20.2) (2026-09-25) @@ -482,24 +972,52 @@ # [2.20.0](https://github.com/ExaDev/eslint-config/compare/v2.19.4...v2.20.0) (2026-09-19) +### Features + +* **config:** register prefer-options-object-param and max-params ([2fbaf46](https://github.com/ExaDev/eslint-config/commit/2fbaf467f002e500fe354e1838868cd83fab4b70)) +* **rules:** add prefer-options-object-param rule ([112bccf](https://github.com/ExaDev/eslint-config/commit/112bccf7b4d79aea9419213d12efd42a97d0f2c7)) + + ### Bug Fixes * **no-non-barrel-reexport:** bundle fixer and sourceCode into one context param ([727b223](https://github.com/ExaDev/eslint-config/commit/727b22380c892ef9ff747742ba2ab6879aeb7db2)) -### Features +### Code Refactoring -* **config:** register prefer-options-object-param and max-params ([2fbaf46](https://github.com/ExaDev/eslint-config/commit/2fbaf467f002e500fe354e1838868cd83fab4b70)) -* **rules:** add prefer-options-object-param rule ([112bccf](https://github.com/ExaDev/eslint-config/commit/112bccf7b4d79aea9419213d12efd42a97d0f2c7)) +* **ts-node-guards:** add firstTokenOrThrow ([4fe7d28](https://github.com/ExaDev/eslint-config/commit/4fe7d28aaa177c5aa6cb82cda02a108d8b89f0e1)) ## [2.19.4](https://github.com/ExaDev/eslint-config/compare/v2.19.3...v2.19.4) (2026-09-18) + +### Documentation + +* link external resources and update config examples in README ([04801cc](https://github.com/ExaDev/eslint-config/commit/04801cca270883b7eb9a129c339902f9301f0efb)) + ## [2.19.3](https://github.com/ExaDev/eslint-config/compare/v2.19.2...v2.19.3) (2026-09-18) + +### Documentation + +* make rule names in README clickable ([64801b7](https://github.com/ExaDev/eslint-config/commit/64801b792ceac1ec77d1512f0e9667686dec03d1)) + ## [2.19.2](https://github.com/ExaDev/eslint-config/compare/v2.19.1...v2.19.2) (2026-09-18) + +### Documentation + +* improve rule documentation formatting and clarity ([ae47821](https://github.com/ExaDev/eslint-config/commit/ae47821c301122bd08cefa3dada9c0ab14956bf0)) +* indent rule rationales in README ([8bf2dbc](https://github.com/ExaDev/eslint-config/commit/8bf2dbcaf3d76f604376f8b13afb03c2f1beac70)) + ## [2.19.1](https://github.com/ExaDev/eslint-config/compare/v2.19.0...v2.19.1) (2026-09-18) + +### Documentation + +* clarify minimumReleaseAgeExclude comment for unscoped packages ([c0e6820](https://github.com/ExaDev/eslint-config/commit/c0e68206537c2233e9127b8300988667a7d21e9d)) +* make file paths in README clickable ([d374eb3](https://github.com/ExaDev/eslint-config/commit/d374eb38a7e172545ac05b568f5948dfba9ee8da)) +* refine README content and structure ([a388628](https://github.com/ExaDev/eslint-config/commit/a3886289fb87df5b68a574640387d50741e7ceb4)) + # [2.19.0](https://github.com/ExaDev/eslint-config/compare/v2.18.1...v2.19.0) (2026-09-18) @@ -507,8 +1025,18 @@ * **barrel-policy:** add auto mode that detects single vs banned from package.json ([c829516](https://github.com/ExaDev/eslint-config/commit/c829516ddfb1d399698e3742024a4302aef475c2)) + +### Documentation + +* document barrel-policy auto mode and the auto-detecting default ([2f7411f](https://github.com/ExaDev/eslint-config/commit/2f7411f78870206f5facb379c04af7443503c0b3)) + ## [2.18.1](https://github.com/ExaDev/eslint-config/compare/v2.18.0...v2.18.1) (2026-09-17) + +### Documentation + +* record the autofixer pair interactions and their stable escapes ([c6e1ce0](https://github.com/ExaDev/eslint-config/commit/c6e1ce0f209ae5e25ca4462a1ad3096c10815e71)) + # [2.18.0](https://github.com/ExaDev/eslint-config/compare/v2.17.2...v2.18.0) (2026-09-15) @@ -516,10 +1044,49 @@ * add exadev/test-file-kind rule requiring a kind suffix ([2d64ec5](https://github.com/ExaDev/eslint-config/commit/2d64ec5a5c70bf05cf435eeeacd51547e9cc2749)) + +### Documentation + +* document test-file-kind and the kind-suffix test naming convention ([f795757](https://github.com/ExaDev/eslint-config/commit/f795757aff0d79fe8fbf935dda86bf620215e70f)) + ## [2.17.2](https://github.com/ExaDev/eslint-config/compare/v2.17.1...v2.17.2) (2026-09-15) + +### Code Refactoring + +* extract shared scope/type-node guard helpers ([c84e27c](https://github.com/ExaDev/eslint-config/commit/c84e27ccb17867d7d4675429d317c839be6636c3)) +* remove a dead guard and share the identifier-name invariant ([0745889](https://github.com/ExaDev/eslint-config/commit/0745889bceb96cfb458a0e35d4eec442c7046832)) +* remove provably-dead guards in the mutation-detection trio ([3482945](https://github.com/ExaDev/eslint-config/commit/34829453f0c8afc44cac27c180718fb4d0c07e31)) +* remove three provably-dead guard checks in the type-aware rules ([917ba94](https://github.com/ExaDev/eslint-config/commit/917ba9448b1d24a6b7685b45b6f8df982ca27acd)) +* remove two provably-dead constructs in package-json-key-order ([ab12eda](https://github.com/ExaDev/eslint-config/commit/ab12eda84ace7acde0287652ac3cf7fee31c9c75)) + + +### Tests + +* kill remaining Stryker survivors from module-level literals ([b107f75](https://github.com/ExaDev/eslint-config/commit/b107f75b7e3e748235f83533aae8a83eada1984b)) +* kill remaining survivors in no-pointless-reassignment ([2380c7c](https://github.com/ExaDev/eslint-config/commit/2380c7c8af53502f1ff7bcd0900f13a411cc390c)) +* kill Stryker survivors in package-json-key-order ([fe9c200](https://github.com/ExaDev/eslint-config/commit/fe9c200371001d534b21916e021fb5464575ec96)) +* kill Stryker survivors in the barrel-discipline rule family ([4739b67](https://github.com/ExaDev/eslint-config/commit/4739b67cf66d57f5dca78c99b5a86ba75c2d90ef)) +* kill Stryker survivors in the isArray/instanceof mutation rules ([1a1fb7a](https://github.com/ExaDev/eslint-config/commit/1a1fb7a1cb741e9367799fc6f27052d80ca0b07c)) +* kill Stryker survivors in the readonly-param and sort-compare rules ([3dd10e1](https://github.com/ExaDev/eslint-config/commit/3dd10e178bf6cc943c0efc83406185992a8ce1f7)) +* kill Stryker survivors in the reassignment/assign/enum rules ([ae46661](https://github.com/ExaDev/eslint-config/commit/ae466616c151a0fcc45c5d99b1a0637b1681d193)) +* kill Stryker survivors in the top-level config-builder files ([0f5ab14](https://github.com/ExaDev/eslint-config/commit/0f5ab14888a2d7ab186d0190ff88f512200de86e)) +* perform each json-canonical import inside its own test body ([b55dbb4](https://github.com/ExaDev/eslint-config/commit/b55dbb471b6d8c05b758d867e8cc2e77ccf3387c)) +* prove legacy consumer-compatibility patterns resolve at runtime ([83f7eae](https://github.com/ExaDev/eslint-config/commit/83f7eae8eacc23210a6641c8b1ace4fda042be29)) +* verify barrel-policy schema rejection through a plain Linter ([d1cce74](https://github.com/ExaDev/eslint-config/commit/d1cce742f8024814e4460365b46815a82f6a60d5)), closes [Linter#verify](https://github.com/Linter/issues/verify) + + +### Chores + +* wire up Stryker mutation testing ([a7e5eca](https://github.com/ExaDev/eslint-config/commit/a7e5eca0d47db5959c324a084d62ccfdbe83b7dd)) + ## [2.17.1](https://github.com/ExaDev/eslint-config/compare/v2.17.0...v2.17.1) (2026-09-15) + +### Chores + +* bump eslint-plugin-json-canonical to 2.1.0 ([12b24d7](https://github.com/ExaDev/eslint-config/commit/12b24d7ac50ea249ff8aada4eeb15a594eed0f5a)) + # [2.17.0](https://github.com/ExaDev/eslint-config/compare/v2.16.1...v2.17.0) (2026-09-15) @@ -541,18 +1108,28 @@ * bump eslint-plugin-json-canonical to v2 for pretty-printing and JSONC ([a77cec1](https://github.com/ExaDev/eslint-config/commit/a77cec1f5529003d9f95f0f02406cf1f372db9c1)) -# [2.15.0](https://github.com/ExaDev/eslint-config/compare/v2.14.0...v2.15.0) (2026-09-15) +### Documentation -### Bug Fixes +* update RFC 8785 section for eslint-plugin-json-canonical v2 ([2db10a5](https://github.com/ExaDev/eslint-config/commit/2db10a52b169ae985a254f63c601fd9527140dd9)) -* **eslint.config:** scope js.configs.recommended and type-imports rules to JS/TS files ([3c9e555](https://github.com/ExaDev/eslint-config/commit/3c9e5554dafaf8ab934edd4066e61efef4de4ee4)) + +### Styles + +* pretty-print and canonically order this repo's own JSON files ([d483cc9](https://github.com/ExaDev/eslint-config/commit/d483cc93ac7208b91ce0f8abde51c64a99cc34f7)) + +# [2.15.0](https://github.com/ExaDev/eslint-config/compare/v2.14.0...v2.15.0) (2026-09-15) ### Features * add package-json-key-order rule for syncpack-compatible ordering ([7598ac3](https://github.com/ExaDev/eslint-config/commit/7598ac301012633c3e5009c358956fb1c98ed320)) + +### Bug Fixes + +* **eslint.config:** scope js.configs.recommended and type-imports rules to JS/TS files ([3c9e555](https://github.com/ExaDev/eslint-config/commit/3c9e5554dafaf8ab934edd4066e61efef4de4ee4)) + # [2.14.0](https://github.com/ExaDev/eslint-config/compare/v2.13.0...v2.14.0) (2026-09-15) @@ -576,6 +1153,11 @@ ## [2.12.2](https://github.com/ExaDev/eslint-config/compare/v2.12.1...v2.12.2) (2026-09-14) + +### Chores + +* bump pinned package manager to pnpm 12.4.1 ([e80286f](https://github.com/ExaDev/eslint-config/commit/e80286f452810b03eb584051867311fd94975c1a)) + ## [2.12.1](https://github.com/ExaDev/eslint-config/compare/v2.12.0...v2.12.1) (2026-09-14) @@ -583,6 +1165,11 @@ * pin eslint-plugin-jsdoc to an exact, already-mature version ([81c6f76](https://github.com/ExaDev/eslint-config/commit/81c6f767dd331b24621b8ba2b1d28ee17d4940cf)) + +### Chores + +* write exact dependency versions instead of caret ranges ([919c305](https://github.com/ExaDev/eslint-config/commit/919c3059d4cc8dbe9fdacb749cd1133ec4705a4a)) + # [2.12.0](https://github.com/ExaDev/eslint-config/compare/v2.11.0...v2.12.0) (2026-09-14) @@ -593,6 +1180,11 @@ # [2.11.0](https://github.com/ExaDev/eslint-config/compare/v2.10.6...v2.11.0) (2026-09-12) +### Features + +* validate JSDoc/TSDoc quality on existing doc comments ([fb17d2a](https://github.com/ExaDev/eslint-config/commit/fb17d2a677057b049c236b67a004c797944f3902)) + + ### Bug Fixes * **ci:** push release commits over SSH using a deploy key ([7f3beb0](https://github.com/ExaDev/eslint-config/commit/7f3beb0b8aab12cff9fbbd4139da228f821fc784)) @@ -600,12 +1192,22 @@ * **release:** push over SSH via repositoryUrl, not a git config rewrite ([a402b71](https://github.com/ExaDev/eslint-config/commit/a402b71656335637250874701bb81040bc448815)) -### Features +### Tests + +* raise the suite timeout for typescript-eslint's rule-tester cases ([9c5cf64](https://github.com/ExaDev/eslint-config/commit/9c5cf64c4fadaefcf306cba51b13892d0fcc27b0)) -* validate JSDoc/TSDoc quality on existing doc comments ([fb17d2a](https://github.com/ExaDev/eslint-config/commit/fb17d2a677057b049c236b67a004c797944f3902)) + +### Continuous Integration + +* add a Required Checks job aggregating commitlint, lint, and typecheck ([683b41e](https://github.com/ExaDev/eslint-config/commit/683b41eb90b9ebe3c6785ed2c31afddc9aaea014)) ## [2.10.6](https://github.com/ExaDev/eslint-config/compare/v2.10.5...v2.10.6) (2026-09-06) + +### Chores + +* dogfood defineConfig() now that exadevConfig() satisfies it ([011505a](https://github.com/ExaDev/eslint-config/commit/011505a152cac4cb10623f6fd646935ef54dd5ed)) + ## [2.10.5](https://github.com/ExaDev/eslint-config/compare/v2.10.4...v2.10.5) (2026-09-06) @@ -634,6 +1236,16 @@ * reject unknown/any/never/primitive aliases in prefer-readonly-object-param ([48862cc](https://github.com/ExaDev/eslint-config/commit/48862cc94d79aa17c40818e1eeedffe9a5f99edf)) + +### Documentation + +* record that Readonly narrows a parameter, not just wraps it redundantly ([14a05f8](https://github.com/ExaDev/eslint-config/commit/14a05f8f4899a2a7aa9c331bba91db39e14d3e26)) + + +### Tests + +* pin prefer-readonly-object-param's object-type gate in both directions ([5912a97](https://github.com/ExaDev/eslint-config/commit/5912a972d63439c2a1d71edafaab6f2f780a5a70)) + ## [2.10.1](https://github.com/ExaDev/eslint-config/compare/v2.10.0...v2.10.1) (2026-08-31) @@ -650,6 +1262,11 @@ ## [2.9.1](https://github.com/ExaDev/eslint-config/compare/v2.9.0...v2.9.1) (2026-08-26) + +### Tests + +* give the test-file-relaxation test a real project service ([0fb9303](https://github.com/ExaDev/eslint-config/commit/0fb9303fdcb681b109d7d308148dac980d112c57)) + # [2.9.0](https://github.com/ExaDev/eslint-config/compare/v2.8.0...v2.9.0) (2026-08-26) @@ -664,6 +1281,11 @@ * enable @typescript-eslint/strict-void-return ([61f4cb8](https://github.com/ExaDev/eslint-config/commit/61f4cb8eb838b65cc99d351b7222464de9382a65)) + +### Continuous Integration + +* allow the release job to run on workflow_dispatch too ([4e99a69](https://github.com/ExaDev/eslint-config/commit/4e99a6991d7fc62177665962c86e8a645d09bcec)) + # [2.7.0](https://github.com/ExaDev/eslint-config/compare/v2.6.2...v2.7.0) (2026-08-26) @@ -673,14 +1295,19 @@ ## [2.6.2](https://github.com/ExaDev/eslint-config/compare/v2.6.1...v2.6.2) (2026-08-26) + +### Chores + +* enable noUncheckedSideEffectImports and strictBuiltinIteratorReturn ([3c8d464](https://github.com/ExaDev/eslint-config/commit/3c8d46438568fb337f18f17116345fa235f840db)) + ## [2.6.1](https://github.com/ExaDev/eslint-config/compare/v2.6.0...v2.6.1) (2026-08-26) -# [2.6.0](https://github.com/ExaDev/eslint-config/compare/v2.5.0...v2.6.0) (2026-08-26) +### Build System -### Bug Fixes +* enable every remaining TypeScript strictness flag ([1ded5a8](https://github.com/ExaDev/eslint-config/commit/1ded5a8b6d264f415ae414cf0d72d37e704c0d79)) -* catch a local variable, not just a parameter, in three rules ([b3ecfd8](https://github.com/ExaDev/eslint-config/commit/b3ecfd81a799e2eb24f067499601258e741d6e5f)) +# [2.6.0](https://github.com/ExaDev/eslint-config/compare/v2.5.0...v2.6.0) (2026-08-26) ### Features @@ -688,6 +1315,16 @@ * add prefer-readonly-object-param rule with real autofix ([6b768bd](https://github.com/ExaDev/eslint-config/commit/6b768bdf9b4b7babe257434b44dbf45cf9263819)) * register prefer-readonly-object-param in the type-checked bundle ([458d2bc](https://github.com/ExaDev/eslint-config/commit/458d2bcf1eef343a20ba4504ab858023ef199ec6)) + +### Bug Fixes + +* catch a local variable, not just a parameter, in three rules ([b3ecfd8](https://github.com/ExaDev/eslint-config/commit/b3ecfd81a799e2eb24f067499601258e741d6e5f)) + + +### Documentation + +* document prefer-readonly-object-param and the widened scope ([36c64bf](https://github.com/ExaDev/eslint-config/commit/36c64bfe3cb33a7476144c465cc64339ab7d112f)) + # [2.5.0](https://github.com/ExaDev/eslint-config/compare/v2.4.0...v2.5.0) (2026-08-26) @@ -699,6 +1336,11 @@ * add prefer-readonly-array-param rule with real autofix ([c8429d3](https://github.com/ExaDev/eslint-config/commit/c8429d3e9eb71d90af4f6e74422dd7c2cad144a9)) * enable 3 native rules, register the four new rules ([aafb702](https://github.com/ExaDev/eslint-config/commit/aafb70290f4d612999736a095bc97a3695da4ed3)) + +### Documentation + +* document the four new rules and three native rule additions ([7faa9d0](https://github.com/ExaDev/eslint-config/commit/7faa9d0c5557a750117eab6f2af0c0e0fa0a4614)) + # [2.4.0](https://github.com/ExaDev/eslint-config/compare/v2.3.0...v2.4.0) (2026-08-26) @@ -708,6 +1350,11 @@ * add no-enum-reverse-lookup-widening rule for unchecked enum reverse lookups ([b45dfe0](https://github.com/ExaDev/eslint-config/commit/b45dfe0e8bf4e9fe62be4c80a3019d542d6d95a0)) * enable 10 native typescript-eslint rules, register the two new rules ([61315d6](https://github.com/ExaDev/eslint-config/commit/61315d66737e749effbf53e4d75e33de2e49f44d)) + +### Documentation + +* document the two new rules and the ten native rule additions ([ae0a2d6](https://github.com/ExaDev/eslint-config/commit/ae0a2d6e1398f2392af06d2020f2c8438645a6c2)) + # [2.3.0](https://github.com/ExaDev/eslint-config/compare/v2.2.0...v2.3.0) (2026-08-26) @@ -725,6 +1372,11 @@ * add no-object-assign rule for its unchecked source-property types ([d336498](https://github.com/ExaDev/eslint-config/commit/d3364981eb9d1154b9b37787eacf252d4d3668d2)) * register the three new rules, enable method-signature-style ([936af64](https://github.com/ExaDev/eslint-config/commit/936af64561bef31d0a6afe3e89ac99c55ad42c09)) + +### Documentation + +* document the three new rules and method-signature-style ([02b1b0d](https://github.com/ExaDev/eslint-config/commit/02b1b0d82c29679d1924c8b36ebbfbf8091eb842)) + ## [2.1.2](https://github.com/ExaDev/eslint-config/compare/v2.1.1...v2.1.2) (2026-08-24) @@ -732,8 +1384,18 @@ * stop no-pointless-reassignment producing broken or meaning-changing autofixes ([c0227f9](https://github.com/ExaDev/eslint-config/commit/c0227f94f18ca9d813e350f951556fe4a87b25fa)) + +### Documentation + +* record when no-pointless-reassignment withholds its autofix ([e551f10](https://github.com/ExaDev/eslint-config/commit/e551f1021ee2ef3453ccf9be596eba4b011a55b1)) + ## [2.1.1](https://github.com/ExaDev/eslint-config/compare/v2.1.0...v2.1.1) (2026-08-08) + +### Documentation + +* condense README ([b037724](https://github.com/ExaDev/eslint-config/commit/b0377246c5551ff7202590e00b056110cf4ed11f)) + # [2.1.0](https://github.com/ExaDev/eslint-config/compare/v2.0.0...v2.1.0) (2026-08-07) @@ -744,7 +1406,9 @@ # [2.0.0](https://github.com/ExaDev/eslint-config/compare/v1.4.1...v2.0.0) (2026-08-07) -* feat!: make the type-checked bundle the default export, drop the separate subpath ([aed49bb](https://github.com/ExaDev/eslint-config/commit/aed49bb40b8c1a9b062f3681364b679f80d95ce9)) +### Features + +* make the type-checked bundle the default export, drop the separate subpath ([aed49bb](https://github.com/ExaDev/eslint-config/commit/aed49bb40b8c1a9b062f3681364b679f80d95ce9)) ### BREAKING CHANGES @@ -770,6 +1434,11 @@ for the lighter, non-type-checked rules/configs. ## [1.4.1](https://github.com/ExaDev/eslint-config/compare/v1.4.0...v1.4.1) (2026-08-07) + +### Continuous Integration + +* bump actions/cache to v6 ([7b4a9a0](https://github.com/ExaDev/eslint-config/commit/7b4a9a07d9f9c0688fb7211d27c88cb0a3bfcc31)) + # [1.4.0](https://github.com/ExaDev/eslint-config/compare/v1.3.0...v1.4.0) (2026-08-07) @@ -793,8 +1462,31 @@ for the lighter, non-type-checked rules/configs. ## [1.2.2](https://github.com/ExaDev/eslint-config/compare/v1.2.1...v1.2.2) (2026-08-07) + +### Documentation + +* document the tseslint.config() extends incompatibility and the unscoped-recommended misfire ([24f6c7b](https://github.com/ExaDev/eslint-config/commit/24f6c7bddb43ae8b4a2c614b9e541e74dedfbe04)) + ## [1.2.1](https://github.com/ExaDev/eslint-config/compare/v1.2.0...v1.2.1) (2026-08-07) + +### Documentation + +* document the vitest test setup and coverage reporting ([edfa960](https://github.com/ExaDev/eslint-config/commit/edfa96042ab7310115eb4163fc8ece75e0d7b831)) + + +### Tests + +* add RuleTester coverage for the four plugin rules ([3a9a561](https://github.com/ExaDev/eslint-config/commit/3a9a5618896d06cf723172f0bf7041569e80de84)) +* add vitest test runner with RuleTester wiring ([8296d19](https://github.com/ExaDev/eslint-config/commit/8296d196dc0bbc3f6b142c02671c8e3615fb6d7c)) +* measure and report coverage via @vitest/coverage-v8 ([f78b8e8](https://github.com/ExaDev/eslint-config/commit/f78b8e8538035c296851ea683fb5bb5d3b28b401)) + + +### Continuous Integration + +* cache .eslintcache across CI runs ([f4c5e13](https://github.com/ExaDev/eslint-config/commit/f4c5e136103f3c589642522d5a4b5e3d7d1e58d5)) +* run the test suite in CI and the pre-push hook ([221c16c](https://github.com/ExaDev/eslint-config/commit/221c16ca04c033f46e2592333cc48a48604e51dc)) + # [1.2.0](https://github.com/ExaDev/eslint-config/compare/v1.1.2...v1.2.0) (2026-08-07) @@ -802,10 +1494,26 @@ for the lighter, non-type-checked rules/configs. * bundle typescript-eslint's typed-linting baseline into recommended ([86397dc](https://github.com/ExaDev/eslint-config/commit/86397dc047ed917f70276f2e776721d823748445)) + +### Code Refactoring + +* isolate the typed-linting bundle into its own module ([2665aaf](https://github.com/ExaDev/eslint-config/commit/2665aafbbcc4b8268ba68c4fa02cb32806516b7b)) + ## [1.1.2](https://github.com/ExaDev/eslint-config/compare/v1.1.1...v1.1.2) (2026-08-07) + +### Documentation + +* add GitHub/npm/Release/CI badges to the README ([b2f70af](https://github.com/ExaDev/eslint-config/commit/b2f70af4d69a56bc1140ccca4fe9bf4f6fef2715)) +* rewrite README as a unified project guide with symlinked agent instructions ([6efd3d2](https://github.com/ExaDev/eslint-config/commit/6efd3d29988215192c0a54f0e1c4465ec85aceaa)) + ## [1.1.1](https://github.com/ExaDev/eslint-config/compare/v1.1.0...v1.1.1) (2026-08-07) + +### Code Refactoring + +* split plugin construction out of src/index.ts ([a3660f1](https://github.com/ExaDev/eslint-config/commit/a3660f1da7d1cf89655208ef92b2e65879c7f990)) + # [1.1.0](https://github.com/ExaDev/eslint-config/compare/v1.0.1...v1.1.0) (2026-08-07) @@ -815,14 +1523,19 @@ for the lighter, non-type-checked rules/configs. ## [1.0.1](https://github.com/ExaDev/eslint-config/compare/v1.0.0...v1.0.1) (2026-08-07) -# 1.0.0 (2026-08-07) +### Documentation -### Bug Fixes +* decouple package description from the documents.js family ([a44d8c0](https://github.com/ExaDev/eslint-config/commit/a44d8c0b4c2db887cafbf302bcf557db17568fb1)) -* ignore the false-export-default attw rule ([667b7e7](https://github.com/ExaDev/eslint-config/commit/667b7e78e9183714ea1e53575fc6e5d973945692)) +# 1.0.0 (2026-08-07) ### Features * initial ESLint plugin combining the shared custom rules ([29b86ff](https://github.com/ExaDev/eslint-config/commit/29b86ff64d321c401be3ebf9c578b6eb69dff8bc)) + + +### Bug Fixes + +* ignore the false-export-default attw rule ([667b7e7](https://github.com/ExaDev/eslint-config/commit/667b7e78e9183714ea1e53575fc6e5d973945692))