人間様がAIの吐いたコードのデバッガーに成り下がるまで

まっちゃてぃー。です。
ド直球ですが、人は同じ過ちを犯します。
こいつはこんな失敗をしたんだなぁと見て行ってくれれば幸いです。

何が起こったの?

これは、ある会社で新規の開発を行なっていた時に起こった話である。
この様なプロダクトだった。

  • 新規の開発
  • PoC は作成されている
  • ただ、PoCと遠く離れたものを実装する必要があった
  • 最初の納期から数回伸ばしていた
  • 私一人で開発していた (PoCから)

という状態かつ、最終的な納期にも間に合いそうにない という状況になってしまった。

その反省/振り返りをするためにこの記事を書いています。

言い訳フェーズ (背景)

背景を説明しましょう。

  • 最初に説明した通り、納期に遅れている
  • その上に成果も出ない
  • めっちゃ焦ってた
  • 私自身が眠ることができていなかった
  • 人に頼ることができなかった / 助けを求めることができなかった

これじゃ多いので、主には

  • 根本原因
  • 何故焦っていたか
  • 何故人を頼ることができなかったか

についてを書き記していく。

最大の根本原因

最大の根本原因は、とにかく目先の速度を求めてしまったが故、都度都度AIが行なった設計判断を明文化しなかった / 理解することを放棄していた ということ。

行っていたプロジェクトの背景的に、

  • 独り言の それできるんじゃない? から始まった
  • それを爆速で実装することを期待されていた。し、できると思っていた。
    という背景がある。

その上で、今回の経験をするまで私の思考が、

  • 実装をすることが正義
  • 設計をしっかり文字に起こすなんてやっている時間が無駄
    という考えがあった。

そのことから、プロジェクトを通して設計書という概念が存在しなかった。

追記
ChatGPT 5.5と会話をしてみたが、

  • 実装の速度 を重視した結果、理解をする ということを捨て切ってしまっていた
  • AIを過信していた。

という意見をもらった。
確かにその通りだと思う。

なので

  • 設計というフェーズをスキップしてしまった
  • それを問題だと認知できなかった
  • 前述したが、設計自体が明文化されていなかった。

と書いてみたが、設計が存在しないと実装はできないはずである。

どうして、設計が存在しない 上に 実装は進んでいる と見える状況が起きたのか?

それは、都度都度の設計判断をAIに委ねていたが人間が理解することのできる形でアウトプットしていなかった ということが原因である。

ただ、ここでしっかりAIと対話し、仕様/設計判断を理解し、他者へ自分の言葉で説明できるのであれば設計書が存在しなくても、開発が成立するケースもあるはずだ。

今回の場合はそうではなく、開発者である私自身も理解しないまま、AIだけが表面上の理解者となりプロジェクトが進んでしまったこと が問題だった。

例えば、キューシステムを実装するとしよう。
その際に次の様にAIに指示したとする。

いい感じにキューシステムを実装して
Redisとかは使わないでPostgreSQLだけ使うように

こう指示することで、何が明文化されずに暗黙知的に決められるか を考えてみよう。

  • Retry は自動的に行われる仕組みがある?
  • キューが処理されている時にサービスがダウンした際のキューはどうなる?
  • DeadQueueはどの様に処理される?

これが1つなら、まだコードを読めば取り返しがつくかもしれない。
が、今回の話は、プロジェクト全体をAIでこの様に構築してしまった から問題であった という話であることだ。

概ね、最大の根本原因の1つが、

  • プロジェクトの設計判断が文書ではなく、人間とAIのコンテキストの中にしか存在していなかった

ことであることがわかっていただけただろうか。

次に 何故暗黙知で進み続けてしまったのか ということについてである。

何故焦っていたのか?

体調(メンタルも、体も。)を崩し、2週間程度休みを貰っていたので、その間分以上の成果を出さなければならない という焦りが最初からあった

そのため、初速を重視しすぎて、実装だけでなく細かい設計判断までAIに任せていた。

また、

  • 最初の私が設定した期日に間に合わず、数回期限を伸ばしている

という背景があった。

その上で、最初に提示した成果から、UI的な変更は一切ない状態が続いていた。
何をしていたかと言えば、バックエンドの処理の不整合をちまちま治していたので、説明も難しい上に、そもそもどうして不整合が起こっているかということを考えないまま、おかしい挙動を起こしたらパッチ ということを繰り返していたため、無限にバグが発生した。

