Skip to content

機能仕様書: CLI実行効率の最適化 #88

@akiojin

Description

@akiojin

Spec

機能仕様書: CLI実行効率の最適化

機能ID: SPEC-a7206673
作成日: 2026-02-23
ステータス: 実装中
入力: ユーザー説明: "CLI実行効率の最適化"

実行フロー (main)

1. 入力からユーザー説明を解析
   → 完了: "CLI実行効率の最適化"
2. 説明から主要概念を抽出
   → アクター: LLMユーザー、Claude Codeスキル
   → アクション: デーモン経由コマンド実行、バッチ実行、キュードレイン、バイナリ最適化
   → データ: DaemonRequest/Response、ConnectionPool、バッチコマンド列
   → 制約: TCP接続のライフサイクル管理、Unityメインスレッド制約
3. 不明確な側面: なし
4. ユーザーシナリオ&テストセクションを記入
   → 4つの主要ユーザーストーリー定義済み
5. 機能要件を生成
   → 20個の機能要件をテスト可能な形式で定義
6. 主要エンティティを識別
   → UnitydMode、DaemonRequest、DaemonResponse、ConnectionPool
7. レビューチェックリストを実行
   → 技術詳細は参考実装セクションに分離
   → 要件はテスト可能
8. 戻り値: SUCCESS (計画準備完了)

機能概要

LLMワークフロー中の unity-cli コマンド実行レイテンシを削減する機能。デーモンプロセスによるTCP接続の永続化、バッチコマンドによる一括実行、Unity側のキュードレインによるフレーム内複数処理、バイナリ最適化による起動時間短縮の4段階で改善する。

ビジネス価値

  • 累計レイテンシの削減: LLMが数十回のツール呼び出しを行うワークフローで、接続確立コストの排除により全体の応答時間を大幅に短縮
  • スループット向上: バッチ実行とキュードレインにより、複数コマンドを1回のIPC往復で処理し、フレーム内で一括完了
  • 起動時間の短縮: バイナリ最適化により、コマンド初回実行のコールドスタートを改善
  • 既存互換性の維持: デーモン未起動時は従来どおりのワンショット接続にフォールバックし、破壊的変更なし

ユーザーシナリオ&テスト

主要ユーザーストーリー

US-1: デーモン経由の高速コマンド実行

AS LLMユーザー
I WANT デーモンプロセスが保持するTCP接続を再利用してコマンドを実行したい
SO THAT 毎回の接続確立コストを排除し、コマンド実行のレイテンシを削減できる

受け入れ基準:

  • unity-cli unityd start でデーモンをバックグラウンド起動できる
  • unity-cli unityd stop でデーモンを停止できる
  • unity-cli unityd status でデーモンの稼働状態を確認できる
  • デーモン経由のコマンド実行は、接続済みTCPを再利用する
  • デーモン未起動時は従来のワンショット接続にフォールバックする
  • アイドルタイムアウト後にデーモンは自動終了する
  • (host, port)ごとにコネクションプールを管理する

US-2: バッチコマンドによる一括実行

AS LLMユーザー
I WANT 複数のコマンドを1回のCLI呼び出しで一括実行したい
SO THAT 複数ツール呼び出し時のIPC往復回数を削減できる

受け入れ基準:

  • セミコロン区切りまたはJSON配列でバッチコマンドを指定できる
  • バッチ内の各コマンドの結果をJSON配列で返却する
  • バッチ内の1つが失敗しても残りは実行継続する
  • デーモン経由・ワンショットの両方でバッチを利用できる

US-3: Unity側キュードレインによるフレーム内複数処理

AS Unity開発者
I WANT Unityが1フレーム内で複数のコマンドをまとめて処理してほしい
SO THAT コマンドあたりのフレーム待機コストを排除できる

受け入れ基準:

  • Unity側がキューに溜まったコマンドを1フレーム内で連続処理する
  • バッチ10コマンドのキュー消化が16ms以内に完了する
  • 既存の1コマンドずつの処理との後方互換性がある

US-4: バイナリ最適化による起動時間短縮

AS LLMユーザー
I WANT CLIバイナリの起動を高速化したい
SO THAT コールドスタート時のレイテンシを低減できる

受け入れ基準:

  • リリースビルドにLTO・codegen-units=1・strip等の最適化プロファイルを適用する
  • バイナリサイズが削減される
  • 既存テストがすべて通過する

