Skip to content

[eslint-miner] Add ESLint rule: require-error-code-in-thrown-error - #51042

Merged
pelikhan merged 1 commit into
mainfrom
eslint-miner/require-error-code-in-thrown-error-352e9ecfcf6a2b46
Aug 7, 2026
Merged

[eslint-miner] Add ESLint rule: require-error-code-in-thrown-error#51042
pelikhan merged 1 commit into
mainfrom
eslint-miner/require-error-code-in-thrown-error-352e9ecfcf6a2b46

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Overview

Adds a new custom ESLint rule, require-error-code-in-thrown-error, to the eslint-factory package (part of the "eslint-miner" family of custom lint rules). The rule enforces that thrown Error messages reference a standardized error code (ERR_* constant from error_codes.cjs) in files that already import that module, keeping error-code coverage consistent for log/dashboard filtering. Registered at "warn" severity.

Files changed

File Change
eslint-factory/eslint.config.cjs Registers gh-aw-custom/require-error-code-in-thrown-error as "warn" in the shared config.
eslint-factory/src/index.ts Imports requireErrorCodeInThrownErrorRule and adds it to the plugin's rules map.
eslint-factory/src/rules/require-error-code-in-thrown-error.ts (new, 78 lines) Rule implementation.
eslint-factory/src/rules/require-error-code-in-thrown-error.test.ts (new, 56 lines) Vitest RuleTester coverage.