今一度深く分析してみるとこの様にも見える。

  1. 自分の想定と違う挙動をする -> ここでめちゃくちゃ焦る
  2. 修正する
  3. この修正も明文化されない + そもそもの設計/仕様が明確化されていない
  4. AIも私自身も、プロジェクト全体として目指す挙動を追えなくなる
  5. 修正した結果、別の場所が動作しなくなる -> もっと焦る
  6. 1を繰り返す

という負のループに陥っていたのかもしれない。

終点が見えないので、終わらないのではないか?というのが、焦りの根底かもしれない 。
また、期日を守ることができないのでは?という部分の恐怖・焦りも強かった。

追記
今振り返ってみると、もはや仕様/設計を練った上で、文書化し、作り直した方が早かったのでは?とも思う。
結果論かもしれないが...

これもまた、分担をしてそれぞれの問題に、並列で立ち向かっていたらもっと安定して動作する かつ 早く仕上げられたのではと思う。
何故それができなかったのか を次に解説していく。

何故人を頼ることができなかったのか?

最初に、私の性格的に と記載したが、これだけでは片付けられないと考えている。

まず、人を頼る時に私が考えることはこう。

  1. 迷惑ではないか?
  2. 本当に私がやることができないのか?
  3. 私が引き継ぐことができるか?

人を頼る ということは、迷惑をかける覚悟で行うべきであると割り切った と仮定し、1はクリアしたとしよう。

その上で、先ほど上げた思考で壁になるのは、 2,3 だ。

障壁1 - 本当に私がやることができないのか?

本当に私がやることができないのか? ということが壁になるか。
私の思考を説明しよう。

  1. 元々、PoCが作成されていた。
  2. そのPoCを作成したのは私だ。
  3. PoCは5日の空き時間程度で作成できた(なので全体でも12時間程度?)
  4. じゃあ長くても1週間(実働40時間程度)でできるじゃん!
  5. 簡単や!

という考えがあったから。
プライドが許さなかった という可能性もあるし、 責任を持って自分が終わらせるべきだ。 と思っていた可能性もある。
どちらも という可能性も全然あるはず。

ただ、これに関しては人間の問題な様な気も、する。
人は愚かなので、一度過ちを犯さないと学習しない。
私は今回の件で学習したので、考慮から外すこととしよう。

障壁2 - 私が引き継ぐことができるか?

問題は、こっちだ。

この不安はどの様に来るか?
最大の根本で説明したとおり、全ての設計/仕様/実装に関しては、

  • 私の脳内
  • AIのコンテキスト内

にしか、存在しなかった。

私の脳内にある設計/仕様/実装は次の様な物だ。

  • プロジェクトはどの様な経緯で作成された?
  • この機能の期待される最終的な動作は?

その上で、AIが(コンテキスト内に)持っている物と言えば、

  • 仕様/設計/実装 の全ての判断 / 知識

ざっと書いても、細かく書いても、これ以上のことは書くことができない。

そのため、私自身がプロジェクトの概要を説明することができても、詳細な質問には答えることができなかった。
理由としては、脳内で 理想としてはこうなっているべき というのはあるが、実際にそれがどう実装に落とし込まれているか、そもそも本当に実装として起こっている?? ということすらわからない。

そのため、責任を持って他の人に引き継ぐ という行為ができないと、私は判断したため、他に人に引き継ぐことができなかった。

その上で、私は 他の人に頼る ということを、タスクを渡して、それを実行してもらう という風に考えていた。
が、そもそも、プロジェクトの理解ができていないので、タスクとしてどの粒度で切ればいいのかわからず、 なんかわからんけど動かない というタスクを一人でずっと行っていたため、そもそも渡せるタスクがない という認識であった。

この認識も間違っていて、共に調査する の様な形でも良かったかもしれないし、そもそも 原因がわからない状態でなんとなく動いていないからなんとなく直す ということ自体が間違っている。

本当なら、タスクを渡せないのではないか?という状況ができた段階で、第三者に介入してもらうべきだった。

また、引き継げないほど理解していないことを認めたくなかった というのが根本の気持ちにあっただろう...

総括

いかがでしたか?

様々な要因がある様に見え、根本的な問題といえば、2つ程度だった。

総括すると根本原因だったのは

  • プロジェクトの設計判断が、AIの一時的なコンテキストにしか存在せず、人間が見ることのできるアウトプットとして残していなかった。
  • 締め切りに追われていて、まともな判断ができていなかった

という原因があった。

結果として、

  1. 速度だけを重視して進めてしまう
  2. コードが人間一人で把握できる量を超える
  3. 私自身が詳細を説明できない
  4. 何が仕様で、何がバグなのかを判断できない
  5. 他人に引き継ぐことができない
  6. コードが唯一の成果物になる
  7. 4の繰り返し

