diet-remove
uzomuzozuダイエット分析で特定された依存関係を削除します。デフォルトではissue経由での実行、または直接PRでの実行に対応しています。
description の原文を見る
Remove a dependency identified by uzomuzo diet — analysis + issue (default) or direct PR
SKILL.md 本文
Diet Remove: $ARGUMENTS
依存関係 $ARGUMENTS の削除を分析・計画し、アクションを実行します。
モード選択
- デフォルト (Issue モード): Phase 1 の分析を実行し、その結果と提案された移行計画を記載した GitHub Issue をファイルします。外部の OSS 貢献やビルド環境を所有していない大規模プロジェクトに適しています。
--pr(PR モード): 削除のライフサイクル全体をローカルで実行します: 分析 → 置き換え → 検証 → コミット。プロジェクトを所有しており、ローカルでビルド/テストを実行できる場合のみ使用してください。
$ARGUMENTS をフラグについて解析します:
--prが存在する場合 → PR モード (直接実装)--repo owner/repoが存在する場合 → その Issue の対象リポジトリ- それ以外 → Issue モード (デフォルト)
使用時期: /diet-evaluate-removal が依存関係の削除が価値ある理由を確認した後、または uzomuzo diet がそれを trivial/easy として評価した場合。
安全原則: すべての削除はコミット前にビルド + vet + テストに合格する必要があります。いずれかのステップが失敗した場合は停止して診断してください — 無理に進めないでください。
エコシステム検出
PURL スキームまたはモジュールパスからエコシステムを検出します (pkg:golang/ → Go、pkg:npm/ → npm、pkg:pypi/ → Python、pkg:maven/ → Maven、pkg:githubactions/ → GitHub Actions)。
エコシステムが Go でない 場合は、進行前にこの通知をユーザーに表示してください:
注: このスキルの PR モードコマンドと一般的なパターンは Go に最適化されています。Issue モードと IBNC 安全性チェックはすべての言語で機能しますが、エコシステム固有の PR モードガイダンス (検証コマンド、エッジケース、ロックファイルの処理) はまだ {ecosystem} 向けに開発中です。この削除中に問題や改善点を発見した場合は、future-architect/uzomuzo-oss の issue または PR を通じて貢献してください。
その後、フロー全体を続行してください — 分析、IBNC チェック、および Issue テンプレートは言語に依存しません。
GitHub Actions 検出
対象の PURL が pkg:githubactions/ で始まる、または GitHub Action 名 (owner/action) の場合:
- 使用を検索:
grep -rn "{action-name}" .github/workflows/ --include="*.yml" --include="*.yaml" - 影響を評価: 影響を受けるワークフローファイルとジョブの数をカウントします。リリース重要なパイプラインが関わっているかどうかに注意してください。
- 置き換えを検索: 公式の置き換え、保守されているフォーク、または第一者の代替案が存在するかを確認します (例:
tibdex/github-app-token→actions/create-github-app-token)。 - ピン戦略: 置き換えはバージョンコメント付き SHA ピンを使用する必要があります (例:
uses: actions/checkout@<sha> # v4.2.0)。
フロー全体の残り (重複チェック、Issue テンプレート等) は同じように進行します。使用内訳表では、ソースファイルの代わりにワークフローファイルを記載します。
Phase 1: 事前チェック
コードを書く前に、これらのチェックを実行してください:
1. 実際に消えるのか?
uzomuzo diet 出力の STAYS カラム (または JSON の stays_as_indirect) を確認します:
- STAYS =
-→ この依存関係を削除すると、依存関係ツリーから完全に削除されます。進めてください。 - STAYS =
yes→ 別の直接依存がこれを推移的に依存しています。削除後は間接依存として残ります。それでも価値があります (バージョン管理の委譲、将来の削除準備)、ただし期待値を設定してください: go.sum / ロックファイルには残ります。
詳細出力では、IndirectVia フィールドがそれを推移的に引き込む直接依存を正確に示します。これらは Phase 5 (Upstream Diet) のアップストリームターゲットです。
diet 出力が利用できない場合、手動で検証できます:
# Go
go mod why -m $ARGUMENTS
# npm
npm ls $ARGUMENTS
# pip
pip show $ARGUMENTS | grep "Required-by"
2. 置き換えは何か?
置き換え戦略を決定します。優先順位順に:
| 戦略 | 使用時機 | 例 |
|---|---|---|
| 削除 | 未使用 (0 インポート) | go.mod/package.json から削除、tidy を実行 |
| 標準ライブラリ | stdlib 相当がある | go-homedir → os.UserHomeDir() |
| 統合 | 別の依存が既にこれを行っている | 2 つの JSON ライブラリ → 1 つを保持 |
| 自己実装 | 小さく、非暗号、よく定義された API | lfshook → 20 行の logrus.Hook 実装 |
| サブモジュール分離 | 1 つのサブコマンド/ツールでのみ使用 | gosnmp → contrib/snmp2cpe/go.mod |
| フレームワーク剥離 | 依存がフルに必要としないフレームワーク経由で来る | Trivy fanal → 直接パーサー呼び出し |
決して自己実装しないでください: 暗号化、TLS、プロトコルネゴシエーション、認証トークン処理、または微妙なバグがセキュリティ脆弱性を生み出す何か。
3. 隠れた複雑さがないか?
開始前にこれらを確認してください:
-
API リークage: この依存関係の型はエクスポートされた識別子に表示されますか? はいの場合、削除は破壊的な変更です — メジャーバージョンバンプまたは非推奨期間が必要です。
# Go: 依存関係の型を使用するエクスポートされた識別子を検索 grep -rn "func.*$ARGUMENTS\|type.*$ARGUMENTS" --include="*.go" | grep -v _test.go | grep "^[A-Z]" -
ビルドタグ: インポートがビルドタグの背後にありますか? (例:
//go:build jsoniter) はいの場合、依存関係はデフォルトビルドに影響しないかもしれません — タグ付けられたファイルを削除することを検討してください。 -
生成されたコード:
// Code generatedヘッダを持つファイルは置き換えツールでジェネレーターを再実行することで簡単に移行できます。 -
ブランク / 副作用インポート: 以下のステップ 4 の IBNC チェックリストを参照してください。
4. IBNC 安全性チェック (インポートしているがコール していないパターン)
依存関係が 0 コールサイトを示しているが >0 個のインポートファイルがある場合、それでも必要な場合があります。以下でないことを確認してください:
- 副作用インポート (
import _ "pkg"、import 'pkg'、割り当てなしのrequire('pkg')) - データベース / ドライバー登録 (ブランクインポートまたは条件付き
require()) - 設定駆動プラグイン (eslint、tailwind、babel、postcss — config ファイルで参照、インポートではない)
- フレームワーク DI / デコレーター (
@Entity、@Autowired、extends Framework、Ember DI) - 注釈のみの使用 (Java:
@NotNull、@JsonProperty— 注釈 が 使用です) - 型のみ / 定数のみパッケージ (型または定数のためにインポート、ゼロの関数呼び出し)
- 委譲されたコンポジション (SDK ラッパーまたはフレームワークコンテキストオブジェクトを通じて間接的に呼び出される)
いずれかが当てはまる場合、コールサイト分析が 0 コール を示している場合でも、依存関係は削除するには 安全ではありません。79 以上の OSS プロジェクトからの証拠を含む完全なパターン分類については、docs/ibnc-patterns.md を参照してください。
5. SBOM ツール認識
どの SBOM ツール (trivy/syft/cdxgen) とバージョンが依存関係データを生成したかをメモしてください。ツール選択は同じプロジェクトの依存関係数に 10-20 倍の分散を生じることができ、表示される依存関係と結合スコアに影響を与えます。依存関係数が予期外に低い場合は、別のツールで相互確認してください。
Issue モード (デフォルト): GitHub Issue をファイル
Step 0: 重複チェック (必須)
何かをファイルする前に、既存の Issue と議論を検索してください。GitHub 検索は単語レベルで字句解析されます — セマンティックではありません — そのため 複数のフレーズで複数のクエリを実行 して偽陰性を減らしてください:
# パッケージ名で検索 (完全一致)
gh search issues "{dependency}" --repo {owner/repo} --limit 10
# 置き換えパッケージ名で検索
gh search issues "{replacement}" --repo {owner/repo} --limit 10
# 変更を説明するキーワードで検索
gh search issues "replace deprecated {short-name}" --repo {owner/repo} --limit 10
# ディスカッションを検索 (同じクエリ)
gh api graphql -f query='{ search(query: "repo:{owner/repo} {dependency} type:discussion", type: DISCUSSION, first: 10) { nodes { ... on Discussion { title url } } } }'
@vercel/kv の例:
gh search issues "@vercel/kv" --repo vercel/next.js --limit 10
gh search issues "@upstash/redis" --repo vercel/next.js --limit 10
gh search issues "replace deprecated kv" --repo vercel/next.js --limit 10
事後フィルター: GitHub ファジー検索は偽陽性を返すことができます。各ヒットが実際に同じ依存関係削除についてであることを確認してください — 単なる通過の言及ではなく。
マッチする Issue/ディスカッションが既に存在する場合、重複をファイルしないでください。代わりに、新しい分析 (例: diet からの影響データ) でコメントを追加して停止してください。
Step 1: Issue またはディスカッションをファイル
Phase 1 を完了した後、実装の代わりに Issue をファイル してください。これがデフォルトである理由は:
- 外部の貢献者は CI を実行またはロックファイルを再生成できません
- メンテナーは変更を評価するためにコンテキストが必要です
- 大規模なモノレポはプロジェクト固有のビルド/テスト要件を持ちます
Issue テンプレート
次の構造で gh issue create を使用してください:
Title: dep: replace EOL {dependency} with {replacement}
Body:
## Problem
`{dependency}` は {lifecycle status} です。
{このことが重要な理由についての 1-2 文 — セキュリティリスク、パッチなし等}
## Impact analysis
- **Detected by**: [uzomuzo diet](https://github.com/future-architect/uzomuzo-oss) with {sbom-tool} {version}
- **Files**: {N} files import this dependency
- **Call sites**: {N} calls across {N} APIs
- **Exclusive transitive deps**: {N} (removed together)
- **Stays as indirect**: {yes/no}
- **Difficulty**: {trivial/easy/moderate/hard}
### Usage breakdown
| File | Usage | Category |
|------|-------|----------|
{ファイルと使用方法のテーブル}
## Proposed replacement
{replacement} — {これが正しい代替である理由}
### API mapping
| Current | Replacement |
|---------|-------------|
{API レベルの移行テーブル}
### Environment variable changes
{必要な環境変数の名前変更、または "None"}
## False-positive risk
{依存関係が IBNC パターン (副作用インポート、設定駆動プラグイン、フレームワーク DI 等) に一致する場合、ここに注記してください。当てはまるものがない場合は、"None — all usage is via direct function calls." と書いてください}
## Cross-project context
{同じ依存関係が他の主要な OSS プロジェクトで EOL/アーカイブされていることが知られている場合、ここに注記してください。例: "mitchellh/go-homedir is archived and also affects Trivy, Terraform, Vault, and MinIO." 相互プロジェクトデータが利用できない場合は、"No cross-project data available." と書いてください}
## Notes
- {Phase 1 ステップ 3 からの隠れた複雑さ}
- {API リークage? ビルドタグ? 生成されたコード?}
正しいチャネルを選択
ファイルする前に、対象リポジトリの Issue テンプレートを確認してください:
ls <repo>/.github/ISSUE_TEMPLATE/を実行するか、config.ymlでblank_issues_enabledを確認してくださいblank_issues_enabled: falseで bug/docs テンプレートのみが存在する場合、プロジェクトはおそらく提案に Discussions を使用しています。代わりにIdeasカテゴリでファイルしてください:# Issue が特定のテンプレートを必要とする場合は GitHub Discussions を使用 gh api graphql -f query='mutation { createDiscussion(input: { repositoryId: "...", categoryId: "...", title: "...", body: "..." }) { discussion { url } } }'- ブランク Issue が有効化されている、または "feature request" テンプレートが存在する場合は、
gh issue createを使用してください
ファイル後
実装に進まないでください。Issue/ディスカッションが納品物です。
フォローアップガイダンス:
- メンテナーの応答がない場合 2 週間後、丁寧なピングコメントを追加してください。
- メンテナーが "PR welcome" で応答した場合、
--prを指定して再実行して実装できます (ただし最初に CI をローカルで再現できるかを確認してください)。 - 同じ依存関係が 複数のプロジェクト にわたって EOL の場合 (例: mitchellh/* パッケージ)、各本文の Issue を相互参照してメンテナーがエコシステム全体のパターンを見るようにしてください。
- 依存関係が 個別の削除ではなく構造的な改革 の恩恵を受ける場合 (例: 多くの EOL 依存を引き込むフレームワーク)、Notes セクションでこれを言及してください — 自分で実装できなくても、その洞察は価値があります。
--pr が指定された場合、このセクションをスキップして以下の Phase 1.5 に続行してください。
PR モード (--pr): 直接実装
以下の Phase は PR モードにのみ適用されます。プロジェクトを所有している場合、これを使用してください。
Phase 1.5: テストカバレッジチェック — anything を触る前に
置き換えコードを書く前に、この依存関係を使用するコードにテストがあるかを確認してください。
# 依存関係をインポートするすべてのファイルを検索 (プロダクションコードのみ)
grep -rn "$ARGUMENTS" --include="*.go" -l | grep -v _test.go
# 各ファイルについて、対応するテストファイルが存在するかを確認
# 例: reporter/email.go → reporter/email_test.go
テストが存在する場合: 進めるのは安全です
既存のテストが期待される動作を定義します。置き換え後、実行してください — 合格した場合、置き換えは正しいです。
テストが存在しない場合: 何かを変更する前に、まずテストを作成してください
これはプロセス全体で最も重要なステップです。 置き換える前に、現在の (動作する) 実装に対してテストを作成してください。 これにより、置き換えの動作の違いをキャッチするセーフティネットが得られます。
- 契約を識別: このコードはこの依存関係で何をしますか? 入出力は何ですか?
- 現在の動作をキャプチャするテストを作成:
- 通常のケース (ハッピーパス)
- 依存関係の動作に固有のエッジケース (例: nil をどう処理するか? 空入力は? unicode は?)
- エラーケース (依存関係がエラーを返すときはどうなるか?)
- 現在のコードに対してテストを実行 — 何かを変更する前に成功する必要があります
- その後 Phase 2 に進んでください
後ではなく前である理由は? 置き換え後にテストを作成した場合、新しいコードが するべき ことをテストしているだけです — 古いコードが 実際に した것ではありません。動作の違いはすり抜けます。
実例: c-robinson/iplib は IPv4 /31 と /32 CIDR プリフィックスを net/netip とは異なり処理しました。置き換え後にテストが作成された場合、エッジケースは見落とされていたはずです。なぜなら、テストは新しい (間違った) 動作に一致していたからです。
フレームワーク剥離の場合: 回帰テストハーネスを構築
高インパクト削除 (フレームワーク置き換え、パーサー書き直し) の場合、ユニットテストでは不十分です。比較ハーネスを構築します:
# Before と after のバイナリを構築
git stash && go build -o /tmp/before ./cmd/... && git stash pop
go build -o /tmp/after ./cmd/...
# 両方を実世界の入力に対して実行し、出力を比較
/tmp/before < input.json > /tmp/out-before.json
/tmp/after < input.json > /tmp/out-after.json
diff /tmp/out-before.json /tmp/out-after.json
vuls fanal フレームワーク削除はこのアプローチを使用しました: 17 の実 OSS ロックファイル、7,198 ライブラリを比較 — 1 つの正当な違い (pnpm バグ修正) が見つかりました。
Phase 2: 実装
Step 1: 置き換えを作成
Phase 1 の戦略に基づいて:
stdlib 置き換えの場合:
- すべてのインポートサイトを検索:
grep -rn "$ARGUMENTS" --include="*.go" | grep -v _test.go - 各サイトについて、API 呼び出しを stdlib 相当物に置き換え
- インポートを更新
- 置き換え API のエラー処理または戻り値の型が異なる場合、呼び出しサイトを適応させます
自己実装の場合:
- それを使用するのと同じパッケージに置き換えを書く (単一の使用サイトの共有ユーティリティを作成しないでください)
- 最小限に保つ — 完全なライブラリではなく、実際に使用する API サーフェスのみと一致します
- 元のライブラリと同じ動作をカバーするテストを作成します
サブモジュール分離の場合:
contrib/<tool>/go.modを独自のモジュールパスで作成- 関連するコードを
contrib/<tool>/の下に移動 - ルートモジュールへのインポートを監視 (特に
version.go、configパッケージ) - 必要に応じて
go.workを追加 (ローカル開発用)
フレームワーク剥離の場合:
- フレームワークを通じて実際に呼び出す特定の関数を識別
- フレームワークの登録/発見層をバイパスして、それらを直接呼び出す
- これは最も高い努力の戦略ですが、最も高い報酬を持ちます
- 開始する前に包括的な回帰テストを構築します (ゴールデンファイル、A/B 比較)
Step 2: エッジケースを処理
実際の依存関係削除から学んだ教訓:
-
機械的な置き換えは完全に機械的ではありません。
xerrors→fmt.Errorfは sed ジョブのように見えましたが、788 の呼び出しサイトの 10 にはエッジケースがありました:[]errorが%wに渡される (needserrors.Join)- 非エラー型が
%wに渡される (needs%v) - 古いライブラリの緩い型チェックで隠されていた既存バグ
-
stdlib 相当物の動作の違いを確認:
net/smtpは凍結していますが非推奨ではありません — 使用しても安全です- IPv4 ネットワーク/ブロードキャストアドレスの処理はライブラリ間で異なります
tls.Dial+smtp.NewClientはライブラリのDialTLSと同じではありません
-
Linter ルールが変わる可能性があります:
xerrors.Newからerrors.Newに切り替えると、古いライブラリが免除されていたエラーメッセージ大文字化についてのreviveルールをトリガーする場合があります。
Step 3: 依存関係マニフェストを更新
Go の場合:
# 直接依存を削除
go mod edit -droprequire $ARGUMENTS
go mod tidy
npm の場合: package.json から削除、npm install または相当物を実行します。
Python の場合: requirements.txt / pyproject.toml から削除、pip install を実行します。
Maven の場合: pom.xml から削除します。
モノレポ警告: ワークスペース管理ロックファイル (pnpm、yarn workspaces、Gradle マルチモジュール) を使用するモノレポでは、ロックファイルはモノレポ環境で再生成する必要があります。パッケージマネージャーをローカルで実行できない場合は、PR モード の代わりに Issue モードを使用してください — next.js の @vercel/kv 削除は、pnpm-lock.yaml が再生成されなかったため CI 完全に失敗しました。
Phase 3: 検証
3 つすべてが合格する必要があります。例外はありません。
# 1. ビルド
go build ./...
# 2. スタティック分析
go vet ./...
# 3. テスト
go test ./... -count=1
Go 以外のプロジェクトの場合、同等のビルド + lint + テストパイプラインを実行してください。
高インパクト削除の場合の追加検証:
-
go.sum 削減を確認:
wc -l go.sum # before と比較go.sum が縮小しなかった場合、依存関係は間接的に残ります。
-
バイナリサイズを確認 (コンパイル言語の場合):
go build -o /tmp/binary-after ./cmd/... ls -la /tmp/binary-after -
フレームワーク剥離の場合: A/B 比較 古いバージョンと新しいバージョンの両方を構築し、実世界の入力に対して実行し、出力を比較します。 これはユニットテストが見逃す微妙な動作の変更をキャッチします。
Phase 4: コミット
明確なメトリクスとフォーカスしたコミットを作成してください:
fix: remove {dependency} — replace with {replacement}
{何をした、そしてなぜか}
Before: {N} direct deps, go.sum {N} lines
After: {N} direct deps, go.sum {N} lines
Binary: {size before} → {size after} ({reduction}%)
Phase 5: Upstream Diet — 依存関係が間接的に残る場合
uzomuzo diet がSTAYS = yes を示した場合 (またはこの依存関係が削除後に go.sum / ロックファイルに残っていることが見えた場合)、それは間接依存として残ります。
diet 詳細出力の IndirectVia フィールドは、それを推移的に引き込む直接依存を正確に既に教えています。これを使用してアップストリーム削除を計画します。
アップストリームはあなたの管理下にありますか?
アップストリームが組織のリポジトリの場合 (例: 会社の他の OSS プロジェクト):
- 同じ削除 PR をそのアップストリームリポに提出
- マージおよびタグ付けされるのを待機
go.modを新しいバージョンに更新: `
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- future-architect
- ライセンス
- Apache-2.0
- 最終更新
- 2026/5/11
Source: https://github.com/future-architect/uzomuzo-oss / ライセンス: Apache-2.0