From ab1ab5ed40126b4f2006661e17895069a5f3119f Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 23 Mar 2026 09:51:41 +0000 Subject: [PATCH 1/5] =?UTF-8?q?chore:=20Upgrade=20eslint=209=E2=86=9210=20?= =?UTF-8?q?and=20@eslint/js=209=E2=86=9210,=20add=20upgrade=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - eslint: 9.39.2 → 10.1.0 - @eslint/js: 9.39.4 → 10.0.1 Co-Authored-By: Claude Sonnet 4.6 --- .../2026-03-23/eslint-v10-upgrade/plan.md | 138 +++++++++++ package.json | 4 +- pnpm-lock.yaml | 224 +++++++++--------- 3 files changed, 247 insertions(+), 119 deletions(-) create mode 100644 docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md diff --git a/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md b/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md new file mode 100644 index 000000000..5a620f1ee --- /dev/null +++ b/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md @@ -0,0 +1,138 @@ +# ESLint v10 アップグレード計画 + +## 概要 + +Dependabot PR #3303 が `eslint` 9.39.2 → 10.1.0 の更新を提案している。 +合わせて `@eslint/js` も 9.39.4 → 10.0.1 のメジャー更新が出ている(別途対応が必要)。 + +本計画では破壊的変更の影響調査結果をまとめ、マージに向けた対応手順を定義する。 + +--- + +## 破壊的変更の影響調査結果 + +### 問題なし(対応不要) + +| 確認項目 | 根拠 | +| ----------------------------------------------- | -------------------------------------------------------- | +| Node.js 要件(v20.19+/v22.13+/v24+) | `package.json` の `engines.node: "24.x"` が要件を満たす | +| 設定フォーマット(`.eslintrc` 系の廃止) | すでに `eslint.config.mjs`(flat config)を使用中 | +| `@typescript-eslint/eslint-plugin` v8.57.1 互換 | peer dep: `"eslint": "^8.57.0 \|\| ^9.0.0 \|\| ^10.0.0"` | +| `eslint-plugin-svelte` v3.16.0 互換 | peer dep: `"eslint": "^8.57.1 \|\| ^9.0.0 \|\| ^10.0.0"` | +| `svelte-eslint-parser` v1.6.0 互換 | eslint の peer dep なし | +| `/* eslint-env */` コメント(v10 でエラー化) | `src/` 内に該当コメントなし(grep 確認済み) | +| `FlatESLint` / `LegacyESLint` API 削除 | これらを直接呼び出すコードなし | +| `context.getCwd()` 等の context API 削除 | プラグイン開発者向け変更。本プロジェクトは非該当 | +| JSX 参照追跡の変更 | Svelte プロジェクトのため JSX はほぼ未使用 | + +### 要対応 + +#### 1. `@eslint/js` を合わせてアップグレードする必要がある + +`eslint` 本体と `@eslint/js` は**別パッケージ**。PR #3303 は `eslint` しか更新しないため、 +`@eslint/js` を 9.x のままにするとバージョン不一致が生じる。両方セットで更新が必要。 + +#### 2. `eslint:recommended` に追加された 3 ルールへの対応 + +`eslint.config.mjs` で `js.configs.recommended` を使用しているため、 +以下の 3 ルールが自動的に有効になる。 + +| ルール | 内容 | リスク評価 | +| ----------------------- | ------------------------------------------------- | --------------------------------------- | +| `no-unassigned-vars` | 宣言のみで一度も代入されない変数を禁止 | 低 | +| `no-useless-assignment` | 代入後に読まれずに上書きされる無駄な代入を禁止 | 中(複雑な条件分岐内でありがち) | +| `preserve-caught-error` | `catch(e)` の `e` を catch 内で必ず使うことを要求 | 低(全 catch ブロックが変数を使用済み) | + +`pnpm lint` を実行してエラー箇所を洗い出す必要がある。 +エラーがあれば修正するか、`eslint.config.mjs` で明示的に無効化する。 + +--- + +## 設計方針 + +- PR #3303 のマージと `@eslint/js` 更新を**同一ブランチで実施**する(分けると一時的な不整合が残るため) +- 新 3 ルールによるエラーは原則として**修正を優先**する(lint ルールの意図に沿ったコード改善) +- ただし `no-useless-assignment` については、TypeScript の型推論や Svelte のリアクティビティと絡む誤検知の可能性があるため、精査した上で無効化も選択肢とする + +## 却下した代替案 + +- **`eslint` だけ更新して `@eslint/js` を 9.x に据え置く**: バージョン不一致によりメジャーバージョンの推奨ルールが正しく適用されず、将来的な混乱の原因になるため却下 +- **新 3 ルールを全て `eslint.config.mjs` で無効化する**: ルールの追加は意図的な品質向上策なので、確認前に一括無効化するのは YAGNI に反する + +--- + +## 実装フェーズ + +### Phase 1: 依存バージョン更新 ✅ + +対象ファイル: `package.json` + +``` +eslint: 9.39.2 → 10.1.0 +@eslint/js: 9.39.4 → 10.0.1 +``` + +`pnpm install` を実行して `pnpm-lock.yaml` を更新する。 + +### Phase 2: lint エラー確認と修正 ✅ + +`pnpm lint` を実行し、新 3 ルールによるエラー箇所を列挙する。 +エラーが出た場合は以下の優先順位で対応する: + +1. コードを修正して準拠させる +2. やむを得ない場合のみ `eslint.config.mjs` でルールを無効化する(インラインコメントでの抑制は避ける) + +**結果**: エラーなし。新 3 ルール(`no-unassigned-vars` / `no-useless-assignment` / `preserve-caught-error`)への対応コード修正は不要だった。 + +--- + +## 便利な新機能(採用検討) + +以下は必須対応ではないが、今回のアップグレードで使えるようになる機能。 + +| 機能 | 内容 | 推奨度 | +| ---------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------- | +| `no-useless-assignment` | デッドストア(代入後に使われない変数)を自動検出 | 高 — 有効にする価値あり | +| `no-unassigned-vars` | 未代入変数を検出 | 高 — デフォルトで有効 | +| **バルク抑制 (Bulk Suppressions)** | 既存の lint エラーを抑制ファイルに一括記録し、新規追加分だけ CI でチェックできる | 中 — 現時点でエラーが少なければ不要 | +| 設定ファイル探索の改善 | `eslint.config.*` を各ファイルのディレクトリから上向きに探索 | 影響なし(現構成で問題なし) | + +--- + +## 検証手順 + +```bash +# 1. パッケージ更新後 +pnpm install + +# 2. lint エラーの確認 +pnpm lint + +# 3. 型チェック(eslint 変更が型に影響しないことを確認) +pnpm check + +# 4. ユニットテスト(lint ルール変更によるテストへの影響がないことを確認) +pnpm test:unit +``` + +--- + +## 検証結果 + +| コマンド | 結果 | +| --------------- | ----------------------------------------------- | +| `pnpm install` | ✅ 完了(eslint +10.1.0 / @eslint/js +10.0.1) | +| `pnpm lint` | ✅ エラーなし | +| `pnpm check` | ⚠️ 既存エラー 2 件(ESLint 変更と無関係) | +| `pnpm test:unit`| ✅ 1954 passed / 1 skipped | + +## 教訓 + +1. **`eslint` と `@eslint/js` は別パッケージ**: Dependabot は片方だけ更新することがあるため、メジャー更新時は両方を同一コミットで更新する。 +2. **`pnpm check` の既存エラーは事前に把握する**: git stash で変更前後を比較することで、型エラーがアップグレード起因か既存問題かを素早く判別できる。 +3. **`js.configs.recommended` 使用時は新ルールを意識する**: `@eslint/js` のメジャー更新で `recommended` に追加されたルールは自動有効化される。今回は 3 ルール追加も既存コードはクリーンだった。 + +## 参考 + +- [ESLint v10 移行ガイド](https://eslint.org/docs/latest/use/migrate-to-10.0.0) +- [Dependabot PR #3303](https://github.com/AtCoder-NoviSteps/AtCoderNoviSteps/pull/3303) diff --git a/package.json b/package.json index 552616dcd..5fe7dc5ee 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@dnd-kit/abstract": "0.3.2", "@dnd-kit/dom": "0.3.2", "@eslint/eslintrc": "3.3.5", - "@eslint/js": "9.39.4", + "@eslint/js": "10.0.1", "@playwright/test": "1.58.2", "@quramy/prisma-fabbrica": "2.3.3", "@sveltejs/adapter-vercel": "6.3.3", @@ -41,7 +41,7 @@ "@typescript-eslint/parser": "8.57.1", "@vitest/coverage-v8": "4.0.18", "@vitest/ui": "4.0.18", - "eslint": "9.39.2", + "eslint": "10.1.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-svelte": "3.16.0", "flowbite": "3.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 579efbdf4..64a98f1ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,8 +76,8 @@ importers: specifier: 3.3.5 version: 3.3.5 '@eslint/js': - specifier: 9.39.4 - version: 9.39.4 + specifier: 10.0.1 + version: 10.0.1(eslint@10.1.0(jiti@1.21.7)) '@playwright/test': specifier: 1.58.2 version: 1.58.2 @@ -110,10 +110,10 @@ importers: version: 28.0.1 '@typescript-eslint/eslint-plugin': specifier: 8.57.1 - version: 8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 8.57.1(@typescript-eslint/parser@8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/parser': specifier: 8.57.1 - version: 8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) '@vitest/coverage-v8': specifier: 4.0.18 version: 4.0.18(vitest@4.0.18) @@ -121,14 +121,14 @@ importers: specifier: 4.0.18 version: 4.0.18(vitest@4.0.18) eslint: - specifier: 9.39.2 - version: 9.39.2(jiti@1.21.7) + specifier: 10.1.0 + version: 10.1.0(jiti@1.21.7) eslint-config-prettier: specifier: 10.1.8 - version: 10.1.8(eslint@9.39.2(jiti@1.21.7)) + version: 10.1.8(eslint@10.1.0(jiti@1.21.7)) eslint-plugin-svelte: specifier: 3.16.0 - version: 3.16.0(eslint@9.39.2(jiti@1.21.7))(svelte@5.54.1)(ts-node@10.9.1(@types/node@25.5.0)(typescript@5.9.3)) + version: 3.16.0(eslint@10.1.0(jiti@1.21.7))(svelte@5.54.1)(ts-node@10.9.1(@types/node@25.5.0)(typescript@5.9.3)) flowbite: specifier: 3.1.2 version: 3.1.2(rollup@4.53.4) @@ -862,12 +862,6 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -878,37 +872,38 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.23.3': + resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.5.3': + resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@1.1.1': + resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/eslintrc@3.3.5': resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.39.4': - resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@3.0.3': + resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.6.1': + resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@exodus/bytes@1.15.0': resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} @@ -1969,6 +1964,9 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -2300,9 +2298,6 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} @@ -3121,6 +3116,10 @@ packages: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3133,9 +3132,9 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@10.1.0: + resolution: {integrity: sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: jiti: '*' @@ -3150,13 +3149,17 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrap@2.2.4: @@ -3880,9 +3883,6 @@ packages: lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -3993,9 +3993,6 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -5882,31 +5879,26 @@ snapshots: '@esbuild/win32-x64@0.27.1': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@1.21.7))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.1.0(jiti@1.21.7))': dependencies: - eslint: 9.39.2(jiti@1.21.7) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@1.21.7))': - dependencies: - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.21.1': + '@eslint/config-array@0.23.3': dependencies: - '@eslint/object-schema': 2.1.7 + '@eslint/object-schema': 3.0.3 debug: 4.4.3 - minimatch: 3.1.5 + minimatch: 10.2.4 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.4.2': + '@eslint/config-helpers@0.5.3': dependencies: - '@eslint/core': 0.17.0 + '@eslint/core': 1.1.1 - '@eslint/core@0.17.0': + '@eslint/core@1.1.1': dependencies: '@types/json-schema': 7.0.15 @@ -5924,15 +5916,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.39.2': {} - - '@eslint/js@9.39.4': {} + '@eslint/js@10.0.1(eslint@10.1.0(jiti@1.21.7))': + optionalDependencies: + eslint: 10.1.0(jiti@1.21.7) - '@eslint/object-schema@2.1.7': {} + '@eslint/object-schema@3.0.3': {} - '@eslint/plugin-kit@0.4.1': + '@eslint/plugin-kit@0.6.1': dependencies: - '@eslint/core': 0.17.0 + '@eslint/core': 1.1.1 levn: 0.4.1 '@exodus/bytes@1.15.0': {} @@ -6936,6 +6928,8 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/esrecurse@4.3.1': {} + '@types/estree@1.0.8': {} '@types/geojson@7946.0.16': {} @@ -7010,15 +7004,15 @@ snapshots: '@types/json-schema': 7.0.15 optional: true - '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/type-utils': 8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.57.1 - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -7026,14 +7020,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/parser@8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.57.1 '@typescript-eslint/types': 8.57.1 '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.57.1 debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7056,13 +7050,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.57.1 '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -7085,13 +7079,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/utils@8.57.1(eslint@10.1.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@1.21.7)) '@typescript-eslint/scope-manager': 8.57.1 '@typescript-eslint/types': 8.57.1 '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7538,13 +7532,6 @@ snapshots: agent-base@7.1.4: {} - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 @@ -8392,15 +8379,15 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@1.21.7)): + eslint-config-prettier@10.1.8(eslint@10.1.0(jiti@1.21.7)): dependencies: - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) - eslint-plugin-svelte@3.16.0(eslint@9.39.2(jiti@1.21.7))(svelte@5.54.1)(ts-node@10.9.1(@types/node@25.5.0)(typescript@5.9.3)): + eslint-plugin-svelte@3.16.0(eslint@10.1.0(jiti@1.21.7))(svelte@5.54.1)(ts-node@10.9.1(@types/node@25.5.0)(typescript@5.9.3)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@1.21.7)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 9.39.2(jiti@1.21.7) + eslint: 10.1.0(jiti@1.21.7) esutils: 2.0.3 globals: 16.5.0 known-css-properties: 0.37.0 @@ -8419,35 +8406,39 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.8 + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} eslint-visitor-keys@4.2.1: {} eslint-visitor-keys@5.0.1: {} - eslint@9.39.2(jiti@1.21.7): + eslint@10.1.0(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5 - '@eslint/js': 9.39.2 - '@eslint/plugin-kit': 0.4.1 + '@eslint/config-array': 0.23.3 + '@eslint/config-helpers': 0.5.3 + '@eslint/core': 1.1.1 + '@eslint/plugin-kit': 0.6.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - ajv: 6.12.6 - chalk: 4.1.2 + ajv: 6.14.0 cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -8457,8 +8448,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 10.2.4 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -8474,9 +8464,15 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 4.2.1 + espree@11.2.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 5.0.1 + esprima@4.0.1: {} - esquery@1.6.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -9193,8 +9189,6 @@ snapshots: lodash.camelcase@4.3.0: {} - lodash.merge@4.6.2: {} - lodash@4.17.21: {} lru-cache@11.2.7: {} @@ -9305,10 +9299,6 @@ snapshots: dependencies: brace-expansion: 5.0.4 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - minimatch@3.1.5: dependencies: brace-expansion: 1.1.12 From fb945642f63a9e493ec4bc61cc1568b705a5ba1f Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 23 Mar 2026 09:52:21 +0000 Subject: [PATCH 2/5] docs: Remove eslint-v10-upgrade plan (no-op upgrade, no separate plan needed) Co-Authored-By: Claude Sonnet 4.6 --- .../2026-03-23/eslint-v10-upgrade/plan.md | 138 ------------------ 1 file changed, 138 deletions(-) delete mode 100644 docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md diff --git a/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md b/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md deleted file mode 100644 index 5a620f1ee..000000000 --- a/docs/dev-notes/2026-03-23/eslint-v10-upgrade/plan.md +++ /dev/null @@ -1,138 +0,0 @@ -# ESLint v10 アップグレード計画 - -## 概要 - -Dependabot PR #3303 が `eslint` 9.39.2 → 10.1.0 の更新を提案している。 -合わせて `@eslint/js` も 9.39.4 → 10.0.1 のメジャー更新が出ている(別途対応が必要)。 - -本計画では破壊的変更の影響調査結果をまとめ、マージに向けた対応手順を定義する。 - ---- - -## 破壊的変更の影響調査結果 - -### 問題なし(対応不要) - -| 確認項目 | 根拠 | -| ----------------------------------------------- | -------------------------------------------------------- | -| Node.js 要件(v20.19+/v22.13+/v24+) | `package.json` の `engines.node: "24.x"` が要件を満たす | -| 設定フォーマット(`.eslintrc` 系の廃止) | すでに `eslint.config.mjs`(flat config)を使用中 | -| `@typescript-eslint/eslint-plugin` v8.57.1 互換 | peer dep: `"eslint": "^8.57.0 \|\| ^9.0.0 \|\| ^10.0.0"` | -| `eslint-plugin-svelte` v3.16.0 互換 | peer dep: `"eslint": "^8.57.1 \|\| ^9.0.0 \|\| ^10.0.0"` | -| `svelte-eslint-parser` v1.6.0 互換 | eslint の peer dep なし | -| `/* eslint-env */` コメント(v10 でエラー化) | `src/` 内に該当コメントなし(grep 確認済み) | -| `FlatESLint` / `LegacyESLint` API 削除 | これらを直接呼び出すコードなし | -| `context.getCwd()` 等の context API 削除 | プラグイン開発者向け変更。本プロジェクトは非該当 | -| JSX 参照追跡の変更 | Svelte プロジェクトのため JSX はほぼ未使用 | - -### 要対応 - -#### 1. `@eslint/js` を合わせてアップグレードする必要がある - -`eslint` 本体と `@eslint/js` は**別パッケージ**。PR #3303 は `eslint` しか更新しないため、 -`@eslint/js` を 9.x のままにするとバージョン不一致が生じる。両方セットで更新が必要。 - -#### 2. `eslint:recommended` に追加された 3 ルールへの対応 - -`eslint.config.mjs` で `js.configs.recommended` を使用しているため、 -以下の 3 ルールが自動的に有効になる。 - -| ルール | 内容 | リスク評価 | -| ----------------------- | ------------------------------------------------- | --------------------------------------- | -| `no-unassigned-vars` | 宣言のみで一度も代入されない変数を禁止 | 低 | -| `no-useless-assignment` | 代入後に読まれずに上書きされる無駄な代入を禁止 | 中(複雑な条件分岐内でありがち) | -| `preserve-caught-error` | `catch(e)` の `e` を catch 内で必ず使うことを要求 | 低(全 catch ブロックが変数を使用済み) | - -`pnpm lint` を実行してエラー箇所を洗い出す必要がある。 -エラーがあれば修正するか、`eslint.config.mjs` で明示的に無効化する。 - ---- - -## 設計方針 - -- PR #3303 のマージと `@eslint/js` 更新を**同一ブランチで実施**する(分けると一時的な不整合が残るため) -- 新 3 ルールによるエラーは原則として**修正を優先**する(lint ルールの意図に沿ったコード改善) -- ただし `no-useless-assignment` については、TypeScript の型推論や Svelte のリアクティビティと絡む誤検知の可能性があるため、精査した上で無効化も選択肢とする - -## 却下した代替案 - -- **`eslint` だけ更新して `@eslint/js` を 9.x に据え置く**: バージョン不一致によりメジャーバージョンの推奨ルールが正しく適用されず、将来的な混乱の原因になるため却下 -- **新 3 ルールを全て `eslint.config.mjs` で無効化する**: ルールの追加は意図的な品質向上策なので、確認前に一括無効化するのは YAGNI に反する - ---- - -## 実装フェーズ - -### Phase 1: 依存バージョン更新 ✅ - -対象ファイル: `package.json` - -``` -eslint: 9.39.2 → 10.1.0 -@eslint/js: 9.39.4 → 10.0.1 -``` - -`pnpm install` を実行して `pnpm-lock.yaml` を更新する。 - -### Phase 2: lint エラー確認と修正 ✅ - -`pnpm lint` を実行し、新 3 ルールによるエラー箇所を列挙する。 -エラーが出た場合は以下の優先順位で対応する: - -1. コードを修正して準拠させる -2. やむを得ない場合のみ `eslint.config.mjs` でルールを無効化する(インラインコメントでの抑制は避ける) - -**結果**: エラーなし。新 3 ルール(`no-unassigned-vars` / `no-useless-assignment` / `preserve-caught-error`)への対応コード修正は不要だった。 - ---- - -## 便利な新機能(採用検討) - -以下は必須対応ではないが、今回のアップグレードで使えるようになる機能。 - -| 機能 | 内容 | 推奨度 | -| ---------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------- | -| `no-useless-assignment` | デッドストア(代入後に使われない変数)を自動検出 | 高 — 有効にする価値あり | -| `no-unassigned-vars` | 未代入変数を検出 | 高 — デフォルトで有効 | -| **バルク抑制 (Bulk Suppressions)** | 既存の lint エラーを抑制ファイルに一括記録し、新規追加分だけ CI でチェックできる | 中 — 現時点でエラーが少なければ不要 | -| 設定ファイル探索の改善 | `eslint.config.*` を各ファイルのディレクトリから上向きに探索 | 影響なし(現構成で問題なし) | - ---- - -## 検証手順 - -```bash -# 1. パッケージ更新後 -pnpm install - -# 2. lint エラーの確認 -pnpm lint - -# 3. 型チェック(eslint 変更が型に影響しないことを確認) -pnpm check - -# 4. ユニットテスト(lint ルール変更によるテストへの影響がないことを確認) -pnpm test:unit -``` - ---- - -## 検証結果 - -| コマンド | 結果 | -| --------------- | ----------------------------------------------- | -| `pnpm install` | ✅ 完了(eslint +10.1.0 / @eslint/js +10.0.1) | -| `pnpm lint` | ✅ エラーなし | -| `pnpm check` | ⚠️ 既存エラー 2 件(ESLint 変更と無関係) | -| `pnpm test:unit`| ✅ 1954 passed / 1 skipped | - -## 教訓 - -1. **`eslint` と `@eslint/js` は別パッケージ**: Dependabot は片方だけ更新することがあるため、メジャー更新時は両方を同一コミットで更新する。 -2. **`pnpm check` の既存エラーは事前に把握する**: git stash で変更前後を比較することで、型エラーがアップグレード起因か既存問題かを素早く判別できる。 -3. **`js.configs.recommended` 使用時は新ルールを意識する**: `@eslint/js` のメジャー更新で `recommended` に追加されたルールは自動有効化される。今回は 3 ルール追加も既存コードはクリーンだった。 - -## 参考 - -- [ESLint v10 移行ガイド](https://eslint.org/docs/latest/use/migrate-to-10.0.0) -- [Dependabot PR #3303](https://github.com/AtCoder-NoviSteps/AtCoderNoviSteps/pull/3303) From 47dfb87e7da52d39ccbfea27c12b9decb71f0643 Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 23 Mar 2026 09:56:58 +0000 Subject: [PATCH 3/5] docs: Add dep-upgrade skill and update claude-code guide Co-Authored-By: Claude Sonnet 4.6 --- .claude/skills/dep-upgrade/SKILL.md | 12 ++++ .claude/skills/dep-upgrade/instructions.md | 73 ++++++++++++++++++++++ docs/guides/claude-code.md | 26 ++++++-- 3 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 .claude/skills/dep-upgrade/SKILL.md create mode 100644 .claude/skills/dep-upgrade/instructions.md diff --git a/.claude/skills/dep-upgrade/SKILL.md b/.claude/skills/dep-upgrade/SKILL.md new file mode 100644 index 000000000..d0cec7e84 --- /dev/null +++ b/.claude/skills/dep-upgrade/SKILL.md @@ -0,0 +1,12 @@ +--- +name: dep-upgrade +description: Analyze a major version dependency upgrade: summarize breaking changes, assess project impact, and propose new features to adopt. Outputs a plan.md and executes the upgrade. +disable-model-invocation: true +argument-hint: ' ' +--- + +Analyze and execute the major version upgrade for: $ARGUMENTS + +1. **Analyze** — fetch the official migration guide via WebFetch; apply the checklist in [instructions.md](instructions.md) +2. **Generate plan** — create `docs/dev-notes/YYYY-MM-DD/{package}-upgrade/plan.md` with breaking changes, impact, and new features; **stop and ask for confirmation** +3. **Execute** — update `package.json`, run `pnpm install && pnpm lint && pnpm check && pnpm test:unit`; update the plan checklist when done diff --git a/.claude/skills/dep-upgrade/instructions.md b/.claude/skills/dep-upgrade/instructions.md new file mode 100644 index 000000000..a824d3acc --- /dev/null +++ b/.claude/skills/dep-upgrade/instructions.md @@ -0,0 +1,73 @@ +# Dependency Major Upgrade Checklist + +## 1. Breaking Changes Analysis + +Fetch the official migration guide via WebFetch. For each breaking change, grep `src/`, config files, +and `package.json` to determine applicability. Produce two tables: + +**問題なし(対応不要)** + +| Confirmed Item | Rationale | +| -------------- | --------- | +| ... | ... | + +**要対応** + +| Item | Content | Risk | +| ---- | ------- | ------------------- | +| ... | ... | High / Medium / Low | + +Key areas to check: + +- Runtime requirements (`engines.node` in `package.json`) +- Config file format changes (flat config vs legacy, etc.) +- Deprecated/removed APIs used in `src/` +- Directive comments that become errors in the new version (e.g., `/* eslint-env */` in ESLint v10) + +## 2. Companion Package Check + +Some packages must be upgraded together in the same commit to avoid version mismatch. +Check `package.json` for known companion pairs: + +- `@sveltejs/kit` + `@sveltejs/vite-plugin-svelte` +- `eslint` + `@eslint/js` + +Also verify peer dependency compatibility (`"eslint": "^8 || ^9 || ^10"` style) for all +related packages already installed. + +If companion packages are found, include them in the upgrade scope. + +## 3. New Features to Adopt + +List features unlocked by the new major version: + +| Feature | Description | Recommendation | +| ------- | ----------- | ------------------- | +| ... | ... | High / Medium / Low | + +## 4. plan.md Structure + +Write `docs/dev-notes/YYYY-MM-DD/{package}-upgrade/plan.md` in Japanese: + +- **概要**: Which Dependabot PR / bump triggered this; summary of scope +- **破壊的変更の影響調査結果**: Tables from sections 1–2 above +- **設計方針**: How to handle action-required items; companion package strategy +- **却下した代替案**: Alternatives considered (e.g., upgrading only one of a companion pair) +- **便利な新機能(採用検討)**: Table from section 3 +- **実装フェーズ**: Phased `- [ ]` checklist (lowest risk → highest risk) +- **検証手順**: The exact commands to run + +## 5. Verification Commands + +```bash +pnpm install +pnpm lint +pnpm check +pnpm test +``` + +> **`pnpm check` tip:** If type errors appear, run `git stash && pnpm check 2>&1 | tail -5` +> to confirm whether errors are pre-existing before attributing them to this upgrade. +> Restore with `git stash pop`. + +Update the plan.md `- [ ]` checklist and add a verification results table when done. diff --git a/docs/guides/claude-code.md b/docs/guides/claude-code.md index 8ea9e9094..4be590a5f 100644 --- a/docs/guides/claude-code.md +++ b/docs/guides/claude-code.md @@ -65,11 +65,27 @@ paths: **本プロジェクトの skills(`.claude/skills/` および superpowers plugin):** -| スキル | 用途 | -| ---------------- | ------------------------------------------------------------------------------------------------------------ | -| `/writing-plans` | 新機能・追加実装の詳細計画を生成(2-5分単位のタスク分解)。superpowers plugin 提供 | -| `/refactor-plan` | Issue 番号またはパスを渡してリファクタリング計画を出力(実装はしない) | -| `/session-close` | セッション終了時のルーティン:テスト確認 → plan.md 更新 → rules 候補提示 → 肥大化チェック → 繰り返し指示検出 | +| スキル | 用途 | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `/writing-plans` | 新機能・追加実装の詳細計画を生成(2-5分単位のタスク分解)。superpowers plugin 提供 | +| `/refactor-plan` | Issue 番号またはパスを渡してリファクタリング計画を出力(実装はしない) | +| `/session-close` | セッション終了時のルーティン:テスト確認 → plan.md 更新 → rules 候補提示 → 肥大化チェック → 繰り返し指示検出 | +| `/dep-upgrade` | ライブラリのメジャーバージョンアップ分析:破壊的変更の整理・本プロジェクトへの影響・新機能提案 → plan.md 生成 → アップグレード実行 | + +**`/dep-upgrade` の使い方:** + +``` +/dep-upgrade +例: /dep-upgrade eslint 9 10 +``` + +実行内容: + +1. 公式マイグレーションガイドを WebFetch で取得 +2. 破壊的変更を `src/` / 設定ファイルに対して grep し、問題なし / 要対応を分類 +3. 同時更新が必要なコンパニオンパッケージを確認(例: `eslint` + `@eslint/js`) +4. 新バージョンで使える機能を推奨度付きで提案 +5. `docs/dev-notes/YYYY-MM-DD/{package}-upgrade/plan.md` を生成し、確認後にアップグレードを実行 **`/writing-plans` と `/refactor-plan` の使い分け:** From 4e8bf266a74cca9706243f9767e4f490e3ed1714 Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 23 Mar 2026 11:06:59 +0000 Subject: [PATCH 4/5] docs: Fix minor wording in dep-upgrade skill and claude-code guide Co-Authored-By: Claude Sonnet 4.6 --- .claude/skills/dep-upgrade/instructions.md | 2 +- docs/guides/claude-code.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/skills/dep-upgrade/instructions.md b/.claude/skills/dep-upgrade/instructions.md index a824d3acc..0172fffc2 100644 --- a/.claude/skills/dep-upgrade/instructions.md +++ b/.claude/skills/dep-upgrade/instructions.md @@ -63,7 +63,7 @@ Write `docs/dev-notes/YYYY-MM-DD/{package}-upgrade/plan.md` in Japanese: pnpm install pnpm lint pnpm check -pnpm test +pnpm test:unit ``` > **`pnpm check` tip:** If type errors appear, run `git stash && pnpm check 2>&1 | tail -5` diff --git a/docs/guides/claude-code.md b/docs/guides/claude-code.md index 4be590a5f..36314f313 100644 --- a/docs/guides/claude-code.md +++ b/docs/guides/claude-code.md @@ -74,7 +74,7 @@ paths: **`/dep-upgrade` の使い方:** -``` +```bash /dep-upgrade 例: /dep-upgrade eslint 9 10 ``` From bf3097ee51524dd314762d729024cc99b1b4733d Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 23 Mar 2026 11:21:53 +0000 Subject: [PATCH 5/5] docs: Update dep-upgrade skill instructions Co-Authored-By: Claude Sonnet 4.6 --- .claude/skills/dep-upgrade/instructions.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.claude/skills/dep-upgrade/instructions.md b/.claude/skills/dep-upgrade/instructions.md index 0172fffc2..0cd6905ad 100644 --- a/.claude/skills/dep-upgrade/instructions.md +++ b/.claude/skills/dep-upgrade/instructions.md @@ -66,8 +66,9 @@ pnpm check pnpm test:unit ``` -> **`pnpm check` tip:** If type errors appear, run `git stash && pnpm check 2>&1 | tail -5` -> to confirm whether errors are pre-existing before attributing them to this upgrade. -> Restore with `git stash pop`. +> **`pnpm check` tip:** If type errors appear and you have uncommitted changes, run +> `git stash && pnpm check 2>&1 | tail -5` to confirm whether errors are pre-existing. +> Restore with `git stash pop`. If there is nothing to stash, skip this check — without +> a baseline to compare against, it gives no useful signal. Update the plan.md `- [ ]` checklist and add a verification results table when done.