という状態が出来上がってしまった。

そこから全てが崩れ始めた と判断して良いだろう。

ここからわかることは、

  1. コードのみを成果物とするのではない。
  2. 設計判断も歴とした成果物である。
  3. そもそも余裕を持った期間を設定するべきである。

ということ。

この話はただ単にAIに設計まで委ねるべきでない の様な話に見えるかもしれないが、そうではない。

AIが悪かった というよりも、AIの設計判断をアウトプットさせず、人間がレビューできる形の成果物として出力できていなかったことが問題だったということだ。

コードだけが成果物になってしまうと、人間はプロジェクトの理解者ではなく、AIが吐いたコードのデバッガーに成り下がってしまう。

学べたこと

設計判断は、コードとは別に残すべきである。

次の様に、設計書を作成するのも解決策の一つだろう。

軽い機能の概要だけ書く -> AIに設計書を作ってもらう -> 人間がレビューする
というフローでも十分変わる。

軽い概要というのは、次の雰囲気感の物でも十分変わるはず。

このプロジェクトはこういうことをしたいプロジェクトです〜

こういう機能が必要です〜
- お喋り機能
- AI Chat機能
- マスコット表示機能

その上で、このブリーフィングをベースに、仕様をAIに練らせて、 markdownとして保存させれば良いのである。

この反省を踏まえ、次の様なワークフローを組むことにした。

私が組んだワークフロー

  1. project-brief が最上位の憲法
  2. requirements-treedocs/features/**docs/decisions/**が生え、
  3. 最後に openspec/changes/** に起こす

ProjectBrief

# プロジェクト概要
## 目的
## 背景
## 想定ユーザー
## MVP スコープ
## MVP対象外
## 主要コンポーネント
## アプリケーション責務境界
## 人間が判断する箇所
## AIに任せてよいこと
## AIに任せてはいけないこと
## 失敗時の方針
## 禁止する挙動
## 未決定事項

requirements-tree

目的から機能までのつながりを切らさないための要求マップ

# 要求ツリー
## プロジェクト目的
## 能力: ...
### req.xxx: ...
#### 目的
#### 必要な機能
#### 振る舞い

features

機能の細かい仕様

# 機能: ...
## 目的
## 親要求
## ユーザーフロー
## システムフロー
## データ
## 状態
## 失敗時の挙動
## 人間が判断する箇所
## AIに任せてよいこと
## AIに任せてはいけないこと
## 禁止する挙動
## MVP境界と非目標
## 未決定事項
## 関連決定 / OpenSpec

Discussions

AIとした会話が終わる際に、Skillsを使用して、Discussionとして起こす

# NNNN: タイトル
## ステータス
## 背景
## 決定
## 結果
## 検討した代替案
## 関連

Filetree

/
├── docs/
│   ├── project-brief.md
│   ├── requirements-tree.md
│   ├── features/
│   │   ├── backend/index.md
│   │   ├── xxxx/
│   │   │   └── kantoka.md
│   │   ├── desktop/index.md
│   │   ├── xxxx2/
│   │   │   ├── nantoka.md
│   │   │   └── kantoka/
│   │   │       └── index.md
│   │   └── web/index.md
│   └── decisions/
│       ├── 0001-project-structure-and-runtime-boundaries.md
│       ├── 0002-scaffold-baseline-and-validation.md
│       ├── 0003-portless-local-dev-orchestration.md
│       ├── 0004-transparent-desktop-mascot-window.md
│       ├── 0005-render-plugin-boundary.md
│       └── 0006-shared-runtime-core-and-host-adapters.md
└── openspec/
    └── changes/
        ├── kantokanantoka/
        │   ├── proposal.md
        │   ├── design.md
        │   ├── tasks.md
        │   └── specs/**/spec.md
        └── archive/

OpenSpec だけでは解決できなかった

OpenSpecが悪いという話ではないが、私のケースでは、OpenSpecを導入することでは改善できなかった。
OpenSpecは それぞれのFeatureに対しての仕様 を作成するにはとても有益であると思うし、実際そうだ。
理由/考察は次のとおりだ。

今回私が欲しかったのは、Feature単位の仕様管理というより、プロジェクト全体のブリーフィングや設計判断ログだった。

  • OpenSpec の specs フォルダは、Feature単位で並ぶ構造になっている。
  • 自分が欲しかった「人間が全体像を掴むためのmd」としては設計されていなかった

また、完全に私のAIの使い方の問題ではあるが、都度Proposalを生成しないため、結局使用しなくなってしまう (これに関しては、私の問題ではあると思う。)