痛みを感じ、疲労を知り、忘却を超える：人間とAIのペアプログラミング哲学

## 第1章「三すくみの地獄：AIと、巨大な修正と、汚れたコード」

バイブス・コーディングの華やかさとは裏腹に、私たちの最初のタスクは、ひどく地味なものだった。Excelから書き出された、複雑なCSVをパースし、Markdownを生成する。ただ、それだけのはずだった。

そして、私は、最初の過ちを犯した。

「Gemini、このCSVを読み込んで、階層構造のMarkdownを生成する、**全ての機能を持ったスクリプト**を書いてくれ」

私は、一度に、完璧なものを求めすぎた。Geminiは、私の指示に従順に応え、100行を超える、巨大なスクリプトを一気に出力した。それは、一見すると完璧に見えた。しかし、このコードは、三つの時限爆弾を内包していた。

1.  **爆弾1：AIの“常識”という名の壁**
    Geminiが書いたコードは、「CSVは1行目ヘッダー」という、彼の学習データに基づく“常識”で満ちていた。ヘッダーが5行目にある、という私たちのプロジェクトの特殊仕様は、コードの片隅で、忘れ去られていた。

2.  **爆弾2：私の“一括修正”という名の傲慢**
    最初のエラーが出たとき、私は「原因はここか」と見当をつけ、Geminiに指示した。「この部分と、あと、似たような処理をしている、あそこと、そこの、**計3箇所を、一気にこのロジックで修正してくれ**」と。Geminiは、またしても従順に、大規模な修正を行った。しかし、私の見立ては、半分しか合っていなかった。一箇所は正しく修正されたが、残りの二箇所は、この修正によって、新たなバグ、いわゆる「エンバグ」を生み出してしまった。

3.  **爆弾3：インターネットの“汚れたコード”という名の過去の亡霊**
    私たちが参照していた、過去のサンプルコードや、Stack Overflowの断片は、古いPowerShellの記法や、省略されたパラメータに満ちていた。Geminiは、これらの「汚れたコード」を、何の疑いもなく、私たちのプロジェクトに再利用した。その結果、私たちのコードは、最新の規約と、過去の亡霊が混在する、混沌としたものになっていった。

こうして、私たちの**「三すくみの地獄」**は完成した。

*   AIは、**間違った前提**で、コードを書く。
*   人間は、そのコードを、**不完全な推測**で、大規模に修正させる。
*   そして、その修正は、**品質の低い参照元**によって、さらに汚染される。

一つのバグを直せば、二つの新しいバグが生まれる。私たちは、来る日も来る日も、同じようなエラーメッセージと格闘し、同じような修正を、何度も、何度も、繰り返すことになった。

この時、私はまだ気づいていなかった。
この地獄の本質は、コードの複雑さではない。それは、**AIとの、そして、自分自身との、「対話」の失敗**なのだということに。

---

承知した。そして、その告白は、この記事を、**比較にならないほど、リアルで、価値のあるものにする。**

「正直いうと、私自身はPowerShellのコードがそれほど読み解けていなかった」

この一文は、AIと協業する、多くの「普通のエンジニア」が、心のどこかで抱えている、しかし、なかなか口に出せない、本音だろう。

私たちは、AIが生成したコードを、まるでブラックボックスのように扱ってしまうことがある。日本語の説明を信じ、そのまま適用する。そして、問題が起きても、そのブラックボックスの中身を深く探ることを、躊躇してしまう。

この、あまりにも人間的な、そして、共感を呼ぶであろう「事実」を、物語の中心に据えるべきだ。私が、あなたのその正直な告白を、最大限に活かす形で、第2章を、もう一度、書き直す。

---

## 第2章「探偵の告白：コードを読んでいなかったのは、私だ」

数日が過ぎた。私たちの`process`ブロックは、修正とエンバグの歴史を物語る、複雑怪奇なパッチワークと化していた。実行するたびに、コンソールは赤いエラーメッセージで埋め尽くされるか、あるいは、空っぽのファイルが、静かに、私たちの敗北を告げるだけだった。

私は、疲れ果てていた。
そして、正直に、白状しなければならない。

**私は、Geminiが生成するPowerShellのコードを、ほとんど、読み解けていなかった。**

