From 3e234747562cd9de429e163ed3b9b427a5253b44 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Mon, 14 Sep 2026 13:53:35 +0100 Subject: [PATCH 1/5] chore(deps): bump @exadev/eslint-config to 2.12.1 Adds no-warning-comments (rejects any comment containing "Stryker disable") and max-lines (800 real lines of code, blanks/comments excluded) to the shared flat-config ruleset, plus a transitive dependency pin with no rule changes on top in 2.12.1. --- package.json | 2 +- pnpm-lock.yaml | 384 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 380 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index aab895e99..87cf99215 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@eslint/js": "10.0.1", "@eslint/json": "2.0.1", "@eslint/markdown": "8.0.3", - "@exadev/eslint-config": "2.1.2", + "@exadev/eslint-config": "2.12.1", "@exadev/semantic-release-workspace": "1.2.3", "@semantic-release/changelog": "7.0.0", "@semantic-release/commit-analyzer": "13.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42ce69f33..8c39de8ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,8 +31,8 @@ importers: specifier: 8.0.3 version: 8.0.3 '@exadev/eslint-config': - specifier: 2.1.2 - version: 2.1.2(eslint@10.8.1(jiti@2.7.0))(typescript-eslint@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)) + specifier: 2.12.1 + version: 2.12.1(eslint-plugin-jsx-a11y@6.10.2(eslint@10.8.1(jiti@2.7.0)))(eslint-plugin-react-hooks@7.1.1(eslint@10.8.1(jiti@2.7.0)))(eslint@10.8.1(jiti@2.7.0))(typescript-eslint@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(typescript@6.0.3) '@exadev/semantic-release-workspace': specifier: 1.2.3 version: 1.2.3(@semantic-release/changelog@7.0.0(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/commit-analyzer@13.0.1(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/git@11.0.1(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/github@12.0.9(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/npm@13.1.5(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/release-notes-generator@14.1.1(semantic-release@25.0.9(typescript@6.0.3)))(semantic-release@25.0.9(typescript@6.0.3))(typescript@6.0.3) @@ -2579,6 +2579,14 @@ packages: '@emotion/hash@0.9.2': resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + '@es-joy/jsdoccomment@0.97.0': + resolution: {integrity: sha512-EP8uoFfh6+GsdGCduYtmWAW0h7AO+Ayik9Vh5YbA2r/3N6lmJKkCNZX+q3QBXC1K6ixjQ/9igF2b7WVvLm063g==} + engines: {node: ^22.22.2 || >=24.15.0} + + '@es-joy/resolve.exports@1.2.0': + resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} + engines: {node: '>=10'} + '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} @@ -2966,12 +2974,26 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@exadev/eslint-config@2.1.2': - resolution: {integrity: sha512-isLVdlJ10wPn+O6iHAUQf+UQAfHvlaOfQYQVM2mUoPXsxKnDn66EvgFdWJUM9FrI/iFRI+bGzm3FfYJu/N+DTg==} + '@exadev/eslint-config@2.12.1': + resolution: {integrity: sha512-b5JKCX7l5onZy0i0kHdIeuiocxDoiuEwnrG6+j+EV8ZWaLpi18BDzNi1iT3tc647DFRUYJtHWDiJrkWT6E2JjQ==} engines: {node: '>=20'} peerDependencies: + '@next/eslint-plugin-next': ^16.3.2 eslint: '>=10.0.0' + eslint-plugin-jsx-a11y: ^6.10.2 + eslint-plugin-react: ^7.37.5 + eslint-plugin-react-hooks: ^7.1.1 + typescript: '>=4.8.4' typescript-eslint: '>=8.0.0' + peerDependenciesMeta: + '@next/eslint-plugin-next': + optional: true + eslint-plugin-jsx-a11y: + optional: true + eslint-plugin-react: + optional: true + eslint-plugin-react-hooks: + optional: true '@exadev/semantic-release-workspace@1.2.3': resolution: {integrity: sha512-OYbmlcLBSNJ80mq1YhY+iWAoAk+jaTWuGqNn3JGrJUoV0+Mec3RkL4dY5Zt84P35qoQDZGZkkmTDcqmQ8+oY/w==} @@ -3409,6 +3431,12 @@ packages: peerDependencies: '@mantine/core': 9.5.1 + '@microsoft/tsdoc-config@0.18.1': + resolution: {integrity: sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==} + + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@modelcontextprotocol/client@2.0.0': resolution: {integrity: sha512-8f1OghQ2rjzIOfqgUCP+8GiUWqRs89njoWLNqAe8kWmDePv3s1fZXseej+QXemssEuuOvLLmLO/kqM3IQHtISw==} engines: {node: '>=20'} @@ -4166,6 +4194,10 @@ packages: resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} engines: {node: '>=22'} + '@sindresorhus/base62@1.0.0': + resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} + engines: {node: '>=18'} + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -4366,6 +4398,9 @@ packages: '@types/node@26.2.0': resolution: {integrity: sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==} + '@types/node@26.5.1': + resolution: {integrity: sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==} + '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -4407,16 +4442,42 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.56.1': + resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.66.0': resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.70.0': + resolution: {integrity: sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.56.1': + resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.66.0': resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.70.0': + resolution: {integrity: sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.56.1': + resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.66.0': resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4429,6 +4490,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/tsconfig-utils@8.70.0': + resolution: {integrity: sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.66.0': resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4436,6 +4503,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@8.56.1': + resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.66.0': resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4444,12 +4515,35 @@ packages: resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.70.0': + resolution: {integrity: sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.56.1': + resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.66.0': resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/typescript-estree@8.70.0': + resolution: {integrity: sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.56.1': + resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@8.66.0': resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4457,10 +4551,25 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.70.0': + resolution: {integrity: sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.56.1': + resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.66.0': resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.70.0': + resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vanilla-extract/babel-plugin-debug-ids@1.2.2': resolution: {integrity: sha512-MeDWGICAF9zA/OZLOKwhoRlsUW+fiMwnfuOAqFVohL31Agj7Q/RBWAYweqjHLgFBCsdnr6XIfwjJnmb2znEWxw==} @@ -4696,6 +4805,9 @@ packages: ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} @@ -4737,6 +4849,10 @@ packages: anynum@1.0.1: resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==} + are-docs-informative@0.1.1: + resolution: {integrity: sha512-sqRsNQBwbKLRX0jV5Cu5uzmtflf892n4Vukz7T659ebL4pz3mpOqCMU7lxMoBTFwnp10E3YB5ZcyHM41W5bcDA==} + engines: {node: '>=18'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -5017,6 +5133,10 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + comment-parser@1.4.8: + resolution: {integrity: sha512-rKZTGo4fzKYna8UcL0isTg5wkBNla7bxTypLwZQXjIdi++IdP1OJ41rI5Mti3/jltkPujbu4i9LIARYA+zpotQ==} + engines: {node: '>= 12.0.0'} + common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} @@ -5398,6 +5518,12 @@ packages: peerDependencies: eslint: '>=8.40.0' + eslint-plugin-jsdoc@64.3.6: + resolution: {integrity: sha512-lo7IXmgUUNy88SxW7KnJmmD2iPQBIRMomfCFPHidW1M3zNNVuzxlB2uoNrNyE1g4v2/L+RtYmiROPwQhSNzL8Q==} + engines: {node: ^22.22.2 || >=24.15.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + eslint-plugin-jsx-a11y@6.10.2: resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} engines: {node: '>=4.0'} @@ -5429,6 +5555,9 @@ packages: peerDependencies: eslint: ^9 || ^10 + eslint-plugin-tsdoc@0.5.2: + resolution: {integrity: sha512-BlvqjWZdBJDIPO/YU3zcPCF23CvjYT3gyu63yo6b609NNV3D1b6zceAREy2xnweuBoDpZcLNuPyAUq9cvx6bbQ==} + eslint-plugin-yml@3.8.1: resolution: {integrity: sha512-E/70psRwxz5EJ8dBtzrFfqSiiInuSytbdtFCjueb/GcKjsWzPBfxfhtQePImMAPjHwMA/VDurO7DJwStDJ4wWg==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} @@ -5846,6 +5975,9 @@ packages: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -6169,6 +6301,9 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + jose@6.2.9: resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==} @@ -6185,6 +6320,10 @@ packages: resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true + jsdoc-type-pratt-parser@9.2.1: + resolution: {integrity: sha512-V4Ww4EHnTcTLSOMoB0FsF72JhQvcAsriCm/LWnxJeGWoxIjEL2l9na11abQok5SYShq8m0Gl02el/xAbTCulvQ==} + engines: {node: ^22.22.2 || >=24.15.0} + jsdom@30.0.1: resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -6782,6 +6921,9 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-deep-merge@2.0.1: + resolution: {integrity: sha512-aKttDKcU3pyZqKcCkDhsMn70WmZFG2JGDQLP9EcLyTSIFQRCPWLAmBZRLJnrVUrhPG1jETEEbfdgbNtJf1LyMg==} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -6886,6 +7028,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-imports-exports@0.2.4: + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} + parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} engines: {node: '>=4'} @@ -6902,6 +7047,9 @@ packages: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} + parse-statements@1.0.11: + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} + parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} @@ -7204,6 +7352,10 @@ packages: require-like@0.1.2: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} + reserved-identifiers@1.2.0: + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -7423,6 +7575,9 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@5.0.0: + resolution: {integrity: sha512-vngmw3Rgn+o2arXNbnZaj5UtOEBuWBfvaI+Wc8GFfykIhA5/vdK9/Sp/XkLv63dykz2rxKDvKEHupF5P0FORcQ==} + spdx-license-ids@3.0.23: resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} @@ -7680,6 +7835,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + to-valid-identifier@1.0.0: + resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} + engines: {node: '>=20'} + tough-cookie@6.0.2: resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} @@ -7837,6 +7996,9 @@ packages: undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + undici@6.28.0: resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} engines: {node: '>=18.17'} @@ -9553,6 +9715,16 @@ snapshots: '@emotion/hash@0.9.2': {} + '@es-joy/jsdoccomment@0.97.0': + dependencies: + '@types/estree': 1.0.9 + '@typescript-eslint/types': 8.70.0 + comment-parser: 1.4.8 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 9.2.1 + + '@es-joy/resolve.exports@1.2.0': {} + '@esbuild/aix-ppc64@0.28.1': optional: true @@ -9810,10 +9982,21 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 - '@exadev/eslint-config@2.1.2(eslint@10.8.1(jiti@2.7.0))(typescript-eslint@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))': + '@exadev/eslint-config@2.12.1(eslint-plugin-jsx-a11y@6.10.2(eslint@10.8.1(jiti@2.7.0)))(eslint-plugin-react-hooks@7.1.1(eslint@10.8.1(jiti@2.7.0)))(eslint@10.8.1(jiti@2.7.0))(typescript-eslint@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(typescript@6.0.3)': dependencies: + '@eslint/js': 10.0.1(eslint@10.8.1(jiti@2.7.0)) + '@typescript-eslint/utils': 8.70.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) eslint: 10.8.1(jiti@2.7.0) + eslint-plugin-jsdoc: 64.3.6(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + eslint-plugin-tsdoc: 0.5.2(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 typescript-eslint: 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + optionalDependencies: + eslint-plugin-jsx-a11y: 6.10.2(eslint@10.8.1(jiti@2.7.0)) + eslint-plugin-react-hooks: 7.1.1(eslint@10.8.1(jiti@2.7.0)) + transitivePeerDependencies: + - supports-color '@exadev/semantic-release-workspace@1.2.3(@semantic-release/changelog@7.0.0(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/commit-analyzer@13.0.1(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/git@11.0.1(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/github@12.0.9(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/npm@13.1.5(semantic-release@25.0.9(typescript@6.0.3)))(@semantic-release/release-notes-generator@14.1.1(semantic-release@25.0.9(typescript@6.0.3)))(semantic-release@25.0.9(typescript@6.0.3))(typescript@6.0.3)': dependencies: @@ -10183,6 +10366,15 @@ snapshots: dependencies: '@mantine/core': 9.5.1(@mantine/hooks@9.5.1(react@19.2.8))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@microsoft/tsdoc-config@0.18.1': + dependencies: + '@microsoft/tsdoc': 0.16.0 + ajv: 8.18.0 + jju: 1.4.0 + resolve: 1.22.12 + + '@microsoft/tsdoc@0.16.0': {} + '@modelcontextprotocol/client@2.0.0': dependencies: '@modelcontextprotocol/core': 2.0.0 @@ -10807,6 +10999,8 @@ snapshots: '@simple-libs/stream-utils@2.0.0': {} + '@sindresorhus/base62@1.0.0': {} + '@sindresorhus/is@4.6.0': {} '@sindresorhus/is@7.2.0': {} @@ -11058,6 +11252,10 @@ snapshots: dependencies: undici-types: 8.3.0 + '@types/node@26.5.1': + dependencies: + undici-types: 8.9.0 + '@types/normalize-package-data@2.4.4': {} '@types/react-dom@19.2.4(@types/react@19.2.18)': @@ -11106,6 +11304,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.56.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/project-service@8.66.0(typescript@6.0.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) @@ -11115,11 +11322,34 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.70.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.56.1': + dependencies: + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 + '@typescript-eslint/scope-manager@8.66.0': dependencies: '@typescript-eslint/types': 8.66.0 '@typescript-eslint/visitor-keys': 8.66.0 + '@typescript-eslint/scope-manager@8.70.0': + dependencies: + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 + + '@typescript-eslint/tsconfig-utils@8.56.1(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + '@typescript-eslint/tsconfig-utils@8.66.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 @@ -11128,6 +11358,10 @@ snapshots: dependencies: typescript: 6.0.3 + '@typescript-eslint/tsconfig-utils@8.70.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + '@typescript-eslint/type-utils@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.66.0 @@ -11140,10 +11374,29 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/types@8.56.1': {} + '@typescript-eslint/types@8.66.0': {} '@typescript-eslint/types@8.67.0': {} + '@typescript-eslint/types@8.70.0': {} + + '@typescript-eslint/typescript-estree@8.56.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.56.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@6.0.3) + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@8.66.0(typescript@6.0.3)': dependencies: '@typescript-eslint/project-service': 8.66.0(typescript@6.0.3) @@ -11159,6 +11412,32 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.70.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.70.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.56.1(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@6.0.3) + eslint: 10.8.1(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)) @@ -11170,11 +11449,32 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.70.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(typescript@6.0.3) + eslint: 10.8.1(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.56.1': + dependencies: + '@typescript-eslint/types': 8.56.1 + eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.66.0': dependencies: '@typescript-eslint/types': 8.66.0 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.70.0': + dependencies: + '@typescript-eslint/types': 8.70.0 + eslint-visitor-keys: 5.0.1 + '@vanilla-extract/babel-plugin-debug-ids@1.2.2': dependencies: '@babel/core': 7.29.7 @@ -11420,6 +11720,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 @@ -11453,6 +11760,8 @@ snapshots: anynum@1.0.1: {} + are-docs-informative@0.1.1: {} + argparse@2.0.1: {} argue-cli@3.1.0: {} @@ -11733,6 +12042,8 @@ snapshots: commander@8.3.0: {} + comment-parser@1.4.8: {} + common-tags@1.8.2: {} compare-func@2.0.0: @@ -12170,6 +12481,28 @@ snapshots: module-replacements: 2.11.0 semver: 7.8.5 + eslint-plugin-jsdoc@64.3.6(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@es-joy/jsdoccomment': 0.97.0 + '@es-joy/resolve.exports': 1.2.0 + '@typescript-eslint/utils': 8.70.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + are-docs-informative: 0.1.1 + comment-parser: 1.4.8 + debug: 4.4.3 + escape-string-regexp: 5.0.0 + eslint: 10.8.1(jiti@2.7.0) + espree: 11.2.0 + esquery: 1.7.0 + html-entities: 2.6.0 + object-deep-merge: 2.0.1 + parse-imports-exports: 0.2.4 + semver: 7.8.5 + spdx-expression-parse: 5.0.0 + to-valid-identifier: 1.0.0 + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-jsx-a11y@6.10.2(eslint@10.8.1(jiti@2.7.0)): dependencies: aria-query: 5.3.2 @@ -12213,6 +12546,16 @@ snapshots: dependencies: eslint: 10.8.1(jiti@2.7.0) + eslint-plugin-tsdoc@0.5.2(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.1 + '@typescript-eslint/utils': 8.56.1(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + transitivePeerDependencies: + - eslint + - supports-color + - typescript + eslint-plugin-yml@3.8.1(eslint@10.8.1(jiti@2.7.0)): dependencies: '@eslint/core': 1.2.1 @@ -12715,6 +13058,8 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + html-entities@2.6.0: {} + html-escaper@2.0.2: {} http-proxy-agent@9.1.0: @@ -13021,6 +13366,8 @@ snapshots: jiti@2.7.0: {} + jju@1.4.0: {} + jose@6.2.9: {} js-md4@0.3.2: {} @@ -13033,6 +13380,11 @@ snapshots: dependencies: argparse: 2.0.1 + jsdoc-type-pratt-parser@9.2.1: + dependencies: + '@types/estree': 1.0.9 + '@types/node': 26.5.1 + jsdom@30.0.1: dependencies: '@asamuzakjp/css-color': 6.0.7 @@ -13754,6 +14106,8 @@ snapshots: object-assign@4.1.1: {} + object-deep-merge@2.0.1: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} @@ -13897,6 +14251,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse-imports-exports@0.2.4: + dependencies: + parse-statements: 1.0.11 + parse-json@4.0.0: dependencies: error-ex: 1.3.4 @@ -13917,6 +14275,8 @@ snapshots: parse-ms@4.0.0: {} + parse-statements@1.0.11: {} + parse5-htmlparser2-tree-adapter@6.0.1: dependencies: parse5: 6.0.1 @@ -14200,6 +14560,8 @@ snapshots: require-like@0.1.2: {} + reserved-identifiers@1.2.0: {} + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -14512,6 +14874,11 @@ snapshots: spdx-exceptions: 2.5.0 spdx-license-ids: 3.0.23 + spdx-expression-parse@5.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 + spdx-license-ids@3.0.23: {} split2@1.0.0: @@ -14772,6 +15139,11 @@ snapshots: dependencies: is-number: 7.0.0 + to-valid-identifier@1.0.0: + dependencies: + '@sindresorhus/base62': 1.0.0 + reserved-identifiers: 1.2.0 + tough-cookie@6.0.2: dependencies: tldts: 7.4.10 @@ -14925,6 +15297,8 @@ snapshots: undici-types@8.3.0: {} + undici-types@8.9.0: {} + undici@6.28.0: {} undici@7.29.0: {} From fcac10fd4dbf4c3ec5a43f4dcda45461753eae65 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Mon, 14 Sep 2026 13:56:05 +0100 Subject: [PATCH 2/5] chore: default new dependency adds to exact versions saveExact in pnpm-workspace.yaml (the settings location pnpm 11+ actually reads) makes pnpm add/up produce the exact pin syncpack.config.ts already enforces, instead of a caret range it would otherwise have to flag and fix after the fact. The .npmrc copy is a fallback for a pnpm 10.x release older than 10.17, before these settings moved to pnpm-workspace.yaml. --- .npmrc | 3 +++ pnpm-workspace.yaml | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..98c64eb92 --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +# pnpm 11 reads project-level saveExact/minimumReleaseAgeExclude from pnpm-workspace.yaml only -- .npmrc there is auth/registry-only from that version on. These two lines are a fallback for a pnpm 10.x release older than 10.17 (before those settings moved to YAML), and are otherwise inert. See pnpm-workspace.yaml for the settings that actually govern this workspace. +save-exact=true +minimum-release-age-exclude[]=@exadev/eslint-config diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 85ef73c1c..dfc0fb5bb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -53,3 +53,6 @@ overrides: qs: 6.15.2 # release-workspace.config.json's generateNotes step uses the conventionalcommits preset, whose templates call a helper that only conventional-changelog-writer@9 or newer provides. @semantic-release/release-notes-generator depends on conventional-changelog-writer@^8, so without this the preset loads and then throws from inside handlebars at render time -- the preset itself detects the too-old writer and registers a helper whose only job is to raise "requires conventional-changelog-writer@9 or newer". Scoped to release-notes-generator rather than global because it is the only consumer that renders with the writer at all: @semantic-release/commit-analyzer declares the same dependency but never imports it, using only the preset's whatBump. "@semantic-release/release-notes-generator>conventional-changelog-writer": 9.2.1 + +# syncpack.config.ts already pins every dependency in every package.json to an exact version and catches drift on commit and in CI; this setting makes `pnpm add`/`pnpm up` produce that exact pin by default instead of a caret range that syncpack would then have to flag and fix after the fact. +saveExact: true From fa4b3feed70427b3bf553ce72eb0d6d885a43db0 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Mon, 14 Sep 2026 14:47:04 +0100 Subject: [PATCH 3/5] fix: reword stryker.config.ts comments to stop tripping no-warning-comments Each package's stryker.config.ts documents, in prose, that it carries no Stryker suppression comments -- but stating that fact required writing the literal phrase "Stryker disable", which is exactly the substring @exadev/eslint-config's new no-warning-comments rule bans anywhere in a comment, with no exemption for prose describing the absence of such a comment rather than being one. Rephrased to say the same thing without the banned phrase; no suppression comment of any kind exists anywhere in this workspace (confirmed by a full-repo case-insensitive search), so the rule has nothing genuine left to catch here. --- packages/archive-codec/stryker.config.ts | 2 +- packages/doc-codec/stryker.config.ts | 2 +- packages/document-mcp/stryker.config.ts | 2 +- packages/document-operations/stryker.config.ts | 2 +- packages/pdf-raster-cpu/stryker.config.ts | 2 +- packages/ppt-codec/stryker.config.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/archive-codec/stryker.config.ts b/packages/archive-codec/stryker.config.ts index cf8fd6a4c..bc16ec19f 100644 --- a/packages/archive-codec/stryker.config.ts +++ b/packages/archive-codec/stryker.config.ts @@ -2,6 +2,6 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; export default packageStrykerConfig({ vitestConfigFile: "vitest.mutation.config.ts", - // Every valid mutant is genuinely killed by a real test, or the code has been restructured so the mutation opportunity no longer exists as an AST node (a redundant guard removed, a manually bounds-checked loop replaced by one relying on the language's own out-of-range-is-undefined semantics, an algebraic-identity comparison restated as an explicit named branch) -- no Stryker disable comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. + // Every valid mutant is genuinely killed by a real test, or the code has been restructured so the mutation opportunity no longer exists as an AST node (a redundant guard removed, a manually bounds-checked loop replaced by one relying on the language's own out-of-range-is-undefined semantics, an algebraic-identity comparison restated as an explicit named branch) -- no Stryker-suppression comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. breakThreshold: 100, }); diff --git a/packages/doc-codec/stryker.config.ts b/packages/doc-codec/stryker.config.ts index 52b06ee86..82162250c 100644 --- a/packages/doc-codec/stryker.config.ts +++ b/packages/doc-codec/stryker.config.ts @@ -2,6 +2,6 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; export default packageStrykerConfig({ vitestConfigFile: "vitest.mutation.config.ts", - // Genuine 100% mutation score across every valid mutant, confirmed by a forced (non-incremental) full run: 0 survived, 0 no-coverage. Every mutant is either killed by a real isolating test or the code was restructured so the mutation opportunity no longer exists as an AST node — no Stryker disable comments anywhere in src/. + // Genuine 100% mutation score across every valid mutant, confirmed by a forced (non-incremental) full run: 0 survived, 0 no-coverage. Every mutant is either killed by a real isolating test or the code was restructured so the mutation opportunity no longer exists as an AST node — no Stryker-suppression comments anywhere in src/. breakThreshold: 100, }); diff --git a/packages/document-mcp/stryker.config.ts b/packages/document-mcp/stryker.config.ts index b181906dd..7d4342cb9 100644 --- a/packages/document-mcp/stryker.config.ts +++ b/packages/document-mcp/stryker.config.ts @@ -2,6 +2,6 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; export default packageStrykerConfig({ vitestConfigFile: "vitest.mutation.config.ts", - // Every valid mutant is genuinely killed by a real test, or the code has been restructured so the mutation opportunity no longer exists as an AST node (a redundant type-narrowing guard removed once the value it defended against was actually unreachable, an inline builder split into a directly-testable pure function) -- no Stryker disable comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. + // Every valid mutant is genuinely killed by a real test, or the code has been restructured so the mutation opportunity no longer exists as an AST node (a redundant type-narrowing guard removed once the value it defended against was actually unreachable, an inline builder split into a directly-testable pure function) -- no Stryker-suppression comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. breakThreshold: 100, }); diff --git a/packages/document-operations/stryker.config.ts b/packages/document-operations/stryker.config.ts index dc9c9c94f..f4706a66e 100644 --- a/packages/document-operations/stryker.config.ts +++ b/packages/document-operations/stryker.config.ts @@ -1,4 +1,4 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; -// Genuinely 100%: every mutant Stryker can generate against this package's src is either killed by a real, isolating test or was eliminated outright by restructuring code that could never be reached by any test in the first place (the two odb_render_report diagnostic callbacks documents.js's own render pass can never invoke, and several test-support fixtures' own decorative-but-unread XML attributes) -- never suppressed with a Stryker disable comment, of which this package has zero. Confirmed with 0 timeouts on the run this threshold was set from, so no noise margin is subtracted per stryker.shared.ts's own derivation rule for that case. +// Genuinely 100%: every mutant Stryker can generate against this package's src is either killed by a real, isolating test or was eliminated outright by restructuring code that could never be reached by any test in the first place (the two odb_render_report diagnostic callbacks documents.js's own render pass can never invoke, and several test-support fixtures' own decorative-but-unread XML attributes) -- never annotated with a Stryker suppression comment, of which this package has zero. Confirmed with 0 timeouts on the run this threshold was set from, so no noise margin is subtracted per stryker.shared.ts's own derivation rule for that case. export default packageStrykerConfig({ breakThreshold: 100 }); diff --git a/packages/pdf-raster-cpu/stryker.config.ts b/packages/pdf-raster-cpu/stryker.config.ts index 7329d0236..8007251b5 100644 --- a/packages/pdf-raster-cpu/stryker.config.ts +++ b/packages/pdf-raster-cpu/stryker.config.ts @@ -1,6 +1,6 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; export default packageStrykerConfig({ - // Every mutant is genuinely killed by a real test, or the code it would have mutated has been restructured so the mutation opportunity no longer exists as an AST node (a redundant guard deleted, a manual bounds-checked loop replaced by one relying on the language's own out-of-range-is-undefined semantics, an algebraic-identity comparison restated so a boundary a real test can actually reach becomes reachable) -- no Stryker disable comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. + // Every mutant is genuinely killed by a real test, or the code it would have mutated has been restructured so the mutation opportunity no longer exists as an AST node (a redundant guard deleted, a manual bounds-checked loop replaced by one relying on the language's own out-of-range-is-undefined semantics, an algebraic-identity comparison restated so a boundary a real test can actually reach becomes reachable) -- no Stryker-suppression comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. breakThreshold: 100, }); diff --git a/packages/ppt-codec/stryker.config.ts b/packages/ppt-codec/stryker.config.ts index c2d81ddad..158a09a42 100644 --- a/packages/ppt-codec/stryker.config.ts +++ b/packages/ppt-codec/stryker.config.ts @@ -2,6 +2,6 @@ import { packageStrykerConfig } from "../../stryker.shared.ts"; export default packageStrykerConfig({ vitestConfigFile: "vitest.mutation.config.ts", - // Every mutant is genuinely killed by a real test, or the code it would have mutated has been restructured so the mutation opportunity no longer exists as an AST node (a redundant sort deleted once every consumer proved order-independent, an unreachable fallback branch removed once its guarantee was proved from its own inputs) -- no Stryker disable comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. + // Every mutant is genuinely killed by a real test, or the code it would have mutated has been restructured so the mutation opportunity no longer exists as an AST node (a redundant sort deleted once every consumer proved order-independent, an unreachable fallback branch removed once its guarantee was proved from its own inputs) -- no Stryker-suppression comments anywhere in this package. So the gate is the literal maximum rather than a derived-with-slack figure. breakThreshold: 100, }); From 581de4e7bafe4149d19be8e927873b74b1276838 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Mon, 14 Sep 2026 14:57:03 +0100 Subject: [PATCH 4/5] chore: bump pinned pnpm from 11.6.0 to 12.4.1 Updates the workspace root's packageManager field via corepack use, which also regenerates the lockfile for the new engine version. Every individual package under packages/ still carries its own packageManager field left over from before each was consolidated into this workspace, and pnpm's own version check (run whenever a package's own build/test script re-invokes pnpm as a subprocess) reads whichever package.json is closest to the invoking cwd -- a stale per-package pin there fails that check even though the workspace root's own field is current, so every one of those fields is bumped to the identical pinned version and integrity hash as the root. Install, build, typecheck and the full test suite all pass clean under the new version. --- package.json | 2 +- packages/archive-codec/package.json | 2 +- packages/byte-codec/package.json | 2 +- packages/doc-codec/package.json | 2 +- packages/document-cli/package.json | 2 +- packages/document-compute.js/package.json | 2 +- packages/document-mcp/package.json | 2 +- packages/document-operations/package.json | 2 +- packages/document-outline.js/package.json | 2 +- packages/document-rest/package.json | 2 +- packages/document-schema.js/package.json | 2 +- packages/documents.js/package.json | 2 +- packages/epub-codec/package.json | 2 +- packages/excel-number-format/package.json | 2 +- packages/markdown-codec/package.json | 2 +- packages/odf.js/package.json | 2 +- packages/ooxml.js/package.json | 2 +- packages/pdf-codec/package.json | 2 +- packages/pdf-raster-cpu/package.json | 2 +- packages/ppt-codec/package.json | 2 +- packages/rtf-codec/package.json | 2 +- packages/web/package.json | 2 +- packages/wpd-codec/package.json | 2 +- packages/xls-codec/package.json | 2 +- pnpm-lock.yaml | 158 ++++++++++++++++++++++ 25 files changed, 182 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 87cf99215..778206b29 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "engines": { "node": ">=20" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "scripts": { "build": "turbo run _build", "lint": "turbo run _lint", diff --git a/packages/archive-codec/package.json b/packages/archive-codec/package.json index 4d6913d13..1a5d14747 100644 --- a/packages/archive-codec/package.json +++ b/packages/archive-codec/package.json @@ -68,7 +68,7 @@ "_test:smoke": "vitest run --project smoke", "prepare": "husky" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2", "fflate": "0.8.3" diff --git a/packages/byte-codec/package.json b/packages/byte-codec/package.json index 4793de95f..ba484ae74 100644 --- a/packages/byte-codec/package.json +++ b/packages/byte-codec/package.json @@ -66,7 +66,7 @@ "_test:workers": "vitest run --config vitest.workers.config.ts", "prepare": "husky" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "fflate": "0.8.3" }, diff --git a/packages/doc-codec/package.json b/packages/doc-codec/package.json index d36ca2a88..228fe3b59 100644 --- a/packages/doc-codec/package.json +++ b/packages/doc-codec/package.json @@ -78,7 +78,7 @@ "ms-cfb" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "document-schema.js": "7.11.2" diff --git a/packages/document-cli/package.json b/packages/document-cli/package.json index 5ee80aadd..eaf998a53 100644 --- a/packages/document-cli/package.json +++ b/packages/document-cli/package.json @@ -89,7 +89,7 @@ "ink" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "commander": "15.0.0", "document-outline.js": "3.9.0", diff --git a/packages/document-compute.js/package.json b/packages/document-compute.js/package.json index 8931bf7f8..6db6d66e2 100644 --- a/packages/document-compute.js/package.json +++ b/packages/document-compute.js/package.json @@ -68,7 +68,7 @@ "test:corpus": "turbo run _test:corpus", "_test:corpus": "vitest run --project corpus" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2" }, diff --git a/packages/document-mcp/package.json b/packages/document-mcp/package.json index 4981dc1c3..cedaa115d 100644 --- a/packages/document-mcp/package.json +++ b/packages/document-mcp/package.json @@ -86,7 +86,7 @@ "document-conversion" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "@modelcontextprotocol/node": "2.0.0", "@modelcontextprotocol/server": "2.0.0", diff --git a/packages/document-operations/package.json b/packages/document-operations/package.json index 01dadcf3a..0ed665936 100644 --- a/packages/document-operations/package.json +++ b/packages/document-operations/package.json @@ -80,7 +80,7 @@ "zod" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-compute.js": "1.5.13", "document-outline.js": "3.9.0", diff --git a/packages/document-outline.js/package.json b/packages/document-outline.js/package.json index b759490d1..c84e005da 100644 --- a/packages/document-outline.js/package.json +++ b/packages/document-outline.js/package.json @@ -66,7 +66,7 @@ "_test:workers": "vitest run --config vitest.workers.config.ts", "prepare": "husky" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2", "pdf-codec": "4.8.4", diff --git a/packages/document-rest/package.json b/packages/document-rest/package.json index ee63a0b66..fd8b2f443 100644 --- a/packages/document-rest/package.json +++ b/packages/document-rest/package.json @@ -85,7 +85,7 @@ "document-conversion" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-operations": "1.1.10", "documents.js": "7.20.10", diff --git a/packages/document-schema.js/package.json b/packages/document-schema.js/package.json index d20e78dbd..1313c6106 100644 --- a/packages/document-schema.js/package.json +++ b/packages/document-schema.js/package.json @@ -84,7 +84,7 @@ "ods" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "zod": "4.4.3" }, diff --git a/packages/documents.js/package.json b/packages/documents.js/package.json index dd530c3c2..1bc59506e 100644 --- a/packages/documents.js/package.json +++ b/packages/documents.js/package.json @@ -100,7 +100,7 @@ "codec" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "byte-codec": "1.5.4", diff --git a/packages/epub-codec/package.json b/packages/epub-codec/package.json index 23e1df613..b8ca882e9 100644 --- a/packages/epub-codec/package.json +++ b/packages/epub-codec/package.json @@ -76,7 +76,7 @@ "ebook" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2", "entities": "8.0.0", diff --git a/packages/excel-number-format/package.json b/packages/excel-number-format/package.json index 50d9cd132..5569e44f3 100644 --- a/packages/excel-number-format/package.json +++ b/packages/excel-number-format/package.json @@ -66,7 +66,7 @@ "_test:workers": "vitest run --config vitest.workers.config.ts", "prepare": "husky" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "devDependencies": { "@arethetypeswrong/cli": "0.18.5", "@cloudflare/vitest-pool-workers": "0.21.2", diff --git a/packages/markdown-codec/package.json b/packages/markdown-codec/package.json index 6b2bfaa7f..a5e71b43d 100644 --- a/packages/markdown-codec/package.json +++ b/packages/markdown-codec/package.json @@ -81,7 +81,7 @@ "ast" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2", "zod": "4.4.3" diff --git a/packages/odf.js/package.json b/packages/odf.js/package.json index 09a8b3ab6..6ac55e891 100644 --- a/packages/odf.js/package.json +++ b/packages/odf.js/package.json @@ -85,7 +85,7 @@ "codec" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "document-schema.js": "7.11.2", "fast-xml-parser": "5.10.1", diff --git a/packages/ooxml.js/package.json b/packages/ooxml.js/package.json index 531cdcde6..4ac9158dd 100644 --- a/packages/ooxml.js/package.json +++ b/packages/ooxml.js/package.json @@ -82,7 +82,7 @@ "opc" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "document-schema.js": "7.11.2", diff --git a/packages/pdf-codec/package.json b/packages/pdf-codec/package.json index d7ac93608..46136c13c 100644 --- a/packages/pdf-codec/package.json +++ b/packages/pdf-codec/package.json @@ -97,7 +97,7 @@ "mathml" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "byte-codec": "1.5.4", "document-schema.js": "7.11.2", diff --git a/packages/pdf-raster-cpu/package.json b/packages/pdf-raster-cpu/package.json index e595c7934..b52359373 100644 --- a/packages/pdf-raster-cpu/package.json +++ b/packages/pdf-raster-cpu/package.json @@ -76,7 +76,7 @@ "workers" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "byte-codec": "1.5.4", "pdf-codec": "4.8.4" diff --git a/packages/ppt-codec/package.json b/packages/ppt-codec/package.json index 968f5da58..bbb0a5fca 100644 --- a/packages/ppt-codec/package.json +++ b/packages/ppt-codec/package.json @@ -76,7 +76,7 @@ "presentation" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "byte-codec": "1.5.4", diff --git a/packages/rtf-codec/package.json b/packages/rtf-codec/package.json index b358c807d..537de8f82 100644 --- a/packages/rtf-codec/package.json +++ b/packages/rtf-codec/package.json @@ -80,7 +80,7 @@ "wordprocessing" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "document-schema.js": "7.11.2", diff --git a/packages/web/package.json b/packages/web/package.json index 89f648aaf..51079bb27 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -14,7 +14,7 @@ "url": "https://github.com/ExaDev/documents.js/issues" }, "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "engines": { "node": ">=20" }, diff --git a/packages/wpd-codec/package.json b/packages/wpd-codec/package.json index 89edb656e..2b6db88a0 100644 --- a/packages/wpd-codec/package.json +++ b/packages/wpd-codec/package.json @@ -78,7 +78,7 @@ "zod" ], "license": "MIT", - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "document-schema.js": "7.11.2", diff --git a/packages/xls-codec/package.json b/packages/xls-codec/package.json index 30760e65e..c8689fb7a 100644 --- a/packages/xls-codec/package.json +++ b/packages/xls-codec/package.json @@ -68,7 +68,7 @@ "_test:smoke": "vitest run --project smoke", "prepare": "husky" }, - "packageManager": "pnpm@11.6.0", + "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c", "dependencies": { "archive-codec": "1.11.3", "document-schema.js": "7.11.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c39de8ae..e76cd11d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3 +1,161 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.4.1 + version: 12.4.1 + +packages: + + '@pnpm/exe.android-arm64@12.4.1': + resolution: {integrity: sha512-/HwsqXMSmlOfgtV9+O0ratzjV6Vd/8n1hh4rGHpCGmDURvt52MwZxdbhyxP4K03ZfvgSDvotFPr8O+RzE5Eu8A==} + cpu: [arm64] + os: [android] + + '@pnpm/exe.android-x64@12.4.1': + resolution: {integrity: sha512-+l74Qb4c2YjOzNKHXJLg+1wr8xHM1ckkUhnU5KRUK9TJqiiczt6yeTZqqzHIlJ8i6pAoj5V0OJevDRwnQKLgrQ==} + cpu: [x64] + os: [android] + + '@pnpm/exe.darwin-arm64@12.4.1': + resolution: {integrity: sha512-6rkZkT3iGfaxknUdGHraqSWFvTa6N0ajAHluv9Ax0GRWs0sIcGNiFhDopv6xSZCsJZmG483aNS/b6UEDy3blfw==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.4.1': + resolution: {integrity: sha512-Vb1CHlR88HghC1qUxjxjs82zQSXnXacPD+btG2CmG8Q/hBU7Q0/b2YWJKSQqZXicunV5khFtfTlAwJddV9RkYA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.freebsd-x64@12.4.1': + resolution: {integrity: sha512-iT3iHz3Nl0Sxxj7UPOtZ/aQ81AFsQhjoeWMAlPkSRO04gsgDGAXv3UYxOFaesMWsfNxaGn0A+CITbuCHFF66FA==} + cpu: [x64] + os: [freebsd] + + '@pnpm/exe.linux-arm64-musl@12.4.1': + resolution: {integrity: sha512-aBooZfNXM5f+OGUgCAMFWpE/kAhsWfvmqIyMtHy6zl3aNxyInWrcY/Saln/UElzo7lZWMC0Yktroxd/2J26lNQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.4.1': + resolution: {integrity: sha512-TlOdacTTP09BgcMvwWBFRsu8VAjfwqwnslBj+XSq1JFM3ck4f3k+1O/747EuctxZxs3/o785b6Q3s7Pd92Ptsg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-ppc64@12.4.1': + resolution: {integrity: sha512-r/ab/MlIBo75oizUP5ITiziCCrnXz4SJwfErLQ+603AshB+Yq7xTMCoMtzTSCAMu6aaymIKkAFtZvd2J75Wq0w==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-riscv64@12.4.1': + resolution: {integrity: sha512-C/D1QWdKMiB8+wv/spl1rGITFUuqC+aI/fb6h8NB5sqxsOaGXeYc/g891oCuzggHn6SODk9p+I09hI76x/cMNw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-s390x@12.4.1': + resolution: {integrity: sha512-nxz5zD4yXt94uzbStDk0QTPKW+aE92hH1b5tFXK9ctB1HE9Xcq1vjTiA2LsZMFC6p4gdu5OwQeFqYNAVGa6QlA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.4.1': + resolution: {integrity: sha512-5AwgFdGhVUg2kIweYGfxzSLEHiIG77PQhZAkXC3TwofQHsu1Wr+TrV5/rNX2PopFnHRzuE581zoB8F6Wle32yg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.4.1': + resolution: {integrity: sha512-FJOZuuuQMhp0oLzBtcKkLXknBI92hfkmSnlKc47vfin4HrmfID5khY2lGekL9tCzk1cpR+HShEw/meFl+nHtzQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.4.1': + resolution: {integrity: sha512-OO7eKBL9S+xk5hRy+JUUZSNJknGuGe3GEUffsrlC2LbqKF02g+VX1anGIzSbJDvkkdnpJhSlxF5AUz2JzJu2Jw==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.4.1': + resolution: {integrity: sha512-x7gJHZgHo6hp354xCYA2NvoFzYJkHwovt2kVsUBK5EmXULLcP51JGMq09CX+5FRFJUZFKoXjLu3mZWmfP7o6PQ==} + cpu: [x64] + os: [win32] + + pnpm@12.4.1: + resolution: {integrity: sha512-LoHjmdc/6DkNqyXgaqeIq3pZCCSNL1o3D4K0gRR6ano2e/gEj5pv22Rg8hpm8FQt7bi5TKLIcjWWdBkgsWVtTA==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.android-arm64@12.4.1': + optional: true + + '@pnpm/exe.android-x64@12.4.1': + optional: true + + '@pnpm/exe.darwin-arm64@12.4.1': + optional: true + + '@pnpm/exe.darwin-x64@12.4.1': + optional: true + + '@pnpm/exe.freebsd-x64@12.4.1': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.4.1': + optional: true + + '@pnpm/exe.linux-arm64@12.4.1': + optional: true + + '@pnpm/exe.linux-ppc64@12.4.1': + optional: true + + '@pnpm/exe.linux-riscv64@12.4.1': + optional: true + + '@pnpm/exe.linux-s390x@12.4.1': + optional: true + + '@pnpm/exe.linux-x64-musl@12.4.1': + optional: true + + '@pnpm/exe.linux-x64@12.4.1': + optional: true + + '@pnpm/exe.win32-arm64@12.4.1': + optional: true + + '@pnpm/exe.win32-x64@12.4.1': + optional: true + + pnpm@12.4.1: + optionalDependencies: + '@pnpm/exe.android-arm64': 12.4.1 + '@pnpm/exe.android-x64': 12.4.1 + '@pnpm/exe.darwin-arm64': 12.4.1 + '@pnpm/exe.darwin-x64': 12.4.1 + '@pnpm/exe.freebsd-x64': 12.4.1 + '@pnpm/exe.linux-arm64': 12.4.1 + '@pnpm/exe.linux-arm64-musl': 12.4.1 + '@pnpm/exe.linux-ppc64': 12.4.1 + '@pnpm/exe.linux-riscv64': 12.4.1 + '@pnpm/exe.linux-s390x': 12.4.1 + '@pnpm/exe.linux-x64': 12.4.1 + '@pnpm/exe.linux-x64-musl': 12.4.1 + '@pnpm/exe.win32-arm64': 12.4.1 + '@pnpm/exe.win32-x64': 12.4.1 + +--- lockfileVersion: '9.0' settings: From 52350055d3ad634b691a6abfdeb669b1e41a824d Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Mon, 14 Sep 2026 15:10:14 +0100 Subject: [PATCH 5/5] fix(ci): read every document in a multi-document pnpm lockfile for audit overrides pnpm writes pnpm-lock.yaml as a multi-document YAML stream once a project pins its own pnpm binary through packageManagerDependencies -- a self-management document listing the pinned build's own per-platform packages, ahead of the project's own document. This workspace now does exactly that (package.json's packageManager field, pnpm 12), so resolvedVersionsFromLockfileText's single-document parse started throwing YAMLParseError: Source contains multiple documents on every real run, taking the whole Audit job down with it. Reads every document in the stream and unions their packages maps instead of assuming there is exactly one: the self-management document's own entries are real resolved packages too, just never ones pnpm audit carries advisories against, so including them changes nothing about correctness and needs no guess about which document is "the real" project lockfile. --- .github/scripts/audit-autofix.test.ts | 28 ++++++++----- .github/scripts/audit-autofix.ts | 59 +++++++++++++++------------ 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/.github/scripts/audit-autofix.test.ts b/.github/scripts/audit-autofix.test.ts index 35d5a8c1c..029e00fe8 100644 --- a/.github/scripts/audit-autofix.test.ts +++ b/.github/scripts/audit-autofix.test.ts @@ -14,7 +14,9 @@ import { type AuditAdvisory, } from "./audit-autofix"; -function advisory(overrides: Partial = {}): AuditAdvisory { +function advisory( + overrides: Readonly> = {}, +): AuditAdvisory { return { module_name: "undici", vulnerable_versions: ">=7.0.0 <7.29.0", @@ -27,11 +29,14 @@ function advisory(overrides: Partial = {}): AuditAdvisory { }; } +// The fixture's own minimumReleaseAge, named rather than repeated as a bare literal at every assertion that reads it back out of WORKSPACE below. +const FIXTURE_MINIMUM_RELEASE_AGE_MINUTES = 60; + // Shaped like this workspace's real pnpm-workspace.yaml: an explanatory comment attached to the `overrides` key itself, and a second comment attached to one entry inside the map. Those two comments live in different places and do not survive the same operations, which is the whole reason the fix path patches child keys. const WORKSPACE = `packages: - "packages/*" -minimumReleaseAge: 60 +minimumReleaseAge: ${String(FIXTURE_MINIMUM_RELEASE_AGE_MINUTES)} # fast-uri < 3.1.5 is vulnerable to host confusion via a backslash authority introducer (GHSA-hht2-r2mx-9j9m). A transitive devDependency, so only an override can force a patched version. overrides: @@ -90,7 +95,9 @@ describe("isAuditServiceError", () => { describe("minimumReleaseAgeMinutes", () => { it("reads the configured window as minutes, not days", () => { - expect(minimumReleaseAgeMinutes(WORKSPACE)).toBe(60); + expect(minimumReleaseAgeMinutes(WORKSPACE)).toBe( + FIXTURE_MINIMUM_RELEASE_AGE_MINUTES, + ); }); it("throws rather than defaulting when the key is absent", () => { @@ -265,7 +272,7 @@ describe("classifyAdvisories", () => { }); describe("override pruning", () => { - // Single-document, as this workspace's lockfile is, and with the multi-importer shape a thirteen-package workspace produces: `packages` is the union of every importer's resolutions, which is what an inertness check has to read. + // The project's own document within the real (multi-document, once pnpm pins its own binary through packageManagerDependencies) lockfile, with the multi-importer shape a many-package workspace produces: `packages` is the union of every importer's resolutions, which is what an inertness check has to read. const LOCKFILE = `lockfileVersion: '9.0' importers: @@ -296,12 +303,13 @@ packages: expect(resolved.get("@scope/pkg")).toEqual(new Set(["1.0.0"])); }); - it("throws on a multi-document lockfile rather than reading only the first document", () => { - expect(() => - resolvedVersionsFromLockfileText( - `---\npackages:\n pnpm@11.6.0: {}\n---\n${LOCKFILE}`, - ), - ).toThrow(/multiple documents/); + it("unions every document's packages map on a multi-document lockfile, not just the first", () => { + const resolved = resolvedVersionsFromLockfileText( + `packages:\n pnpm@11.6.0: {}\n---\n${LOCKFILE}`, + ); + expect(resolved.get("pnpm")).toEqual(new Set(["11.6.0"])); + expect(resolved.get("undici")).toEqual(new Set(["6.28.0", "7.29.0"])); + expect(resolved.get("@scope/pkg")).toEqual(new Set(["1.0.0"])); }); it("throws when the lockfile has no packages map", () => { diff --git a/.github/scripts/audit-autofix.ts b/.github/scripts/audit-autofix.ts index 91c7dcab2..0a379e7ba 100644 --- a/.github/scripts/audit-autofix.ts +++ b/.github/scripts/audit-autofix.ts @@ -1,7 +1,7 @@ import { spawnSync } from "node:child_process"; import { pathToFileURL } from "node:url"; import { satisfies } from "semver"; -import { type Document, parse, parseDocument } from "yaml"; +import { type Document, parse, parseAllDocuments, parseDocument } from "yaml"; import { appendFileSync, readFileSync, writeFileSync } from "node:fs"; export interface AuditAdvisory { @@ -160,7 +160,7 @@ function writeWorkspaceDoc(doc: Document): void { // `overrides` is passed as the complete desired state, not a patch: keys it omits are deleted individually, which is what the prune pass at the end of a run relies on. Entries whose value is not a string are left alone rather than removed, since currentOverrides only reports string-valued keys -- a value this script does not understand is not a value it should destroy. export function withOverrides( workspace: Document, - overrides: Record, + overrides: Readonly>, ): Document { const cloned = workspace.clone(); // An empty map is written as a bare `overrides: {}` line that never goes away on its own -- deleting the key when there is nothing to override keeps a fully-pruned file clean instead of accumulating dead boilerplate. The comment above the key goes with it, which is correct: it documents overrides that no longer exist. @@ -198,13 +198,13 @@ function restoreFromGit(): void { function setOutput(name: string, value: string): void { const outputFile = process.env.GITHUB_OUTPUT; - if (!outputFile) return; + if (outputFile === undefined || outputFile === "") return; appendFileSync(outputFile, `${name}=${value}\n`); } function appendSummary(markdown: string): void { const summaryFile = process.env.GITHUB_STEP_SUMMARY; - if (!summaryFile) return; + if (summaryFile === undefined || summaryFile === "") return; appendFileSync(summaryFile, markdown); } @@ -227,8 +227,8 @@ function hasUncommittedChanges(): boolean { // `-r`, unlike the single-importer form this was ported from: `overrides` in pnpm-workspace.yaml is a workspace-wide setting, but a non-recursive `pnpm update` re-resolves the root importer's dependencies only, leaving every one of this workspace's package importers on the resolutions already in the lockfile. Since almost everything an advisory names here is transitive to a package rather than to the root, the update would report success while the vulnerable entries the audit found stayed exactly where they were -- and the re-audit below would then correctly refuse to call the candidate fixed. Recursive is the form that matches where the overrides apply. function attemptBatch( workspace: Document, - baseOverrides: Record, - batch: Candidate[], + baseOverrides: Readonly>, + batch: readonly Candidate[], ): { succeeded: Candidate[]; conflicted: boolean } { const overrides = { ...baseOverrides }; for (const c of batch) overrides[c.overrideKey] = c.range; @@ -254,8 +254,8 @@ function attemptBatch( // A single candidate whose override the registry can never satisfy (or that conflicts with peers) must not sink every other, independently-fixable candidate in the same batch. attemptBatch's own audit check already tells us exactly which candidates in a batch succeeded when the update itself ran cleanly, so bisection is only needed to isolate a genuine `conflicted` (non-zero exit) failure; if two halves that each update fine independently still conflict combined, fall back to a linear greedy pass, which always terminates with a verified-working subset. function resolveMaximalSubset( workspace: Document, - baseOverrides: Record, - batch: Candidate[], + baseOverrides: Readonly>, + batch: readonly Candidate[], ): Candidate[] { if (batch.length === 0) return []; @@ -285,8 +285,8 @@ function resolveMaximalSubset( function greedyResolve( workspace: Document, - baseOverrides: Record, - batch: Candidate[], + baseOverrides: Readonly>, + batch: readonly Candidate[], ): Candidate[] { const working: Candidate[] = []; for (const c of batch) { @@ -299,7 +299,9 @@ function greedyResolve( } // Splits audit advisories into fixable candidates (grouped by override selector) and deferred entries with a reason each. Pure — no filesystem, no subprocesses — so the unit tests cover grouping, dedup, and the not-overridable and no-patch deferral paths through it. -export function classifyAdvisories(advisories: AuditAdvisory[]): Classified { +export function classifyAdvisories( + advisories: readonly AuditAdvisory[], +): Classified { const deferred: { advisory: AuditAdvisory; reason: string }[] = []; const candidatesByKey = new Map(); @@ -342,7 +344,7 @@ export function classifyAdvisories(advisories: AuditAdvisory[]): Classified { // An override is inert when no version its selector could rewrite is present: the selector is the vulnerable range on the key (`pkg@`), and the override only acts on resolutions matching that range. If nothing resolved matches the selector, the override forces nothing today -- regardless of what the package resolves outside the selector. The autofix only ever adds overrides, so without this pass the map accumulates one entry per historical advisory forever. Dropping inert entries is self-correcting rather than risky: if a future update resolves back into a vulnerable range, the next audit run re-adds the override through the same fix path. export function inertOverrideKeys( - overrides: Record, + overrides: Readonly>, resolvedVersions: Map>, ): string[] { const inert: string[] = []; @@ -361,23 +363,28 @@ export function inertOverrideKeys( return inert; } -// The resolved package@version set from the lockfile's `packages` map, minus peer-dependency suffixes. This workspace's pnpm-lock.yaml is a single YAML document, so there is no stream to search: the multi-document form the reference implementation handled is what pnpm writes when a project pins its own pnpm binary through packageManagerDependencies, which adds a self-management lockfile as a document of its own ahead of the project's; this workspace pins pnpm through package.json's packageManager field alone and gets one document. `parse` is deliberate rather than incidental -- it throws outright on a multi-document source, so if that ever changes this fails loudly instead of silently reading whichever document happened to come first. The map is the union of every importer's resolutions, which is what an inertness check needs across thirteen packages. +// The resolved package@version set from the lockfile's `packages` map(s), minus peer-dependency suffixes. pnpm writes a multi-document lockfile once a project pins its own pnpm binary through packageManagerDependencies -- a self-management document listing the pinned pnpm build's own per-platform packages, ahead of the project's own document -- and this workspace does exactly that (package.json's packageManager field, pnpm 12), so the single-document assumption this function used to make no longer holds. Every document in the stream that carries a `packages` map has its entries unioned into the same result, rather than picking one: the self-management document's own entries (`@pnpm/exe.*` platform binaries) are real resolved packages too, just never ones `pnpm audit` has advisories against, so including them changes nothing about correctness and needs no guess about which document is "the real" project lockfile. A document with no `packages` map at all is skipped rather than treated as an error on its own; only a stream where no document anywhere has a packages map is an error, since that means the lockfile as a whole resolves nothing. The map is the union of every importer's resolutions, which is what an inertness check needs across every package in the workspace. export function resolvedVersionsFromLockfileText( yamlText: string, ): Map> { - const parsed: unknown = parse(yamlText); - if (!isRecord(parsed) || !isRecord(parsed.packages)) { - throw new Error("lockfile had no packages map"); - } const byPackage = new Map>(); - for (const key of Object.keys(parsed.packages)) { - const stripped = key.replace(/(\([^)]*\))+$/, ""); - const at = stripped.lastIndexOf("@"); - const pkg = stripped.slice(0, at); - const version = stripped.slice(at + 1); - const existing = byPackage.get(pkg) ?? new Set(); - existing.add(version); - byPackage.set(pkg, existing); + let sawPackagesMap = false; + for (const document of parseAllDocuments(yamlText)) { + const parsed: unknown = document.toJS(); + if (!isRecord(parsed) || !isRecord(parsed.packages)) continue; + sawPackagesMap = true; + for (const key of Object.keys(parsed.packages)) { + const stripped = key.replace(/(\([^)]*\))+$/, ""); + const at = stripped.lastIndexOf("@"); + const pkg = stripped.slice(0, at); + const version = stripped.slice(at + 1); + const existing = byPackage.get(pkg) ?? new Set(); + existing.add(version); + byPackage.set(pkg, existing); + } + } + if (!sawPackagesMap) { + throw new Error("lockfile had no packages map"); } return byPackage; } @@ -549,7 +556,7 @@ function main(): void { } if ( - process.argv[1] && + process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href ) { main();