hyuntae's blog

AIにコーディングを任せ始めてから② — AIが「働く」システム、検証オーナーシップを整えるまで

2026-06-29AI|閲覧数: 15
目次

AI適応記(全4部)

  1. さまざまなツールを試し、最後は自分で作るまで
  2. AIが「働く」システム — エンジニアリングと検証オーナーシップ ← 今読んでいる記事
  3. AIサーバーが落ちたら自分も馬鹿になる — ローカルLLMとAI依存
  4. AIを追いかけながら、AIとともに — 学び方まで変わった

第1部が「何を使うか」についての話だったとすれば、この記事は「どう働くか」についての話だ。正直に言うと、ツールを何度も乗り換えるあいだに本当に大きく変わったのは、ツールではなく自分の作業スタイルそのものだった。AIを使うことと、AIと働くシステムを持つことはまったく別の話だ。後者になるには、賢いモデル一つではなく、そのモデルを取り囲む記憶・検証・分離の仕組みが必要だった。

最初に変わったのは「記憶の仕方」だった

AIと働きながら最初に崩れた幻想は、「一緒に働いていれば知識は勝手に積み上がるだろう」というものだった。

3月初め、Andrej KarpathyがまとめたObsidianベースのLLMウィキ方式に触れて、自分もObsidianを導入した。その日から、すべての作業セッションをObsidianに蓄積し始めた。構造は二層になっている。

  • メモリ(要約・ポインタのみ、短く) — コンピュータで言えばRAMだ。すぐに参照できる要点だけを置く。
  • Obsidianウィキ(詳細な原本) — SSDだ。決定の根拠、デバッグの経緯、失敗の文脈といったものを長く残す。

最初は、セッションログがObsidianに溜まりさえすれば「ウィキ化」まで勝手に回ると思っていた。勘違いだった。それが自動ではないと気づいたのは6月になってからで、そのときObsidianにはrawセッションログが2,500件、ただ積み上がっているだけだった。それまでは、作業が終わるたびにウィキ化を頼んだり、AIが先に提案してくれたものだけが一部拾われていて、残りの大半はrawの山に埋もれたままだった。だから次に同じ問題にぶつかると、自分はまた最初からデバッグし直していた。

そこで6月から、ウィキ化をバックグラウンドのcronで回し始めた。溜まったセッションを一つずつ洗い、記録する価値があるものだけをウィキに拾い上げる。ただしタダではない — 溜まった2,500件を遡って処理する分、今もトークンが着実に減り続けている。

理由ははっきりしている。LLMのコンテキストは揮発性が強い。あるセッションで苦労して辿り着いた結論も、ウィンドウを閉じれば蒸発する。モデルが覚えていてくれると信じるのは思い違いで、その揮発性を外部記憶で埋め合わせることが肝だった。ウィキが正確にどんな効果を生むかは、正直まだ十分に証明できていない。ただ、きちんと整理された自分だけの記録が、AIがコンテキストを見つけてより良い判断を下すのに役立つはずだという信念で積み上げている。(このウィキは、第1部prefillスキルが参照する、まさにその知識ベースでもある。)

検証を「信頼」ではなく「手順」に

第1部で触れた「疑う習慣」は、時間が経つにつれいくつかの手順として固まっていった。AIの成果物を信じているからではなく、信じなくて済むように検証をワークフローに組み込んだということだ。

ゴールデンテストで動作の同一性を保証する

大規模なリファクタリングやポーティングで一番怖いのは、「見た目は同じように動くのに、微妙に変わってしまった」コードだ。だから手を加える前に、現在の動作を入力と出力の境界だけで固定するテストを敷いておく。内部ロジックはあえて覗かない。レガシーのリファクタリングでよく使われるゴールデンテスト(golden master test、Michael Feathersのcharacterization test系列)の手法だ。

原理は単純だ。「今のコードが出す出力」そのものを正解(golden)として固定する。その動作が正しかろうが間違っていようが、とにかく現在の動作を基準として釘を刺す。内部実装ではなく入出力だけを検証するので、リファクタリングで中身を丸ごと作り替えても、このテストは壊れない。

AIと一緒に使うとき、この網が真価を発揮する。リファクタリング前に一度通しておき(GREEN)、AIがコードを移したり書き直したりした後も依然としてGREENなら入出力が同じ — つまり動作が保たれているということになる。AIがもっともらしく書き換えたコードが実は動作を変えてしまっていたケースを、まさにこの段階で捕まえる。

デプロイ前にはAIを「攻撃者」に回す

本番に出す直前、自分はAIに役割を変えさせる。「このコードを壊してみろ。どこが間違っているのか見つけ出せ」。作るときのAIと壊すときのAIを分けるわけだ。この敵対的な事前レビューが効くのは、デフォルトを「疑い」に設定しているからだ。コードを擁護しようとする慣性の代わりに、反証しようとする慣性で読むと、テストは通るのに意味が逆転しているようなバグがあぶり出される。実際にこの段階で、boolean一つの意味がまったく逆になっていた欠陥を捕まえたことがある。値はちゃんと入っていてテストも青信号なのに、その値が意味するところが逆だったケースだ。作る目では絶対に見えないものが、壊す目では見えた。

すべての作業をワークツリーで分離する

機能単位の作業はすべてgit worktreeで分離する。理由は二つだ。一つは、AIが複数の作業を並列で回すときに互いの変更を踏まないようにするため。もう一つは、失敗した実験をまるごと捨てやすくするためだ。AIに仕事を任せると、実験の試行回数そのものが増える。そのかなりの割合は捨てられる運命にあり、分離しておかないと捨てるコストが大きくなる。ワークツリーの作成には多少のディスクとセットアップのコストがかかるが、「一つの実験がこけてもメインはきれいなまま」という安心感が、そのコストに十分見合う。