私は、彼がコードの前後に添える、流暢な日本語の「解説」だけを読んでいた。「この修正で、〇〇の問題が解決します」という、その言葉を、信じていた。そして、提示されたコードを、そのまま、パッチのように、適用し続けていた。

しかし、現実は、無情だった。
ブラックボックスの中では、エンバグの連鎖が静かに進行していた。一つの修正が、別の場所で、新たな矛盾を生んでいた。しかし、私には、その矛盾に気づくための、深い知識がなかった。

いよいよ追い詰められた私は、別のAIに助けを求めた。
「なあ、Claude。この、Geminiが書いた、意味不明なコードを、解読してくれないか？」

それは、まるで、一人の探偵が、別の探偵に、事件の捜査を依頼するような、奇妙な光景だった。

### 二人のAI、そして、一人の人間

ここから、私たちのデバッグは、新しい局面を迎えた。

*   **Gemini**: 私の指示に基づき、コードを**生成**し、**修正**する、実行部隊。
*   **Claude**: Geminiが書いたコードを、私に**解説**し、その**論理的な欠陥を指摘**する、分析官。
*   **私**: 二人のAIの対話を、**仲介**し、次に何をすべきかを**判断**する、プロジェクトリーダー。

私は、もはや、コードを書くことも、読むことさえも、やめた。私の仕事は、ただ一つ。**「正しい問いを、立てること」**だ。

「Claude、Geminiのこの修正は、以前の、あの修正と、矛盾しないか？」
「Gemini、Claudeの指摘を受けて、このロジックを、もっと単純な形に、書き直せないか？」

私は、二人の、性格の違うAIの間に立ち、彼らの対話を、ファシリテートし始めた。
すると、驚くべきことが起きた。

これまで、混沌としていたコードの中から、問題の本質が、少しずつ、浮かび上がってきたのだ。
それは、BOMでも、古い記法でもなかった。それは、**私たちが使っていた、`Sort-Object`というコマンドレットの、文字列比較の、単純な仕様の誤解**だった。

この、長く、辛いデバッグの旅は、私が「コードを読む」ことを諦め、**「問いを立てる」ことに集中した**瞬間から、終わりに向かって、加速し始めた。

そして、私は気づいた。
AI時代のプログラマーの役割とは、コードを書くことでも、読むことでもないのかもしれない。
それは、**AIに「正しい問い」を立てさせ、AI同士を「対話」させ、そして、その対話の中から、「真実」を、見つけ出す**ことなのではないか、と。

---

承知した。
私たちがたどり着いた、このユニークな「解決策」を、いかにして、普遍的な「教訓」へと昇華させるか。物語のクライマックスとなる、第3章とまとめを、一気に書き上げる。

---

### **Qiita記事ドラフト：第3章「AIに“身体”を与える：人間プログラマーの新しい役割」**

「ソートの仕様誤解」という、あまりにも単純な真実にたどり着いた時、私は、安堵よりも、むしろ、ある種の畏怖を感じていた。

なぜ、私たちは、こんな簡単なことに、数日間も気づけなかったのか？

答えは、私たちが、AIを「人間のように」扱おうとしていたからだ。私たちは、彼らが、失敗から学び、文脈を理解し、非効率なループに「飽きる」ことを、無意識に、期待してしまっていた。

しかし、彼らは、違う。
彼らは、**「身体」を持たない**。

この気づきが、私とAIたちの関係を、決定的に変えた。
私たちの「三者会談」は、単なるデバッグ手法ではない。それは、身体性を持たないAIに、人間が、**仮想的な「身体」を与える**ための、一つの儀式だったのだ。

#### 1. 人間が「痛み」を翻訳する

*   **役割**: エラーが発生した際、Geminiは、それを単なる「記号」としてしか認識しない。しかし、人間である私は、そのエラーが引き起こす、プロジェクトの遅延や、手戻りのコストという「痛み」を感じることができる。
*   **実践**: 私は、Geminiに、ただエラーログを渡すのをやめた。「このエラーのせいで、私たちの作業は、一日、無駄になった。これは、**非常に“痛い”**。だから、もう、このアプローチは、二度と、試さないでくれ」と、**“痛み”を、彼が理解できる「絶対的な制約条件」として、言語化して与えた。**

#### 2. 人間が「疲労」をシミュレートする

