関連 issue: #61 Geminiを実装メイドにしたい
Gemini CLI / Gemini Code Assist 経由の Gemini を、Butler の implement intent を処理する AI Maid として追加する。
この実装案では、既存の Goose 向け ImplementMaid を無理に分岐拡張せず、まずは Gemini CLI 専用の Maid を追加する。
理由:
ImplementMaid は Goose の --instructions、provider/model指定、worker_mcp拡張、watchdog前提が強い--output-format json|stream-json で構造化結果を返せるため、専用に扱う方が実装意図が明確になるImplementMaid と揃えるBrain / Codex / Claude Code
-> Butler MCP facade / Python API
-> runtime routing
-> GeminiCliImplementMaid
-> gemini CLI
-> Google AI Pro / Gemini Code Assist
本運用想定コマンド:
GOOGLE_GENAI_USE_GCA=true \
GEMINI_CLI_TRUST_WORKSPACE=true \
gemini --approval-mode auto_edit --output-format json -p "..."
調査・読み取り専用タスクでは --approval-mode plan を使う。
--approval-mode yolo は初期実装では使わない。
config/maid_registry.yml に研究枠として追加する。
- maid_id: gemini_cli_implement
kind: cli
label: Gemini CLI Implement
provider: google_ai_pro
model: gemini-cli-auto
role: implement
enabled: false
launch_config:
entrypoint: butler.maids.gemini_cli_implement_maid:GeminiCliImplementMaid
command: gemini --approval-mode auto_edit --output-format json -p
command_env: GEMINI_CLI_COMMAND
max_attempts: 2
progress_poll_seconds: 10
stagnation_timeout_seconds: 90
terminate_grace_seconds: 15
output_format: json
approval_mode: auto_edit
command_env_vars:
GOOGLE_GENAI_USE_GCA: "true"
GEMINI_CLI_TRUST_WORKSPACE: "true"
verification_profile:
match_fields: []
file_checks: []
http_checks: []
test_commands: []
exact_output: []
補足:
enabled: false で追加し、明示的な検証時だけ route するmodel は Gemini CLI 側が auto 選択するため、Butler の識別用には gemini-cli-auto とするGEMINI_CLI_COMMAND が未設定なら launch_config.command を使うcommand_env_vars は既存 registry schema にないため、実装時に読み取り対応を追加するか、専用 Maid 内で固定値として扱う初期は既定 route を切り替えず、研究枠として条件付き route を追加する。
- intent: implement
maid_id: gemini_cli_implement
delegatable: true
conditions_json:
execution_profile: gemini_cli_trial
retry_policy_json:
max_attempts: 2
Brain / Codex 側は、試験時だけ execution_profile: gemini_cli_trial を指定する。
既定の goose_openrouter_grok41fast_implement route は維持する。
注意:
butler/router.py の route_matches() は operation / operation_in のみを解釈するconditions_json.execution_profile は現状のままでは route 条件として効かないroute_matches() が task.payload.execution_profile を解釈できるようにするexecution_profile 条件に対応するまでは、Gemini CLI route を既定 route より前に置くと全 implement が Gemini CLI に流れるため避ける追加する主なファイル:
butler/maids/gemini_cli_implement_maid.pytests/test_gemini_cli_implement_maid.py更新するファイル:
config/maid_registry.ymlconfig/intent_maid_routes.ymldocs/capabilities/implement/仕様書.mddocs/モデル追加手順.mdGeminiCliImplementMaid は、Gemini CLI に実装を委譲し、Butler 側で結果を監督する Maid である。
担当すること:
json 出力を parse するresponse、stats、tool情報、token情報を evidence に残す担当しないこと:
work_record / work_publish の代替--approval-mode yolo の本運用#50 / #52 以降、Brain-facing な作業記録・共有は Git/Gitea の低レベル操作ではなく、Butler Work Record System (BWR) の work_* / issue_* API に寄せる方針になっている。
Gemini CLI 専用 Maid は Brain-facing API ではなく worker / maid 側の実装体である。
そのため、実装中の差分検出や verification のために内部で git を読むこと自体は許容する。
同様に、Butler 内部の作業隔離として git branch を使うことも、BWR 方針そのものとは衝突しない。
BWR 方針が主に要求するのは、Butler 内部の git branch / commit / push を Brain にそのまま低レベル操作として意識させないことである。
Brain へ見せるときは、git branch ではなく work_branch を主役にした作業抽象として扱い、記録・共有の入口は work_record() / work_publish() に寄せる。
ただし、Maid が Butler の作業記録体系を迂回してはいけない。
方針:
git add / git commit / git push / git merge / git rebase を禁止するImplementMaid と同じく butler/task-{task_id} のような task branch で作業を隔離する方向を基本とするImplementMaid と同じく、Gemini 実行後の未コミット変更を Butler 側で commit する方向を基本とするwork_branch / work_record / work_publish 的な作業抽象として見せるwork_branch を主役にし、既存互換のために branch_name を残す場合は deprecated 扱いにするissue_comment() / issue_close() または work_finish() が担当するchanged_files、verification 結果、scope violation、AI による git 操作疑いを evidence として返すだけに留めるGoose 版と同じ内部振る舞いへ寄せる理由:
ImplementMaid は、clean worktree を前提に task branch を作り、worker 実行後に Butler 側で commit するimplement intent なのに evidence、後続 action、失敗時の復旧手順が分岐しすぎるgit_commit / git_push を直接意識させる導線であるwork_branch / work_publish 的な抽象へ寄せるのが自然である現状の Phase 1 実装との差分:
work_record を促すImplementMaid の branch 作成・Butler 側 commit・direct commit 検知・verification 後 evidence を Gemini 版へ移植または共通化する#56 の残課題である「Brain が Bash 経由で git に戻る導線」は、Gemini CLI 版でも別経路として意識する必要がある。
特に Gemini CLI は repo 内で shell / tool を使えるため、git 書き込み系コマンドを prompt 禁止だけに頼らず、事後検知も行う。
検知方針:
HEAD / branch / changed files baseline を記録するHEAD が変わっていないことを確認するHEAD が変わっていた場合は、Gemini CLI が Butler 管理外の commit を作った可能性として扱うfailed_stage=bwr_policy / failure_reason=ai_direct_commit_detected で失敗させるchanged_files は成果物 evidence として返すが、記録・公開はしない_detect_goose_commits は _detect_ai_commits のような provider 非依存名に変更し、Goose / Gemini CLI の双方で使うつまり、Gemini CLI Maid が扱う git は「監督・検証のための内部観測」であり、Brain-facing な作業記録・公開操作ではない。
Butler 内部で branch 隔離を使う場合も、この線引きを守り、Brain-facing には work_branch / work_record / work_publish のような作業抽象として見せる。
branch_name は内部 git branch の詳細であり、外部互換のために残す場合も work_branch の補助情報として扱う。
初期実装では ImplementMaid を直接継承しない。
理由:
ImplementMaid は Goose 起動を前提にした処理が多い-p 引数で渡し、結果を JSON として受け取るstats は Goose にはない重要 evidence であるただし、以下の処理は既存 ImplementMaid から移植または共通化候補とする。
_run_git_record_baseline_changed_files_watch_files_watch_hashes_run_verifier_scope_violation_supervision_lines_detect_goose_commits初期実装では重複を多少許容し、動作確認後に butler/maids/implement_common.py のような共通部品へ抽出する。
重要:
ImplementMaid と同じ evidence 名、失敗分類、再試行判断に寄せるPhase 1 では Gemini CLI の疎通を優先し、既存 ImplementMaid の関数を必要最小限で移植してもよい。
Phase 2 では、Goose 非依存の処理を butler/maids/implement_common.py へ抽出する。
この抽出は Gemini CLI 版の branch / commit 化の前提作業とする。
先に共通化せず Gemini 版へ個別移植すると、Goose 版と Gemini 版の監督意味論が再びずれるためである。
抽出候補:
_run_git_record_baseline_changed_files_watch_files_watch_hashes_run_verifier_command_run_verifier_scope_violation_supervision_lines_detect_goose_commits を _detect_ai_commits のような provider 非依存名に変更する抽出しないもの:
json / stream-json parsestats 集計Runtime の _execute_with_supervision() は Maid 非依存のため、Gemini CLI 専用 Maid でもそのまま使う。
Gemini CLI 側は、runtime が再依頼に使える failed_stage / failure_reason / failed_verifications / scope_violation / changed_files を既存 shape で返す。
Gemini CLI 版では、既存の実装メイドで検討済みの supervision / verification 設計を再発明しない。
#9 で implement の Butler 側 supervision は実装済み。
継承すること:
butler/runtime.py の supervision loop を基本にするsupervision_context を渡すsupervision.attempts と attempt_count を残すverification_plan、failed_stage、failure_reason、next_recommendation を evidence に残すGemini CLI 専用 Maid は、この shape に接続できる evidence を返す。
#10 では、厳しすぎる verifier が実装成果を false fail にする問題が整理された。
継承すること:
essential / evidence / soft / scope_guard の考え方を維持するclear-fail にしないuncertain 相当では、Brain が判断しやすい最小 evidence を返すscope_guard は重要だが、検証条件の書き方ミスで成果物を歪めないようにするwatchdog は成功保証ではなく、無限待機を防ぎ、成果物・stdout・stderr を回収する救済装置として扱うGemini CLI 版でも、process exit / auth error / verification result / changed_files を混ぜて単純な成功失敗にしない。
#11 では、モデル特性に合わせて task を小さく切る仕組みとして execution_profile / complexity_score が導入された。
継承すること:
execution_profile で明示的に選ぶneed_input で返す方針を維持するcommand_execution と verification は別軸で扱うverification_passed=True でも clean exit できない場合は、成果物ありの uncertain / review 寄りにできる余地を残すGemini CLI の評価でも、まずは小さい docs / code task から観測し、既定 route 化は Phase 3 で判断する。
#7 では、repo root 直実行、hidden task dir、strict verifier、baseline dirty が結果を歪めることが確認された。
継承すること:
__pycache__ / .pyc を scope violation に混ぜないこのため、Gemini CLI 版の実装案では「Phase 2 supervision を作る」ではなく「既存 supervision / verifier の意味論に接続する」と表現する。
1. runtime が intent=implement の TaskContract を受け取る
2. route 条件により gemini_cli_implement を選択する
3. GeminiCliImplementMaid が preflight を行う
4. 実行前 git baseline を記録する
5. TaskContract から Gemini CLI 用 prompt を構築する
6. Gemini CLI を起動する
7. JSON出力を parse する
8. 実行後 git 状態を確認する
9. changed_files / stats / response を evidence 化する
10. verification_profile に基づき検証する
11. ResultContract を返す
Gemini CLI には、Brain からの spec をそのまま投げず、Butler が定型 prompt に整形して渡す。
必ず含める内容:
禁止事項:
git commitgit pushgit merge結果報告形式:
## Summary
...
## Changed Files
- ...
## Verification
- command: ...
result: ...
## Notes
...
Gemini CLI の --output-format json では、この報告全体が response 文字列として返る。
Butler は初期実装では response を厳密 parse せず、human-readable evidence として保存する。
機械判定は git diff、changed_files、verification_profile、process returncode、stats.files で行う。
Gemini CLI JSON の想定:
{
"session_id": "...",
"response": "...",
"stats": {
"models": {},
"tools": {},
"files": {}
}
}
ResultContract evidence に入れる項目:
gemini.session_idgemini.responsegemini.stats.modelsgemini.stats.toolsgemini.stats.filesgemini.total_requestsgemini.total_tokenschanged_filesverificationraw_stdout_excerptraw_stderr_excerptgemini.total_requests は stats.models.*.api.totalRequests を合計する。
response の厳密な構造化 parse は初期実装では行わない。
必要性が見えた時点で、後続改善として扱う。
初期実装では、既存 ImplementMaid と同程度の watchdog を目指す。
最低限:
可能なら追加:
stream-json による進捗監視tool_use イベントの監視ただし、初期実装の標準出力は json とし、stream-json は監視強化フェーズで導入する。
Gemini CLI の認証は Google AI Pro に紐づく Sign in with Google を前提にする。
Butler は OAuth 認証を自動で行わない。
初期実装の前提:
gemini 対話起動でログイン済みGOOGLE_GENAI_USE_GCA=trueGEMINI_CLI_TRUST_WORKSPACE=true未認証・トークン期限切れ時:
need_input または failed とする判断:
need_input ステートGemini CLI の未認証・トークン期限切れ・再ログイン要求は、Butler 側では need_input として返す設計にする。
この前提は確認済み。
butler.models.ResultContract.status に need_input は定義済みbutler.result.need_input() も定義済みneed_input を返しているしたがって、need_input は未解決事項ではなく、Gemini CLI 認証エラー時の返却候補として利用してよい。
検証では、Gemini CLI が Ripgrep is not available. Falling back to GrepTool. を出した。
原因候補:
rg は VS Code 拡張配下にあるrg だけを採用するrg は trusted system path ではない初期実装では blocker にしない。
ただし、repo探索性能に影響する可能性があるため、運用改善として /usr/local/bin/rg など trusted system path に ripgrep を用意するか検討する。
GeminiCliImplementMaid を追加するgemini_cli_implement を enabled: false で追加するroute_matches() に conditions_json.execution_profile の解釈を追加するexecution_profile: gemini_cli_trial 条件で追加するGOOGLE_GENAI_USE_GCA=true / GEMINI_CLI_TRUST_WORKSPACE=true を付けて Gemini CLI を起動する完了条件:
execution_profile: gemini_cli_trial の task だけが gemini_cli_implement に route されるimplement task は既存 goose_openrouter_grok41fast_implement route のまま目的は、Gemini CLI 用に新しい監督体系を作ることではない。
既存 ImplementMaid / runtime で固めた verification / supervision の意味論に、Gemini CLI の実行結果を接続する。
実装順序:
butler/maids/implement_common.py を作り、Goose 非依存の純粋関数・git観測・verification helper を抽出するwork_publish() を upstream なし task branch に対応させるGeminiCliImplementMaid を task branch / Butler 側 commit 方式へ寄せるImplementMaid の Brain-facing 表現を git_push / git_commit から work_publish / work_record へ置き換える実装状況メモ:
implement_common.py への共通helper抽出、work_publish() の upstream なし branch 対応、Gemini CLI watchdog / process group cleanup、認証誤判定対策まで実装済みGeminiCliImplementMaid は task branch を作成し、Gemini CLI には commit / push をさせず、検証成功後に Butler 内部で implement: {task_id} commit を作る方式へ移行済みwork_branch を主役にし、成功時の next_required_action は work_publish、開始前dirty時は work_record に統一済み依存関係:
implement_common.py を抽出するwork_publish() の upstream なし branch 対応は、Gemini / Goose の成功時 next action を work_publish に揃える前に済ませるnext_required_action: git_push -> work_publish 変更時は、Brain 側プロンプト・MCP tool description・運用メモも同時に更新するwork_branch を Brain-facing evidence の主役にし、branch_name は内部互換・deprecated 情報として扱うwork_observe() の現状:
現状の _unpublished_count() は git rev-list --count @{u}..HEAD に失敗すると None を返す
そのため upstream がない新規 butler/task-* branch は work_state=unknown になり得る
task branch を work_publish() へ渡す運用にする前に、upstream なし branch を「未公開記録あり」と見なすように変更する
verification_profile の test_commands / file_checks を既存 ImplementMaid と同じ意味で適用する
payload.verification の essential / evidence / soft / scope_guard を既存 verifier と同じ分類で扱う
scope violation を検出し、scope_guard_results / scope_violation として evidence に残す
git 直叩き検知を実装または既存処理から共通化する
Goose 非依存の既存関数を implement_common.py へ抽出し、ImplementMaid と GeminiCliImplementMaid の双方から使う
retry_policy_json に基づく再試行は runtime supervision loop を基本にし、Gemini Maid 内で独自 retry 体系を作らない
command_execution failure と verification failure を分けて evidence に残す
watchdog_stagnation / timeout 時も、changed_files と verification 結果を回収できる形にする
failed_stage / failure_reason / next_recommendation / verification_plan / why_uncertain を既存 shape に揃える
AI worker が direct commit した場合は、Butler 側 commit をスキップし、failed_stage=bwr_policy / failure_reason=ai_direct_commit_detected として失敗させる
完了条件:
okfailed または runtime supervision retryimplement_common.py の共通関数に対して、既存 ImplementMaid と GeminiCliImplementMaid の双方から使える unit test があるwork_publish になるwork_branch が主役で、branch_name は互換情報として扱われる完了条件:
追加するテスト:
test_build_prompt_includes_constraintstest_execute_success_parses_gemini_jsontest_execute_records_stats_and_changed_filestest_execute_returns_need_input_on_auth_errortest_execute_fails_on_invalid_jsontest_execute_fails_on_timeouttest_registry_can_load_gemini_cli_maidtest_route_can_select_gemini_cli_trialmock 方針:
subprocess.run / subprocess.Popen は mock するImplementMaid テストのパターンを流用する現時点では、Gemini CLI 専用 Maid は 実装に進めてよい。
ただし初期状態では既定 route にしない。
まずは execution_profile: gemini_cli_trial の研究枠として導入し、明示的に指定したときだけ使う。
既定 route 化は、Phase 3 の観測後に判断する。
conditions_json.execution_profile 対応の実装範囲rg を trusted system path に置く必要性stream-json を初期実装から使うか、監視強化フェーズに回すか