受け入れシナリオ

  1. 前提 デーモン未起動、実行 unityd start結果 デーモンがバックグラウンドで起動し、接続を受け付ける
  2. 前提 デーモン起動済み、実行 tool call ping --json '{}'結果 デーモン経由でコマンドが実行され、ワンショットより高速に応答する
  3. 前提 デーモン未起動、実行 tool call ping --json '{}'結果 従来のワンショット接続で実行される(フォールバック)
  4. 前提 デーモン起動済み&600秒間アイドル、実行 何もしない、結果 デーモンが自動終了する
  5. 前提 デーモン起動済み、実行 バッチコマンド(3コマンド)、結果 3つの結果がJSON配列で返る
  6. 前提 Unity側キュードレイン有効、実行 バッチ10コマンド送信、結果 1フレーム内で全コマンドが処理される
  7. 前提 リリースプロファイル最適化済み、実行 cargo build --release結果 最適化済みバイナリが生成される

エッジケース

  • デーモンが異常終了した場合、クライアントはフォールバックに切り替わるか?
  • PIDファイルが残っているがプロセスが死んでいる場合、staleファイルをクリーンアップできるか?
  • 同一(host, port)に対して複数クライアントが同時接続した場合の挙動は?
  • バッチ内で接続エラーが発生した場合、どこまでの結果が返るか?
  • Unity側のキュードレインで処理時間がフレーム予算を超えた場合の挙動は?
  • デーモンのアイドルタイムアウト中に新しいリクエストが来た場合、タイマーはリセットされるか?

要件

デーモンライフサイクル機能要件

  • FR-001: システムは unityd start コマンドでデーモンプロセスをバックグラウンド起動できる必要がある
  • FR-002: システムは unityd stop コマンドでデーモンプロセスを停止できる必要がある
  • FR-003: システムは unityd status コマンドでデーモンの稼働状態(PID、接続数、稼働時間)を返却できる必要がある
  • FR-004: システムは unityd serve コマンドでフォアグラウンドデーモンを起動できる必要がある(内部用)
  • FR-005: デーモンは設定可能なアイドルタイムアウト後に自動終了する必要がある

自動モード機能要件

  • FR-006: システムはコマンド実行時に常にデーモンへの接続を試行し、成功すればデーモン経由で実行する必要がある
  • FR-007: デーモンへの接続が失敗した場合、従来のワンショット接続にフォールバックする必要がある
  • FR-008: システムはユーザー設定なしで常に auto 相当(接続試行→失敗時フォールバック)として動作する必要がある
  • FR-009: システムは UNITY_CLI_UNITYD 環境変数の値に依存せず、設定されていても挙動を変更しない必要がある

コネクションプール機能要件

  • FR-010: デーモンは(host, port)の組み合わせごとにTCP接続をプールする必要がある
  • FR-011: プール内の接続が切断された場合、新しい接続を再確立する必要がある
  • FR-012: プール内の接続は設定可能な最大数を超えない必要がある

バッチコマンド機能要件

  • FR-013: システムはセミコロン区切りの文字列でバッチコマンドを受け付ける必要がある
  • FR-014: システムはJSON配列形式でバッチコマンドを受け付ける必要がある
  • FR-015: バッチ実行の結果はJSON配列で各コマンドの結果を返却する必要がある
  • FR-016: バッチ内の1コマンドが失敗しても、残りのコマンドは実行を継続する必要がある
  • FR-017: バッチコマンドはデーモン経由・ワンショットの両方で動作する必要がある

Unity側キュードレイン機能要件

  • FR-018: Unity側は受信キューに溜まったコマンドを1フレーム内で連続処理する必要がある
  • FR-019: キュードレインはフレーム予算(16ms)を超えた場合に次フレームへ繰り越す必要がある
  • FR-020: 既存の1コマンドずつの処理フローとの後方互換性を維持する必要がある

非機能要件

性能要件

  • NFR-001: デーモン経由単発コマンドのオーバーヘッド(デーモンIPC + 接続再利用)は20ms以下であること
  • NFR-002: デーモン未起動時のフォールバックコストは現状のワンショット実行と同等であること
  • NFR-004: バッチ10コマンドのキュー消化は1フレーム(16ms)以内に完了すること

信頼性要件

  • NFR-003: デーモンのアイドルタイムアウトはデフォルト600秒であること
  • NFR-005: デーモンの異常終了後、staleなPIDファイル・ソケットファイルは自動クリーンアップされること
  • NFR-006: プール内の接続断は自動再接続により透過的にリカバリされること

互換性要件

  • NFR-007: デーモン接続試行はデフォルト有効だが、未起動・接続失敗時は既存のワンショットCLI動作を維持すること
  • NFR-008: バッチコマンドの個別結果フォーマットは単発実行時と同一であること

