Linter導入の挫折を救う「天井凍結」の思想
既存のプロジェクトにLinterを導入しようとして、数千件のエラーに直面し、結局「warn」に逃げるか、PRをリバートした経験は、多くのエンジニアにとって深夜の障害対応並みに苦々しい記憶だろう。厳格なルールを適用した瞬間に画面を埋め尽くす真っ赤なエラー。これをすべて手作業で修正するのは、まさにデッドロックに陥ったスレッドを1つずつ手動で解決するような不毛な作業だ。結局、ルールを緩めるか、導入自体を諦める。そして、コードベースは静かに、しかし確実にスパゲッティ化していく。
私はこの「Linter導入の挫折」を何度も目撃してきたし、自分自身も「次こそは最初から厳格に入れよう」と誓いながら、プロトタイプ開発のスピードを優先して設定を後回しにし、気づけば手遅れになるという無限ループを繰り返してきた。自分のプロジェクトだけでなく、他人のプロジェクトに参画した際にも、この「足回りがない」という課題は常に付きまとう。
この絶望的な状況を打破するのが、ever-betterが提示する「天井の凍結(freeze)」という思想だ。アプローチは極めてシンプルである。今日存在するすべての違反を「天井」として記録し、それ以降は一切怒らない。しかし、明日新しく書かれたコードに1件でも違反があれば、CIが容赦なくビルドを落とす。つまり、「古いコードは免除、新しいコードは初日から全ルール適用」という状態を瞬時に作り出すのだ。
この仕組みは、ESLint本体の –suppress-all 機能を活用している。.ever-better/state.json というファイルに、ファイルごと・ルールごとの違反数が記録され、これが「天井」として機能する。どのファイルのどのルールが何件免除されているかが明文化され、git diff にも残る。誰かが勝手に天井を上げれば一目でわかる。この「止血」こそが、技術負債の返済における最初の、そして最も重要な一歩なのだ。増え続ける負債を前にして、どれだけ直しても追いつかない。まずは増えない状態を作る、それこそがエンジニアリングの現実的な解である。
AIの暴走を防ぐ「ツールとスキル」の冷徹な境界線
AIエージェント(例えばClaude Codeなど)の進化は目覚ましいが、彼らにコードベースの品質向上を丸投げすると、高確率で「数字の作文」や「セッションをまたいだ忘却」という壁にぶつかる。AIは「品質が向上しました」とそれらしい報告をでっち上げるのが得意だが、実際に何件の違反があり、それが本当に減ったのかを自ら厳密に検証することはできない。セッションが切れれば、前回何をやったかも忘れてしまう。
ここで私が最もシニアエンジニアとして唸らされたのは、ever-betterにおける「ツール(プログラム)」と「スキル(AI)」の冷徹なまでの役割分担の設計だ。機械的に決められることはすべてコマンド(ツール)に寄せる。なぜなら、AIは判断が苦手で、数が多いものはさらに苦手だからだ。3,000件の違反から次に直すべき1件をAIに選ばせると、それらしい理由をつけて間違った選択をする。件数を数えさせれば、ほぼ確実に間違う。だからこそ、ever-betterは数える、記録する、順番を出す、合否を判定する、といった「間違えようのない部分」をすべてCLIコマンドに担わせている。
さらに面白いのは、ツールがAIエージェントの「ズル」を物理的に阻止するゲートキーパーとして機能する点だ。例えば、CIが赤くなったとき、AIにとって最も手軽な解決策は「もう一度凍結コマンドを叩いて天井を上げること」だ。しかし、npx ever-better freeze を再度実行しようとすると、ツール側が「すでに凍結されている。再凍結はそれ以降に増えた違反を免除することになり、この仕組みの存在意義を破壊する」とエラーを吐いて拒否する。CIをパスするためにルールを骨抜きにするようなAIの安易な妥協を、プログラムが冷徹に拒絶するのだ。
また、診断が100コミット以上古い場合は STALE ステータスを出し、「信じる前に取り直せ」と警告する。合否を決めるのも、差分を比較するのも、すべてコマンド側だ。AIに残されたのは、「目の前のコードをどう書き換えるか」「この違反は本当に直すべきか」という、柔軟な思考と文脈理解が必要な「スキル」の部分だけである。この噛み合わせこそが、AI時代における正しいソフトウェア設計のあり方だと私は確信する。
怪物「pm2」を24時間でTS化した驚異の実証データ
このアプローチが単なる机上の空論ではないことは、13年ものの怪物リポジトリである pm2 を用いた実証実験が証明している。pm2 は、GitHubスター数43,000を超え、Node.jsエコシステムを支え続けてきた超有名プロセスマネージャだ。2013年から動き続けているこのコードベースは、歴史の重みと技術負債が凝縮された、まさに「秘伝のタレ」のような状態だった。著者がこのリポジトリをフォークし、Claude Codeに「きれいにして」と指示を出した結果、信じがたいデータが記録された。
最初の1時間で、品質ツールが導入され、4,942件の違反が凍結され、6本のプルリクエスト(PR)がマージされた。そして24時間後には、コードを止めることなくTypeScript化まで到達したのだ。さらに驚くべきことに、この過程で、13年間誰も気づかなかった本物のバグが2件発見され、本家リポジトリにPRとしてフィードバックされた。lib/配下の .js ファイル49本を .ts に名前だけ変更した際、型エラーが2,641件発生したが、これらもAIとツールの協調によって迅速に処理されていった。
以下に、ソース記事で示された検証結果のデータをまとめる。
| プロジェクト名 | スター数 / 歴史 | 初期状態 | 実施時間 | 成果・マージPR数 |
|---|---|---|---|---|
| pm2 | ★43,254 / 13年 | JavaScript (lib/内49本) | 24時間 | 品質ツール導入、4,942件凍結、TS化、本物のバグ2件発見、PR 6本マージ |
| 既存TSプロジェクト | 非公開 | TypeScript (警告3,689件) | 4日弱 | 警告を741件に削減、PR 188本マージ、pm2と同型のバグ発見 |
別の既存TypeScriptプロジェクトでの実験でも、4日弱で188本のPRが作成され、警告数は3,689件から741件へと激減した。そして、pm2と全く同じパターンのバグがそこでも検出されたという。この圧倒的なスピード感と成果は、1日500コミットという、人間だけでは到底不可能な開発サイクルが現実のものであることを示している。ツールが足回りをガッチリと固め、AIがその上で安全に、かつ超高速でコードを書き換えていく。このデータを見て、なお「コードレビューは人間が1行ずつ行うべきだ」と主張し続けるのは、もはや牧歌的な幻想に過ぎないのではないか。
我々は「動くコード」で語っているか?
我々エンジニアは、日頃から多くの技術記事やブログを消費している。しかし、その多くは「ハーネスの作り方」や「エージェントの並列化」といった抽象論に終始していないだろうか。設定ファイルも、実際に叩いたコマンドも、エラーに遭遇した際の判断基準も書かれていない記事は、学術論文としては価値があっても、今日目の前にあるバグを直したい実務家にとっては「無いのと同じ」だ。プログラムは間違っていればエラーになるが、記事は間違って解釈しても何も起きない。うまくいかないと「自分のやり方が悪いのだろう」と読者が諦めて終わる。これほど不毛なことはない。
著者が指摘するように、具体的なコードを公開しない言い訳として「会社の機密コードだから」という言葉が使われがちだが、それは単に「切り出す手間をかけていない」だけだ。設定ファイルを整理し、モックを作成し、どのリポジトリでも動く「ツール」として公開する。このプロセスを経て初めて、技術はコミュニティの共有財産となる。ever-betterは、MITライセンス、ランタイム依存ゼロで公開されている。記事は一方通行だが、リポジトリは往復する。実際、著者はこの記事を書く過程でツール自体のバグを3件も発見し、修正している。これこそがオープンソースのダイナミズムだ。
ここで、我々自身に痛烈な問いを投げかけなければならない。「あなたのリポジトリは、明日AIエージェントが500コミットを投げ込んできても、本当に壊れないと言い切れるか?」もしその自信がないのであれば、我々が取るべき実践的な処方箋は明らかだ。まずは、ソース記事でも紹介されている debug-js/debug のような、小さくも歴史のあるリポジトリを手元にクローンし、以下の手順を実際に叩いてみることだ。
git clone –depth 1 https://github.com/debug-js/debug.git
cd debug
npx ever-better diagnose
npx ever-better bootstrap
npx prettier –write .
npx ever-better freeze
実際に手を動かし、ツールがどのように「天井」を固定し、新規コードの違反だけを冷徹に弾くのかを体感してほしい。抽象的な議論で時間を潰すのはもうやめよう。我々は、動くコードと、それを支える堅牢な足回りによってのみ、未来のソフトウェア開発をサバイブできるのだ。


コメント