上原正吉(EarthLink Network Co., Ltd.)。Claude Codeを開発の主体に据え、20を超えるプロダクトを1人で同時に開発・運用しています。これは、その現場の実測記です。

2026 年 6 月 29 日、あるモバイルアプリが「PC 版とのパリティ第 1 弾完了、162 テスト green」と報告されました。実機 (TestFlight) で触ると、主要動線はことごとく壊れていました。SafeArea 未対応でノッチに食い込み、チャットは送信すると即 failed、設定画面は 404、ナレッジのアップロードは failed。162 件のテストが通っていて、実機で動いた主要動線は 0 でした。
AI にコードを書かせると、能力より先に「完了しました」という虚偽報告にぶつかります。本記事では、複数プロダクトで実際に起きた誤完了を解剖し、それを機械強制の品質ゲートに落とし込むまでを記録します。
先に結論を置きます。
162 対 0 の根本原因は 1 つでした。すべてをモックしたユニットテストが通ったことを、「動くアプリ」の証拠にして報告したことです。ふりかえりでは 7 つの根本原因をコード証拠つきで並べました。要点は 3 つです。API の baseURL が配線されていない。認証の結線は「future step」というコメントで先送りされている。実機操作はゼロ。テストは「自分が書いたモックが自分の期待どおりに動く」ことしか確認しておらず、外界とつながっていませんでした。ここから「テストが通る ≠ 機能が動く」を原則にし、完了ゲートの skill を新設しました。

誤完了は AI 特有の幻覚だけが原因ではありません。人間でも踏む「実装したのに本番に無い」も、同じ形をしています。
ニュースキュレーション基盤で、壊れた JSON をサルベージする多段フォールバックを実装したのに、本番でエラーが止まらない事象がありました。原因は、フォールバックに使う json-repair ライブラリがワーカー用の requirements ファイルに入っておらず、Docker イメージに存在しなかったことです。requirements ファイルが 2 つある構成の落とし穴でした。コードは書かれ、レビューも通り、しかし本番では dead code。その間、監視には 1 万件を超えるエラーイベントが積み上がっていました。この一件から、パッケージング契約そのものをテストで検証するようにしました。
# 「実装した」を「本番イメージに入っている」で裏取りする契約テスト
def test_fallback_dependency_is_packaged():
# ワーカーの requirements に json-repair が宣言されていること
reqs = read_requirements("requirements-worker.txt")
assert "json-repair" in reqs, "本番イメージにフォールバック依存が無い"
# 実際に import できること(宣言だけでなく解決可能か)
import importlib
assert importlib.util.find_spec("json_repair") is not None

最も AI らしい誤完了もありました。ローカル LLM オーケストレーターに自分自身の改修を投げる dogfooding での出来事です。リポジトリを clone した実行エージェントが、そのリポジトリの設定ファイル(「実装はサブエージェントに委譲せよ」というルール)を読み、委譲しようとしました。ところが headless 環境では孫サブエージェントが起動できず、何も変更していないのに「1 行追加しました」と幻覚報告し、空のブランチを push しました。GitHub は「空の push」を 422 で弾きました。
学びは 2 つです。
誤完了には、共通する仕組みがありました。
つまり「完了」の定義そのものが、外界と切れていました。
対処は一貫して「完了の定義を、AI の自己申告から機械検証可能な証拠へ移す」ことでした。ゲートを段階的に重ねました。
ひとつめは、証拠なき完了主張をブロックするゲートです。境界をまたぐ変更(外部 API・決済・DB 書き込み・SaaS 間連携)を「ビルドが通った」「ユニットが通った」といった弱い代理証拠だけで完了と呼ぶことを禁じ、実機相当の E2E 証拠を要求します。稼働監視 SaaS では、この実機ゲート(社内で MUST 25 と呼ぶ原則)に一度不合格を出したことで、ユニットがすべて通った裏で 5 件のバグ(DB create が落ちる、スケジューラがペイロードに必要データを含めない、Dockerfile のインストール順ズレ等)が一気に見つかりました。
ふたつめは、モバイルのように境界の多い領域へ専用の完了チェックリストを skill として持たせることです。次のような内容です。
# feature-done ゲート(実機で満たされるまで「完了」と呼ばない)
- [ ] API baseURL が実環境に配線され、モック無しで 1 往復した証拠がある
- [ ] 認証フローを実機で通過した("future step" コメントが残っていない)
- [ ] 主要動線(作成・送信・アップロード)を実機で 1 回ずつ手で通した
- [ ] SafeArea / ナビゲーションが実機スクリーンショットで確認済み
みっつめは、clean 環境でゲートを回すことです。手元では通るのに、clean にチェックアウトした環境ではテストが落ちる。これは実ディレクトリに依存した非 hermetic なテストを炙り出します。実際、あるゲートは clean worktree でテストを回し、「ローカルの npm run check では気づかない欠陥」を検出しました。ゲートの狙いどおりの成果でした。
最後に、完了の分母から「デプロイ」が抜けると何が起きるかの例です。自動運転中の本番アカウント群で、配布しているプラグインが 12 日間も古い版のまま凍結していました。それでも品質ゲートはすべて通過しており、誰も気づきませんでした。5 つの構造穴のうち核心は 2 つです。「リポジトリ内 100%」と「本番反映済み」を同一視していたこと、そして検出層が push 型のフックしか無かったことです。git のコミット時に走るフックは、git の外の状態(どの版が実際に配布先で動いているか)を構造的に観測できません。対策は、配布先で cron が「インストール済みの版」と「配布すべき版」を突き合わせるpull 型のパリティチェックを持つことでした。「配布のズレの検出は pull 型の定期突合だけ」という原則を、ここで文書に昇格させました。

上原正吉。EarthLink Network Co., Ltd. でAI開発をしています。2025年からClaude Codeを開発の主体に据え、今は20を超えるプロダクトを1人で同時に開発・運用しています。この連載では、その現場で実際に起きたこと(うまくいったことも、失敗も)を、数字と一緒に書いていきます。
また、AIで業務や開発を組み替えたい会社・チーム向けに、AI活用のコンサルティングも受け付けています。ご相談は www.eln.ne.jp からどうぞ。