TDDは「Classicist」で強制する

ここはAIの基本傾向と戦う部分だ。LLMにただテストを書けと言うと、Mockist(ロンドン派)寄りの傾向が強く出る。協力オブジェクトを片っ端からmockで塗り固め、「このメソッドが何回呼ばれたか」を検証するテストを書く。こういうテストは実装の細部にべったり張り付いていて、リファクタリングをしただけでばたばた壊れる。振る舞いではなく呼び出し回数を検証するので、肝心の動作が間違っていても通ってしまうことすら起きる。

LLMがこう偏るのは偶然ではない。学習データにそういうテストが多く、「ユニットは孤立させてテストせよ」というヒューリスティックを過剰に適用してしまうからだ。そこで自分は、Kent Beck流のClassicist(シカゴ派)TDD — 失敗するテストから書き、mockの代わりに実際の協力オブジェクトで振る舞いと出力を検証する方式 — をエージェントに強制することにした。ai-testing-rulesのような公開ルール集と、Kent Beckが公開しているTDDの哲学を総合し、自分たちのチームルールとして整えて配布した。mockはシステムの境界(ネットワーク・DB・ファイルシステム・時計・乱数)でだけ使い、内部実装をmockで隠さない。

大きな調査は分割して任せる

規模の大きな調査を一つのセッションにまるごとやらせることはしない。独立したコンテキストを持つ複数のサブエージェントに一片ずつ任せ、結果だけを集める。一つのエージェントがすべての文脈を抱え込むと、かえって判断がぼやける — コンテキストが長くなるほど要点が薄まるからだ。分解が精度を作る。(付け加えると、このシリーズの資料調査も、サブエージェント一つに別途任せて集めた結果だ。そのメタな話は第4部で。)

生産性爆増のパラドックス — 仕事は減るどころか爆増した

5月半ばのことだった。この頃から、「AIが自分たちを置き換えるだろう」という恐れが薄れ始めた。理由は単純だった。AIがそれまで自分たちがさばききれなかった仕事を代わりにこなしてくれるようになり、開発スピードが爆発的に上がったからだ。上層部が望んでいた機能が、恐ろしいスピードで出ていった。

ところが、恐れが消えた後に入ってきたのは余裕ではなく、もっと多くの仕事だった。スピードが上がると、やることは減るどころかむしろ爆増した。ちょうどこの頃目にした、ある投稿が、まさに自分の話だった。

Threadsのある投稿: "いや〇〇AIが開発者を全員クビにするって話だったじゃん / なんでクビにならないんだよ仕事〇〇多いなマジで / 生産性が100倍上がるから / やるべき仕事も100倍増える / ターミナルにタブだけで20個以上開いて回してるのに / ADHDの自分ですら頭が爆発しそう"

— Threadsのある投稿より。「生産性が100倍上がるから、やるべき仕事も100倍増える」。この一行が、あの頃の自分の状態を正確に言い表していた。

複数の作業を同時に回していると、頭の中が完全にパンクしていた。コンテキストスイッチがあまりに頻繁で、少し前まで自分が何の作業をしていたのかさえ忘れかけるほどだった。AIが仕事を早く終わらせてくれるほど、同時に回せる仕事の数が増え、その分だけ自分の頭の中に同時に載せておかなければならない文脈の数も増えた。生産性のボトルネックが「AIの速度」から「自分のコンテキストスイッチング能力」へと移っていったのだ。上で挙げた検証手順と二層の記憶装置は、実はこの爆増に耐えるための防御でもあった。頭で全部抱えきれないから、システムに任せたわけだ。

境界が消え、生き残る人の輪郭が見えた

目が回るような忙しさの中でも、「AI時代にどんな方向を取るべきか」についての勘はぼんやりとつかめてきた。もっともはっきりしていたのは、境界が曖昧になるという感覚だった。AIを使っているうちに、自分が開発者なのか企画者なのか分からなくなるほどだった。もちろん企画の仕事、開発の仕事はそれぞれ依然として残っている。ただ、その間で一人ひとりが一つのチームのように動くようになる。

結局、インフラであれコードベースであれ、その現場を深く知っている人ほどAIをうまく使いこなせた。AIは非常に優れているが、一方で過剰にエンジニアリングしてしまったり(第1部のgstackの話)、逆に穴が空いたまま動いてしまう(前述のbooleanのバグ)問題は依然として残っている。このギャップが将来どこまで埋まるかは分からない。ただ、今のところ二つのタイプが生き残るのではないかと思う。一つはこのギャップを調整できる人、もう一つはトークンを戦略的に使える人だ。

モデルはこれからも強くなり続けるだろうし、今のところはまだ開発者がインフラの仕事を握っている。しかし最近の作業記録を振り返ると、そのインフラすら、CLI上でAIによって急速に置き換えられつつあった。自分が見落としていた部分をキャッチして直し、ログを追って問題を突き止める作業が — 思っていたよりずっと速いスピードで近づいてきていた。

こうして「置き換えられる恐怖」は、ひとまず落ち着いた。ところがその場所に、まったく別の質の恐れが新しく育ちつつあった。AIが自分を置き換えるのではなく、AIなしでは自分が何もできなくなるのではないか。次の記事は、まさにその恐れ — AI依存と、それを減らそうとローカルLLMまで動かしてみた話だ。


続きの記事: ③ AIサーバーが落ちたら自分も馬鹿になる — ローカルLLMとAI依存

この記事が役に立ったら

コメント