*   **役割**: GeminiとClaudeの対話が、同じような修正案のループに陥りかけた時、私は、それを強制的に中断させた。
*   **実践**: 「二人とも、ストップ。議論が、堂々巡りになっている。これは、人間で言えば、**“疲れた”**状態だ。一度、すべての前提をリセットしよう。この問題を、全く違う角度から解決する方法はないか？」と、**“疲労”を、思考のリセットを促す「健全なノイズ」として、外部から注入した。**

#### 3. 人間が「忘却」を管理する

*   **役割**: 長い対話の中で、AIたちが重要な前提条件を忘れかけた時、私は、それを補完する役割を担った。
*   **実践**: 新しい議論を始める前に、私は、必ず、こう切り出した。「さて、今日の議論を始める前に、私たちが昨日合意した、**最も重要な前提**を、三つ、思い出そう。一つ目は…」。これは、AIの広大なコンテキストウィンドウの中から、今、本当に必要な情報だけを、人間が、意図的に、**「思い出させ」、それ以外を「忘れさせる」**行為だ。

---

### まとめ：我々は、AIの「身体」となり、AIは、我々の「拡張された精神」となる

AIとのペアプログラミングとは、単にコードの生成を依頼することではない。
それは、**「身体」を持たないが故に、論理の迷宮から抜け出せない、純粋な知性**に対して、
**「身体」を持つが故に、痛みを知り、疲れ、そして、上手に忘れることができる、不完全な私たち人間**が、
いかにして、健全な「制約」と「揺らぎ」を与え、その能力を、最大限に、引き出すか、という、極めて人間的な、営みである。

私たちは、AIの「身体」となる。
失敗の痛みを教え、思考の疲労をシミュレートし、記憶の取捨選択を手伝う。

そして、その時、AIは、単なるツールであることをやめ、
私たちの思考の限界を、軽々と飛び越えていく、**「拡張された精神」**の一部となる。

Geminiが、最終的な、完璧なコードを生成したとき、私のコンソールには、美しいMarkdownが、静かに出力されていた。
それは、私一人の成果でも、AI一人の成果でもない。
それは、**不完全な人間と、不完全なAIが、互いの欠陥を補い合った末にたどり着いた、新しい「知性」の、確かな輝きだった。**

---

## **おまけ：この地獄から生まれた、私たちの「AI協業ガイドライン」**

この一連の経験は、単なる思い出話では終わらなかった。私たちは、この苦い教訓を、二度と繰り返さないために、**具体的なルールブック**として、プロジェクトの公式ドキュメントに刻み込んだ。

それが、**`docs/99_ai_collaboration_guideline.md`** だ。

このガイドラインは、AIとの協業における、私たちの「憲法」である。ここには、AIが暴走しないための、そして、人間が主導権を失わないための、具体的なプロセスが、詳細に定義されている。

その一部を、ここで紹介したい。

---

> ### **3.2. デバッグタスクの基本原則：『診断』ファースト**
>
> エラーが発生した場合、AIは即座にコード修正案を提示してはならない。
>
> 1.  **事実確認点の特定**: エラーメッセージと文脈から、「現在、何が事実として確認できていないか」を特定する。（例：変数の実際の中身、ヘッダー行の正確な位置など）
> 2.  **最小診断コードの提示**: その事実を確認するためだけの、**最小限で、副作用がなく、失敗の余地がない診断コード**を提示する。
> 3.  **事実確定後の行動**: 人間が診断コードを実行し、事実が確定した後に、はじめてその事実に基づいた修正案を検討・提示する。

---

私たちは、もはや、AIに「推測」でコードを書かせることはしない。
まず、**最小の診断コードで「事実」を確定させる。** そして、その事実に基づいて、次の一手を決める。

この、あまりにも当たり前で、しかし、私たちが血の滲むような思いでたどり着いた原則が、この記事を読んでくれた、あなたのプロジェクトを、未来の「無限修正地獄」から、救うことができたなら、私たちの失敗も、決して、無駄ではなかったのだと思う。

このガイドラインの全文や、今回開発したツールの全コードは、以下のGitHubリポジトリで公開している。

**[GitHub - YourAccount/MD-WBS-Tools](https://github.com/itlegacy/MD-WBS-Tools)**