From 902bb1f82c3b55c17386d819c0108d2d595ae74a Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Thu, 9 Jul 2026 16:58:45 +0200 Subject: [PATCH 1/4] chore(eslint): encode mechanical conventions as lint rules Add unicorn/filename-case (error, kebab-case) to catch macOS/Linux import casing mismatches, plus max-params, max-lines-per-function and promise/prefer-await-to-then as warnings. Relax filename-case for the generated ANTLR parser, snake_case demo fixtures and _-grouped tests, and scope max-lines-per-function to src. Drop the now-linted and unmeasurable clean-code prose from CLAUDE.md. Co-Authored-By: Claude Opus 4.8 --- .eslintrc.js | 33 +++++++++++++++++++- CLAUDE.md | 22 +++---------- package.json | 2 ++ yarn.lock | 88 ++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 120 insertions(+), 25 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2b05fdcf9f..748f713640 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,12 +17,25 @@ module.exports = { sourceType: 'module', project: ['./tsconfig.eslint.json'], }, - plugins: ['@typescript-eslint', 'prettier', 'jest', 'jest-formatting'], + plugins: ['@typescript-eslint', 'prettier', 'jest', 'jest-formatting', 'unicorn', 'promise'], rules: { /**********/ /** Style */ /**********/ + // Kebab-case filenames avoid case-sensitivity mismatches between macOS and Linux CI. + // Generated parser, snake-case demo fixtures, and _-grouped tests are relaxed below. + 'unicorn/filename-case': ['error', { case: 'kebabCase' }], + + // Prefer async/await over .then chains; a smell, not a build blocker. + 'promise/prefer-await-to-then': 'warn', + + // Options-object pattern is the norm; flag drift without forcing signature refactors. + 'max-params': ['warn', 4], + + // Long functions are a smell; scoped to src (excluded for tests below). + 'max-lines-per-function': ['warn', 50], + // Code spacing 'prettier/prettier': 'error', 'arrow-parens': ['error', 'as-needed'], @@ -144,5 +157,23 @@ module.exports = { ], }, }, + { + // Generated ANTLR parser: cannot rename without breaking regeneration. + files: ['**/generated-parser/**/*'], + rules: { 'unicorn/filename-case': 'off' }, + }, + { + // Demo fixtures mirror snake_case database table names. + files: ['packages/datasource-demo-fintech/**/*'], + rules: { 'unicorn/filename-case': 'off' }, + }, + { + // Tests use _-grouped filenames and long describe/it callbacks. + files: ['**/test/**/*'], + rules: { + 'unicorn/filename-case': 'off', + 'max-lines-per-function': 'off', + }, + }, ], }; diff --git a/CLAUDE.md b/CLAUDE.md index 238598e1f2..0e10b58887 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,42 +67,28 @@ yarn workspace @forestadmin/agent test - ✅ `expect(mock).toHaveBeenCalledWith({ host: 'localhost', port: 3000 })` - verifies exact arguments - ✅ `expect(mock).toHaveBeenCalledWith(expect.objectContaining({ host: 'localhost' }))` - partial match when some values are dynamic - **One behavior per test** - Each test should verify one specific behavior -- **Use AAA pattern** - Arrange (setup), Act (execute), Assert (verify) - keep these sections clear - **Test edge cases** - Not just happy paths; test errors, null values, empty arrays, boundaries - **Test behavior, not implementation** - Assert on observable outputs, not internal method calls - **Coverage ≠ quality** - 100% coverage with weak assertions is worse than 80% with strong assertions ## Code Review Principles -### Core Principles - -- **DRY** (Don't Repeat Yourself) - Extract common logic into reusable functions/services -- **KISS** (Keep It Simple, Stupid) - Prefer simple, readable solutions over clever ones -- **YAGNI** (You Aren't Gonna Need It) - Don't implement features "just in case" +Mechanical conventions (function size, parameter count, filename case, async/await +over `.then`) are enforced by ESLint — see `.eslintrc.js`, not this file. ### Function Design -- **Single Responsibility** - One function = one task -- **Size** - Keep functions short (20-30 lines max); split if longer -- **Naming** - Descriptive names that explain *what*, not *how* (`getUserPermissions` not `getData`) -- **Parameters** - Max 3-4 parameters; use an options object for more - **Return early** - Guard clauses at the top, avoid deep nesting ### Code Quality - **No magic numbers/strings** - Use named constants -- **Avoid side effects** - Pure functions when possible - **Handle errors explicitly** - No silent failures -- **Comments** - Explain *why*, not *what* (code should be self-documenting) ### Review Checklist -1. Does this code do one thing well? -2. Can I understand it in 30 seconds? -3. Is there duplication that should be extracted? -4. Are there unused variables/imports? -5. Are edge cases handled? -6. Is the naming clear and consistent? +1. Are edge cases handled? +2. Are there unused variables/imports? ## Linear Tickets diff --git a/package.json b/package.json index d72df52348..0fb69c6cf2 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.6.0", + "eslint-plugin-unicorn": "^48.0.1", "fishery": "^2.2.2", "husky": "^8.0.3", "jest": "^29.3.1", diff --git a/yarn.lock b/yarn.lock index 7384dc3ac9..4bed3d9115 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1030,16 +1030,16 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-identifier@^7.22.5", "@babel/helper-validator-identifier@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" + integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== + "@babel/helper-validator-identifier@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/helper-validator-identifier@^7.29.7": - version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" - integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== - "@babel/helper-validator-option@^7.29.7": version "7.29.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz#cf315be940213b354eb4abcc0bd01ebe3f73bc2a" @@ -1567,6 +1567,13 @@ dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.4.0": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" @@ -5900,6 +5907,11 @@ buildcheck@~0.0.6: resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -6210,7 +6222,7 @@ chownr@^3.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== -ci-info@^3.2.0: +ci-info@^3.2.0, ci-info@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== @@ -6237,6 +6249,13 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== +clean-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" + integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw== + dependencies: + escape-string-regexp "^1.0.5" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -7778,6 +7797,32 @@ eslint-plugin-prettier@^4.2.1: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-promise@^6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz#acd3fd7d55cead7a10f92cf698f36c0aafcd717a" + integrity sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ== + +eslint-plugin-unicorn@^48.0.1: + version "48.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz#a6573bc1687ae8db7121fdd8f92394b6549a6959" + integrity sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + "@eslint-community/eslint-utils" "^4.4.0" + ci-info "^3.8.0" + clean-regexp "^1.0.0" + esquery "^1.5.0" + indent-string "^4.0.0" + is-builtin-module "^3.2.1" + jsesc "^3.0.2" + lodash "^4.17.21" + pluralize "^8.0.0" + read-pkg-up "^7.0.1" + regexp-tree "^0.1.27" + regjsparser "^0.10.0" + semver "^7.5.4" + strip-indent "^3.0.0" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -7879,6 +7924,13 @@ esquery@^1.4.0, esquery@^1.4.2: dependencies: estraverse "^5.1.0" +esquery@^1.5.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -10084,6 +10136,13 @@ is-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -11042,6 +11101,11 @@ jsesc@^3.0.2: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + json-api-serializer@^2.6.6: version "2.6.6" resolved "https://registry.yarnpkg.com/json-api-serializer/-/json-api-serializer-2.6.6.tgz#fa5d283b913e0ea25653f4d04f981dc44d66dd4f" @@ -15082,6 +15146,11 @@ reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: get-proto "^1.0.1" which-builtin-type "^1.2.1" +regexp-tree@^0.1.27: + version "0.1.27" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" + integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== + regexp.prototype.flags@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" @@ -15117,6 +15186,13 @@ registry-auth-token@^5.0.2: dependencies: "@pnpm/npm-conf" "^2.1.0" +regjsparser@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892" + integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA== + dependencies: + jsesc "~0.5.0" + remark-gfm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-1.0.0.tgz#9213643001be3f277da6256464d56fd28c3b3c0d" From 29e9691d19f014c31c99b0f7e7326d4217086bc9 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Thu, 9 Jul 2026 17:41:54 +0200 Subject: [PATCH 2/4] chore(eslint): skip blank and comment lines in max-lines-per-function Count only code lines so the length smell reflects logic, not comments or spacing. Non-blocking (warn); resolves the validator's preferential note. Co-Authored-By: Claude Opus 4.8 --- .eslintrc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 748f713640..d4632a9ed1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,8 +33,8 @@ module.exports = { // Options-object pattern is the norm; flag drift without forcing signature refactors. 'max-params': ['warn', 4], - // Long functions are a smell; scoped to src (excluded for tests below). - 'max-lines-per-function': ['warn', 50], + // Long functions are a smell; count code lines only, scoped to src (excluded for tests below). + 'max-lines-per-function': ['warn', { max: 50, skipBlankLines: true, skipComments: true }], // Code spacing 'prettier/prettier': 'error', From 84fa5312a01cce8288e20a7a0ff53c4fbb756da5 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Fri, 10 Jul 2026 10:22:17 +0200 Subject: [PATCH 3/4] chore(eslint): drop advisory warn rules, keep filename-case enforcement Warnings CI never gates on are dormant documentation, not enforcement. Keep the one rule with teeth (kebab-case filenames, blocks macOS/Linux import-casing bugs) and drop max-params, max-lines-per-function and promise/prefer-await-to-then along with the now-unused promise plugin. Co-Authored-By: Claude Fable 5 --- .eslintrc.js | 18 +++--------------- CLAUDE.md | 3 +-- package.json | 1 - yarn.lock | 5 ----- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d4632a9ed1..052b7c801c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,7 +17,7 @@ module.exports = { sourceType: 'module', project: ['./tsconfig.eslint.json'], }, - plugins: ['@typescript-eslint', 'prettier', 'jest', 'jest-formatting', 'unicorn', 'promise'], + plugins: ['@typescript-eslint', 'prettier', 'jest', 'jest-formatting', 'unicorn'], rules: { /**********/ /** Style */ @@ -27,15 +27,6 @@ module.exports = { // Generated parser, snake-case demo fixtures, and _-grouped tests are relaxed below. 'unicorn/filename-case': ['error', { case: 'kebabCase' }], - // Prefer async/await over .then chains; a smell, not a build blocker. - 'promise/prefer-await-to-then': 'warn', - - // Options-object pattern is the norm; flag drift without forcing signature refactors. - 'max-params': ['warn', 4], - - // Long functions are a smell; count code lines only, scoped to src (excluded for tests below). - 'max-lines-per-function': ['warn', { max: 50, skipBlankLines: true, skipComments: true }], - // Code spacing 'prettier/prettier': 'error', 'arrow-parens': ['error', 'as-needed'], @@ -168,12 +159,9 @@ module.exports = { rules: { 'unicorn/filename-case': 'off' }, }, { - // Tests use _-grouped filenames and long describe/it callbacks. + // Tests use _-grouped filenames. files: ['**/test/**/*'], - rules: { - 'unicorn/filename-case': 'off', - 'max-lines-per-function': 'off', - }, + rules: { 'unicorn/filename-case': 'off' }, }, ], }; diff --git a/CLAUDE.md b/CLAUDE.md index 0e10b58887..5653ba0668 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,8 +73,7 @@ yarn workspace @forestadmin/agent test ## Code Review Principles -Mechanical conventions (function size, parameter count, filename case, async/await -over `.then`) are enforced by ESLint — see `.eslintrc.js`, not this file. +Mechanical conventions are enforced by ESLint — see `.eslintrc.js`, not this file. ### Function Design diff --git a/package.json b/package.json index 0fb69c6cf2..9551c221c6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^6.6.0", "eslint-plugin-unicorn": "^48.0.1", "fishery": "^2.2.2", "husky": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 4bed3d9115..59747f2bec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7797,11 +7797,6 @@ eslint-plugin-prettier@^4.2.1: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz#acd3fd7d55cead7a10f92cf698f36c0aafcd717a" - integrity sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ== - eslint-plugin-unicorn@^48.0.1: version "48.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz#a6573bc1687ae8db7121fdd8f92394b6549a6959" From 99443ce43b5e1bd65ee6b932fddb7410f141eba2 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Fri, 10 Jul 2026 10:53:14 +0200 Subject: [PATCH 4/4] docs: stop implying purged review prose moved to lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only file naming, formatting and unused-variable checks live in ESLint; the deleted principles were removed as generic prose, not migrated. Also drop the unused-variables checklist item — the linter already errors on it. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5653ba0668..0a16cffc5c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,8 @@ yarn workspace @forestadmin/agent test ## Code Review Principles -Mechanical conventions are enforced by ESLint — see `.eslintrc.js`, not this file. +ESLint owns the mechanical rules — file naming, formatting, unused variables +(see `.eslintrc.js`). The points below are judgment calls the linter cannot check. ### Function Design @@ -87,7 +88,6 @@ Mechanical conventions are enforced by ESLint — see `.eslintrc.js`, not this f ### Review Checklist 1. Are edge cases handled? -2. Are there unused variables/imports? ## Linear Tickets