主要エンティティ

  • UnitydMode: デーモン利用方針を表す内部モード。現実装では auto(接続試行→失敗時フォールバック)固定で、UNITY_CLI_UNITYD の値に依存しない
  • DaemonRequest: クライアントからデーモンへのリクエスト。Tool実行、Batch実行、Status照会、Ping、Stopを含む
  • DaemonResponse: デーモンからクライアントへのレスポンス。成功/失敗フラグ、結果データ、エラーメッセージを含む
  • ConnectionPool: (host, port)をキーとするTCP接続のプール。接続の再利用と自動再接続を管理する

スコープ外

以下の機能は本仕様のスコープ外とし、別機能または将来のバージョンで対応:

  • TLS/認証付きデーモン接続(ローカル環境前提のため不要)
  • リモートホストへのデーモン公開(セキュリティ上の理由で対象外)
  • デーモンのマルチプロセスクラスタリング
  • WebSocket/gRPCへのプロトコル変更
  • Unity側のC# Jobsystem / Burst最適化

技術制約

  • 既存の lspd.rs がLSPデーモンとして同パターンを実装済みであり、unityd はこれをモデルとする
  • Unix環境ではUnixドメインソケット、Windows環境ではTCPを使用する(既存パターン踏襲)
  • Unity Editorはメインスレッドで動作するため、キュードレインもメインスレッド上で実行する
  • バイナリ最適化(LTO等)はビルド時間の増加を伴う

参考実装

本仕様の対象は新規実装です。既存のデーモンパターンを参考にします:

既存デーモン実装(モデル):

  • src/lspd.rs - LSPデーモン(start/stop/status/serve/ping パターン)
  • src/cli.rs - CLI定義(LspdCommandサブコマンド構造)

既存トランスポート実装:

  • src/transport.rs - UnityClient(TCP接続・フレームプロトコル)

Unity側実装(キュードレイン対象):

  • UnityCliBridge/Packages/unity-cli-bridge/ - Unity TCPサーバー

レビュー&受け入れチェックリスト

コンテンツ品質

  • ユーザー価値とビジネスニーズに焦点
  • 非技術関係者向けに記述
  • すべての必須セクション完成

要件完全性

  • 要件はテスト可能で曖昧さがない
  • 成功基準は測定可能
  • スコープが明確に境界付けられている
  • 依存関係と前提条件が識別されている

実行ステータス

  • ユーザー説明を解析済み
  • 主要概念を抽出済み
  • 曖昧さをマーク済み(なし)
  • ユーザーシナリオを定義済み
  • 要件を生成済み
  • エンティティを識別済み
  • レビューチェックリスト合格

ステータス: 実装中

Plan

実装計画: CLI実行効率の最適化

機能ID: SPEC-a7206673 | ステータス: 実装中

概要

LLMワークフロー中の unity-cli コマンド実行レイテンシを4フェーズで段階的に改善する。各フェーズはTDDで進め、品質ゲートを通過させる。


フェーズ依存関係

Phase 1: unityd daemon ─────┐
                             ├─→ Phase 2: batch command(Phase 1に依存)
Phase 3: Unity queue drain ──┘   (Phase 3は独立だがPhase 2と連携可能)
Phase 4: binary optimization ───── (独立、低リスク)

Phase 1: unityd デーモン(最優先)

目的: TCP接続を永続化するデーモンプロセスを導入し、コマンドごとの接続確立コストを排除する

モデル: 既存の src/lspd.rs(LSPデーモン)と同パターンで実装