Rule logic

  • Built with @typescript-eslint/utils (ESLintUtils.RuleCreator).
  • Scope guard: only activates in files whose source text matches require\(\s*["']\.\/error_codes\.cjs["']\s*\) — i.e. files that already import error_codes.cjs.
  • On each ThrowStatement, checks if the argument is a new Error(...) call (callee identifier exactly "Error"; other constructors like TypeError or plain thrown identifiers are ignored).
  • Inspects the first constructor argument (TemplateLiteral, Literal, Identifier, or BinaryExpression) via messageReferencesErrorCode(), which recursively checks for ERROR_CODE_PATTERN = /ERR_[A-Z_]+|E[0-9]{3}/ against:
    • raw text of the argument,
    • template literal quasis and expressions (Identifier or MemberExpression.property name),
    • plain Identifier name,
    • both sides of a + BinaryExpression, recursively.
  • Reports missingErrorCode on the new Error(...) node when no code reference is found.

Test coverage

require-error-code-in-thrown-error.test.ts uses vitest + ESLint RuleTester (CommonJS, ecmaVersion 2022) across 4 groups:

  • Files not importing error_codes.cjs are never flagged, even without an error code.
  • Errors referencing ERR_* codes (via template interpolation, string concatenation, or embedded literal) are valid.
  • Files importing error_codes.cjs with throw new Error(...) lacking any ERR_ reference are flagged (missingErrorCode).
  • Non-Error throws (throw someError) and other constructors (throw new TypeError(...)) are not flagged.> Generated by PR Description Updater for [eslint-miner] Add ESLint rule: require-error-code-in-thrown-error #51042 · auto · 28.9 AIC · ⊞ 6.8K ·

Adds a new custom ESLint rule that flags thrown Error messages
lacking a standardized error code (ERR_*, from error_codes.cjs) in
files that already import error_codes.cjs. This keeps error-code
coverage consistent so logs/dashboards can filter reliably.

Motivated by issue #51018 (add_labels.cjs / dismiss_pull_request_review.cjs
missing standardized error codes) — scanning actions/setup/js found 111
throw sites across 27 files that import error_codes.cjs but still throw
uncoded errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Great work, @github-actions! 🎉 This PR looks ready for review.

Summary: This adds a focused, well-tested ESLint rule (require-error-code-in-thrown-error) to enforce consistent error-code usage across actions/setup/js files. The implementation:

  • ✅ Activates only in files that import error_codes.cjs (no false positives)
  • ✅ Detects throw new Error(...) calls lacking standard error codes (e.g., ERR_API, ERR_NOT_FOUND)
  • ✅ Handles template literals, concatenation, and identifier references
  • ✅ Includes comprehensive tests (4 test cases, all passing)
  • ✅ Emits a warn diagnostic with actionable guidance
  • ✅ No external dependencies or behavioral changes

Why this matters: Issue #51018 flagged 111 uncoded throw new Error(...) sites across 27 files already using the error-code convention. This rule provides IDE-level feedback and catches violations at linting time, improving error-log consistency for monitoring and alerting.

Validation: The PR body documents:

  • Build passes
  • Test suite passes (4/4 tests)
  • Lint runs clean with the new rule enabled
  • Evidence: 111 existing violations identified

The code is focused, well-scoped to eslint-factory, and ready for integration.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • patchdiff.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "patchdiff.githubusercontent.com"

See Network Configuration for more information.

Generated by ✅ Contribution Check · auto · 57.3 AIC · ⊞ 8.7K ·

@pelikhan
pelikhan marked this pull request as ready for review August 7, 2026 13:43
Copilot AI balanced review requested due to automatic review settings August 7, 2026 13:43
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Security scanning failed for Design Decision Gate 🏗️. Review the logs for details.

No ADR enforcement needed: PR does not have the implementation label and has 0 new lines of code in business logic directories (default_business_additions=0, threshold=100).

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Security scanning failed for PR Code Quality Reviewer. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Security scanning failed for Matt Pocock Skills Reviewer. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Security scanning failed for Test Quality Sentinel. Review the logs for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an ESLint rule intended to enforce standardized error codes in setup-handler errors.

Changes:

  • Implements and tests error-code detection.
  • Registers the rule in the custom plugin.
  • Enables it at warning severity.
Show a summary per file
File Description
eslint-factory/src/rules/require-error-code-in-thrown-error.ts Implements error-code validation.
eslint-factory/src/rules/require-error-code-in-thrown-error.test.ts Adds rule tests.
eslint-factory/src/index.ts Registers the rule.
eslint-factory/eslint.config.cjs Enables the rule.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Balanced


const createRule = ESLintUtils.RuleCreator(name => `https://github.com/github/gh-aw/tree/main/eslint-factory#${name}`);

const ERROR_CODE_PATTERN = /\bERR_[A-Z_]+\b|\bE[0-9]{3}\b/;
Comment on lines +51 to +54
const importsErrorCodes = /require\(\s*["']\.\/error_codes\.cjs["']\s*\)/.test(fullText);

if (!importsErrorCodes) {
return {};
Comment on lines +59 to +60
const arg = node.argument;
if (!arg || arg.type !== AST_NODE_TYPES.NewExpression) return;
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

🧪 Test Quality Sentinel Report

Overview

PR adds a new ESLint rule (require-error-code-in-thrown-error) with comprehensive test coverage. 4 test cases (via vitest describe/it blocks) verify both happy-path behavior and constraint enforcement.

Test Coverage Summary

Metric Value Status
Test Quality Score 85/100 ✅ Excellent
Test/Prod Ratio 0.72:1 ✅ Balanced
Design Tests 4/4 (100%) ✅ All behavioral
Edge Cases 3/4 tests ✅ Strong
Implementation Tests 0% ✅ No ratio violation
Hard Violations None ✅ Clean

Test Cases Analyzed

4 Test Cases — All Design-Focused
Test Type Coverage Invariant
valid: files that do not import error_codes.cjs are not flagged Happy path Import context respected Rule only applies when file imports error_codes
valid: thrown errors that reference an ERR_ code are not flagged Happy path Multiple code formats (ERR_*, templates, concat) Correct codes pass validation
invalid: thrown Error without a code is flagged Constraint enforcement Missing codes in templates and concatenation Missing codes are caught
invalid: non-Error throws and other constructs are ignored Edge case / Boundary Type exclusion, direct throw, TypeError Rule scope limited to new Error()

Structural Quality

Pattern Coverage

  • Template literals with interpolation
  • String concatenation (binary + operator)
  • Hardcoded strings
  • Identifier references to error constants
  • Non-matching patterns (TypeError, direct throw)

Framework Idiomatic

  • Uses ESLint RuleTester (correct for rule testing)
  • Vitest describe/it blocks (co-located with source)
  • Clear, descriptive test names

Valid + Invalid Paths

  • 2 tests verify acceptance cases (5 valid scenarios)
  • 2 tests verify rejection/edge cases (2 violations + 2 edge cases)

Test/Production Ratio: 0.72:1

  • Test file: 56 added lines
  • Rule file: 78 added lines
  • Excellent balance (< 1:1 = no inflation)

Summary

All 4 tests are design-focused (verify user-visible rule behavior, not implementation details). No mock-heavy patterns, no implementation inflation. The test suite covers:

  1. Import context (when rule applies)
  2. Valid error code formats (acceptance)
  3. Missing codes (rejection)
  4. Type boundaries (scope)

No violations detected. Ready to merge. ✅

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 13.4 AIC · ⊞ 7.7K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 85/100 Excellent. All 4 tests are design-focused with 0% implementation-test ratio (well below 30% threshold). Test/production ratio is 0.72:1 (excellent balance). No hard violations detected. Design invariants properly covered: import context, valid error code formats, missing code detection, and type boundaries.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: require-error-code-in-thrown-error

Good addition — the motivation is clear and the opt-in approach (only activates when error_codes.cjs is already imported) avoids false positives in unrelated files. Two correctness bugs need fixing before merge, plus a minor test naming issue.

Blocking issues (2)

  1. Full-text regex for import detection (line 58) — matches require('./error_codes.cjs') inside comments or strings, activating the rule incorrectly. Use AST walking (CallExpression) instead. See inline comment.

  2. .raw cast on non-Literal nodes (line 15) — the leading (node as unknown as {raw?:string}).raw cast is dead code for Identifier/BinaryExpression and reads the wrong property for Literal nodes (raw vs value). See inline comment.

Non-blocking (1)

  1. Misleading test title (test file line 50) — "invalid: non-Error throws..." block has only valid entries. Rename to "valid: ...". See inline comment.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 25 AIC · ⊞ 5.4K

}

return {
ThrowStatement(node: TSESTree.ThrowStatement) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: import detection via full-text regex can false-positive on commented-out require calls.

Using sourceCode.getText() regex to detect the error_codes.cjs import will match occurrences inside comments or string literals, e.g.:

// const { ERR_API } = require('./error_codes.cjs')  // commented out
throw new Error('plain message');

This activates the rule on a file that doesn't actually use the convention, causing spurious warnings.

Prefer walking the AST instead:

let importsErrorCodes = false;
return {
  CallExpression(node) {
    if (
      node.callee.type === AST_NODE_TYPES.Identifier &&
      node.callee.name === 'require' &&
      node.arguments[0]?.type === AST_NODE_TYPES.Literal &&
      (node.arguments[0] as TSESTree.Literal).value === './error_codes.cjs'
    ) {
      importsErrorCodes = true;
    }
  },
  ThrowStatement(node) {
    if (!importsErrorCodes) return;
    // ... existing logic
  },
};

@copilot please address this.

function messageReferencesErrorCode(node: TSESTree.Node): boolean {
const text = (node as unknown as { raw?: string }).raw ?? "";
if (ERROR_CODE_PATTERN.test(text)) return true;
if (node.type === AST_NODE_TYPES.TemplateLiteral) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: .raw cast on non-Literal/TemplateLiteral nodes returns "" and silently skips the code check.

The function begins with:

const text = (node as unknown as { raw?: string }).raw ?? "";
if (ERROR_CODE_PATTERN.test(text)) return true;

For Identifier or BinaryExpression nodes, .raw is undefined, so text is always "". This first check never contributes for those node types — it's dead code that adds confusion.

For Literal nodes the correct property is node.value (a string), not node.raw (which includes surrounding quotes, e.g. "\"ERR_API: ...\""). This means a plain string literal like "ERR_API: failed" would match only because node.raw includes the quotes around the string that happen to contain ERR_API. While the pattern still matches, the logic is incidental.

Recommend replacing the raw-cast with an explicit Literal branch:

if (node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string') {
  return ERROR_CODE_PATTERN.test(node.value);
}

and removing the leading .raw cast entirely.

@copilot please address this.

it("invalid: non-Error throws and other constructs are ignored", () => {
cjsRuleTester.run("require-error-code-in-thrown-error", requireErrorCodeInThrownErrorRule, {
valid: [
`const { ERR_API } = require("./error_codes.cjs"); function f() { throw someError; }`,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misleading test description: "invalid" test block contains only valid cases.

The it block at line ~49 is titled "invalid: non-Error throws and other constructs are ignored" but its RuleTester call has only valid entries and an empty invalid array. The title implies rule violations are tested, but none are. Rename to "valid: non-Error throws and other constructs are not flagged" to avoid confusion for future contributors.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /tdd — requesting changes on two correctness issues in the rule implementation and two test-quality gaps.

📋 Key Themes & Highlights

Key Themes

  • Fragile activation guard (line 57, rule file): the importsErrorCodes check scans raw source text, making it vulnerable to comments or string literals that happen to contain require("./error_codes.cjs"). AST traversal is the correct approach here.
  • Unsafe cast + redundant code path (line 13, rule file): reading .raw via as unknown as { raw?: string } before type-narrowing creates an unclear code path. Literal nodes should be handled explicitly first.
  • Missing boundary test (test file): no coverage for paths like ../error_codes.cjs that intentionally should not activate the rule, leaving the scope contract undocumented.
  • Under-constrained error assertions (test file): errors arrays only check messageId, not node type — a future report-location change would pass silently.

Positive Highlights

  • ✅ Excellent scope discipline: the importsErrorCodes guard keeps false-positive rate at zero for non-convention files.
  • ✅ Good coverage of the detection patterns: template literals, identifiers, binary concatenation, and member expressions.
  • ✅ Correct severity (warn) consistent with the rest of the factory rules.
  • ✅ Clean integration: registration in index.ts and eslint.config.cjs follows established patterns exactly.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 35.3 AIC · ⊞ 7.1K
Comment /matt to run again

return {};
}

return {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The require() detection uses a full-text regex scan (sourceCode.getText()), which means a commented-out require("./error_codes.cjs") or a string literal containing that path will falsely activate the rule. Prefer AST traversal over source-text matching.

💡 Suggested fix

Add a CallExpression visitor that sets a flag when the actual AST require() call is detected:

let importsErrorCodes = false;
return {
  CallExpression(node) {
    if (
      node.callee.type === AST_NODE_TYPES.Identifier &&
      node.callee.name === "require" &&
      node.arguments[0]?.type === AST_NODE_TYPES.Literal &&
      (node.arguments[0] as TSESTree.StringLiteral).value === "./error_codes.cjs"
    ) importsErrorCodes = true;
  },
  ThrowStatement(node) {
    if (!importsErrorCodes) return;
    // ... existing logic
  },
};

This avoids false positives from comments or string literals containing the path.

@copilot please address this.

* or a SAFE_OUTPUT_E001-style numeric code).
*/
function messageReferencesErrorCode(node: TSESTree.Node): boolean {
const text = (node as unknown as { raw?: string }).raw ?? "";

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] messageReferencesErrorCode reads .raw via an unsafe cast to { raw?: string } before checking the node type. If the node is a Literal (not a template), .raw may exist but the code falls through to specific type checks anyway — the early regex test on .raw is redundant and could match non-Literal nodes unexpectedly. The type narrowing should come first.

💡 Suggested refactor

Move the Literal check ahead of the generic .raw access:

function messageReferencesErrorCode(node: TSESTree.Node): boolean {
  if (node.type === AST_NODE_TYPES.Literal) {
    return ERROR_CODE_PATTERN.test(String(node.value));
  }
  if (node.type === AST_NODE_TYPES.TemplateLiteral) { ... }
  if (node.type === AST_NODE_TYPES.Identifier) { ... }
  if (node.type === AST_NODE_TYPES.BinaryExpression && node.operator === "+") { ... }
  return false;
}

This removes the as unknown cast, improves type safety, and makes the logic easier to follow.

@copilot please address this.

},
});

describe("require-error-code-in-thrown-error", () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] There is no test for a file that imports error_codes.cjs via a path that does not match the exact literal ./error_codes.cjs (e.g. '../error_codes.cjs' or a variable). Documenting this as an intentional scope boundary (or adding a test for it) would prevent confusion.

💡 Suggestion

Add an explicit valid case to the "files that do not import error_codes.cjs" group:

// Files importing from a different relative path are not flagged
`const { ERR_API } = require('../error_codes.cjs'); throw new Error('no code');`

This makes the scope boundary visible in the test suite and guards against accidentally widening the regex in future.

@copilot please address this.

code: `const { ERR_API } = require("./error_codes.cjs"); function f(id) { throw new Error("Cannot mark issue as duplicate of " + id); }`,
errors: [{ messageId: "missingErrorCode" }],
},
],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The invalid test cases only verify messageId but not the reported node location. Without a loc assertion, a future refactor that moves the report from the NewExpression to the ThrowStatement (or the message argument) would silently pass these tests despite a different UX.

💡 Suggestion

Add type: 'NewExpression' (or column/line) to pin the reported node:

errors: [{ messageId: "missingErrorCode", type: "NewExpression" }],

This matches the pattern used in other rule tests across the repo and documents intent.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: Request changes

The rule's design has a correctness gap that undermines its stated purpose, plus a fragile detection mechanism and an inherent heuristic weakness.

Themes
  • Coverage gap (high): only throw new Error(...) is checked; throw Error(...) (no new) is completely ignored, so a meaningful subset of the 111 uncoded throws this PR aims to surface could slip through undetected.
  • Fragile import detection (medium/high): whole-file textual regex for require("./error_codes.cjs") can false-positive on comments/strings and false-negative on ESM imports or path variants.
  • Heuristic limitation (medium): name-based identifier matching (ERR_*-named variable) doesn't verify the actual referenced value contains a code — acceptable as a heuristic, but worth documenting as a known limitation.

No test coverage exists for the throw Error() (no new) case, +-concatenated identifier-only messages, or ESM import detection — these gaps in tests mirror the gaps in the implementation.

🔎 Code quality review by PR Code Quality Reviewer · auto · 67.2 AIC · ⊞ 7.8K
Comment /review to run again

return {
ThrowStatement(node: TSESTree.ThrowStatement) {
const arg = node.argument;
if (!arg || arg.type !== AST_NODE_TYPES.NewExpression) return;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only detects throw new Error(...)throw Error(...) (no new, valid and common JS) silently bypasses the rule entirely.

💡 Missing throw-without-new coverage

arg.type !== AST_NODE_TYPES.NewExpression rejects any CallExpression callee, so throw Error("failed to fetch") is never inspected. Some of the 27 offending files referenced in the PR description may well use bare Error(...) calls, and this rule silently gives them a pass — undermining the stated goal of catching all uncoded throws.

Fix: also accept CallExpression with callee Error.

create(context) {
const sourceCode = context.sourceCode;
const fullText = sourceCode.getText();
const importsErrorCodes = /require\(\s*["']\.\/error_codes\.cjs["']\s*\)/.test(fullText);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole-file textual detection of error_codes.cjs usage is a brittle regex that can both false-positive and false-negative.

💡 Fragile presence check via source-text regex

/require\(\s*["']\.\/error_codes\.cjs["']\s*\)/ matches the literal string anywhere in the file's text — including inside comments or unrelated string literals — causing false activation. It also fails to detect ESM import { ERR_API } from "./error_codes.cjs", different relative paths (../error_codes.cjs), or destructured require("./error_codes") without the .cjs suffix, causing false negatives that silently disable the rule for files that do use the convention.

Better: walk the AST for CallExpression/ImportDeclaration nodes with a source matching /error_codes(\.cjs)?$/ rather than a raw text regex.

if (ERROR_CODE_PATTERN.test(quasi.value.raw)) return true;
}
for (const expr of node.expressions) {
if (expr.type === AST_NODE_TYPES.Identifier && ERROR_CODE_PATTERN.test(expr.name)) return true;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matching against an identifier's name (not its value) is a weak heuristic that can be satisfied without the message actually containing a code at runtime.

💡 Name-based check doesn't verify actual code presence

expr.type === AST_NODE_TYPES.Identifier && ERROR_CODE_PATTERN.test(expr.name) passes as soon as a variable is merely named like ERR_something, regardless of what string it actually holds. E.g. const ERR_LABEL = "whoops"; throw new Error(\${ERR_LABEL}: bad`)` would pass the lint even though the rendered message never contains a real error code — defeating the stated goal ("logs/dashboards can filter reliably"). Given this file only checks identifier names heuristically (no cross-file/data-flow resolution), that's an inherent limitation worth calling out in the rule's doc comment so contributors don't over-trust the warning.

@pelikhan
pelikhan merged commit 6c04306 into main Aug 7, 2026
50 checks passed
@pelikhan
pelikhan deleted the eslint-miner/require-error-code-in-thrown-error-352e9ecfcf6a2b46 branch August 7, 2026 14:08
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

🎉 This pull request is included in a new release.

Release: v0.86.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation cookie Issue Monster Loves Cookies! eslint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants