AIコーディングエージェントによるGUIアプリ生成のベストプラクティス_20260720

Table of Contents

AIコーディングエージェントによるGUIアプリ生成のベストプラクティス_20260720

本書の目的: AIコーディングエージェント(Claude Code、Cursor、Copilot等)と協働してGUIアプリケーションを開発する際の、汎用的かつ実践的な方法論を提供する。

元になった事例: Electron + React + ローカルEmbedding + LLM API による Windows デスクトップ RAG アプリの開発記録。本書の各プラクティスは、この実証データと一般的なソフトウェア工学知識の両方に基づく。


目次

Part I: 戦略・プロセス編

  1. 開発プロセスの全体設計
  2. 技術スタック選定
  3. AIコーディングエージェントとの協働術
  4. ドキュメント駆動と知識管理

Part II: 設計・実装編

  1. アーキテクチャ設計の基本原則
  2. GUIフレームワーク固有の設計
  3. データ・永続化の堅牢性
  4. 外部依存の防御的設計
  5. LLM連携とプロンプトエンジニアリング
  6. エラーハンドリング・UX設計
  7. ログ・可観測性
  8. セキュリティ・秘密情報管理

Part III: 検証・リリース編

  1. テスト・検証戦略
  2. パッケージング・配布

Part IV: 実践ツール

  1. フェーズ別チェックリスト
  2. アンチパターン集

Part I: 戦略・プロセス編

1. 開発プロセスの全体設計

1.1 CLIファースト / レイヤード開発(最重要原則)

GUIから作り始めない。 以下の3層構造を意識し、下から順に完成させる。

Layer 1: コアロジック   … 副作用のない純粋な関数群(抽出・変換・検索・生成)
Layer 2: CLIラッパー    … コアロジックをコマンドとして呼び出す薄い層
Layer 3: GUIラッパー    … IPC越しにコアロジックを呼ぶだけの薄い層

この順序には複数の相乗効果がある:

効果 説明
検証可能性 エージェントがGUIなしに機能を自動テストできる。「できたかどうか」をエージェント自身が確認できるため、人間の目視確認コストが激減する
問題の分離 バグが「コアロジック由来」か「GUI/IPC由来」かを即座に切り分けられる
テスタビリティ 純粋関数はユニットテストが容易。CLIはE2Eテストのハーネスになる
デバッグ効率 GUI起動・操作なしで再現できるため、エージェントとの「症状→修正→検証」ループが高速に回る

📌 事例: cli.mjs ingest <file> が「DB保存なし・テスト用」の副作用のないコマンドとして実装され、パイプライン完走検証に活用された。最終的にCLIは全機能をカバーするテストスイート(test-all)となり、GUI実装前にコア機能の安定性が担保された。

1.2 「常に動くもの」を維持するフェーズゲート

  • 各フェーズの終了時に必ずエンドツーエンドで動作する状態を作る。半完成の機能を抱えたまま次に進まない
  • フェーズが変わるたびに「なぜ前のフェーズがダメだったか」を1行でも記録する。この変遷ログがあると、エージェントが過去に却下された構成を再提案するのを防げる

📌 事例: Phase 1: Renderer実行 → ESM/CJS競合で挫折 / Phase 2: CDN読み込み → config.json破損で挫折 / Phase 3: Main集約 → 安定稼働 という変遷記録が、最終設計の妥当性を裏付ける資料になった。

1.3 MVP思考とスコープ管理

  • 最初のバージョンは「価値仮説を検証する最小の1本道」に絞る。事例では「PDF取込→評価→生成」という1フローがMVPだった
  • エージェントは指示していない改善(余計な抽象化・機能追加・設定項目)を盛り込みがち。スコープ外の提案は記録だけして実装は後回しにする
  • 「残存課題リスト」を仕様書内に維持し、意図的にやらないことを明示する(例: 「OCR未実装」「Chrome PDFはPhase2」)

2. 技術スタック選定

2.1 「使い慣れたスタックからの乖離コスト」をリスクの第一予測因子とする

開発で詰まる場所の多くは「アプリ固有の複雑さ」ではなく、エコシステム固有の癖に集中する。選定時に以下を自問する:

  1. このスタックのプロセスモデル/実行モデルを説明できるか?(例: ElectronのMain/Renderer分離)
  2. 配布・パッケージングの方法を知っているか?(例: NSIS、コード署名、OS権限)
  3. 主要な重量級依存のモジュール形式・ランタイム要件を把握しているか?

📌 事例: 13件のエラーの大半は「GUIアプリ一般の難しさ」ではなく「Electron/Node.jsのプロセスモデル(ESM/CJS競合、Workerパス解決、dynamic require)」と「Windowsネイティブ配布(winCodeSign、管理者権限)」に集中していた。React画面実装自体はWeb実務経験と相性が良くほぼ問題にならなかった。

乖離が大きい場合の対処:

  • (a) 該当領域のチートシートを事前に1枚作成してから着手する(下記2.4)
  • (b) 普段のエコシステムに寄せた代替を検討する(例: Python中心の開発者なら Electron の代わりに pywebview + ローカル FastAPI)
  • (c) それでも乖離スタックを選ぶ場合は、検証用の最小プロトタイプを本実装前に作り、リスキーな依存(ESM-onlyライブラリ等)の動作確認を済ませる

2.2 依存ライブラリの採用前チェックリスト

重量級依存は採用に以下を確認する:

確認項目 方法 回避できる事故
ESM-only / CJS-only / デュアル package.json"type"exports フィールド、npm info <pkg> ERR_REQUIRE_ESM 系の設計手戻り
Node.js API依存(fs等) ライブラリのブラウザ対応表記、issues検索 バンドル後の Dynamic require of "fs"
動的import/requireの使用 ソース検索、バンドラの警告 バンドラの静的解析破綻
Worker/追加アセットの有無 ドキュメント、配布ファイル構成 Cannot find module '*.worker.*'
ネイティブモジュールの有無 binding.gyp、prebuild有無 クロスプラットフォームビルド失敗

2.3 バンドラ(Vite/webpack等)の静的解析の限界を理解する

  • 動的import・動的requireに依存するライブラリは、バンドラによる静的解析でパス解決が破綻しうる
  • 対処パターンを事前に知っておく: external 指定によるバンドル除外 → require.resolve() で絶対パス取得 → pathToFileURL()file:// URL化 → 動的import、というバイパス手法
// Viteの静的解析を完全にバイパスして ESM-only ライブラリを読み込む定石
const resolved = require.resolve('some-esm-lib/entry.mjs')
const url = pathToFileURL(resolved).href
const lib = await import(url)

2.4 「最初から正しい構成」チートシート

フレームワークには、試行錯誤の末にたどり着く「正解構成」が存在することが多い。着手前に以下を明文化する:

  • どのレイヤー/プロセスで何を実行するか
  • 重量級依存はどこに置くか
  • 通信インターフェース(IPC/HTTP等)の型定義方針

📌 事例: 最終構成 Main Process (CJS): 全処理集約 / Renderer (ESM): 純粋UIラッパー・重量級importゼロ は、3フェーズの試行錯誤なしに初期設計として採用できれば、多くのエラーの手戻りを回避可能だった。


3. AIコーディングエージェントとの協働術

3.1 根本原因の「形を変えた再発」を検出する(メタ認知ルール)

エージェントは目の前のエラーメッセージに局所パッチを当てがちである。以下のルールを人間側に課す:

「2回目の類似エラーで立ち止まり、3回目が出たら設計原則から見直す」

  • エラーメッセージが違っても、発生レイヤー・依存・操作が同じなら同一根本原因を疑う
  • 局所修正が3連続で別エラーを生んだら、それは設計が実行モデルと不整合を起こしているサインである

📌 事例: ERR_REQUIRE_ESM → Workerパス解決失敗 → workerSrc未指定 → Dynamic require of "fs" は4つの別エラーに見えて、実質すべて「ESM-onlyライブラリとElectronのCJSプロセスモデルの不整合」という同一原因だった。個別対処ではなく「Main Process集約」という設計変更で一括解決した。

3.2 コンテキストエンジニアリング: 「現在の正しい構成」だけを渡す

  • 試行錯誤の過程をコンテキストに残したまま次の指示を出すと、エージェントは古い構成の残骸を混ぜた提案をし続ける
  • 構成が確定するたびにドキュメントを更新し、エージェントにはその最新版のみを参照させる
  • 長いセッションでは定期的にコンテキストを圧縮・リセットし、「現在地(確定済み設計・未解決課題・次のタスク)」だけを要約して引き継ぐ
  • コードベース全体を闇雲に読ませず、関連ファイル + インターフェース定義(型・IPC一覧)をピンポイントで与える方が精度が上がる

3.3 タスク分割の粒度

  • 1タスク = 1つの検証可能な変更に分割する(例: 「PDF抽出を実装してCLIで確認」は良い粒度。「取込〜生成まで全部」は悪い粒度)
  • 大きなタスクほどエージェントの出力品質が落ち、検証も困難になる
  • 各タスクには完了条件(検証コマンドと期待出力)を必ず添える: 「実装して」ではなく「実装して node cli.mjs ingest sample.pdf で ○○ が出力されることを確認して」

3.4 エージェントの能力・限界の前提

  • エージェントは実環境で実行して初めて判明する事実(OS依存、ランタイム依存、外部APIの実際の応答)を推測で埋めがち。実行ベースの検証を必須化する
  • 無料/軽量モデルでのエージェント利用は「プロトタイピング速度」と引き換えに「指示追従性・精度の保証なし」と心得る
  • エージェントの提案は採用・却下の判断を人間が行い、却下理由を記録する(同じ提案の再提示を防ぐため)

3.5 gitによる安全網

  • 動作確認が取れるたびに即コミット。エージェントは大胆に既存コードを書き換えるため、いつでも戻れる地点を高頻度で作る
  • エージェントへの大きな変更指示の前には必ずコミットする
  • コミットメッセージに「なぜ」を書くと、後でエージェントへの経緯説明資料になる

4. ドキュメント駆動と知識管理

4.1 仕様書は「事前計画書」ではなく「living document」として運用する

  • 実装結果・設計変更・判明した制約をその都度仕様書に反映する
  • 改訂履歴を残す(何が変わったかが後の判断材料になる)
  • 実装完了時点で仕様書は「実態の正確な記述」になっており、次のプロジェクト/エージェントへの最高の引き継ぎ資料となる

📌 事例: 仕様書改訂履歴に「実装結果を反映: Main Process集約、safeStorage撤廃、評価システム詳細化、CLI追加…」と記録され、後続の評価・改善作業の基盤となった。

4.2 仕様書に含めるべき項目(エージェント協働向け)

  1. アーキテクチャ図と処理フロー(実装ベースで)
  2. データスキーマ定義(型・デフォルト値・nullの意味)
  3. インターフェース一覧(IPCチャンネル/APIエンドポイントの方向・payload)
  4. エラーハンドリング表(ケース × UX × 処理 × ログ)
  5. 既知の制約事項(「〜非対応」を明示)
  6. 検証用CLIコマンド一覧
  7. 環境構築・ビルド手順(権限要件の注記含む)

4.3 ADR(Architecture Decision Records): 却下した案も記録する

  • 「なぜこの設計か」だけでなく「なぜ別案を却下したか」を残す。エージェントは却下された案を再提案する傾向がある
  • 1行でもよいので理由を書く(例: 「safeStorage暗号化 → 撤廃。OS間・ユーザー間で復号失敗リスクがあり、単一ユーザーデスクトップ用途に過剰」)

Part II: 設計・実装編

5. アーキテクチャ設計の基本原則

5.1 状態と副作用の分離

  • コアロジックは副作用のない純粋関数として設計する(入力→出力が再現可能)
  • 副作用(ファイルI/O、ネットワーク、DB書込、時刻取得)は層の外縁に押し出す
  • この分離により、テスト容易性・エージェントによる検証容易性・デバッグの局所性がすべて向上する

5.2 遅延初期化と「全経路チェック」

  • 重いリソース(モデル、DB接続)は遅延初期化が有効だが、初期化保証は全公開関数の入口で一貫して行う
  • 「一度動いたから大丈夫」は禁物。全呼び出し経路を洗い出して確認する

📌 事例: 起動時に getStats()ensureDb() 未呼出で空配列を参照し、101件のデータがあっても0件表示された(エラー8)。対処は「全エクスポート関数の冒頭に ensureDb() を追加」——入口の網羅が本質だった。

5.3 設定・定数・プロンプトの集約

  • 型定義は shared/types.ts のように共有モジュールに集約し、境界(IPC/API)両側で同じ型を使う
  • プロンプト・定数・制約条件も1ファイルに集約すると、エージェントへの「変更指示の着地点」が明確になり、バージョン変遷(v1→v5)の管理も容易になる

6. GUIフレームワーク固有の設計

6.1 プロセス分離型フレームワーク(Electron/Tauri等)の鉄則

  • Node.js API・ネイティブ依存を使う処理は、最初から特権プロセス(Main)に集約すると決め打ちする
  • 描画プロセス(Renderer)は「表示とイベント送信だけ」の薄い層に保つ
  • 「どっちでも動きそう」な処理ほど、配置を曖昧にすると後で大きな手戻りになる

6.2 セキュアなIPC設計(Electronの場合)

  • contextIsolation: true / nodeIntegration: false を前提に、contextBridge最小限のAPIのみ公開
  • IPCチャンネル設計を表形式で明文化する(チャンネル名・方向・payload・用途)
  • Renderer/Main間で共有する型を shared/ に置き、インターフェースのずれを構造的に防ぐ

6.3 GUIアプリの非同期UX

  • 長時間処理(モデルロード、Embedding、API呼出)は進捗表示と処理中の操作ブロック方針を設計に含める
  • 可能ならキャンセル手段を用意する。少なくとも「処理中である」ことがユーザーに伝わる状態表示は必須
  • 重い初期化はアプリ起動をブロックせず、遅延ロード+状態表示で体感速度を守る

7. データ・永続化の堅牢性

7.1 「ファイルが存在する」は「中身が正しい」を意味しない

  • 大容量アセット(モデル等)を初回DLする設計では、DL処理に検証を組み込む:
    • リダイレクトの多段追跡(3xxを5段程度まで)
    • 内容の妥当性検証(JSONならパース可否、バイナリならサイズ/マジックナンバー/ハッシュ)
  • ディレクトリ構造・同梱ファイルの期待仕様(onnx/model.onnxtokenizer_config.json等)をライブラリの期待に合わせて確認する

📌 事例: HuggingFace CDNのリダイレクトを追跡できず、config.json"Temporary Redirect..." というHTMLが保存されていた(エラー5)。ファイル存在チェックだけでは発見できない。

7.2 書き込みの原子性とバックアップ

  • 自前のJSON永続化等は書き込み中のクラッシュで破損しうる前提で設計する:
    1. atomic write: 一時ファイルに完全に書いてから rename(renameは原子的)
    2. 自動バックアップ: 直近N世代を保持し、パース失敗時に自動復元
  • 「破損したらどう検出し、どう復旧するか」をエラーハンドリング表に明記する

7.3 外部入力ファイルの多様性を最初から想定する

  • 「動作確認済み」を単一の生成経路で判断しない
  • 同じフォーマットでも生成元によって内部構造が大きく異なる(PDF、CSV、画像等すべてに言える)
  • 対応可否の判別ロジックと、非対応時のユーザー誘導をセットで設計する

📌 事例: Chrome「PDFに保存」はテキストをベクターパス化するため抽出結果が全0件、Firefox + MS Print to PDF は正常。単一経路の検証だけではこの差に気づけない(エラー9, 10)。


8. 外部依存の防御的設計

8.1 非決定的な外部要素をシステムの信頼の前提にしない

信頼できないもの: LLM出力、外部APIの応答形式、ネットワーク、ユーザーの入力ファイル、無料枠のレート制限。それぞれに検証→フォールバック→部分的成功の設計を用意する。

8.2 リトライ設計

  • 一時的失敗に対しては指数バックオフ付きリトライ(回数上限あり)を標準装備する
  • リトライしても構造的に成功しないケース(モデルが形式を出せない等)はリトライでなく方式変更で解決する
  • リトライ状況はログに出す([WARN] リトライ N/3

8.3 HTTP・文字コードの地雷を避ける

  • HTTPヘッダーに非ASCII文字を直接使わない(RFC的にByteString制約がある)。アプリ名等をヘッダーに載せる設計はASCII別名を用意する
  • URLエンコード、BOM、改行コード(CRLF/LF)など、テキストの境界面では常にエンコーディングを意識する

📌 事例: X-Title: 日本語アプリ名 がASCII制約に違反し ByteString エラー(エラー6)。暗号化データの混入でも同エラーが再発した(エラー7)。


9. LLM連携とプロンプトエンジニアリング

9.1 第一原則: LLMの出力形式を信頼しない

  • 構造化出力(JSON等)はモデル機能差が大きいresponse_format: json_object 等の機能は対応モデルを確認してから設計に組み込む
  • 後処理(サニタイズ/抽出)は保険ではなく必須コンポーネントとして最初から設計に組み込む
  • 「プロンプトだけで完全な出力制御ができる」という前提を置かない

9.2 堅牢な出力契約の設計

  • パースが甘くても成立するシンプルな形式を選ぶ(JSON → TAGS: a, b 形式への変更は好例)
  • フォールバック可能な形式を階層化する: 理想形式 → 簡易形式 → 正規表現抽出 → デフォルト値
  • 正確性が必須な要素(URL・日付・固有名詞・数値・ID)はLLMに生成させず、後付けする

📌 事例: URLをプロンプトに含めず、生成後に末尾へ後付けする方式(v5)で、「プレースホルダー誤出力」(v3の失敗)と「URL捏造」(v4の失敗)という2つのリスクを同時に回避した。この発想は日付・金額・人名など全般に応用できる。

9.3 プロンプト設計の実践知

  • 出力テンプレートはプロンプト末尾に置く(LLMは最後のトークン付近を最も重視する傾向)
  • Few-shot例は有効だが、思考が長いモデルでは例の模倣が推論の長文化を招くことがある。効果を計測してから採用する
  • max_tokens は推論トークンの消費を見込んで設定する(推論が長いモデルで小さすぎると本文が途中切断される)
  • stop シーケンスは万能ではない。後処理と併用する
  • 制約は絞る。文字数指定・文数指定・構成指定を同時に課すと守備率が下がる。重要な制約から優先順位をつけ、守れない制約は廃止または後処理に回す
  • プロンプトの変更はバージョン管理し、各版の成否を記録する(v1〜v5の変遷表のように)

9.4 モデル選定のプロセス

  • 無料/軽量モデルでのプロトタイピングは速いが、指示追従性が要件の機能は本番品質の保証にならない前提で進める
  • 要件が固まった時点で、候補モデルをCLIレベルで横断的に試す仕組みを作る(モデル名を設定値にしておき、同じ入力で出力品質を比較)
  • モデルは交換可能な設計にする(APIクライアント層の抽象化)

9.5 RAG設計の注意点

  • 自己類似性バイアス: 入力テキストと同一ソースのチャンクが検索上位を独占しがち。ソース多様性フィルタ(各ソースから1件ずつ取得→不足分を補完)を初期設計から組み込む
  • スコアリングへのメタデータ活用(例: score = cosine_similarity * (1 + rating/5) のような評価重み)は、Human-in-the-loopデータと相性がよい
  • 検索結果の出典をプロンプト内で明示([ソース名] 表記)すると、生成の根拠追跡とユーザー検証が容易になる
  • RAGの効果はデータ蓄積に依存するため、「データが少ない初期状態での挙動」も設計・説明に含める

10. エラーハンドリング・UX設計

10.1 エラーメッセージは「原因説明」ではなく「ユーザーが取れる行動」を示す

  • 非エンジニア向けアプリでは特に重要。技術的原因の説明より、具体的な解決手順を提示する
  • 良い例: 「Firefoxで表示 → Microsoft Print to PDF で出力したPDFを使ってください」
  • 悪い例: 「PDF text extraction failed: items=0」

10.2 部分的フォールバック: アプリ全体を止めない

  • 二次機能の失敗がコア機能を巻き込まないように設計する
  • 例: タグ提案(二次機能)が失敗 → 空配列 + 手動入力へ切替。DB登録・生成(コア機能)は継続可能
  • 各機能について「失敗時の degraded mode(縮退動作)」をエラーハンドリング表で定義する

10.3 エラーハンドリングの設計を表で管理する

仕様書に以下の形式の表を含めると、実装の抜け漏れを防げる:

ケース UX(ユーザーに見せるもの) 内部処理 ログ
APIキー未設定 設定画面への誘導 生成処理を中断 [ERROR] [API] APIキー未設定
入力ファイル非対応 対応手順の提示 処理中断・状態復帰 [ERROR] [PDF] 抽出失敗
二次機能失敗 手動入力フォーム フォールバック継続 [WARN] リトライ N/3
DB破損 復元通知 バックアップから自動復元 [ERROR] [DB] 破損検出、復元

10.4 遅延登録(確定まで永続化しない)パターン

  • ユーザーが評価・確認するまでDBに書き込まない「遅延登録」は、Human-in-the-loop系UIで有効
  • 「一時状態(メモリ)→ 確定操作 → 永続化」の流れを明示すると、中途半端なデータ混入を防げる

11. ログ・可観測性

11.1 GUIアプリこそログへの投資効果が高い

  • ブラウザのDevToolsのような気軽な確認手段がないデスクトップアプリでは、アプリ内蔵のログビューア(tail表示タブ)の有無がデバッグ効率を大きく左右する
  • ログは「開発者のデバッグ用」だけでなく「エージェントが自己診断するための目」でもある。エージェントにログを読ませて原因分析させるワークフローが成立する

11.2 ログ設計の実践

  • 処理の実行"前"にGUIイベントをログする: 処理途中でクラッシュしても「何をしようとしていたか」が追跡できる
  • 構造化: タイムスタンプ・レベル・モジュールタグを統一([INFO] [Embed] ...)。grep/フィルタが効く
  • APIの生応答と後処理結果の両方を残す: raw responsecleaned output を両方記録すると、プロンプト問題か後処理問題かを切り分けられる
  • ログ出力先を環境変数で上書き可能にする(例: MYAPP_LOG_PATH): CLI/自動テストから検証しやすくなる
  • CLIからtailできるようにする(例: node cli.mjs logs 50 -f): GUIを起動せずに観測できる

11.3 エンドユーザー向けの配慮

  • エラーの詳細はログに集約し、GUIにはユーザーの行動指針だけを表示するという責務分離を明確にする
  • サポート時に「ログファイルの場所」をユーザーに伝えられるよう、ログパスをアプリ内で確認可能にする

12. セキュリティ・秘密情報管理

12.1 OS標準の暗号化の特性を理解してから採否する

  • OS標準の暗号化API(Electron safeStorage、Windows DPAPI、macOS Keychain)は、OSユーザーアカウントに紐づいた鍵管理であることが多い
  • 含意: 別マシン・別ユーザーへの設定ファイル移行で復号失敗する。バックアップからの復元でも同様
  • 「暗号化 = 安全」ではなく「この暗号化方式のポータビリティ制約は何か」を事前に把握して採否を決める

📌 事例: safeStorage で暗号化したAPIキーが復号時に破損し、結局暗号化を撤廃して平文保存へ。単一ユーザーのデスクトップアプリという脅威モデルを考えれば合理的な判断だが、事前に制約を把握していれば手戻りを回避できた。

12.2 平文保存を選ぶ場合の低コスト防御

脅威モデル上「平文で許容」と判断した場合でも、以下は実施する:

  • 設定ファイルのファイルパーミッション制限(可能な範囲で)
  • .gitignore への追加(秘密情報のリポジトリ混入防止。最重要)
  • UI上での明示: 「APIキーは平文でローカルに保存されます」と告知
  • 秘密情報をログに出力しない(マスク処理)

12.3 その他のセキュリティ基本

  • IPCの公開面を最小化する(6.2参照)
  • 外部入力(PDF、テキスト)のサイズ上限・形式検証を設ける
  • 依存ライブラリの既知脆弱性を npm audit 等で定期的に確認する

Part III: 検証・リリース編

13. テスト・検証戦略

13.1 検証の階層をCLI中心に組み立てる

レベル1: ユニットテスト      … 純粋関数(チャンク分割、後処理、スコア計算)
レベル2: CLI結合テスト       … コマンド実行 → 期待出力の確認(パイプライン完走)
レベル3: スモークテスト      … GUI起動 → 主要1フローの手動/半自動確認
  • エージェントが自分で実行して確認できるレベル1-2を先に作る。これがエージェント協働の速度を決める
  • 副作用のない「ドライラン」コマンド(例: ingest <file> = DB保存なし)を用意すると、安全に反復検証できる

13.2 実データでの検証

  • 理想化されたテストデータだけでなく、実際の運用に近い多様な入力で検証する(7.3のPDF多様性の教訓)
  • 失敗した入力は回帰テストケースとして保存する

13.3 検証結果の記録

  • 「何を確認したか」を作業報告書に残す(実施済み機能一覧の✅表など)
  • 確認手順は再現可能な形(コマンド列)で記録する

14. パッケージング・配布

14.1 ビルド環境の要件を開発初期に確認する

  • パッケージング特有の権限・環境要件(例: electron-builder + NSIS では winCodeSign の symlink 展開のため管理者権限 or Developer Mode が必要になる場合がある)は、リリース直前ではなく初期に一度ビルドを通して確認する
  • ビルドコマンドに権限要件の注記を添える

14.2 署名と配布ポリシー

  • コード署名なし配布の影響(Windows SmartScreen警告、macOS Gatekeeper)を織り込む
  • 個人利用・少数配布なら許容、広い配布を見据えるなら署名コストを将来計画に入れる
  • インストーラのUX選択(oneClickか、インストール先変更可か、ショートカット作成等)も配布対象に合わせて決める

14.3 大容量アセットの同梱戦略

  • モデル等の大容量ファイルはリポジトリ外に置き、DLスクリプト or extraResources で同梱する設計を早めに確定する
  • 同梱ファイルのパス解決は、開発時とパッケージ後で変わる点に注意(process.resourcesPath 等の考慮)

14.4 リリース前チェック

  • クリーン環境(開発依存のない状態)でのインストール→起動→主要フロー確認
  • データ保存先(%APPDATA% 等)の作成と権限の確認
  • ログ・設定・DBファイルが期待通りの場所に生成されること

Part IV: 実践ツール

15. フェーズ別チェックリスト

企画・設計フェーズ

  • [ ] MVPの「1本道フロー」を一文で書ける
  • [ ] 技術スタックと自分の経験の乖離度を評価した
  • [ ] 重量級依存のモジュール形式(ESM/CJS)・Node API依存・Worker要否を確認した
  • [ ] 「正解構成」チートシート(どの層で何を動かすか)を1枚書いた
  • [ ] リスキーな依存の最小プロトタイプで動作確認した

実装フェーズ

  • [ ] コアロジック(純粋関数)→ CLI → GUI の順で作った
  • [ ] 各タスクに「検証コマンドと期待出力」を添えてエージェントに指示した
  • [ ] エージェントに渡すコンテキストは「現在の正しい構成」だけに絞った
  • [ ] 動作確認のたびにコミットした
  • [ ] 類似エラー2回目で根本原因を疑い、3回目で設計を見直した
  • [ ] 却下した案と理由を記録した

堅牢化フェーズ

  • [ ] DL/読込処理に内容検証(パース可否・サイズ・ハッシュ)を入れた
  • [ ] 永続化に atomic write + バックアップ復元を入れた
  • [ ] 全公開関数の入口で初期化保証(遅延初期化)を確認した
  • [ ] 外部APIにリトライ+フォールバック+部分的成功の設計を入れた
  • [ ] LLM出力の後処理(サニタイズ/抽出)を実装した
  • [ ] 正確性必須の要素(URL・日付等)はLLM生成でなく後付けにした
  • [ ] エラーハンドリング表(ケース×UX×処理×ログ)を完成させた
  • [ ] 処理前ログ・構造化ログ・ログビューア・CLI tail を実装した

リリースフェーズ

  • [ ] パッケージングを初期に一度通し、権限要件を確認した
  • [ ] クリーン環境でインストール→主要フローを確認した
  • [ ] 署名なし配布の影響を把握し、ポリシーを決めた
  • [ ] 仕様書を実装実態に合わせて更新し、残存課題を明記した

16. アンチパターン集

アンチパターン 症状 処方箋
GUIファースト 動作確認にGUI操作が必要で検証ループが遅い コアロジック+CLIを先に作る
局所パッチの連鎖 エラーを直すたび別エラーが出る 同一レイヤーの連続エラーは設計不整合を疑う
古い構成の混入 エージェントが却下済み設計を再提案する 最新ドキュメントのみ渡す・却下理由を記録
形式過信 LLMのJSON出力をそのままパースして例外 後処理・簡易形式・フォールバックの多重化
単一経路の動作確認 特定の生成元のファイルだけで「OK」と判断 実データの多様性を最初からテストに含める
存在チェックのみ DLしたファイルがHTMLリダイレクトページ 内容検証(パース/サイズ/ハッシュ)を必須化
暗号化盲信 OS標準暗号化で復号失敗・ポータビリティ喪失 脅威モデルとポータビリティ制約を事前評価
技術的エラーの垂れ流し ユーザーが何をすべきか分からない 行動指示型メッセージ + 詳細はログへ
スコープクリープ エージェントの提案を全部実装して収拾がつかない MVP一本道 + 残存課題リスト運用
リリース直前ビルド 配布ビルドが権限/環境問題で失敗 初期に一度ビルドを通す

本書の要約(エッセンス10か条)

  1. GUIから作るな。コアロジック→CLI→GUIの順で、常に検証可能な状態を保て
  2. 技術スタックの「経験からの乖離度」が最大のリスク予測因子。乖離分はチートシートと最小プロトタイプで埋めろ
  3. エージェントには「現在の正しい構成」だけを渡し、却下した案は理由とともに記録せよ
  4. 類似エラーの2回目で立ち止まれ。局所パッチの連鎖は設計不整合のサインだ
  5. LLMの出力形式を信頼するな。後処理は必須コンポーネント、正確性必須の値は後付けせよ
  6. 「ファイルがある」≠「中身が正しい」。外部データは内容検証を義務付けろ
  7. 永続化は書き込み中クラッシュを前提に設計せよ(atomic write + バックアップ)
  8. エラーメッセージは原因でなく行動を示せ。詳細は構造化ログに集約し、GUI内にtailビューアを内蔵せよ
  9. 動いたら即コミット。仕様書は実装実態に追随させ、living documentとして運用せよ
  10. 配布ビルドは開発初期に一度通せ。権限・署名・同梱アセットの問題は最後に出すな

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です