設計方針

  • src/unityd.rs を新規作成。lspd.rs のアーキテクチャ(start/stop/status/serve/ping)を踏襲
  • CLIに Unityd サブコマンド(UnitydCommand enum: Start/Stop/Status/Serve)を追加
  • デーモン ↔ クライアント間は既存の改行区切りJSON(DaemonRequest / DaemonResponse
  • デーモン内部に ConnectionPool を保持し、(host, port) ごとに UnityClient を再利用
  • コマンド実行フローはユーザー設定なしで常に auto 相当(接続試行→失敗時フォールバック)で動作
  • UNITY_CLI_UNITYD は互換のため設定されていても挙動に反映しない
  • Unix: Unixドメインソケット、Windows: TCP(既存パターン)
  • アイドルタイムアウト: デフォルト600秒

TDDアプローチ

  1. RED: unityd startunityd status → running=true のテスト
  2. RED: unityd stopunityd status → running=false のテスト
  3. RED: デーモン経由の tool call が結果を返すテスト
  4. RED: デーモン未起動時のフォールバックテスト
  5. RED: UNITY_CLI_UNITYD=on/off/auto を指定しても挙動が変わらないテスト
  6. RED: アイドルタイムアウト後の自動終了テスト
  7. RED: ConnectionPool の接続再利用テスト
  8. GREEN: 最小実装で各テストを通過
  9. REFACTOR: lspd.rs との共通部分を抽出

品質ゲート

cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets

Phase 2: バッチコマンド(Phase 1 完了後)

目的: 複数コマンドを1回のCLI呼び出しで実行し、IPC往復回数を削減する

依存: Phase 1(デーモンのDaemonRequestにBatch型を追加)

設計方針

  • DaemonRequestBatch { commands: Vec<SingleCommand> } バリアントを追加
  • CLIに --batch オプションまたは batch サブコマンドを追加
  • セミコロン区切り文字列 → パースして Vec<SingleCommand> に変換
  • JSON配列入力もサポート
  • 結果は Vec<DaemonResponse> をJSON配列で返却
  • ワンショットモードでもバッチ実行を可能にする(接続1本で連続送信)

TDDアプローチ

  1. RED: セミコロン区切りパーサーのユニットテスト
  2. RED: JSON配列入力のパーサーテスト
  3. RED: バッチ3コマンドの実行結果が配列で返るテスト
  4. RED: バッチ内1コマンド失敗時に残りが継続するテスト
  5. GREEN: 最小実装
  6. REFACTOR: パーサーとエグゼキュータの分離

品質ゲート

cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets

Phase 3: Unity側キュードレイン(独立)

目的: Unity Editorが1フレーム内で複数コマンドを処理し、コマンドあたりのフレーム待機コストを排除する

依存: なし(Phase 1/2 と独立で着手可能だが、バッチ機能との連携で効果が最大化)

設計方針

  • UnityCliBridge/Packages/unity-cli-bridge/ のTCPサーバー処理を修正
  • 現在の「1フレーム1コマンド」を「キューが空になるまで連続処理」に変更
  • フレーム予算(16ms)を超えたら次フレームへ繰り越し
  • 既存の1コマンドずつの動作との後方互換性を維持

TDDアプローチ

  1. RED: 同時に3コマンドを送信し、1フレーム内で全結果が返るテスト
  2. RED: フレーム予算超過時に次フレームへ繰り越すテスト
  3. GREEN: キュードレインループの実装
  4. REFACTOR: フレーム予算の設定可能化

品質ゲート

cargo test --all-targets
dotnet test lsp/Server.Tests.csproj

Phase 4: バイナリ最適化(独立・低リスク)

目的: リリースビルドのバイナリサイズ削減と起動時間短縮

依存: なし(いつでも着手可能)

設計方針

  • Cargo.toml[profile.release] セクションを追加
  • LTO: lto = true
  • codegen-units: codegen-units = 1
  • strip: strip = true
  • opt-level: opt-level = "s" (サイズ最適化)
  • panic: panic = "abort"

TDDアプローチ

  1. RED: 最適化前後のバイナリサイズ比較(手動計測)
  2. GREEN: [profile.release] を設定
  3. REFACTOR: opt-level の "s" vs "z" の比較検証

品質ゲート

cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
cargo build --release

横断的な品質ゲート

全フェーズ完了後、以下を満たすことを確認:

cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
dotnet test lsp/Server.Tests.csproj

リスクと緩和策

リスク 影響 緩和策
デーモンのstaleプロセス残留 ポートバインド失敗 PIDファイル + ソケットクリーンアップを lspd.rs パターンで実装
ConnectionPool の接続リーク リソース枯渇 接続数上限 + アイドル接続の自動切断
Unity キュードレインのフレーム超過 Editor のカクつき フレーム予算チェック + 繰り越しロジック
LTO によるビルド時間増加 CI遅延 リリースビルドのみに適用(開発ビルドは影響なし)

Tasks

タスク: CLI実行効率の最適化

機能ID: SPEC-a7206673 | ステータス: 実装中


Phase 1: unityd デーモン

基盤

  • src/unityd.rs を新規作成(lspd.rs をモデルにスキャフォールド)
  • cli.rsUnityd サブコマンド(UnitydCommand: Start/Stop/Status/Serve)を追加
  • main.rsCommand::Unityd のディスパッチを追加
  • UnitydMode enum(auto 固定)を定義
  • (N/A)--daemon グローバルオプション追加(常に auto 相当へ仕様変更のため不要)

DaemonRequest / DaemonResponse

  • unityd::DaemonRequest を定義(Tool / Status / Ping / Stop)
  • unityd::DaemonResponse を定義(ok / result / error)
  • ソケットパス / PIDファイルパスのヘルパー関数を実装

デーモンサーバー

  • serve_forever() を実装(UnixSocket / TCP リスナー、アイドルタイムアウト)
  • handle_request() を実装(Ping / Status / Stop / Tool ディスパッチ)
  • handle_stream() を実装(改行区切りJSON読み書き)
  • PIDファイル書き込み・クリーンアップを実装

クライアント

  • start_background() を実装(バックグラウンドプロセス起動 + 起動待ち)
  • stop() を実装(Stopリクエスト送信)
  • status() を実装(Statusリクエスト送信)
  • ping() を実装(Pingリクエスト送信)
  • call_tool() を実装(デーモン経由のTool実行)

ConnectionPool

  • ConnectionPool 構造体を定義(HashMap<(String, u16), UnityClient>
  • 接続の取得・再利用ロジックを実装
  • 切断検知・再接続ロジックを実装
  • 接続数上限の管理を実装

自動モード

  • コマンド実行フローを常に auto 相当(デーモン接続試行 → 失敗時フォールバック)に固定
  • UNITY_CLI_UNITYD の値に依存せず、指定されても挙動を変えない

テスト(TDD)

  • RED: unityd startunityd status で running=true
  • RED: unityd stopunityd status で running=false
  • RED: デーモン経由 call_tool が結果を返す
  • RED: デーモン未起動時のフォールバック
  • RED: UNITY_CLI_UNITYD=on/off/auto を指定しても挙動が不変
  • RED: アイドルタイムアウト後の自動終了
  • RED: ConnectionPool の接続再利用
  • GREEN: 全テストを通す最小実装
  • REFACTOR: lspd.rs との共通部分抽出

Phase 2: バッチコマンド

パーサー

  • セミコロン区切り文字列のバッチパーサーを実装
  • JSON配列入力のバッチパーサーを実装
  • SingleCommand 構造体を定義(tool_name, params)

DaemonRequest拡張

  • DaemonRequest::Batch { commands: Vec<SingleCommand> } バリアントを追加
  • デーモン側の handle_request() にBatch処理を追加
  • バッチ結果を Vec<DaemonResponse> で返却

CLIインターフェース

  • batch サブコマンドまたは --batch オプションを追加
  • バッチ入力のバリデーションを実装

ワンショットバッチ

  • ワンショットモードでのバッチ実行(1接続で連続送信)を実装

テスト(TDD)

  • RED: セミコロン区切りパーサーのユニットテスト
  • RED: JSON配列入力のパーサーテスト
  • RED: バッチ3コマンドの結果が配列で返る
  • RED: バッチ内1コマンド失敗時に残りが継続する
  • GREEN: 全テストを通す最小実装
  • REFACTOR: パーサーとエグゼキュータの分離

Phase 3: Unity側キュードレイン

C#実装

  • UnityCliBridge のTCPサーバー処理でキュードレインループを実装
  • フレーム予算(16ms)チェックを実装
  • フレーム予算超過時の次フレーム繰り越しを実装
  • 既存の1コマンド処理との後方互換性を維持

テスト(TDD)

  • RED: 同時3コマンド送信で1フレーム内に全結果が返る
  • RED: フレーム予算超過時の繰り越し動作
  • GREEN: 最小実装
  • REFACTOR: フレーム予算の設定可能化

Phase 4: バイナリ最適化

Cargo.toml

  • [profile.release] セクションを追加
  • lto = true を設定
  • codegen-units = 1 を設定
  • strip = true を設定
  • opt-level = "s" を設定
  • panic = "abort" を設定

検証

  • 最適化前後のバイナリサイズを計測・比較
  • opt-level = "s" vs "z" の比較検証
  • cargo build --release でビルドが通ることを確認
  • 全テストが通ることを確認

ドキュメント更新

  • docs/development.md にデーモン運用セクションを追加
  • docs/development.md にバッチコマンドの使い方を追加
  • スキル定義の更新(デーモン関連スキルの追加)
  • CLAUDE.md の更新(必要に応じて)

品質ゲート(全フェーズ共通)

  • cargo fmt --all -- --check 通過
  • cargo clippy --all-targets -- -D warnings 通過
  • cargo test --all-targets 通過
  • dotnet test lsp/Server.Tests.csproj 通過

TDD

TODO

Research

TODO

Data Model

TODO

Quickstart

TODO

Contracts

Artifact files under contracts/ are managed in issue comments with contract:<name> entries.

Checklists

Artifact files under checklists/ are managed in issue comments with checklist:<name> entries.

Acceptance Checklist

  • Add acceptance checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions