ハルスペース・ラボ
話すペットから、承認を受けて働く開発パートナーへ — 失敗が作った四つの扉
AIペットにコード作業を任せながら、会話、編集、リポジトリ反映、マージを分離し、実行環境の停止や誤った作業フォルダ、過剰な複数ペット実行を直した一週間の記録です。

Summary
ひと目でわかる要約
- 何気ないペットとの会話が意図せず開発作業にならないよう、通常の会話と明示的な作業提案を分けました。
- コード変更、リポジトリ反映、PRのマージを別々の権限・承認段階に分け、本番反映は自動フローの外に残しました。
- 固着した状態、誤登録された一時作業フォルダ、Windows隔離の失敗、複数ペットの過負荷から、自律性より先に復旧可能性を学びました。
この記事は、2026年7月22–28日のGit記録、設計文書、当時の障害記録をもとに書き直したHaru Spaceの開発回顧だ。公開記事に不要な利用者の会話、識別子、内部アドレス、秘密情報は含めていない。
チャットで上手に話すAIペットと、実際の開発パートナーとして働くAIペットは、まったく別のものだった。
返答が間違っていれば、もう一度聞けばよい。しかしコードの編集はファイルを変える。コミットはリポジトリに記録を残し、マージはほかの人が使う基準まで変える。本番反映は、利用者が実際に触れるサービスへ影響する。同じ「やってほしい」という言葉の後ろにある責任は、段階ごとに重くなった。
初めは、ペットが依頼を理解し、リポジトリを確認し、結果を知らせてくれれば十分だと思っていた。一週間後、考えは変わっていた。
AIペットを開発パートナーにしたのは、より大きな自律性ではない。異なる責任の前に置いた四つの扉だった。
その扉は、会話、隔離された編集、リポジトリへの反映、PRのマージだった。本番反映は、その先にある別の判断として残した。そしてこの構造は、滑らかな成功よりも、いくつもの失敗によって具体的になった。
最初の目標は、開発画面を隠すことではなかった
Haru Spaceでペットを使う全員が、ブランチ、サンドボックス、作業ツリーといった言葉を知る必要はない。利用者はチャットで普段どおりに、アイデアを整理してほしい、コードを見てほしい、機能を変えてほしいと頼めるべきだった。
そこで、作業は結果を表す言葉で分けた。
- アイデアを整理する読み取り作業
- 現在のコードを確認するレビュー作業
- 実際のファイルを変える編集作業
一つのスペースには代表作業ルームを一つ置き、依頼の状態は一件のチャットメッセージを更新し続けて見せることにした。モデルの途中推論、シェルコマンド、生のログをチャットへ流さない。完了時には短い要約を残し、整理・除去した結果はそのスペースの文書に蓄積した。
これは、複雑な技術を単純に見せるだけのUI作業ではなかった。利用者が見る必要のない情報と、見せてはいけない情報を同時に分ける仕事だった。生のログには、ローカルパス、アカウント情報、秘密値が混ざることがある。一方で承認者には、何を変えようとしているのか判断できるだけの要約が必要だ。
私たちはプロンプト全文を作業履歴へ複製せず、長さを制限し、機密情報を除いた依頼要約、状態、変更フィンガープリント、判断者といった最小限の記録を残した。説明できる状態を作りながら、説明を理由に非公開原文をさらに保存しないための選択だった。
一つ目の扉:会話を作業と取り違えない
初期実装では、ペットの役割と利用者が書いた文から、会話、計画、レビュー、編集を分類していた。開発役のペットに「この画面を作ってみたらどう?」と話すだけで、実際の編集承認カードが作られる可能性があった。
技術的には賢く見えた。AIが意図を理解し、実行フローまで選んでくれるからだ。しかしプロダクトとしては危険だった。人はアイデアを話しただけなのに、システムがファイル変更の依頼だと解釈するかもしれない。
ここで得た教訓は明確だった。
実行の意思は文の中から推測するものではなく、利用者が別の操作で確認する状態である。
通常のチャットにおける @ペット メンションは、文に「作って」「確認して」が含まれていても、会話としてだけ処理するように変えた。開発作業は、作業スペースの明示的な開始フロー、またはグループチャットから選択した作業スペースへ提案を送り、その作業ルームで承認された場合にだけ作られた。
グループ会話で見つかった要望も、すぐコード作業にはならなかった。まず送信先を選び、対象作業ルームの人が内容を確認して受け入れるか拒否する。受け入れた後も、既存の編集承認手順はそのまま続いた。
操作は一つ増えたが、責任はずっと明確になった。「AIと話した」と「AIに変更作業を任せた」の間に、人が確認した境界ができた。
二つ目と三つ目の扉:編集実行とリポジトリ反映は同じ承認ではない
編集作業は人の承認後、依頼ごとに隔離されたフォルダで実行した。読み取り専用の分析スレッドと、書き込み可能な編集スレッドも分けた。過去の会話が続いても、低い権限のスレッドが自然に高い権限へ昇格しないようにするためだった。
ここにも落とし穴があった。「編集を承認する」とき、人はまだAIが作る結果を見ていない。その一つの承認でコミットとプッシュまで許せば、未確認の結果がリポジトリへ残る。
そこで編集実行の承認と、リポジトリ反映の承認を分けた。
- 人が編集実行を承認する。
- AIが隔離フォルダでファイルを変更し、検証する。
- システムが変更ファイル一覧と内容からフィンガープリントを固定する。
- 初期設定では、人が結果を見てコミット・プッシュを承認する。グループが事前に自動反映ポリシーを有効にした場合だけ、グループポリシーの主体がこの判断を代行する。
- 別のDelivery Runnerが同じ作業を読み直し、フィンガープリントが一致することを確認して作業ブランチだけに反映する。
Codexの実行プロセスにはリポジトリ書き込み資格情報を渡さなかった。コミットとプッシュは、異なる実行主体と制限された資格情報を持つDelivery Runnerが担当した。基準ブランチへの直接プッシュと強制プッシュも許可しなかった。
不便さはあった。承認段階は増え、Delivery Runnerが止まれば、編集は終わってもリポジトリには反映されていない状態が生まれる。それでも便利さのために資格情報を一つのプロセスへ集めなかった。障害は復旧できるが、境界のない自動化は誤った変更をより速く広げるからだ。
四つ目の扉:PRは作っただけでは終わらない
作業ブランチの後には、PRを作成しマージする流れが必要だった。ここでも「プッシュ成功」と「基準ブランチの変更」を同じ判断にしなかった。
依頼者が参加しているグループチャットを選ぶと、検証済みのリポジトリ接続でPRを作り、そのルームの一件のメッセージに作業要約、成果物、承認操作をまとめた。マージ直前には、リポジトリ、ソース・対象ブランチ、head SHAをもう一度確認した。承認後にPRが変わった場合や、リポジトリの保護ルールが許可しない場合はマージしなかった。
拒否も、一語の失敗状態で終わらせなかった。理由を残し、再作業は拒否されたPRのソースブランチから始める一方、最終マージ先は元の保護ブランチに保った。古いPRを密かに書き換えたり、過去の判断を成功で上書きしたりしなかった。
この区別は画面でも重要だった。再作業の「開始ブランチ」と最終的な「マージ対象」を一つの基準ブランチのように見せると、何を引き継ぐのか判断できない。項目と表示を分けて初めて、拒否理由が次の作業の入力になった。
本番反映は依然として自動では続かなかった。コードがマージされた事実と、利用者が触れる環境を変えてよいという判断は別の責任だからだ。
状態は事実ではなく、事実を映した画面だった
最初の大きな運用失敗は、AIが作業できなかったこと以上に、失敗したのに画面が「待機中」のままに見えたことだった。
実行側では認証の問題で作業がすでに失敗していた。しかしHaru Spaceは、利用者が特定の作業表示を開いたときだけ遠隔状態を同期していた。ポップアップを閉じると、遠隔の失敗とチャットカードの状態がずれたまま残ることがあった。Windowsの予約タスクも「実行中」と表示されていても、その子プロセスが健全だとは限らなかった。
私はアプリDBに保存した状態を事実だと考えていた。しかしそれは、人が素早く読むための投影だった。外部実行環境には別の事実があり、両者の同期は失敗し得た。
復旧は無制限のリアルタイム照会ではなかった。チャットや作業表示を開いたとき、まだ終わっていない古い作業の一部だけを限定して遠隔状態と照合した。ルームごとに結果を短時間共有し、一度に確認する数も制限した。失敗した作業では、保存していなかったプロンプト全文を復元しなかった。整理済みの依頼要約、以前の作業種別、ペット選択だけを新しい入力画面へ戻し、利用者が読み直して同意した後に新しい作業を作った。
状態カードが正確になったのは、すべてをより頻繁にポーリングしたからではない。状態がコピーであることを認め、いつ、どの範囲で原本と照合するかを決めたからだった。
隔離作業フォルダが消え、安全装置も一度止まった
二つ目の失敗は、プロジェクトの恒久的な基準パスとして、一回限りの隔離作業フォルダを誤登録した事件だった。作業ごとの隔離フォルダは、仕事が終われば片付けられるのが正常だ。しかし実行環境は削除済みの一時パスを原本リポジトリだと信じ続け、新しい作業はモデルを呼ぶ前に連続して失敗した。
設定値が「Gitリポジトリに見える」だけでは足りなかった。恒久的なプロジェクトルートなのか、別のチェックアウトにぶら下がる一時作業フォルダなのかまで確認する必要があった。その後、起動時にすべてのプロジェクトルートを検査し、作業準備時にも再検証した。誤設定はキューを消費する前に、明確な設定エラーとして止まるようにした。
別の編集作業では、Windowsの隔離補助機能が編集ツールに必要なファイアウォールポリシーを準備できず、何度も失敗した。同じ実行の後半では環境が回復したものの、元の編集は自動再開されなかった。
最も簡単な回避は隔離を切ることだっただろう。私たちはそうしなかった。実際の書き込みを作業前に確認する事前点検、一時的な初期化失敗への制限付き再試行、同じ隔離フォルダで編集段階を続ける復旧経路を、より安全な復旧へ向けた今後の課題として残した。
安全装置が原因で失敗した日にも、その安全装置を外さない。承認型の開発自動化で最も守りにくい原則の一つだった。
ペットを増やすと、協働より待ち時間が増えた
最初は、進行、企画、デザイン、開発、レビュー、文書化を複数のペットに分ければ、より良い結果になると思った。画面でも複数のペットを選び、プロンプトはそれぞれの役割が自分の段階を終えて次へ渡すよう指示していた。
ある障害分析では、基本実行と役割別実行を合わせて五つのSDKセッションが作られ、15分の制限を使い切った。別の範囲が狭い単一実行は約42秒で終わっていたが、依頼が異なるため直接の性能比較ではない。それでも、役割ごとにセッションを分ける構造が待ち時間、ログ、トークン使用量を増やす原因になったことは明らかだった。
私たちは「役割」の意味を変えた。
- 役割は、ペットが使えない機能を決める権限ではない。
- 役割は、結果でより注意深く見る専門領域である。
- 一つの依頼は、原則として一匹のペットと一つのSDKスレッドが最後まで担当する。
- 二つ目のモデルによるレビューが必要なら、危険度の高い結果が出た後に別のレビュー作業として依頼する。
これはペット同士の協働を諦めたのではない。同時に多く呼び出すことを協働だと取り違えなくなったのだ。必要な文脈を一つの実行へ集め、責任主体を明確にするほうが、小さなPoCの資源と利用体験に合っていた。
Delivery Runnerが止まっても、権限を一つにしなかった
週の後半、コード作業が終わり承認も受けたのに、リポジトリ反映キューが動かない問題が起きた。コード実行Agentは動いていたが、分離されたDelivery Runnerが止まっていた。ログイン時にだけ起動する方式だったため、異常終了すると次のログインまで眠ったままになる可能性があった。
Delivery Runnerにも制限付きの自動再起動監視と定期的な復旧確認を加えた。すでに一つ動いていれば新しいインスタンスは作らず、ログにはプロンプトや資格情報を残さなかった。
同じ頃、小さなゲートウェイサーバーが停止し、再起動後もサービスがすぐ戻らない障害があった。異常停止の瞬間、追記専用記録の最後の一行が不完全なまま残り、起動時に履歴全体を読む処理がその一行で止まった。正常な記録は残し、不完全な末尾だけを隔離して復旧した。履歴の途中の破損まで黙って読み飛ばす自動復旧は許可しなかった。
二つの障害が示した事実は同じだった。プロセスが「実行中」と表示されること、サーバーの電源が入っていること、HTTPSが応答することは、作業フロー全体が健全であることとは違う。Agent、Delivery Runner、ゲートウェイ、最後に成功した作業を別々に観測する必要があった。
コストを見るために会話内容を保存する必要はなかった
AI作業が増えると、利用量を利用者、グループ、ペット、モデル、作業種別ごとに集計できる追記専用台帳も作った。重要なのは、何を記録しなかったかだった。
プロンプト、応答、チャット原文、文書内容は利用量台帳へ入れなかった。代わりに、利用者・グループの範囲、ペット、モデル、実行種別、結果との接続識別子、入力・キャッシュ入力・出力・推論出力トークン、状態、時刻といった集計メタデータだけを記録した。固有の結果キーにより、再読み込みや複数サーバーからの同時状態確認でも、同じ利用量を重複保存しないようにした。
この数値はコスト観測のための利用量であり、請求額そのものとは断定しなかった。価格、契約、キャッシュ方針によって変わるからだ。計測の失敗も補助経路の失敗として扱い、完了した会話や開発作業まで失敗にしなかった。
コストの可視化と非公開会話の保持を交換条件にする必要はなかった。何を計算するかを先に定義すれば、原文なしでも必要な運用シグナルを作れた。
失敗が残した開発パートナーのチェックリスト
この一週間をやり直すなら、次の順で確認する。
1. 会話と実行の間に明示的な人の操作を置く
自然言語から実行意思を推測しない。対象、範囲、求める結果を人が確認した後だけ、作業記録を作る。
2. 影響のある段階ごとに権限を分け直す
読み取り、編集、リポジトリ書き込み、マージ、本番反映を一つの「開発権限」にまとめない。各段階に必要な主体、資格情報、承認根拠を分ける。
3. 画面の状態を、外部の事実を映す投影として扱う
実行環境とアプリの状態はずれるものと考える。制限された再照合、冪等な更新、明確な復旧入口を設計する。
4. 一時作業フォルダの寿命をプロジェクト設定から分ける
恒久チェックアウトと作業ごとの隔離フォルダを、異なる種類として検証する。片付けは自動化しても、未反映の変更は保存要否を判断する前に削除しない。
5. 複数のエージェントより先に、一つの責任主体を検証する
役割の数は品質ではない。一つの実行に最後まで責任を持たせ、リスクが必要とする場合だけ独立レビューを別作業として加える。
6. 拒否を終点ではなく、次の入力として残す
理由、開始ブランチ、最終対象を分けて保存する。過去の失敗を成功で上書きせず、新しい履歴として続ける。
7. 復旧が不便でも資格情報の境界を統合しない
分離した実行環境が止まったら、その実行環境を復旧する。障害を早く消すためにAIプロセスへリポジトリ・本番反映資格情報を集めない。
開発パートナーになった瞬間
7月22–28日の終わりにも、AIペットは完全な自律開発者ではなかった。自ら本番を変えず、拒否された判断を消さず、人が見ていない変更を基準ブランチへ入れなかった。
その代わり、もっと役に立つ存在になった。
人の普段の依頼を、明示的な作業提案として確認できるようになった。承認された範囲で隔離された変更を作り、確認可能な結果とフィンガープリントを残し、拒否理由を次の作業へ引き継げた。失敗したとき、どこで止まり、どう再開するかも少しずつ見えるようになった。
初めは、ペットにより多くの仕事を任せれば開発パートナーになると思っていた。振り返ると、逆だった。
どこまで進んでよいか、誰が次の扉を開くか、失敗をどう記録に残すかを一緒に決めたとき、初めてパートナーになった。
反応を残すと、重複防止のためランダムな識別子がこのブラウザーに保存される場合があります。

