code-humanizer について
code-humanizer は、AI 生成コードの構造上の問題を検出・整理し、実装時にその発生を防ぐ Skill です。テストスイートで動作の維持を確認し、既存コードの整理前に問題を報告します。
主な機能
- 01コードの構造上の問題を検出
- 02パターンを分類し重大度を評価
- 03既存コードの整理前に報告
- 04テストで動作維持を確認
- 05実装中の問題発生を予防
活用シーン
- 01リポジトリや変更内の重複を確認
- 02保守担当者の承認後に特定パターンを整理
- 03実装時に不要な抽象化や防御コードを避ける
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ leonardnju/ code-humanizer --skill code-humanizerインストール後、Claude Code で/code-humanizerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.zh.md.gitignoreLICENSEREADME.md詳細
Code Humanizer
リポジトリから AI 生成コードの兆候を取り除くか、Guard モードを使って現在の変更に同じパターンが入り込まないようにします。文章のヒューマナイザーは、AI による 文章作成 のパターンを取り除きます。これは AI による コーディング のパターン、つまり「テストが通る」ことを最適化し、「コードベースの健全性を保つ」ことをおろそかにするエージェントが残す構造上の負債に対処します。
基本原則: AI が書いた粗雑なコードとは、見た目が悪いコードではありません。動作はするものの、すでにあるものを再実装し、誰も求めていない抽象化を追加し、表面化させるべきエラーを握りつぶし、起こり得ない状況に備えることで、リポジトリを劣化させるコードです。文章とは異なり、コードには判定基準があります。何が「意味を保持する」変更かは、テストスイートで判断します。常にテストを実行してください。
厳守するルール
ルール 1~4 は、モード A/B における既存コードのクリーンアップに適用されます。Guard モードでは、実装後に行うクリーンアップに適用されます。要求された機能そのものには適用されません。ルール 5 はすべてのモードに適用されます。
- 動作の保持は絶対です。 動作を変える「クリーンアップ」は、善意から生じたバグです。これには エラーの型と発生するタイミング も含まれます。誤って発生していた
AttributeErrorを「より適切な」ValueErrorに置き換えると、それを捕捉するすべての呼び出し元にとって動作が変わります。潜在的なバグや、見苦しくても重要な動作を見つけた場合は、レポートで指摘してください。クリーンアップの一環として黙って修正してはいけません。 - テストがなければ、クリーンアップの編集はしません。 まずテストスイートを実行してください。テストスイートが存在しない、テストが通らない、またはクリーンアップ対象の既存コードをカバーしていない場合、負債を報告することのみできます(モード A)。まず特性テストを書くことを提案してください。これは、テストが不完全なプロジェクトで要求された変更を実装することを禁じるものではありません。検証上の不足は報告してください。
- 既存コードを書き換える前に報告します。 デフォルトはモード A(調査 → 報告)です。メンテナーが承認した場合、または修正を明示的に求めている場合にのみ、モード B(修正)に移行してください。Guard モードでは、現在の変更で導入された粗雑なコードを直接回避または削除できます。
- クリーンアップのコミットごとに、パターンクラスは 1 つだけにします。 既存の粗雑なコードを削除する各コミットでは、1 種類のパターンのみを扱い、全テストスイートに合格する必要があります。テストが失敗したらそのコミットを取り消してください。無関係なコードを「前向きに修正」してはいけません。Guard モードでの通常の機能コミットでは、予防と実装が切り離せない場合、パターンごとに分割する必要はありません。
- 重複だと判断する前に検索します。 調査または実装を始める前に、リポジトリに既存のヘルパーがあるかを把握してください(
utils、helpers、common、バリデーター、既存の基底クラスを grep します)。既存のものを把握していなければ、再実装を見抜くことはできません。
パターン一覧
指摘ごとの重大度:0 該当なし · 1 存在するが正当な理由がある(→ 対象外とし、変更しない) · 2 軽微な負債 · 3 明らかな負債で、将来の保守コストを増大させる · 4 深刻で、意味またはアーキテクチャ上の境界を損なう
Tier 1 — 重複と再発明
1. 既存のヘルパーの再実装 (AI らしさを示す典型的な兆候)
兆候: 本体が utils/helpers/同階層のモジュール内のコードに似ている新しいプライベート関数、リポジトリですでに実装済みの正規表現/検証/解析/書式設定の処理ブロック、所属するパッケージから何もインポートしていない新しいコード。
問題: エージェントはリポジトリの内側からではなく、プロンプトから外側に向けてコードを書きます。重複するたびに、将来の修正が別々に分岐していきます。
# Before — repo already has utils.validate_email
def _is_valid_email(s):
pattern = r"^[\w.+-]+@[\w-]+\.[\w.]+$"
if re.match(pattern, s):
return True
return False
# After
from .utils import validate_email
2. _v2/_new/_impl のクローン
兆候: foo と foo_v2 がどちらも残っている、enhanced_、improved_、new_ という接頭辞、分岐を 1 つだけ変えたコピー&ペーストの本体。
問題: エージェントは元のコードを変更する勇気がなく、その結果、信頼できる情報源が 2 つになりました。文書化された移行が進行中でない限り、パラメーターまたは新しい方の本体に統合し、名前は 1 つだけ残してください。
3. 標準ライブラリ/インストール済み依存関係の再発明
兆候: 独自に実装した groupby、JSON を経由したディープコピー、手動での URL 解析、独自の日付計算。標準ライブラリまたはすでにインストール済みの依存関係に同等の機能があります。
Tier 2 — 推測的なアーキテクチャ
4. 単一実装の抽象化
兆候: ABC/インターフェース/Protocol に具象クラスがちょうど1つだけある、登録が1件だけのレジストリやファクトリー、呼び出し箇所が1つだけの「プラグ可能なバックエンド」。
問題: 求められてもいない将来に備えた柔軟性です。インライン化しましょう。抽象化は、2つ目の実装が登場したときに戻せばよいのです。
# Before: AbstractReportBackend + BackendRegistry + TextReportBackend (3 classes, 40 lines)
# After:
_BACKENDS = {"text": lambda rows: "\n".join(map(str, rows))}
5. 「将来のため」の不要なコード
兆候: 呼び出し箇所のないヘルパー、呼び出し元が値を渡さないパラメーター、「拡張性のために用意された」export_*/*_to_dict、柔軟、拡張可能、シームレスと記された docstring。
問題: 到達不能なコードでも、レビューの手間や grep の検索結果、誤った安心感を生みます。削除しましょう。git が記録を残しています。まずリポジトリ全体(スクリプトやテンプレートも含む)で使用箇所を grep してください。
6. 何も付け加えないラッパー
兆候: 本体が同じ引数を使った単一の呼び出しだけで構成される関数、すべてを super() に委譲するだけのサブクラス。
7. ローカルな用途に対する設定/API の乱立 兆候: 参照箇所がちょうど1か所だけの新しいグローバルフラグ、設定フィールド、CLI 引数、パブリックパラメーター、読み取る関数が1つだけのモジュールレベル定数。 問題: グローバルな設定項目を増やすたびに、状態空間が際限なく広がります。ローカル変数にするか、必要とする1つの関数のパラメーターにしましょう。
Tier 3 — 過剰な防御コード
8. 広範な例外の握りつぶし
兆候: デフォルト値を返す、何も記録しない、または pass する except Exception:/裸の except、バグを誤った出力に気づかれないまま変えてしまう .get() の連鎖。
問題: クラッシュ(目に見えてデバッグ可能)を破損(見えない状態)に変えてしまいます。実際に発生しうる例外だけに絞るか、そのまま例外を発生させましょう。注意してください。これは動作に関わる変更のため、メンテナーの承認が必要な場合があります(鉄則1)。
9. 正当な理由のない import のフォールバック
兆候: ベンチマークも、パッケージメタデータへの extras エントリーも、フォールバック経路を対象とするテストもない try: import fast_x except ImportError: import x、任意ではない依存関係に対するオプション依存関係の回避策。
問題: コードパスが2つあるのに、テストされているのは1つだけです。その依存関係が重要なら宣言し、そうでなければ削除しましょう。
10. 属性を探り続ける連鎖
兆候: 「dict かオブジェクトか、あるいは None かもしれない」に対応するための hasattr/getattr/isinstance の連鎖、フィールドにアクセスするたびにコピーされた同じ探索式。
問題: エージェントが実際にここを通る型を確認せず、何でも受け入れてしまっています。実際の型を特定して(テストが教えてくれます)、それに合わせて記述しましょう。
11. 根拠のない過剰な再検証
兆候: 直前に構築した値への if x is not None、型システムや上流のゲートですでに保証されている不変条件の再確認。
Tier 4 — ノイズ
12. 内容を語り直すコメント
兆候: 次の行を言い換えるコメント(# Join the rows with newlines)、レビュアーに向けたコメント(# This change ensures correctness)、エージェントが書き、同じ PR で解決した TODO。
ルール: コメントが一行分の価値を持つのは、コードだけでは表現できないこと(制約、不変条件、なぜ自明な方法を使わないのか)を述べる場合だけです。
13. 定型文の docstring
兆候: 関数名をスペースで区切っただけの docstring(def get_user(): """Get the user.""")、宣伝文句の形容詞(堅牢、包括的、シームレス)。
14. 不要な import、未使用変数、装飾的なバナー
兆候: 削除した試行の名残で残っている import、# ===== SECTION ===== のバナー、識別子やログ行の絵文字、残存した print/デバッグログ。
Tier 5 — テストの粗雑さ(デフォルトでは報告のみ)
15. モックを検証するだけのテスト — すべての協力オブジェクトがモック化され、アサーションではモックが呼び出されたことだけを確認するため、実際の理由で失敗することがありません。 16. 些細なアサーションや重複したアサーション — リテラルを検証する、またはカバレッジを水増しするために同じケースを3つの名前で再テストする。
指摘しないもの(誤検知を防ぐための注意点)
重大度1=正当化できる状態です。問題なのはパターンの形ではなく、正当化がないことです。指摘する前に、正当な理由があるか確認してください。
- 理由のあるフォールバック/互換性用シム — 文書化されたプラットフォーム間の差異、追加機能のパッケージ化(
pip install pkg[fast])、移行中のバージョンゲートなどです。問題なのはフォールバックではなく、正当化されていないことです。 - 信頼境界での防御コード — ユーザー入力、ネットワークペイロード、プラグインから渡されたオブジェクトの解析などです。データが信頼できない箇所では、検査や広範な例外捕捉は正当です(ただし、
passではなくログを記録してください)。 - 実際のプラグインシステムにおけるレジストリ/ABC — エントリーポイントが実装を動的に読み込むのであれば、リポジトリ内の実装が1つだけでも、実装が1種類だけとは限りません。
- 測定に基づく理由のある重複 — ベンチマークについてのコメントを伴うホットパスのコピーや、意図的に同期を保っているベンダーコードなどです。
- 文書化された移行中の
_v2— マージする前に、Git の履歴や CHANGELOG を確認してください。 - ログ記録とコメントを伴うエラーの握りつぶし — 意図的な回復性の判断を見直すのはメンテナーの役目であり、あなたではありません。
- 単に好みではないスタイル。 このスキルが解消するのは構造的な負債であり、書式の好みではありません。書式はリンターの役目です。
迷った場合は、重大度1~2で報告し、修正はしないでください。まとまりに注目してください。説明コメントが1つあるだけなら何でもありませんが、説明コメントに、単一実装のレジストリ、_v2、未使用のエクスポートが同じPR内でそろっているなら、白状したも同然です。
ワークフロー
モード A — スキャン(デフォルト):
- **Oracle チェック:**テストスイートを実行し、合格状況と対象ファイルのおおよそのカバレッジを記録します。
- **インデックス作成:**リポジトリに既存のヘルパー/抽象化をマッピングします(これがパターン 1 の基盤になります)。
- **スキャン:**カタログに照らして対象(差分、PR、モジュール、またはリポジトリ全体)を確認します。各指摘について、
パターン番号 · ファイル:行 · 重大度 · 根拠(1 行) · 提案する修正 · 動作リスク(なし/エラー型/メンテナーの判断が必要)を記録します。 - **報告:**指摘をパターンごとにまとめ、ファイルごとの重大度の合計を示し、免除事項とその正当な理由を列挙します。最後に、提案する修正順序(重大度が高く、動作リスクが低いものから)を示します。
モード B — 修正(承認後):
5. 承認された順序で、パターン分類ごとにすべての該当箇所を修正 → フルテストスイートを実行 → コミット(deslop: <pattern> (#N) — <n> instances)します。テストが失敗した場合は、コミットを取り消します。
6. 動作リスクを伴うもの(エラー型、握りつぶされた例外、不明なキーの経路)は、明確にラベル付けした個別のコミットとして提案するか、報告項目として残します。安全な整理と決して混在させません。
7. **監査パス:**結果を再スキャンし、「AI が書いたとレビュー担当者に思わせるものがまだ残っているとしたら、何だろう?」と問いかけます。残りを修正するか、報告します。
8. **要約:**パターンごとの削除件数、LOC の差分、適用した免除、メンテナーの判断待ちとなっている動作リスク項目を示します。
モード C — ガード(実装中):
ユーザーが変更の実装中に AI コーディングの粗雑さを防ぐよう求めた場合は、ガードモードに入ります。これは一般的なコーディング手法ではなく、薄い予防レイヤーです。同じカタログを、現在のタスクにおける実装上の判断と、その結果生じる差分に適用します。ユーザーから求められない限り、リポジトリ全体の整理に広げないでください。
コーディング前 — リポジトリを起点に調べます:
- 新しく作る前に、既存のヘルパー、ユーティリティ、類似の実装、基底クラス、バリデーター、インストール済みの依存関係を検索します。
- 変更対象の経路における実際の型、不変条件、エラー時の動作を追跡します。不明点を補うために、探索的な連鎖や広範なフォールバックを追加しないでください。
- 対象範囲を特定します。探索的なコード、内部モジュール、または安定した/公開された境界のいずれかを見極めます。形を判断する前に、文書化された移行、互換性要件、実際のプラグイン読み込みを確認します。
コーディング中 — 5 つの判断ルールを適用します:
- 再作成する前に再利用する(パターン 1〜3):リポジトリがすでに所有するものを拡張するか呼び出します。ヘルパーや標準ライブラリの動作を分岐させないでください。
- 抽象化より具体化を優先する(パターン 4〜7):ローカルなニーズはローカルに保ちます。実際に 2 つ目の実装が現れるまでは、抽象化、レジストリ、グローバルな設定項目、公開 API を追加しません。
- 防御する前に把握する(パターン 8〜11):実際の契約に基づいて実装します。防御的な柔軟性が必要なのは実際の信頼境界であり、型を調べていない場所ならどこでも必要というわけではありません。
- 内容ではなく理由を説明する(パターン 12〜14):コメントには制約や自明でない理由を記録します。説明の羅列、定型文、実装の残骸は削除します。
- 足場ではなく動作をテストする(パターン 15〜16):モックが呼び出されたことだけでなく、外部から意味のある動作と失敗ケースを検証します。
コーディング後 — 差分を監査し、リポジトリにインデックスを作成します:
- 関連するテストを実行し、現在の差分だけをカタログに照らして確認します。重複のチェックでは、引き続きリポジトリ全体を検索します。
- 現在の変更で生じた安全な粗雑さを修正します。無関係な既存の指摘を機会に乗じてリファクタリングせず、別途報告します。
- 正当な免除事項を簡潔に記録します。重要な負債または動作リスクが残る場合に限り、指摘をすべて含む表にします。
- 最後に、簡潔なガード監査を記載します。例:既存のヘルパーを再利用、新たに推測的な API を追加せず、探索的な免除が 1 件、テスト合格。
探索は本番環境の負債ではありません
探索では、一時的なコードの重複、ハードコードされた値、並行するバリエーション、粗削りなスクリプトが正当化される場合があります。特に experiments/、scratch/、notebooks/、prototypes/ ではその傾向があります。範囲内に収まり、意図的なものであれば、深刻度 1 として扱ってください。コードがコアパッケージ、安定した API、共有モジュール、またはマージ可能な状態のパスに移ると、この例外は適用されなくなります。Guard モードでは発見の余地を残し、ハードニングの段階で一時的な分岐を統合し、通常のカタログを適用します。
スコープ設定: PR/差分を対象にする場合は変更されたファイルのみをスキャンしますが、重複についてはリポジトリ全体を確認してください。リポジトリ全体を対象にする場合は、モジュールごとに進めてください。順序を提案し、メンテナーに取捨選択してもらいます。Guard モードでは、より広範なクリーンアップを依頼されていない限り、編集と後処理の対象を現在のタスクの差分に限定してください。
よくある間違い(実際に見られるもの)
| 間違い | 実情 |
|---|---|
| 「このエラー型は明らかに意図しないものだから、改善しよう」 | これは動作の変更です。呼び出し元は特定の例外を捕捉しています。報告してください。 |
| スクリプト/テンプレート/リフレクションで使われている「未使用」のヘルパーを削除する | パターン 5 の削除を行う前に、コード以外のファイルも含めてすべて grep してください。 |
| 9 つのパターンを直す巨大なコミットを 1 つ作る | レビューも取り消しも困難になります。1 つのパターンクラスにつき 1 コミットにしてください。 |
| テストスイートを一度も実行せずに修正する | 「自分が壊した」のか「もともと壊れていた」のか判断できません。まず基準を確認してください。 |
| 信頼境界で動作している防御的なコードを書き換える | 信頼できない入力は、用心深くしてよい唯一の領域です。 |
| カタログを、項目を最大限チェックするためのリストとして扱う | 目標はリポジトリを健全にすることであり、検出件数を増やすことではありません。深刻度 1 の指摘はそのまま残してください。 |