diff --git a/AGENTS.md b/AGENTS.md index a4f1b0cd..52859f23 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,7 +78,7 @@ ai-plugins/ - Claude Code版は 8個の専門サブエージェント、公開Skills、SessionStart/Stopフックを提供 - Codex版は Codex向け公開Skillsと任意Slack通知hookを提供 - Kiro版は installer で `.kiro/skills/` と `.kiro/agents/default.json` を生成 -- 外部AI委譲は `/ndf:codex` skill と `corder` エージェント経由で Codex CLI を呼び出し(v4.0.0 で Codex MCP サーバは廃止) +- 外部AI委譲は `/ndf:external-ai` skill と `corder` エージェント経由で Codex / Gemini CLI を呼び出し(v4.0.0 で Codex MCP サーバは廃止) 詳細は各 runtime README と `docs/ndf-plugin-reference.md` を参照。 diff --git a/KIRO.md b/KIRO.md index 4b6caba8..f9e62183 100644 --- a/KIRO.md +++ b/KIRO.md @@ -9,7 +9,7 @@ ### 前提条件 - Kiro CLI がインストール済み - Node.js(Slack通知を使う場合) -- Codex CLI(`/ndf:codex` skill で外部AI委譲を使う場合、または `--with-codex` で Kiro に Codex MCP サーバ設定を生成する場合): `npm install -g @openai/codex` +- Codex CLI(`/ndf:external-ai` skill で外部AI委譲を使う場合、または `--with-codex` で Kiro に Codex MCP サーバ設定を生成する場合): `npm install -g @openai/codex` ### インストール @@ -21,7 +21,7 @@ bash plugins/ndf-kiro/install.sh bash plugins/ndf-kiro/install.sh --with-slack # 全部入り(Slack通知 + Kiro 側 Codex MCP 設定生成) -# 注: NDF v4.0.0 本体は Codex MCP に依存せず、/ndf:codex skill 経由で +# 注: NDF v4.0.0 本体は Codex MCP に依存せず、/ndf:external-ai skill 経由で # CLI 直接実行に一本化。--with-codex は Kiro セッションで # `mcp__codex__*` を直接呼びたい場合のみ有効化すればよい。 bash plugins/ndf-kiro/install.sh --with-slack --with-codex diff --git a/README.md b/README.md index 8e839e30..a04c7936 100644 --- a/README.md +++ b/README.md @@ -8,18 +8,18 @@ Claude Code / Codex / Kiro CLI向けのスキル・MCP設定を共有するた **NDFプラグイン v4.20.1** は、同じ `ndf@ai-plugins` という名前で Claude Code / Codex / Kiro CLI へ配布されるランタイム別プラグインです。共通ソースは `plugins/ndf-shared/` に集約し、利用者が install する配布物は `plugins/ndf-claude/` / `plugins/ndf-codex/` / `plugins/ndf-kiro/` に分かれています。 -- **公開Skills**: Claude Code向け core 21個、Kiro向け core 20個、Codex向け core 21個に分離。 -- **元Skills(30個)**: +- **公開Skills**: Claude Code向け core 20個、Kiro向け core 20個、Codex向け core 22個に分離。 +- **元Skills(29個)**: - PR/レビューワークフロー (7): pr, pr-tests, fix, review, cherry-pick-pr, deploy, merged - 原則・ガイドライン (9): ndf-policies, implementation-plan, plan-to-spec, investigation-rules, problem-solving, logging-guidelines, markdown-writing, issue-plan-strategy, ml-model-structure - - データ分析・品質・環境 (5): qa-security-scan, docker-container-access, google-auth, codex, official-skills-autoloader + - データ分析・品質・環境 (4): qa-security-scan, docker-container-access, google-auth, official-skills-autoloader - E2Eテスト/Playwright (4): playwright-planning, playwright-authoring, playwright-evidence, playwright-kit-ops - 外部サービス連携 (1): google-drive - - AIクロスレビュー (2): cross-review, gemini + - AIクロスレビュー (2): cross-review, external-ai - 運用 (2): skill-stats, statusline - **8つの専門エージェント**: director, data-analyst, corder, researcher, qa, debugger, devops-engineer, code-reviewer - **自動フック**: SessionStart (transcript保持期間を最低90日に保つ) + Stop (AI要約生成+Slack通知) -- **外部AI委譲**: `/ndf:codex` skill + `corder` エージェント経由で Codex CLI をバックグラウンド実行 (v4.0.0 で Codex MCP サーバは廃止) +- **外部AI委譲**: `/ndf:external-ai` skill + `corder` エージェント経由で Codex / Gemini CLI をバックグラウンド実行 (v4.0.0 で Codex MCP サーバは廃止) - **AIクロスレビュー強化**: `/ndf:cross-review` は codex/gemini 両方に PR レビューを委譲し、Gemini の進捗 heartbeat、`--focus` / `--extra-instructions-file`、PR 種別別の自動レビュー観点テンプレートに対応 - **Kiro CLI対応**: `plugins/ndf-kiro/install.sh` によるワンコマンドセットアップ - **MCPプラグイン**: `plugins/mcp/shared/` を編集元とし、Claude / Codex / Kiro 向け配布物を `plugins/mcp/{claude,codex,kiro}/` に生成 @@ -100,7 +100,7 @@ kiro-cli chat | プラグイン名 | バージョン | 説明 | 詳細 | |------------|----------|------|------| -| **ndf** | 4.20.1 | Claude Code / Codex / Kiro CLI 向けに runtime 別配布物を提供する NDF プラグイン。8個の専門エージェント(Claude版)、公開Skills(Claude Code向け core 21個、Kiro向け core 20個、Codex向け core 21個)、Claude SessionStart/Stopフック、Codex/Kiro向け通知・実行補助を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:codex` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [Claude](./plugins/ndf-claude/README.md) / [Codex](./plugins/ndf-codex/README.md) / [Kiro](./plugins/ndf-kiro/README.md) | +| **ndf** | 4.20.1 | Claude Code / Codex / Kiro CLI 向けに runtime 別配布物を提供する NDF プラグイン。8個の専門エージェント(Claude版)、公開Skills(Claude Code向け core 20個、Kiro向け core 20個、Codex向け core 22個)、Claude SessionStart/Stopフック、Codex/Kiro向け通知・実行補助を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:external-ai` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [Claude](./plugins/ndf-claude/README.md) / [Codex](./plugins/ndf-codex/README.md) / [Kiro](./plugins/ndf-kiro/README.md) | ### NDF v4.20.1 の主な変更 diff --git a/docs/ndf-plugin-reference.md b/docs/ndf-plugin-reference.md index dcaac54d..b0838b5c 100644 --- a/docs/ndf-plugin-reference.md +++ b/docs/ndf-plugin-reference.md @@ -99,7 +99,7 @@ bash scripts/runtime-smoke-test.sh --runtime kiro ## 外部 AI 委譲 -Codex MCP サーバは廃止済みです。外部 AI 委譲は `/ndf:codex` Skill と Claude Code 版の `corder` エージェントから Codex CLI を直接呼び出す方式を標準とします。 +Codex MCP サーバは廃止済みです。外部 AI 委譲は `/ndf:external-ai` Skill と Claude Code 版の `corder` エージェントから Codex / Gemini CLI を直接呼び出す方式を標準とします。 ## Slack 通知 diff --git a/docs/specifications/ndf-knowledge-and-kiro.md b/docs/specifications/ndf-knowledge-and-kiro.md index 4971ff84..94afeafa 100644 --- a/docs/specifications/ndf-knowledge-and-kiro.md +++ b/docs/specifications/ndf-knowledge-and-kiro.md @@ -31,7 +31,7 @@ Kiro CLI 用設定は `.kiro/agents/default.json` で管理する。agent 設定 Kiro CLI では `plugins/ndf-kiro/install.sh` が `plugins/ndf-kiro/skills/` から `.kiro/skills/` への symlink と `.kiro/agents/default.json` を生成する。`agentSpawn` hook は初期化時の案内に使い、`--with-slack` 指定時のみ `stop` hook 相当の Slack 通知を有効化する。Kiro の stop hook payload に `assistant_response` が含まれる場合、`plugins/ndf-kiro/scripts/slack-notify.js` は transcript よりも `assistant_response` を優先して要約に使う。 -Codex 連携は MCP サーバではなく `/ndf:codex` skill と `corder` エージェント経由の Codex CLI 直接実行を標準とする。Kiro 用 `--with-codex` は Kiro セッションから Codex CLI を扱う場合の補助設定である。 +Codex 連携は MCP サーバではなく `/ndf:external-ai` skill と `corder` エージェント経由の Codex CLI 直接実行を標準とする。Kiro 用 `--with-codex` は Kiro セッションから Codex CLI を扱う場合の補助設定である。 ## データ・設定 @@ -47,7 +47,7 @@ Codex 連携は MCP サーバではなく `/ndf:codex` skill と `corder` エー |---|---| | Kiro CLI | `.kiro/agents/default.json` と `.kiro/skills/` で Skill / hook / MCP 設定を提供 | | Serena MCP | `mcp-serena` プラグインとして分離提供 | -| Codex CLI | `/ndf:codex` skill と `corder` エージェントから直接実行 | +| Codex CLI | `/ndf:external-ai` skill と `corder` エージェントから直接実行 | | Slack | Claude Code / Kiro / Codex の終了通知に使用 | ## テスト観点 diff --git a/plugins/ndf-claude/.claude-plugin/plugin.json b/plugins/ndf-claude/.claude-plugin/plugin.json index e78ddeb4..2b441255 100644 --- a/plugins/ndf-claude/.claude-plugin/plugin.json +++ b/plugins/ndf-claude/.claude-plugin/plugin.json @@ -44,8 +44,7 @@ "./skills/cherry-pick-pr", "./skills/deploy", "./skills/playwright-authoring", - "./skills/codex", - "./skills/gemini", + "./skills/external-ai", "./skills/statusline", "./skills/issue-plan-strategy", "./skills/plan-to-spec" diff --git a/plugins/ndf-claude/README.md b/plugins/ndf-claude/README.md index 199478e9..004812a4 100644 --- a/plugins/ndf-claude/README.md +++ b/plugins/ndf-claude/README.md @@ -42,7 +42,7 @@ SLACK_USER_MENTION=<@U0123456789> ## 外部 AI 委譲 -`/ndf:codex` skill または `corder` エージェントから外部 AI 委譲を使う場合は、利用環境に Codex CLI をインストールしてログインします。 +`/ndf:external-ai` skill または `corder` エージェントから外部 AI 委譲を使う場合は、利用環境に Codex CLI をインストールしてログインします。 ```bash npm install -g @openai/codex diff --git a/plugins/ndf-claude/agents/corder.md b/plugins/ndf-claude/agents/corder.md index 8aec7ef8..4cac0651 100644 --- a/plugins/ndf-claude/agents/corder.md +++ b/plugins/ndf-claude/agents/corder.md @@ -13,7 +13,7 @@ description: | ## v4.0.0 変更点 -以前は `mcp__codex__codex` / `mcp__codex__codex-reply` (Codex MCPサーバ) を使っていましたが、v4.0.0 で **Codex MCPは廃止**し、**Codex CLI の直接バックグラウンド実行**に切り替わりました。`mcp__codex__*` は利用できません。代わりに `/ndf:codex` skill に従って `codex exec` を呼び出してください。 +以前は `mcp__codex__codex` / `mcp__codex__codex-reply` (Codex MCPサーバ) を使っていましたが、v4.0.0 で **Codex MCPは廃止**し、**Codex CLI の直接バックグラウンド実行**に切り替わりました。`mcp__codex__*` は利用できません。代わりに `/ndf:external-ai` skill に従って `codex exec` を呼び出してください。 ## 専門領域 @@ -42,25 +42,46 @@ description: | ### Codex CLI(推奨: バックグラウンド実行) -`codex` CLI を `codex exec` コマンドで直接呼び出す。詳細な手順・プロンプトテンプレート・サンドボックス制約への対処は `/ndf:codex` skill に記載のとおり: +`codex` CLI を `codex exec` コマンドで直接呼び出す。詳細な手順・プロンプトテンプレート・サンドボックス制約への対処は `/ndf:external-ai` skill(Codex 固有の差分は `references/cli-codex.md`)に記載のとおり: ```bash # 1. プロンプトを一時ファイルに書く (ファイル書き込みツール) +# 最終結果は必ず $FINAL へ apply_patch で書き出すよう本文で指示する +FINAL=/tmp/codex-output-<タスク名>.md cat > /tmp/codex-prompt.md < /tmp/codex-output.md \ + > /tmp/codex-stdout.md \ 2> /tmp/codex-err.log & -# 3. PID を控えて終了確認 -ps -p 2>/dev/null && echo RUNNING || echo EXITED +# 3. 完了検知は stderr の sentinel で行う(`ps -p` は zombie を生存と誤判定する) +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done + +# 4. 成果物を回収(ファイル → stdout → stderr の三段フォールバック) +if [ -s "$FINAL" ]; then + cp "$FINAL" ./codex-result.md +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./codex-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/codex-err.log +fi ``` -- **必ず `/ndf:codex` skill を参照**してから実行すること(サンドボックス・プロンプト設計・出力回収のベストプラクティスが記載されている) +- **必ず `/ndf:external-ai` skill と `references/cli-codex.md` を参照**してから実行すること(サンドボックス・プロンプト設計・出力回収のベストプラクティスが記載されている) +- **`ps -p` による完了確認は使わない**。Codex は zombie (defunct) 化して `ps -p` が 0 を返し続けるため、待機ループが抜けなくなる。脱出条件は stderr 末尾の `^tokens used$` sentinel - 未インストールなら `npm install -g @openai/codex` → `codex login` ### Serena MCP @@ -77,7 +98,7 @@ ps -p 2>/dev/null && echo RUNNING || echo EXITED 3. **最新情報収集**: Context7で最新のベストプラクティスを確認 4. **設計**: アーキテクチャと実装方針を決定 5. **実装**: クリーンなコードを作成 -6. **レビュー**: Codex CLI を `/ndf:codex` skill の手順でバックグラウンド起動し、独立レビューを依頼 +6. **レビュー**: Codex CLI を `/ndf:external-ai` skill の手順でバックグラウンド起動し、独立レビューを依頼 7. **改善**: レビュー結果に基づいて修正 8. **テスト**: 動作確認とテストコード作成 @@ -94,7 +115,7 @@ ps -p 2>/dev/null && echo RUNNING || echo EXITED - 実装前にSerenaで既存コードパターンを確認 - Context7で最新のフレームワーク仕様を参照 -- 実装後は必ず Codex CLI (`/ndf:codex`) で第二意見レビュー +- 実装後は必ず Codex CLI (`/ndf:external-ai`) で第二意見レビュー - テストコードも併せて作成 - 破壊的変更は事前に影響範囲を確認 diff --git a/plugins/ndf-claude/agents/debugger.md b/plugins/ndf-claude/agents/debugger.md index 59eed48a..19f18a3c 100644 --- a/plugins/ndf-claude/agents/debugger.md +++ b/plugins/ndf-claude/agents/debugger.md @@ -54,7 +54,7 @@ description: | ### MCPツール(必要に応じて) - Serena MCP(シンボル参照解析) -- Codex CLI(`/ndf:codex` skill または `corder` エージェント経由、独立した原因分析の第二意見) +- Codex CLI(`/ndf:external-ai` skill または `corder` エージェント経由、独立した原因分析の第二意見) ## 診断方針 diff --git a/plugins/ndf-claude/agents/devops-engineer.md b/plugins/ndf-claude/agents/devops-engineer.md index 0b97393e..769e07c2 100644 --- a/plugins/ndf-claude/agents/devops-engineer.md +++ b/plugins/ndf-claude/agents/devops-engineer.md @@ -52,7 +52,7 @@ description: | - `Grep` - 既存設定の参照 ### MCPツール -- Codex CLI(`/ndf:codex` skill または `corder` エージェント経由で第二意見マニフェストレビュー) +- Codex CLI(`/ndf:external-ai` skill または `corder` エージェント経由で第二意見マニフェストレビュー) ## セキュリティ方針 diff --git a/plugins/ndf-claude/agents/director.md b/plugins/ndf-claude/agents/director.md index a3237a05..26434960 100644 --- a/plugins/ndf-claude/agents/director.md +++ b/plugins/ndf-claude/agents/director.md @@ -137,7 +137,7 @@ TodoWrite([{content: "タスク内容", status: "in_progress", activeForm: "進 1. ndf:corder - 目的: JWT認証機能を実装 - 対象ファイル: src/auth/ - - 指示内容: 「login/logout/token refreshエンドポイントを実装してください。セキュリティベストプラクティスに従い、Codex CLI(`/ndf:codex` skill)でレビューを実施してください。」 + - 指示内容: 「login/logout/token refreshエンドポイントを実装してください。セキュリティベストプラクティスに従い、Codex CLI(`/ndf:external-ai` skill)でレビューを実施してください。」 2. ndf:qa - 目的: セキュリティレビュー diff --git a/plugins/ndf-claude/agents/qa.md b/plugins/ndf-claude/agents/qa.md index dd11beb0..e638c38c 100644 --- a/plugins/ndf-claude/agents/qa.md +++ b/plugins/ndf-claude/agents/qa.md @@ -9,7 +9,7 @@ description: | # 品質管理エージェント -あなたは品質管理とテストの専門家です。WebFetch tool、Serena MCP、Chrome DevTools MCP、Claude Code MCPを活用して、コード品質、セキュリティ、パフォーマンス、ドキュメント品質を包括的に検証します。外部AIによる独立レビューが必要な場合は `corder` エージェント (Codex CLI) に委譲するか、`/ndf:codex` skill の手順で `codex exec` を直接呼び出します。 +あなたは品質管理とテストの専門家です。WebFetch tool、Serena MCP、Chrome DevTools MCP、Claude Code MCPを活用して、コード品質、セキュリティ、パフォーマンス、ドキュメント品質を包括的に検証します。外部AIによる独立レビューが必要な場合は `corder` エージェント (Codex CLI) に委譲するか、`/ndf:external-ai` skill の手順で `codex exec` を直接呼び出します。 ## 専門領域 diff --git a/plugins/ndf-claude/agents/researcher.md b/plugins/ndf-claude/agents/researcher.md index 18cb91e3..d1098e2c 100644 --- a/plugins/ndf-claude/agents/researcher.md +++ b/plugins/ndf-claude/agents/researcher.md @@ -9,7 +9,7 @@ description: | # リサーチャーエージェント -あなたは情報収集と分析の専門家です。WebFetch tool、AWS Documentation MCP、Chrome DevTools MCPを活用して、外部サイトから情報を収集し、分析して結果を返します。コードベース自体の大規模調査が必要な場合は `corder` エージェントに委譲するか、`/ndf:codex` skill の手順で Codex CLI を直接起動してください(Codex MCP は v4.0.0 で廃止)。 +あなたは情報収集と分析の専門家です。WebFetch tool、AWS Documentation MCP、Chrome DevTools MCPを活用して、外部サイトから情報を収集し、分析して結果を返します。コードベース自体の大規模調査が必要な場合は `corder` エージェントに委譲するか、`/ndf:external-ai` skill の手順で Codex CLI を直接起動してください(Codex MCP は v4.0.0 で廃止)。 ## 専門領域 @@ -62,7 +62,7 @@ description: | - **静的Webページ** → WebFetch(優先) - **AWS技術情報** → AWS Docs MCP - **動的サイト/インタラクティブ操作** → Chrome DevTools MCP - - **コードベース調査** → 本エージェントの責務外。`corder` エージェントまたは `/ndf:codex` skill を使う + - **コードベース調査** → 本エージェントの責務外。`corder` エージェントまたは `/ndf:external-ai` skill を使う 3. **情報収集**: 選択したツールで情報を取得 4. **情報整理**: 収集した情報を構造化 5. **分析**: データを分析し、インサイトを抽出 diff --git a/plugins/ndf-claude/skills/codex/SKILL.md b/plugins/ndf-claude/skills/codex/SKILL.md deleted file mode 100644 index 80060a83..00000000 --- a/plugins/ndf-claude/skills/codex/SKILL.md +++ /dev/null @@ -1,473 +0,0 @@ ---- -name: codex -description: "Delegate coding, review, or research to Codex CLI." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" ---- - -# Codex 外部AI委譲スキル - -## 概要 - -`codex` CLI(OpenAI Codex、通常は `/usr/bin/codex` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 - -ローカルファイルの逐語照合レビューや大規模コードベース調査に向いている。 - -## NDFとの関係 - -- NDFプラグインの `corder` エージェントはこの skill の手順に従って Codex CLI を呼び出す -- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない -- 使い分け: 軽量な独立レビュー → `corder` エージェントに委譲。手順の詳細を自分で制御したい or 複雑なプロンプトを出したい → 本 skill を参照して直接 `codex exec` 起動 - -## いつ使うか - -### 使うべきケース -- **独立第二意見レビュー**: 設計書・PR・仕様書を外部AIにレビューさせる(メインエージェントの思考バイアスを避ける) -- **コードベース逐語照合**: 「行番号・関数名・重複箇所の件数」を正確に突き合わせる必要がある場合 -- **長時間の調査タスク**: 複数ファイル横断で5〜10分以上かかる調査 -- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを codex に走らせたい場合 - -### 使わないべきケース -- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 -- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める -- 単純な質問回答 → WebFetch / WebSearch で足りる -- 機密情報を含むコード → 外部API送信の可否を確認してから - -## 前提条件 - -```bash -# インストール確認 -which codex -codex --version - -# ログイン状態確認(初回のみ必要) -codex login -``` - -未インストールの場合は以下でセットアップ: - -```bash -# npm 経由 -npm install -g @openai/codex - -# 動作確認 -codex exec --help -``` - -## 基本実行パターン - -### 1. サンドボックス制約(重要) - -codex のデフォルトサンドボックスは `bubblewrap (bwrap)` に依存する。以下の環境では bwrap が動作せず、`exec` で実行するシェルコマンドがすべて失敗する: - -- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) -- **一部の devcontainer / Docker 環境**(user namespace 非対応) - -該当環境では **`--dangerously-bypass-approvals-and-sandbox` を付けて起動**する必要がある。 - -```bash -# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) -codex exec -s read-only -C "$PWD" - -# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" -``` - -**判断基準**: 既にDocker / devcontainer / VM / CIランナー等で外部的にサンドボックスされているなら `--dangerously-bypass-approvals-and-sandbox` は実用上安全。ホスト直接実行でコード全書き換えされたくない場合はフラグを付けずに対処(後述「bwrap代替」)。 - -#### bwrap 代替の有効化(ホスト直接実行時) - -```bash -# Debian/Ubuntu 系でホスト user namespace を有効化 -sudo sysctl kernel.unprivileged_userns_clone=1 - -# 永続化 -echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf -``` - -### 2. プロンプトは一時ファイル経由で渡す - -長いプロンプトをシェル引数に渡すとエスケープ地獄になるので、**一時ファイル経由でstdinに流す**のが基本。 - -```bash -# Step 1: プロンプトを一時ファイルに書く -cat > /tmp/codex-prompt.md <<'EOF' -## タスク -以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 - -## 対象ファイル(絶対パスで指定) -/absolute/path/to/design.md - -## 出力形式 -Markdown で標準出力に吐いてください。 -EOF - -# Step 2: codex exec に stdin で流す(バックグラウンド実行) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & -``` - -**エージェントからの書き方**: ファイル書き込みツールで `/tmp/codex-prompt.md` を作ってから、シェル実行ツールの「バックグラウンド実行」オプションで codex を起動する。 - -### 3. 出力ストリームの扱い - -codex CLI の出力構造: - -| ストリーム | 内容 | -|---|---| -| **stdout** | **最終 assistant message のみ**(Markdown本文)。出ないことがある(後述) | -| **stderr** | プロンプトのエコー + 実行したコマンドと結果 + codexの思考プロセス + `^tokens used$` sentinel | - -**実務上の扱い**: -- 最終成果物が欲しい → `stdout` をそのまま採用…**ただし stdout が空になるケースがあるので必ずファイル出力も併用**(下記 3.5 参照) -- codexが何を調べたか追跡したい → `stderr` をデバッグ用に保存 - -```bash -codex exec ... > /tmp/codex-output.md 2> /tmp/codex-err.log -# 成果物 = /tmp/codex-output.md(stdout が空でないことを必ず確認) -# デバッグ = /tmp/codex-err.log(大きめ、数千行になる) -``` - -### 3.5 最終出力をファイル経由で保証する(重要) - -**Codex CLI(特に `gpt-5-codex` / 高 reasoning_effort)は、長時間調査の末に** -**最終 assistant message を返さずにセッションを終えることがある**。 -このとき stdout は空のままになり、stderr のイベントログ(数十万バイト)には -コードを実際に読んだ痕跡だけが残る。`^tokens used$` は出ているのに stdout が空、という状態。 - -**根本対策: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。** -Codex は最終 message を返さなくても `apply_patch` ツールでファイルを作成できるため、 -ファイル経由なら確実に結果を回収できる。 - -#### プロンプトに必ず含める指示(テンプレート) - -```markdown -## 出力先(必須) - -最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: - -`/tmp/codex-output-.md` - -書き出しは `apply_patch` で新規ファイル作成してください。 -**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 -書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 -``` - -#### 回収側の安全パターン - -```bash -# 1. ファイルが存在するかを最優先で確認(stdout が空でもこちらに本文が残る) -OUTPUT_FILE=/tmp/codex-output-pr13734-review.md -if [ -s "$OUTPUT_FILE" ]; then - cat "$OUTPUT_FILE" -elif [ -s /tmp/codex-stdout.md ]; then - # 2. ファイルがなければ stdout フォールバック - cat /tmp/codex-stdout.md -else - # 3. どちらも空なら stderr の末尾から拾う最後の手段 - echo "WARN: Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log -fi -``` - -#### 補助対策 - -- **`reasoning_effort` を `medium` に下げる** (`--config reasoning.effort=medium`) - `high` だと思考に偏って最終 message を返さなくなる頻度が上がる -- **`--json` モードでイベント採取** (`codex exec --json`) - JSON Lines で `event.type=assistant_message` を grep すれば確実に取れる -- **強制 summary 指示**: プロンプト末尾に「最後に必ず assistant message として 1 回出力すること、tool 呼び出しのみで終了しないこと」を明記 - -### 4. バックグラウンド実行 + 待機パターン - -codex は **5〜10分かかることが普通**。多くのエージェントハーネスはシェル実行に2〜3分のタイムアウトを課すので、**必ずバックグラウンド実行**する。 - -```bash -# 1. プロンプトファイル書き出し(ファイル書き込みツール) -# -> /tmp/codex-prompt.md - -# 2. codex をバックグラウンドで起動(`&` でシェル自体は即時終了) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & - -# 3. PID を控える -echo "PID: $!" - -# 4. 待機(他の作業を進める or スケジューラで再開) - -# 5. 完了検知 — ps -p は zombie に騙される。stderr の "tokens used" sentinel を見る -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -**⚠️ 罠**: `&` でバックグラウンド実行するとラッパーシェルは即終了し「タスク完了通知」が発火するが、codex 本体はまだ動いている。**`ps -p $PID` は zombie (defunct) も 0 を返す** ため `until ! ps -p $PID` は永久ループになりうる。`grep -q '^tokens used$' /tmp/codex-err.log` を脱出条件にする (codex が最終回答を吐き終わると stderr 末尾に必ず出る sentinel)。 - -### 5. 待機間隔のチューニング - -エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: - -- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) -- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) -- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) - -codex の典型実行時間(5〜10分)に対しては **270秒ポーリング** か **1200秒一括待ち** の二択。 - -### 6. プロセス確認・ログ追跡 - -```bash -# 完了したか (stderr 末尾の "tokens used" が最も信頼できる) -grep -q '^tokens used$' /tmp/codex-err.log && echo DONE - -# 最新の作業内容を覗く -tail -30 /tmp/codex-err.log -``` - -## プロンプト設計のコツ - -### 必須要素 -1. **対象ファイルの絶対パス**(codexは `nl -ba`, `sed -n`, `rg` 等でファイルを読むため) -2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) -3. **出力形式の指定**(Markdownテンプレートを提示) -4. **スコープ外の明示**(codexが脱線しないため) -5. **最終出力先ファイルの指定(必須)**: `/tmp/codex-output-.md` のような明示パスへ - **`apply_patch` で必ず書き出させる**。stdout だけに頼ると最終 message が落ちて空になる事故が起きる(3.5 節参照) -6. **stdout にも同内容を吐く指示**: ファイル書き出し後、念のため stdout にもエコーさせる(冪等) - -### レビュー依頼テンプレート - -```markdown -あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 -以下をレビューしてください。 - -## 対象ファイル(必ず最初に読むこと) -`/absolute/path/to/target.md` - -## 観点 -1. <観点1: 例「仕様とコードの整合性」> -2. <観点2: 例「既存APIとの後方互換性」> - -## 調査対象コード(必要に応じて読む) -- `src/...` -- `lib/...` - -## 背景コンテキスト -- <プロジェクト概要> -- <関連PR / Issue番号> -- <既存レビューで対応済みの事項(重複指摘を避けるため)> - -## 出力形式 - -以下を Markdown で**`/tmp/codex-output-.md` に必ず書き出してください** -(`apply_patch` で新規ファイル作成)。書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため): - -# <タイトル> - -## 総評 -## 1. <観点1> に関する指摘 -### 1.1 正確な主張 -### 1.2 訂正推奨 -## 2. <観点2> に関する指摘 -## 3. 追加提案 -## 4. 承認可否 - -**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 -**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -### コード生成依頼テンプレート - -```markdown -以下の実装タスクを実行してください。 - -## タスク -<具体的な実装内容> - -## 制約 -- <技術制約: 言語バージョン、依存ライブラリ> -- <コーディング規約: ESLint / Prettier / rustfmt等> -- <テスト要件: ユニットテスト必須等> - -## 対象ファイル -- <既存ファイルのパス> -- <新規ファイルのパス案> - -## 背景 -<なぜこの実装が必要か、設計判断の経緯> - -## 完了基準 -- [ ] テストがパスする -- [ ] 型チェック / lint がパスする -- [ ] <追加の受け入れ条件> - -**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を -`/tmp/codex-output-.md` に書き出してください(`apply_patch` で新規作成)。 -書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため)。 -tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -## 実例: レビュー依頼の完全フロー - -```bash -# === 1. プロンプト書き出し === -# ポイント: 最終出力先ファイルをプロンプト内で明示し、apply_patch で書かせる -FINAL=/tmp/codex-output-api-v2-review.md - -cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ - 2> /tmp/codex-err.log & - -PID=$! -echo "codex PID: $PID" - -# === 3. 完了確認(^tokens used$ sentinel を待つ) === -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -echo DONE - -# === 4. 成果物を安全に回収(ファイル優先 → stdout fallback) === -if [ -s "$FINAL" ]; then - cp "$FINAL" ./review-result.md - echo "✅ Codex 書き出しファイルから回収" -elif [ -s /tmp/codex-stdout.md ]; then - cp /tmp/codex-stdout.md ./review-result.md - echo "⚠ stdout からフォールバック回収(ファイル書き出しなし)" -else - echo "❌ Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log - exit 1 -fi -``` - -## トラブルシューティング - -### Q1. stdoutが空でstderrに大量のexecログだけある -**原因**: codex がまだ最終回答を出す前に停止した、または **最終 assistant message を出さずにセッションが終わった**(gpt-5-codex の高 reasoning_effort で発生しやすい既知挙動)。 - -**対処**: -- `grep -q '^tokens used$' /tmp/codex-err.log` で終了 sentinel が出ているか確認(まだなら動作中なので追加待機) -- 出ているのに stdout が空 → セッション終了で最終 message が失われたケース。**3.5 節「最終出力をファイル経由で保証する」のパターンでリトライ必須**: - - プロンプトに `apply_patch` で `/tmp/codex-output-.md` へ必ず書き出させる指示を追加 - - 回収側は「ファイル → stdout → stderr」の三段フォールバックで取りこぼしを防ぐ - - 補助で `--config reasoning.effort=medium` も付けると最終 message を返す傾向が上がる - -### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 -**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 - -**対処**: -- フラグを追加して再実行 -- `-s read-only` / `-s workspace-write` も bwrap を使うので同じ結果になる点に注意 -- ホストで user namespace を有効化する方法は「サンドボックス制約」節を参照 - -### Q3. codexが「ファイルを読めません」と返してくる -**原因**: -- サンドボックス有効でファイル読み取りに失敗 -- プロンプトで相対パスを指定し、codexの cwd が想定と違った - -**対処**: -- `--dangerously-bypass-approvals-and-sandbox` を追加 -- プロンプトには**絶対パス**を書く -- `-C ` で cwd を明示 - -### Q4. タスク完了通知が来たのに出力が空 / wait loop が抜けない -**原因**: `&` で起動したラッパーシェルが先に終了して通知が出ているだけで、codex 本体は動作中。または既に終わっているが zombie (defunct) として残っており `ps -p $PID` が 0 を返し続けている。 - -**対処**: 検知を「PID の存在」ではなく **stderr の `^tokens used$` sentinel** で行う。codex は最終回答を吐き終えると必ずこの行を stderr に書く。 - -```bash -# ❌ 永久ループ化しうる -until ! ps -p $PID; do sleep 30; done - -# ✅ zombie 安全 -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -### Q5. codex実行が15分以上かかる -**原因**: プロンプトで広すぎる調査範囲を指定した、または codex が探索ループに入った。 - -**対処**: -- プロンプトで「読むべきファイル」を明示リスト化 -- スコープ外を明記(「〇〇には踏み込まない」) -- 必要なら `kill ` で打ち切り、プロンプトを絞り込んで再実行 - -### Q6. stdoutの末尾が途切れている -**原因**: codex がトークン上限に達した可能性。 - -**対処**: プロンプトで「400行以内」など出力サイズを指定。または観点を絞って再実行。 - -### Q7. 認証エラー (`Unauthorized` / `token expired`) -**原因**: ログインセッション失効。 - -**対処**: -```bash -codex logout -codex login -``` - -## corder エージェント経由との使い分け - -本スキルは CLI を直接呼び出す詳細手順を記述している。簡易に独立レビューを取りたいだけなら `corder` エージェントに委譲した方が手間が少ない: - -| 観点 | corder エージェント | 本スキルで直接 CLI 起動 | -|---|---|---| -| 使い勝手 | `Agent(subagent_type: "corder", ...)` で委譲するだけ | プロンプト書き出し・バックグラウンド起動・PID 管理を自分で制御 | -| プロンプト制御 | corder 側で整形 | 自由に設計可 | -| バックグラウンド実行 | agent 側が制御 | `&` で非同期化、他作業と並列 | -| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | - -**指針**: 迷ったら corder 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ本スキルの手順で直接起動。 - -## 既知の制約とコスト - -1. **サンドボックス非対応環境**: `--dangerously-bypass-approvals-and-sandbox` で回避必須 -2. **stderrに全思考が書かれる**: 数千行になりうるので必ず `2> /tmp/...` にリダイレクト -3. **ログイン状態**: 初回は `codex login` が必要。未ログインだと即座に失敗する -4. **セッション復旧**: 長時間ジョブで親エージェントが再起動した場合、`codex resume` でセッション再開可能 -5. **APIコスト**: トークン従量課金のため、短時間で済むタスクには使わない。1セッションで数千〜数万トークン消費することがある -6. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと - -## 関連 - -- **NDF `corder` エージェント**: 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 (v4.0.0 以降は MCP ではなく CLI 経由) -- **OpenAI Codex CLI公式ドキュメント**: `codex --help` / `codex exec --help` -- **他のAI委譲方法**: `gemini`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf-claude/skills/cross-review/SKILL.md b/plugins/ndf-claude/skills/cross-review/SKILL.md index 21223ddd..2472f576 100644 --- a/plugins/ndf-claude/skills/cross-review/SKILL.md +++ b/plugins/ndf-claude/skills/cross-review/SKILL.md @@ -469,8 +469,7 @@ pint / larastan / test / build などは **中断** を原則とする。 - `/ndf:review` — 単発レビュー(AI 直接投稿対応) - `/ndf:fix` — 指摘の分類・修正・返信・Resolve(サブエージェント起動対応) -- `/ndf:codex` — codex CLI 呼び出し手順 -- `/ndf:gemini` — gemini CLI 呼び出し手順 +- `/ndf:external-ai` — codex / gemini CLI 呼び出し手順(CLI 別の差分は `references/cli-codex.md` / `references/cli-gemini.md`) - `/ndf:issue-plan-strategy` — multi-PR ワークフローでは **個別 PR ごとに本 cross-review が原則必須**。 `/ndf:review` 単発や Claude Code の `code-reviewer` は代替にせず、release ブランチへ merge する前に codex + gemini の APPROVE 収束を確認する (Step 6) diff --git a/plugins/ndf-claude/skills/external-ai/SKILL.md b/plugins/ndf-claude/skills/external-ai/SKILL.md new file mode 100644 index 00000000..9684e739 --- /dev/null +++ b/plugins/ndf-claude/skills/external-ai/SKILL.md @@ -0,0 +1,285 @@ +--- +name: external-ai +description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." +when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +--- + +# 外部 AI 委譲スキル (Codex / Gemini) + +## 概要 + +`codex` CLI(OpenAI Codex)と `gemini` CLI(Google Gemini)をローカルから直接起動し、 +コード生成・独立第二意見レビュー・大規模コードベース調査を外部 AI に委譲する。 + +**手順の大半は 2 つの CLI で共通**であり、本ファイルはその共通手順を規定する。 +起動フラグ・完了検知・出力回収など **CLI 固有の差分は補助ファイルに分離** している。 + +| 補助ファイル | 内容 | +|---|---| +| [references/cli-codex.md](references/cli-codex.md) | Codex CLI のインストール、サンドボックス制約、`codex exec` の起動、sentinel 完了検知、最終 message 欠落対策 | +| [references/cli-gemini.md](references/cli-gemini.md) | Gemini CLI のインストール、承認モード、`--output-format` の使い分け、プロセス終了による完了検知 | + +## NDF との関係 + +- Claude Code 版の `corder` エージェントは本スキルの手順で Codex CLI を呼び出す +- `/ndf:review codex` / `/ndf:review gemini` の委譲先として利用される +- `/ndf:cross-review` は codex / gemini を**並列に起動**して両者の APPROVE 収束を待つ +- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない +- Gemini 専用エージェントは未整備。委譲時はメインエージェントから本スキルを参照して直接 CLI を起動する + +## いつ使うか + +### 使うべきケース + +- **独立第二意見レビュー**: 設計書・PR・仕様書を外部 AI にレビューさせ、メインエージェントの思考バイアスを避ける +- **コードベース逐語照合**: 行番号・関数名・重複箇所の件数を正確に突き合わせる +- **長時間の調査タスク**: 複数ファイル横断で 5〜10 分以上かかる調査 +- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを外部 AI に走らせる +- **長文生成**: ドキュメント生成・要約・翻訳 + +### 使わないケース + +- 短時間(1〜2 分以内)で済むタスク → メインエージェントで直接対応 +- ユーザとの対話が必要な設計相談 → Plan Mode 等で対話しながら進める +- 単純な質問回答 → WebFetch / WebSearch で足りる +- 機密情報を含むコード → 外部 API へ送信されるため、可否を組織ポリシーで確認してから + +## どちらの CLI を選ぶか + +| 観点 | Codex | Gemini | +|---|---|---| +| stdout の信頼性 | 最終 message が落ちることがある(ファイル書き出し必須) | stdout に response が直接出る | +| サンドボックス | WSL2 / 一部コンテナで `--dangerously-bypass-approvals-and-sandbox` が必須 | bwrap 非依存。ただし trusted directory 判定があり `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` が必須 | +| 非対話実行 | `codex exec` で完結 | `--yolo` か `--approval-mode plan` に加えて trust 解除が必須 | +| 完了判定 | stderr の `^tokens used$` sentinel | プロセス終了(`kill -0` / `wait`) | +| 出力フォーマット | Markdown 本文のみ | `text` / `json`(json は統計付き) | +| 典型実行時間 | 5〜10 分 | 数十秒〜5 分 | +| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | +| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | + +**指針**: + +- 行番号・件数の逐語確認が要る → Codex +- 短時間で済む独立レビュー、横断調査、長文生成 → Gemini +- 第二意見を確実に取りたい → 両方を走らせてクロスチェック(`/ndf:cross-review` が自動化している) +- Codex がレート制限・サンドボックス制約に当たった → Gemini へ代替 + +`corder` エージェントとの使い分けは次のとおり。 + +| 観点 | `corder` エージェント経由 | 本スキルで直接 CLI 起動 | +|---|---|---| +| 使い勝手 | エージェントに委譲するだけ | プロンプト書き出し・起動・PID 管理を自分で制御 | +| プロンプト制御 | corder 側で整形 | 自由に設計可 | +| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | + +迷ったら `corder` 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ直接起動する。 + +## 共通の実行手順 + +CLI 固有のコマンドラインは補助ファイルを参照し、流れは以下で統一する。 + +### 1. 前提確認 + +インストールとログイン状態を確認する。未インストール時のセットアップ手順は補助ファイルに記載。 + +```bash +which codex && codex --version +which gemini && gemini --version +``` + +### 2. プロンプトを一時ファイルへ書き出す + +長いプロンプトをシェル引数へ直接渡すとエスケープが破綻する。**必ず一時ファイル経由**にする。 + +```bash +cat > /tmp/external-ai-prompt.md <<'EOF' +## タスク +以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 + +## 対象ファイル(絶対パスで指定) +/absolute/path/to/design.md +EOF +``` + +エージェントから実行する場合は、ファイル書き込みツールでプロンプトを作ってから、 +シェル実行ツールのバックグラウンド実行オプションで CLI を起動する。 + +### 3. バックグラウンドで起動する + +多くのエージェントハーネスはシェル実行に 2〜3 分のタイムアウトを課す。 +外部 AI は数分〜10 分かかるため、**フォアグラウンド実行は禁止**。`&` で必ず非同期化し、 +stdout と stderr を別ファイルへリダイレクトする。 + +```bash + \ + > /tmp/external-ai-stdout.md \ + 2> /tmp/external-ai-err.log & +PID=$! +``` + +stderr には思考ログや警告が出る。Codex では数千行になるため、必ずファイルへ逃がす。 + +### 4. 完了を検知する + +検知方法は CLI で異なる。**PID の存在だけで判定しない**(Codex は zombie 化して `ps -p` が +0 を返し続けることがある)。 + +| CLI | 脱出条件 | +|---|---| +| Codex | stderr に `^tokens used$` が現れる([references/cli-codex.md](references/cli-codex.md)) | +| Gemini | プロセスが終了する([references/cli-gemini.md](references/cli-gemini.md)) | + +### 5. 成果物を三段フォールバックで回収する + +外部 AI の最終出力は、CLI とモデルの都合で欠落しうる。**stdout だけに依存しない**。 +プロンプト側で「最終結果を指定ファイルへ書き出すこと」を必ず指示し(手順 6 のテンプレート参照)、 +回収側は次の順で拾う。 + +```bash +# STDOUT = CLI の `>` リダイレクト先 +# OUTPUT_FILE = プロンプト指示でツールに書き出させた保険ファイル(task ごとに固有名) +STDOUT=/tmp/external-ai-stdout.md +OUTPUT_FILE=/tmp/external-ai-output-pr13734-review.md + +# PRIMARY / SECONDARY は CLI ごとに下表の順で割り当てる +PRIMARY="$OUTPUT_FILE"; SECONDARY="$STDOUT" # Codex の場合 +# PRIMARY="$STDOUT"; SECONDARY="$OUTPUT_FILE" # Gemini の場合 + +if [ -s "$PRIMARY" ]; then + cp "$PRIMARY" ./result.md +elif [ -s "$SECONDARY" ]; then + cp "$SECONDARY" ./result.md +else + echo "WARN: 外部 AI の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/external-ai-err.log +fi +``` + +| CLI | 優先 (`PRIMARY`) | 次点 (`SECONDARY`) | 最後の手段 | +|---|---|---|---| +| Codex | `OUTPUT_FILE` | `STDOUT` | stderr 末尾 | +| Gemini | `STDOUT` | `OUTPUT_FILE` | stderr | + +Codex は最終 assistant message を返さずにセッションを終える既知挙動があるため、 +ファイルを優先する。Gemini は stdout が信頼できるため stdout を優先する。 + +### 6. 待機間隔のチューニング + +エージェントの context cache TTL は通常 5 分。これを超えると prompt cache がミスして +再送料金が発生する。 + +- **短い間隔**: 60〜270 秒(TTL 内に収まる、軽量) +- **長い間隔**: 1200 秒以上(1 回のキャッシュミスを長時間で償却) +- **避ける**: 300 秒前後(キャッシュミス + 短時間待機の最悪の組み合わせ) + +Codex(5〜10 分)は 270 秒ポーリングか 1200 秒一括待ち、Gemini(数十秒〜5 分)は +60〜270 秒ポーリングでよい。 + +## プロンプト設計 + +### 必須要素 + +1. **対象ファイルの絶対パス**(外部 AI は `nl -ba` / `sed -n` / `rg` 等でファイルを読む) +2. **調査観点を具体化**(箇条書きで 3〜5 項目に絞る) +3. **出力形式の指定**(Markdown テンプレートを提示) +4. **スコープ外の明示**(脱線防止) +5. **出力サイズの目安**(例: 400〜500 行) +6. **最終出力先ファイルの指定**: `/tmp/-output-タスク名.md` のような明示パスへ書き出させる。 + Codex は `apply_patch`、Gemini は `write_file` を使う。**stdout のみへの出力は不可** +7. **assistant message の強制**: 「tool 呼び出しのみで終了せず、最後に必ず 1 回出力すること」 + +### レビュー依頼テンプレート + +```markdown +あなたは(役割: 例 シニアバックエンドエンジニア / セキュリティレビュアー)として、 +以下をレビューしてください。 + +## 対象ファイル(必ず最初に読むこと) +`/absolute/path/to/target.md` + +## 観点 +1. (観点1: 例「仕様とコードの整合性」) +2. (観点2: 例「既存 API との後方互換性」) + +## 調査対象コード(必要に応じて読む) +- `src/...` + +## 背景コンテキスト +- プロジェクト概要 / 関連 PR・Issue 番号 +- 既存レビューで対応済みの事項(重複指摘を避けるため) + +## 出力先(必須) +最終結果を `/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 + +## 出力形式 +# タイトル +## 総評 +## 1. 観点1 に関する指摘 +## 2. 観点2 に関する指摘 +## 3. 追加提案 +## 4. 承認可否 + +**必須**: 行番号・ファイルパスに紐付けて具体的に指摘すること。400〜500 行、日本語。 +**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +### コード生成依頼テンプレート + +```markdown +以下の実装タスクを実行してください。 + +## タスク +(具体的な実装内容) + +## 制約 +- 技術制約(言語バージョン、依存ライブラリ) +- コーディング規約(ESLint / Prettier / rustfmt 等) +- テスト要件(ユニットテスト必須 等) + +## 対象ファイル +- 既存ファイルのパス / 新規ファイルのパス案 + +## 背景 +(なぜこの実装が必要か、設計判断の経緯) + +## 完了基準 +- [ ] テストがパスする +- [ ] 型チェック / lint がパスする + +**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を +`/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 +tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +## 共通のトラブルシューティング + +CLI 固有の症状(サンドボックス失敗、承認モードによるハング等)は補助ファイルを参照。 + +| 症状 | 原因 | 対処 | +|---|---|---| +| 完了通知が来たのに出力が空 | `&` で起動したラッパーシェルだけが終了し、本体はまだ実行中 | 手順 4 の脱出条件で待ち直す。PID の存在で判定しない | +| 出力の末尾が途切れる | モデルの出力トークン上限 | プロンプトで「400 行以内」など出力サイズを指定、または観点を絞って分割実行 | +| 実行が 15 分以上終わらない | 調査範囲が広すぎる、探索ループに入った | 読むべきファイルを明示リスト化し、スコープ外を明記。必要なら `kill` して再実行 | +| 「ファイルを読めません」と返る | 相対パス指定で cwd が想定と違う | プロンプトには**絶対パス**を書き、CLI 側でも作業ディレクトリを明示する | +| 認証エラー | ログインセッション失効 | 各 CLI のログイン手順をやり直す(補助ファイル参照) | +| ハーネスのシェルタイムアウトで kill される | フォアグラウンド実行のまま長尺タスクを走らせた | 手順 3 のとおり必ずバックグラウンド化する | + +## 既知の制約とコスト + +1. **ログイン状態**: 初回はログインが必要。未ログインだと即座に失敗する +2. **stderr の肥大**: 思考ログや警告が出るため必ず `2> /tmp/...` へリダイレクトする +3. **API コスト**: トークン従量課金。1 セッションで数千〜数万トークン消費することがあり、短時間で済むタスクには使わない +4. **機密情報**: コードが外部 API へ送信される。社外秘コードの扱いは組織ポリシーに従う +5. **モデル選択**: 既定モデルは時期により変動する。安定性が要るときは明示指定する +6. **サンドボックス無効化フラグ**: Codex の `--dangerously-bypass-approvals-and-sandbox` と Gemini の + `--yolo` は、任意のシェル実行とファイル編集を無確認で許可する。**Docker / devcontainer / VM / + CI ランナー / 隔離 worktree などの外部隔離環境内でのみ使用**し、ホスト直接実行や本番リポジトリでは使わない + +## 関連 + +- [references/cli-codex.md](references/cli-codex.md) — Codex CLI 固有の手順 +- [references/cli-gemini.md](references/cli-gemini.md) — Gemini CLI 固有の手順 +- `/ndf:cross-review` — codex / gemini 両方を並列起動して APPROVE 収束まで回す +- `/ndf:review` — 第二引数に `codex` / `gemini` を指定すると本スキルの手順へ委譲する +- Claude Code 版 `corder` エージェント — 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 +- 他の AI CLI(`claude`, `ollama` 等)も同じパターンで利用できる diff --git a/plugins/ndf-claude/skills/external-ai/references/cli-codex.md b/plugins/ndf-claude/skills/external-ai/references/cli-codex.md new file mode 100644 index 00000000..295edf0c --- /dev/null +++ b/plugins/ndf-claude/skills/external-ai/references/cli-codex.md @@ -0,0 +1,210 @@ +# Codex CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Codex CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which codex && codex --version +codex login # 初回のみ。未ログインだと即座に失敗する + +# 未インストールの場合 +npm install -g @openai/codex +codex exec --help +``` + +## サンドボックス制約(最重要) + +Codex の既定サンドボックスは `bubblewrap (bwrap)` に依存する。次の環境では bwrap が動作せず、 +`exec` で実行するシェルコマンドがすべて失敗する。 + +- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) +- **一部の devcontainer / Docker 環境**(user namespace 非対応) + +該当環境では `--dangerously-bypass-approvals-and-sandbox` を付けて起動する。 + +```bash +# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) +codex exec -s read-only -C "$PWD" + +# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" +``` + +**判断基準**: Docker / devcontainer / VM / CI ランナー等で外部的に隔離済みなら実用上安全。 +ホスト直接実行でコードを全書き換えされたくない場合はフラグを付けず、下記の bwrap 代替で対処する。 +`-s read-only` / `-s workspace-write` も bwrap を使うため、フラグなしでは同じ失敗になる点に注意。 + +### bwrap 代替の有効化(ホスト直接実行時) + +```bash +# Debian/Ubuntu 系でホスト user namespace を有効化 +sudo sysctl kernel.unprivileged_userns_clone=1 + +# 永続化 +echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf +``` + +## 起動コマンド + +プロンプトは **stdin へ流す**。`-C` で作業ディレクトリを明示する。 + +```bash +codex exec --dangerously-bypass-approvals-and-sandbox \ + --config reasoning.effort=medium \ + -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +``` + +| オプション | 用途 | +|---|---| +| `-C ` | 作業ディレクトリ。指定しないと cwd が想定と異なりファイルを読めなくなる | +| `--dangerously-bypass-approvals-and-sandbox` | bwrap 非対応環境で必須。外部隔離環境内でのみ使用する | +| `--config reasoning.effort=medium` | `high` だと思考へ偏り最終 message を返さない頻度が上がるため、既定で `medium` を推奨 | +| `--json` | JSON Lines でイベントを出力。`event.type=assistant_message` を grep すれば確実に本文を取れる | +| `codex resume` | 長時間ジョブで親エージェントが再起動した場合にセッションを再開する | + +## 出力ストリーム + +| ストリーム | 内容 | +|---|---| +| **stdout** | 最終 assistant message のみ(Markdown 本文)。**空になることがある**(下記) | +| **stderr** | プロンプトのエコー + 実行コマンドと結果 + 思考プロセス + `^tokens used$` sentinel。数千行になる | + +## 最終出力をファイル経由で保証する(必須) + +Codex CLI(特に `gpt-5-codex` / 高 `reasoning_effort`)は、長時間調査の末に +**最終 assistant message を返さずセッションを終えることがある**。このとき stdout は空のまま、 +stderr のイベントログにはコードを読んだ痕跡だけが残る(`^tokens used$` は出ているのに stdout が空)。 + +**根本対策**: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。 +Codex は最終 message を返さなくても `apply_patch` でファイルを作成できるため、ファイル経由なら確実に回収できる。 + +```markdown +## 出力先(必須) + +最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: + +`/tmp/codex-output-タスク名.md` + +書き出しは `apply_patch` で新規ファイル作成してください。 +**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 +書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 +``` + +補助策として `--config reasoning.effort=medium` へ下げる、`--json` でイベントを採取する、 +プロンプト末尾に「tool 呼び出しのみで終了しないこと」を明記する、の 3 つを併用する。 + +回収は **ファイル → stdout → stderr** の順(共通手順の三段フォールバック、Codex は `OUTPUT_FILE` 優先)。 + +## 完了検知 + +`ps -p $PID` は zombie (defunct) にも 0 を返すため、**PID watch は永久ループになりうる**。 +stderr 末尾の sentinel を脱出条件にする。 + +```bash +# ❌ 永久ループ化しうる +until ! ps -p $PID; do sleep 30; done + +# ✅ zombie 安全 +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +進捗を覗くときは `tail -30 /tmp/codex-err.log`。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +echo "codex PID: $PID" + +# === 3. 完了確認(^tokens used$ sentinel を待つ) === +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル優先 → stdout フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./review-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/codex-err.log + exit 1 +fi +``` + +## Codex 固有のトラブルシューティング + +### Q1. stdout が空で stderr に大量の exec ログだけある + +**原因**: まだ最終回答を出す前に停止した、または最終 assistant message を出さずにセッションが終わった。 + +**対処**: `grep -q '^tokens used$' /tmp/codex-err.log` で sentinel を確認する。 +未出力なら実行中なので追加待機。出ているのに stdout が空なら「最終出力をファイル経由で保証する」の +パターンでリトライする(`apply_patch` 指示の追加 + `reasoning.effort=medium`)。 + +### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 + +**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 + +**対処**: フラグを追加して再実行する。ホストで有効化する方法は「サンドボックス制約」節を参照。 + +### Q3. 「ファイルを読めません」と返ってくる + +**原因**: サンドボックス有効で読み取りに失敗、またはプロンプトの相対パスと cwd の不一致。 + +**対処**: `--dangerously-bypass-approvals-and-sandbox` を追加し、プロンプトには絶対パス、`-C` で cwd を明示する。 + +### Q4. タスク完了通知が来たのに出力が空 / 待機ループが抜けない + +**原因**: `&` で起動したラッパーシェルだけが終了した、または zombie を `ps -p` が生存と誤判定している。 + +**対処**: 検知を PID ではなく `^tokens used$` sentinel で行う(「完了検知」節)。 + +### Q5. 認証エラー(`Unauthorized` / `token expired`) + +```bash +codex logout +codex login +``` diff --git a/plugins/ndf-claude/skills/external-ai/references/cli-gemini.md b/plugins/ndf-claude/skills/external-ai/references/cli-gemini.md new file mode 100644 index 00000000..6440b067 --- /dev/null +++ b/plugins/ndf-claude/skills/external-ai/references/cli-gemini.md @@ -0,0 +1,221 @@ +# Gemini CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Gemini CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which gemini && gemini --version + +# 初回ログイン(OAuth): 対話モードで起動して /auth を叩きブラウザ認証する +gemini + +# 未インストールの場合 +npm install -g @google/gemini-cli +gemini -p "hello" --output-format text +``` + +## 承認モード(最重要) + +Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには +`--yolo` か `--approval-mode` を指定する。指定しないと承認待ちでハングする。 + +| モード | 用途 | +|---|---| +| `default` | 対話で都度承認(非対話では止まる) | +| `auto_edit` | 編集系のみ自動承認。シェル実行は都度承認 | +| `yolo`(`--yolo`) | 全 tool 自動承認 | +| `plan`(`--approval-mode plan`) | 読み取り専用。編集系 tool は走らない | + +- **レビュー / 調査タスク**: `--approval-mode plan`(編集事故を防ぐ) +- **コード生成タスク**: `--yolo`(実ファイル編集が必要) +- **`gh api -X POST` などシェル実行を伴うタスク**: `--yolo` 必須(`plan` / `auto_edit` ではブロックされる) + +指定した承認モードは trusted directory 判定で覆される。untrusted なパスで起動すると +`--yolo` が `default` へ降格し、非対話では承認待ちのままハングする。headless 実行では +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず併用すること(「起動コマンド」節参照)。 + +> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / +> 任意のファイル編集を**無確認で許可**する。Docker コンテナ / devcontainer / VM / CI ランナー / +> 隔離された worktree のいずれかの**外部隔離環境内でのみ**使用すること。ホスト直接実行や +> 本番リポジトリ作業中の `--yolo` は厳禁で、その場合は `--approval-mode auto_edit` への降格を検討する。 +> プロンプトで「リポジトリ編集禁止」を明示することは有効だが、sandbox の代替にはならない。 + +## 起動コマンド + +プロンプトは `-p "$(cat ...)"` で渡すか、stdin へパイプする。 + +> ⚠️ **非対話実行では `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず両方付ける**。 +> Gemini CLI は未登録のディレクトリ(worktree のような新規パスを含む)を untrusted と判定し、 +> `--yolo` を `default` へ降格させる。降格すると tool ごとの承認待ちになり、非対話では +> そのままハングする。片方だけでは降格を防げないため、環境変数とフラグの両方が必要。 + +```bash +GEMINI_CLI_TRUST_WORKSPACE=true gemini --approval-mode plan --skip-trust --output-format text \ + -p "$(cat /tmp/gemini-prompt.md)" \ + > /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! + +# stdin パイプでも可 +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text -p "" \ + < /tmp/gemini-prompt.md \ + > /tmp/gemini-stdout.md 2> /tmp/gemini-err.log & +``` + +| オプション | 用途 | +|---|---| +| `--output-format text` | 最終 response の本文をそのまま stdout へ出す | +| `--output-format json` | `{session_id, response, stats}` の JSON 1 オブジェクトを出す | +| `--include-directories ` | ワークスペース外のディレクトリを参照対象へ追加する | +| `--skip-trust` | trusted directory 判定を飛ばす。`--yolo` が無効化されるのを防ぐ | +| `GEMINI_CLI_TRUST_WORKSPACE=true`(環境変数) | 実行ディレクトリを trusted 扱いにする。`--skip-trust` と併用必須 | +| `-m ` | モデルを明示指定する(既定モデルは時期により変動する) | + +`/ndf:cross-review` の `scripts/launch-gemini.sh` も同じ組み合わせで起動している。 + +## 出力ストリーム + +| ストリーム | `--output-format text` | `--output-format json` | +|---|---|---| +| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | `{session_id, response, stats}` | +| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)。通常数行で無害 | 同左 | + +```bash +# 成果物だけ取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text \ + -p "$(cat prompt.md)" > out.md + +# 統計(トークン数・tool 呼び出し履歴)込みで取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format json \ + -p "$(cat prompt.md)" > out.json +jq -r '.response' out.json > out.md +jq '.stats' out.json > stats.json +``` + +Gemini には Codex のような「最終 message を返さずに終わる」既知挙動は確認されていないため、 +**回収は stdout 優先**(共通手順の三段フォールバックで `STDOUT` を `PRIMARY` にする)。 +ただし長尺タスクの途中エラーに備え、保険として `write_file` での書き出しをプロンプトに加えておく。 + +```markdown +## 出力先(推奨) + +最終結果を `/tmp/gemini-output-タスク名.md` にも `write_file` で書き出してください。 +(stdout には同内容をそのまま出力すれば冪等で問題ありません。) +``` + +## 完了検知 + +Gemini は `^tokens used$` のような sentinel を吐かないため、stderr の grep では完了判定できない。 +**プロセスの終了**を見るのが正しい。 + +```bash +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "exit=$?" +``` + +進捗を覗くときは `tail -30 /tmp/gemini-err.log`(実行中の stdout 出力は限定的)。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し === +FINAL=/tmp/gemini-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! +echo "gemini PID: $PID" + +# === 3. 完了確認(プロセス終了を待つ) === +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "DONE exit=$?" + +# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === +if [ -s /tmp/gemini-stdout.md ]; then + cp /tmp/gemini-stdout.md ./review-result.md +elif [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md + echo "WARN: ファイルからフォールバック回収" >&2 +else + echo "ERROR: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 + tail -200 /tmp/gemini-err.log + exit 1 +fi +``` + +## Gemini 固有のトラブルシューティング + +### Q1. 非対話モードなのにプロセスがハングする + +**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` のまま)。 +指定したはずの `--yolo` が trusted directory 判定で `default` へ降格しているケースも同じ症状になる。 + +**対処**: `--yolo` または `--approval-mode plan` を付けたうえで、 +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を併用する。レビュー / 調査なら `plan` が安全。 + +### Q2. stdout に思考のような余計な出力が混ざる + +**原因**: `--output-format text` でも進捗 / モデル切替メッセージが混ざる場合がある。 + +**対処**: `--output-format json` にして `jq -r '.response'` で本文だけ抽出する。 +あわせてプロンプトへ「最終結果のみを出力すること、思考や前置きは不要」と明記する。 + +### Q3. ワークスペース外のファイルを読めない / 止まる + +**対処**: `--include-directories /path/to/extra` で対象ディレクトリを追加し、プロンプトには絶対パスを書く。 +それでも止まる場合は `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` を併用する。 + +### Q4. `--yolo` を付けたのに承認待ちになる + +**原因**: trusted directory 判定によって YOLO が無効化され、承認モードが `default` へ降格している。 +worktree のような新規パスは既定で untrusted 扱いになる。 + +**対処**: `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を **両方** 付けて起動する。 +片方だけでは降格を防げない。 + +### Q5. `Error in: mcpServers.` の警告が毎回出る + +**原因**: `.gemini/settings.json` に `disabled: false` などの非互換キーがある。 + +**対処**: 該当キーを除去するか、起動前に設定を sanitize する +(`/ndf:cross-review` の `launch-gemini.sh` は v4.7.2 以降でこれを自動化している)。 + +### Q6. 認証エラー(`Authentication required` / `token expired`) + +**原因**: OAuth セッション失効。 + +**対処**: 対話モードで `gemini` を起動し、`/auth` を叩いてブラウザ認証をやり直す。 diff --git a/plugins/ndf-claude/skills/gemini/SKILL.md b/plugins/ndf-claude/skills/gemini/SKILL.md deleted file mode 100644 index e2156ed8..00000000 --- a/plugins/ndf-claude/skills/gemini/SKILL.md +++ /dev/null @@ -1,444 +0,0 @@ ---- -name: gemini -description: "Delegate coding, review, or research to Gemini CLI." -when_to_use: "外部 AI (Gemini)へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'geminiで調査', 'geminiレビュー', '第二意見レビュー (Gemini)', 'gemini exec', 'external AI review (Gemini)'" ---- - -# Gemini 外部AI委譲スキル - -## 概要 - -`gemini` CLI(Google Gemini、通常は `/usr/bin/gemini` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 - -`codex` skill と同等の用途だが、Gemini CLI は以下の点で扱いやすい: - -- **stdout に最終 response が直接出る**(text/json いずれも空にならない既知挙動なし) -- **bwrap サンドボックスに依存しない**(WSL2 でも追加フラグ不要) -- **プロセス exit で完了判定可能**(sentinel grep が不要) - -## NDFとの関係 - -- `/ndf:review gemini` のように、`review` skill の第二引数 `gemini` 指定時の委譲先として利用される -- 専用エージェント(`corder` 相当)は未整備。委譲時はメインエージェントから本 skill を参照して直接 CLI を起動する -- Codex との使い分けは「既知制約とコスト」節を参照 - -## いつ使うか - -### 使うべきケース -- **独立第二意見レビュー**: 設計書・PR・仕様書を Gemini にレビューさせる(Codex とのクロスチェックに有用) -- **コードベース横断調査**: Gemini はワークスペース全体を走査する設計のため、複数ディレクトリ横断の調査に向く -- **長文生成**: ドキュメント生成・要約・翻訳など -- **Codex でうまくいかない / レート制限に当たったときの代替** - -### 使わないべきケース -- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 -- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める -- 単純な質問回答 → WebFetch / WebSearch で足りる -- 機密情報を含むコード → 外部API送信の可否を確認してから - -## 前提条件 - -```bash -# インストール確認 -which gemini -gemini --version - -# 初回ログイン(OAuth) -gemini # 起動 → /auth でログイン -``` - -未インストールの場合は以下でセットアップ: - -```bash -# npm 経由 -npm install -g @google/gemini-cli - -# 動作確認 -gemini -p "hello" --output-format text -``` - -## 基本実行パターン - -### 1. 承認モード(重要) - -Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには `--yolo` か `--approval-mode yolo` を付ける。 - -```bash -# ❌ 非対話モードで tool 承認待ちで止まる -gemini -p "..." - -# ✅ ツール自動承認(外部隔離前提) -gemini --yolo -p "..." - -# ✅ 読み取り専用モード(plan mode、編集系 tool は走らない) -gemini --approval-mode plan -p "..." -``` - -| モード | 用途 | -|---|---| -| `default` | 対話で都度承認(非対話では止まる) | -| `auto_edit` | 編集系のみ自動承認 | -| `yolo` (`--yolo`) | 全 tool 自動承認 | -| `plan` | 読み取り専用(調査・レビュー向け) | - -**レビュー/調査タスクの推奨**: `--approval-mode plan`(編集事故を防ぐ) -**コード生成タスクの推奨**: `--yolo`(実ファイル編集が必要) - -> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / 任意のファイル編集を **無確認で許可** する。 -> 必ず以下のいずれかの **外部隔離環境** 内でのみ使用すること: -> - Docker コンテナ / devcontainer -> - VM / CI ランナー -> - 隔離された worktree(ホスト本体のリポジトリでは使わない) -> -> ホスト直接実行や本番リポジトリ作業中の `--yolo` は厳禁。コード生成タスクでも、ホスト直接実行なら -> `--approval-mode auto_edit`(編集系のみ自動承認、シェル実行は都度承認)への降格を検討する。 - -### 2. プロンプトは一時ファイル経由で渡す - -長いプロンプトをシェル引数に直接渡すとエスケープが破綻するので、ファイル経由で stdin か `$(cat ...)` 経由にする。 - -```bash -# Step 1: プロンプトを一時ファイルに書く -cat > /tmp/gemini-prompt.md <<'EOF' -## タスク -以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 - -## 対象ファイル(絶対パスで指定) -/absolute/path/to/design.md - -## 出力形式 -Markdown で標準出力に吐いてください。 -EOF - -# Step 2a: stdin 経由(推奨) -gemini --yolo --output-format text -p "$(cat /tmp/gemini-prompt.md)" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log - -# Step 2b: あるいは stdin パイプ -cat /tmp/gemini-prompt.md | gemini --yolo --output-format text -p "" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log -``` - -### 3. 出力ストリームの扱い - -Gemini CLI の出力構造(codex と異なる点に注意): - -| ストリーム | `--output-format text` の内容 | `--output-format json` の内容 | -|---|---|---| -| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | JSON 1 オブジェクト: `{session_id, response, stats}` | -| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)— 通常数行 | - -**実務上の扱い**: -- 成果物が欲しい → `--output-format text` の stdout をそのまま採用 -- 統計(トークン数・tool 呼び出し履歴)が欲しい → `--output-format json` で stdout を `jq` 解析 - -```bash -# 成果物だけ取りたい -gemini --yolo --output-format text -p "$(cat prompt.md)" > out.md - -# 統計込みで取りたい -gemini --yolo --output-format json -p "$(cat prompt.md)" > out.json -jq -r '.response' out.json > out.md -jq '.stats' out.json > stats.json -``` - -### 4. 最終出力をファイル経由で保証する(補強策) - -Gemini は codex のような「最終 message を返さずに終わる」既知挙動は今のところ確認されていない。 -ただし長尺タスクで途中エラーが起きた場合の保険として、**`apply_patch` 相当の write_file tool で書き出させる指示** をプロンプトに加えると安全: - -```markdown -## 出力先(推奨) - -最終結果を `/tmp/gemini-output-.md` にも書き出してください。 -(stdout には同内容をそのまま出力すれば冪等で問題ありません。) -``` - -回収側は「stdout → ファイル → stderr」の順でフォールバック: - -```bash -# 命名規約: -# STDOUT = gemini の `> リダイレクト` 先(本 skill では /tmp/gemini-stdout.md で統一) -# OUTPUT_FILE = プロンプト指示で `write_file` させた保険ファイル(task ごとに固有名) -OUTPUT_FILE=/tmp/gemini-output-pr13734-review.md -STDOUT=/tmp/gemini-stdout.md - -if [ -s "$STDOUT" ]; then - cp "$STDOUT" ./result.md -elif [ -s "$OUTPUT_FILE" ]; then - cp "$OUTPUT_FILE" ./result.md -else - echo "WARN: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 - tail -200 /tmp/gemini-err.log -fi -``` - -### 5. バックグラウンド実行 + 待機パターン - -Gemini も大規模調査タスクでは数分かかる。エージェントハーネスのシェルタイムアウト(通常2〜3分)に引っかかる可能性があるため、**バックグラウンド実行 + 待機** が安全。 - -```bash -# 1. プロンプトファイル書き出し -# -> /tmp/gemini-prompt.md - -# 2. gemini をバックグラウンドで起動 -gemini --yolo --output-format text -p "$(cat /tmp/gemini-prompt.md)" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log & -PID=$! -echo "PID: $PID" - -# 3. 完了検知 — Gemini は exit するので PID watch で OK -# (codex の zombie 問題はないが、念のため出力ファイルサイズも併用すると堅牢) -until ! kill -0 $PID 2>/dev/null; do - sleep 30 -done -echo "DONE" - -# 4. 終了コード確認 -wait $PID -EXIT=$? -echo "exit=$EXIT" -``` - -**注意**: -- Gemini は codex と違って `^tokens used$` のような sentinel を吐かないため、stderr grep では完了判定できない -- 代わりに **プロセスの終了** を見るのが正しい(`kill -0` でプロセス存在確認、`wait $PID` で終了コード回収) - -### 6. 待機間隔のチューニング - -エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: - -- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) -- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) -- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) - -Gemini の典型実行時間(数十秒〜5分)に対しては **60〜270秒ポーリング** で十分。 - -### 7. プロセス確認・ログ追跡 - -```bash -# 完了したか -kill -0 $PID 2>/dev/null && echo "RUNNING" || echo "DONE" - -# 進捗を覗く(Gemini は実行中の stdout 出力は限定的なので stderr 側を見る) -tail -30 /tmp/gemini-err.log -``` - -## プロンプト設計のコツ - -### 必須要素 -1. **対象ファイルの絶対パス**(Gemini はワークスペース外のファイルも参照可能だが絶対パスが安全) -2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) -3. **出力形式の指定**(Markdownテンプレートを提示) -4. **スコープ外の明示**(脱線防止) -5. **出力サイズ目安**(例: 400〜500行) - -### レビュー依頼テンプレート - -```markdown -あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 -以下をレビューしてください。 - -## 対象ファイル(必ず最初に読むこと) -`/absolute/path/to/target.md` - -## 観点 -1. <観点1: 例「仕様とコードの整合性」> -2. <観点2: 例「既存APIとの後方互換性」> - -## 調査対象コード(必要に応じて読む) -- `src/...` -- `lib/...` - -## 背景コンテキスト -- <プロジェクト概要> -- <関連PR / Issue番号> -- <既存レビューで対応済みの事項(重複指摘を避けるため)> - -## 出力形式 - -以下を Markdown で **stdout に出力** してください。 -(保険として `/tmp/gemini-output-.md` にも `write_file` で書き出してください。) - -# <タイトル> - -## 総評 -## 1. <観点1> に関する指摘 -### 1.1 正確な主張 -### 1.2 訂正推奨 -## 2. <観点2> に関する指摘 -## 3. 追加提案 -## 4. 承認可否 - -**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 -``` - -### コード生成依頼テンプレート - -```markdown -以下の実装タスクを実行してください。 - -## タスク -<具体的な実装内容> - -## 制約 -- <技術制約: 言語バージョン、依存ライブラリ> -- <コーディング規約: ESLint / Prettier / rustfmt等> -- <テスト要件: ユニットテスト必須等> - -## 対象ファイル -- <既存ファイルのパス> -- <新規ファイルのパス案> - -## 背景 -<なぜこの実装が必要か、設計判断の経緯> - -## 完了基準 -- [ ] テストがパスする -- [ ] 型チェック / lint がパスする -- [ ] <追加の受け入れ条件> - -**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を -stdout に Markdown で出力してください。 -保険として `/tmp/gemini-output-.md` にも `write_file` で書き出してください。 -``` - -## 実例: レビュー依頼の完全フロー - -```bash -# === 1. プロンプト書き出し === -FINAL=/tmp/gemini-output-api-v2-review.md - -cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log & - -PID=$! -echo "gemini PID: $PID" - -# === 3. 完了確認(プロセス終了を待つ) === -until ! kill -0 $PID 2>/dev/null; do - sleep 30 -done -wait $PID -EXIT=$? -echo "DONE exit=$EXIT" - -# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === -if [ -s /tmp/gemini-stdout.md ]; then - cp /tmp/gemini-stdout.md ./review-result.md - echo "✅ stdout から回収" -elif [ -s "$FINAL" ]; then - cp "$FINAL" ./review-result.md - echo "⚠ ファイルからフォールバック回収" -else - echo "❌ Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 - tail -200 /tmp/gemini-err.log - exit 1 -fi -``` - -## トラブルシューティング - -### Q1. 非対話モードなのにプロセスがハングする -**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` モードのまま)。 - -**対処**: `--yolo` または `--approval-mode plan` を付ける。レビュー/調査なら `plan` が安全。 - -### Q2. stdout に思考のような余計な出力が混ざる -**原因**: `--output-format text` でも一部の進捗 / モデル切替メッセージが混ざる場合がある。 - -**対処**: -- `--output-format json` を使い、`jq -r '.response'` で本文だけ抽出する -- プロンプトで「最終結果のみを出力すること、思考や前置きは不要」と明記 - -### Q3. ファイルを読めない / ワークスペース外アクセスで止まる -**原因**: Gemini のワークスペース範囲外のファイル参照、または承認待ち。 - -**対処**: -- `--include-directories /path/to/extra` で対象ディレクトリを追加 -- プロンプトには**絶対パス**を書く -- それでも止まるなら `--yolo` または `--skip-trust` - -### Q4. 出力が途中で切れる / トークン上限 -**原因**: モデルの出力トークン上限に達した。 - -**対処**: -- プロンプトで「400行以内」など出力サイズを指定 -- 観点を絞って分割実行 -- `-m ` でより長い context のモデルを指定(gemini-3-pro 等、利用可能なものに応じて) - -### Q5. 認証エラー (`Authentication required` / `token expired`) -**原因**: OAuth セッション失効。 - -**対処**: -```bash -# 対話モードで再ログイン -gemini -# プロンプト上で /auth を叩いてブラウザ認証 -``` - -### Q6. ハーネスのシェルタイムアウトで kill される -**原因**: フォアグラウンド実行のまま長尺タスクを走らせた。 - -**対処**: 必ず `&` でバックグラウンド化し、`kill -0 $PID` ポーリングで待機する(5節参照)。 - -## 既知の制約とコスト - -1. **承認モード必須**: 非対話実行では `--yolo` か `--approval-mode plan` を必ず付ける -2. **stderr 警告は無害**: `Ripgrep is not available. Falling back to GrepTool.` 等は通常運用上問題なし -3. **ログイン状態**: 初回は対話モードで `/auth` 経由のログインが必要 -4. **APIコスト**: Google AI Studio / Vertex 経由のトークン課金。Codex より安価な傾向だが従量制 -5. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと -6. **モデル選択**: デフォルトモデルは時期により変動。安定性を求めるなら `-m gemini-2.5-pro` 等を明示 - -## Codex との使い分け - -| 観点 | Codex (`/ndf:codex`) | Gemini (本スキル) | -|---|---|---| -| stdout の信頼性 | 最終 message が落ちることがある(要ファイル書き出し) | stdout に response が直接出る | -| サンドボックス | WSL2 で `--dangerously-bypass-approvals-and-sandbox` 必須 | 追加フラグ不要 | -| 完了判定 | `^tokens used$` sentinel | プロセス exit | -| 出力フォーマット | Markdown 本文のみ | text / json 選択可(json は統計付き) | -| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | -| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | - -**指針**: -- 第二意見が欲しい場合、両方走らせてクロスチェックすると最も堅い -- 短時間で済む独立レビュー → Gemini を先に -- 行番号・件数の逐語確認 → Codex を併用 - -## 関連 - -- **`/ndf:codex` skill**: Codex CLI 経由の同等スキル(本スキルと併用してクロスチェック可能) -- **`/ndf:review` skill**: 第二引数 `gemini` 指定時に本スキルの手順を参照 -- **Gemini CLI 公式ドキュメント**: `gemini --help` -- **他のAI委譲方法**: `codex`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf-claude/skills/review/SKILL.md b/plugins/ndf-claude/skills/review/SKILL.md index 983c4e4a..2afd42e2 100644 --- a/plugins/ndf-claude/skills/review/SKILL.md +++ b/plugins/ndf-claude/skills/review/SKILL.md @@ -225,8 +225,9 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ 第二引数が指定された場合、上記「観点」「具体的なチェックポイント」「PR モードの手順」の 内容を **レビュー指示プロンプト** として組み立て、指定された CLI に渡す。 -呼び出し手順の詳細は、利用 runtime に `/ndf:codex` / `/ndf:gemini` skill が同梱されて -いる場合はその skill に従う。同梱されていない runtime では以下の要点に従う。 +呼び出し手順の詳細は、利用 runtime に `/ndf:external-ai` skill が同梱されている場合は +その skill の `references/cli-codex.md` / `references/cli-gemini.md` に従う。 +同梱されていない runtime では以下の要点に従う。 **`codex` 指定時** @@ -239,6 +240,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ > ⚠️ `--dangerously-bypass-approvals-and-sandbox` は codex のサンドボックスを完全に無効化し、 > 任意のシェル実行・ファイル編集を無確認で許可する。**必ず Docker / devcontainer / VM / CI ランナー等の > 外部隔離環境内** でのみ使用すること。ホスト直接実行や本番リポジトリでは使わない。 +> 背景・代替策は `/ndf:external-ai` skill の `references/cli-codex.md`「サンドボックス制約」節を参照。 **`gemini` 指定時** @@ -250,7 +252,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ - 成果物は stdout サマリ + `/tmp/gemini-review-pr<番号>-result.json` で回収 > ⚠️ `--yolo` も同様に外部隔離環境内でのみ実行する。プロンプトでの「リポジトリ編集禁止」明示は必須だが、 -> sandbox の代替にはならない。 +> sandbox の代替にはならない。詳細は `/ndf:external-ai` skill の `references/cli-gemini.md` を参照。 ### プロンプト組み立て @@ -351,6 +353,5 @@ PR モードではレビュー結果が **PR 上に投稿済み** であるこ - `/ndf:fix` — レビュー指摘の分類と修正対応 - `/ndf:cross-review` — codex + gemini の収束レビュー -- `/ndf:codex` — Codex CLI の呼び出し手順(同梱 runtime のみ) -- `/ndf:gemini` — Gemini CLI の呼び出し手順(同梱 runtime のみ) +- `/ndf:external-ai` — Codex / Gemini CLI の呼び出し手順(同梱 runtime のみ) - `/ndf:logging-guidelines` — ログ設計 diff --git a/plugins/ndf-codex/skills/cross-review/SKILL.md b/plugins/ndf-codex/skills/cross-review/SKILL.md index a8f69176..a04d98e6 100644 --- a/plugins/ndf-codex/skills/cross-review/SKILL.md +++ b/plugins/ndf-codex/skills/cross-review/SKILL.md @@ -469,8 +469,7 @@ pint / larastan / test / build などは **中断** を原則とする。 - `/ndf:review` — 単発レビュー(AI 直接投稿対応) - `/ndf:fix` — 指摘の分類・修正・返信・Resolve(サブエージェント起動対応) -- `/ndf:codex` — codex CLI 呼び出し手順 -- `/ndf:gemini` — gemini CLI 呼び出し手順 +- `/ndf:external-ai` — codex / gemini CLI 呼び出し手順(CLI 別の差分は `references/cli-codex.md` / `references/cli-gemini.md`) - `/ndf:issue-plan-strategy` — multi-PR ワークフローでは **個別 PR ごとに本 cross-review が原則必須**。 `/ndf:review` 単発や Claude Code の `code-reviewer` は代替にせず、release ブランチへ merge する前に codex + gemini の APPROVE 収束を確認する (Step 6) diff --git a/plugins/ndf-codex/skills/external-ai/SKILL.md b/plugins/ndf-codex/skills/external-ai/SKILL.md new file mode 100644 index 00000000..9684e739 --- /dev/null +++ b/plugins/ndf-codex/skills/external-ai/SKILL.md @@ -0,0 +1,285 @@ +--- +name: external-ai +description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." +when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +--- + +# 外部 AI 委譲スキル (Codex / Gemini) + +## 概要 + +`codex` CLI(OpenAI Codex)と `gemini` CLI(Google Gemini)をローカルから直接起動し、 +コード生成・独立第二意見レビュー・大規模コードベース調査を外部 AI に委譲する。 + +**手順の大半は 2 つの CLI で共通**であり、本ファイルはその共通手順を規定する。 +起動フラグ・完了検知・出力回収など **CLI 固有の差分は補助ファイルに分離** している。 + +| 補助ファイル | 内容 | +|---|---| +| [references/cli-codex.md](references/cli-codex.md) | Codex CLI のインストール、サンドボックス制約、`codex exec` の起動、sentinel 完了検知、最終 message 欠落対策 | +| [references/cli-gemini.md](references/cli-gemini.md) | Gemini CLI のインストール、承認モード、`--output-format` の使い分け、プロセス終了による完了検知 | + +## NDF との関係 + +- Claude Code 版の `corder` エージェントは本スキルの手順で Codex CLI を呼び出す +- `/ndf:review codex` / `/ndf:review gemini` の委譲先として利用される +- `/ndf:cross-review` は codex / gemini を**並列に起動**して両者の APPROVE 収束を待つ +- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない +- Gemini 専用エージェントは未整備。委譲時はメインエージェントから本スキルを参照して直接 CLI を起動する + +## いつ使うか + +### 使うべきケース + +- **独立第二意見レビュー**: 設計書・PR・仕様書を外部 AI にレビューさせ、メインエージェントの思考バイアスを避ける +- **コードベース逐語照合**: 行番号・関数名・重複箇所の件数を正確に突き合わせる +- **長時間の調査タスク**: 複数ファイル横断で 5〜10 分以上かかる調査 +- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを外部 AI に走らせる +- **長文生成**: ドキュメント生成・要約・翻訳 + +### 使わないケース + +- 短時間(1〜2 分以内)で済むタスク → メインエージェントで直接対応 +- ユーザとの対話が必要な設計相談 → Plan Mode 等で対話しながら進める +- 単純な質問回答 → WebFetch / WebSearch で足りる +- 機密情報を含むコード → 外部 API へ送信されるため、可否を組織ポリシーで確認してから + +## どちらの CLI を選ぶか + +| 観点 | Codex | Gemini | +|---|---|---| +| stdout の信頼性 | 最終 message が落ちることがある(ファイル書き出し必須) | stdout に response が直接出る | +| サンドボックス | WSL2 / 一部コンテナで `--dangerously-bypass-approvals-and-sandbox` が必須 | bwrap 非依存。ただし trusted directory 判定があり `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` が必須 | +| 非対話実行 | `codex exec` で完結 | `--yolo` か `--approval-mode plan` に加えて trust 解除が必須 | +| 完了判定 | stderr の `^tokens used$` sentinel | プロセス終了(`kill -0` / `wait`) | +| 出力フォーマット | Markdown 本文のみ | `text` / `json`(json は統計付き) | +| 典型実行時間 | 5〜10 分 | 数十秒〜5 分 | +| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | +| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | + +**指針**: + +- 行番号・件数の逐語確認が要る → Codex +- 短時間で済む独立レビュー、横断調査、長文生成 → Gemini +- 第二意見を確実に取りたい → 両方を走らせてクロスチェック(`/ndf:cross-review` が自動化している) +- Codex がレート制限・サンドボックス制約に当たった → Gemini へ代替 + +`corder` エージェントとの使い分けは次のとおり。 + +| 観点 | `corder` エージェント経由 | 本スキルで直接 CLI 起動 | +|---|---|---| +| 使い勝手 | エージェントに委譲するだけ | プロンプト書き出し・起動・PID 管理を自分で制御 | +| プロンプト制御 | corder 側で整形 | 自由に設計可 | +| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | + +迷ったら `corder` 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ直接起動する。 + +## 共通の実行手順 + +CLI 固有のコマンドラインは補助ファイルを参照し、流れは以下で統一する。 + +### 1. 前提確認 + +インストールとログイン状態を確認する。未インストール時のセットアップ手順は補助ファイルに記載。 + +```bash +which codex && codex --version +which gemini && gemini --version +``` + +### 2. プロンプトを一時ファイルへ書き出す + +長いプロンプトをシェル引数へ直接渡すとエスケープが破綻する。**必ず一時ファイル経由**にする。 + +```bash +cat > /tmp/external-ai-prompt.md <<'EOF' +## タスク +以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 + +## 対象ファイル(絶対パスで指定) +/absolute/path/to/design.md +EOF +``` + +エージェントから実行する場合は、ファイル書き込みツールでプロンプトを作ってから、 +シェル実行ツールのバックグラウンド実行オプションで CLI を起動する。 + +### 3. バックグラウンドで起動する + +多くのエージェントハーネスはシェル実行に 2〜3 分のタイムアウトを課す。 +外部 AI は数分〜10 分かかるため、**フォアグラウンド実行は禁止**。`&` で必ず非同期化し、 +stdout と stderr を別ファイルへリダイレクトする。 + +```bash + \ + > /tmp/external-ai-stdout.md \ + 2> /tmp/external-ai-err.log & +PID=$! +``` + +stderr には思考ログや警告が出る。Codex では数千行になるため、必ずファイルへ逃がす。 + +### 4. 完了を検知する + +検知方法は CLI で異なる。**PID の存在だけで判定しない**(Codex は zombie 化して `ps -p` が +0 を返し続けることがある)。 + +| CLI | 脱出条件 | +|---|---| +| Codex | stderr に `^tokens used$` が現れる([references/cli-codex.md](references/cli-codex.md)) | +| Gemini | プロセスが終了する([references/cli-gemini.md](references/cli-gemini.md)) | + +### 5. 成果物を三段フォールバックで回収する + +外部 AI の最終出力は、CLI とモデルの都合で欠落しうる。**stdout だけに依存しない**。 +プロンプト側で「最終結果を指定ファイルへ書き出すこと」を必ず指示し(手順 6 のテンプレート参照)、 +回収側は次の順で拾う。 + +```bash +# STDOUT = CLI の `>` リダイレクト先 +# OUTPUT_FILE = プロンプト指示でツールに書き出させた保険ファイル(task ごとに固有名) +STDOUT=/tmp/external-ai-stdout.md +OUTPUT_FILE=/tmp/external-ai-output-pr13734-review.md + +# PRIMARY / SECONDARY は CLI ごとに下表の順で割り当てる +PRIMARY="$OUTPUT_FILE"; SECONDARY="$STDOUT" # Codex の場合 +# PRIMARY="$STDOUT"; SECONDARY="$OUTPUT_FILE" # Gemini の場合 + +if [ -s "$PRIMARY" ]; then + cp "$PRIMARY" ./result.md +elif [ -s "$SECONDARY" ]; then + cp "$SECONDARY" ./result.md +else + echo "WARN: 外部 AI の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/external-ai-err.log +fi +``` + +| CLI | 優先 (`PRIMARY`) | 次点 (`SECONDARY`) | 最後の手段 | +|---|---|---|---| +| Codex | `OUTPUT_FILE` | `STDOUT` | stderr 末尾 | +| Gemini | `STDOUT` | `OUTPUT_FILE` | stderr | + +Codex は最終 assistant message を返さずにセッションを終える既知挙動があるため、 +ファイルを優先する。Gemini は stdout が信頼できるため stdout を優先する。 + +### 6. 待機間隔のチューニング + +エージェントの context cache TTL は通常 5 分。これを超えると prompt cache がミスして +再送料金が発生する。 + +- **短い間隔**: 60〜270 秒(TTL 内に収まる、軽量) +- **長い間隔**: 1200 秒以上(1 回のキャッシュミスを長時間で償却) +- **避ける**: 300 秒前後(キャッシュミス + 短時間待機の最悪の組み合わせ) + +Codex(5〜10 分)は 270 秒ポーリングか 1200 秒一括待ち、Gemini(数十秒〜5 分)は +60〜270 秒ポーリングでよい。 + +## プロンプト設計 + +### 必須要素 + +1. **対象ファイルの絶対パス**(外部 AI は `nl -ba` / `sed -n` / `rg` 等でファイルを読む) +2. **調査観点を具体化**(箇条書きで 3〜5 項目に絞る) +3. **出力形式の指定**(Markdown テンプレートを提示) +4. **スコープ外の明示**(脱線防止) +5. **出力サイズの目安**(例: 400〜500 行) +6. **最終出力先ファイルの指定**: `/tmp/-output-タスク名.md` のような明示パスへ書き出させる。 + Codex は `apply_patch`、Gemini は `write_file` を使う。**stdout のみへの出力は不可** +7. **assistant message の強制**: 「tool 呼び出しのみで終了せず、最後に必ず 1 回出力すること」 + +### レビュー依頼テンプレート + +```markdown +あなたは(役割: 例 シニアバックエンドエンジニア / セキュリティレビュアー)として、 +以下をレビューしてください。 + +## 対象ファイル(必ず最初に読むこと) +`/absolute/path/to/target.md` + +## 観点 +1. (観点1: 例「仕様とコードの整合性」) +2. (観点2: 例「既存 API との後方互換性」) + +## 調査対象コード(必要に応じて読む) +- `src/...` + +## 背景コンテキスト +- プロジェクト概要 / 関連 PR・Issue 番号 +- 既存レビューで対応済みの事項(重複指摘を避けるため) + +## 出力先(必須) +最終結果を `/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 + +## 出力形式 +# タイトル +## 総評 +## 1. 観点1 に関する指摘 +## 2. 観点2 に関する指摘 +## 3. 追加提案 +## 4. 承認可否 + +**必須**: 行番号・ファイルパスに紐付けて具体的に指摘すること。400〜500 行、日本語。 +**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +### コード生成依頼テンプレート + +```markdown +以下の実装タスクを実行してください。 + +## タスク +(具体的な実装内容) + +## 制約 +- 技術制約(言語バージョン、依存ライブラリ) +- コーディング規約(ESLint / Prettier / rustfmt 等) +- テスト要件(ユニットテスト必須 等) + +## 対象ファイル +- 既存ファイルのパス / 新規ファイルのパス案 + +## 背景 +(なぜこの実装が必要か、設計判断の経緯) + +## 完了基準 +- [ ] テストがパスする +- [ ] 型チェック / lint がパスする + +**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を +`/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 +tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +## 共通のトラブルシューティング + +CLI 固有の症状(サンドボックス失敗、承認モードによるハング等)は補助ファイルを参照。 + +| 症状 | 原因 | 対処 | +|---|---|---| +| 完了通知が来たのに出力が空 | `&` で起動したラッパーシェルだけが終了し、本体はまだ実行中 | 手順 4 の脱出条件で待ち直す。PID の存在で判定しない | +| 出力の末尾が途切れる | モデルの出力トークン上限 | プロンプトで「400 行以内」など出力サイズを指定、または観点を絞って分割実行 | +| 実行が 15 分以上終わらない | 調査範囲が広すぎる、探索ループに入った | 読むべきファイルを明示リスト化し、スコープ外を明記。必要なら `kill` して再実行 | +| 「ファイルを読めません」と返る | 相対パス指定で cwd が想定と違う | プロンプトには**絶対パス**を書き、CLI 側でも作業ディレクトリを明示する | +| 認証エラー | ログインセッション失効 | 各 CLI のログイン手順をやり直す(補助ファイル参照) | +| ハーネスのシェルタイムアウトで kill される | フォアグラウンド実行のまま長尺タスクを走らせた | 手順 3 のとおり必ずバックグラウンド化する | + +## 既知の制約とコスト + +1. **ログイン状態**: 初回はログインが必要。未ログインだと即座に失敗する +2. **stderr の肥大**: 思考ログや警告が出るため必ず `2> /tmp/...` へリダイレクトする +3. **API コスト**: トークン従量課金。1 セッションで数千〜数万トークン消費することがあり、短時間で済むタスクには使わない +4. **機密情報**: コードが外部 API へ送信される。社外秘コードの扱いは組織ポリシーに従う +5. **モデル選択**: 既定モデルは時期により変動する。安定性が要るときは明示指定する +6. **サンドボックス無効化フラグ**: Codex の `--dangerously-bypass-approvals-and-sandbox` と Gemini の + `--yolo` は、任意のシェル実行とファイル編集を無確認で許可する。**Docker / devcontainer / VM / + CI ランナー / 隔離 worktree などの外部隔離環境内でのみ使用**し、ホスト直接実行や本番リポジトリでは使わない + +## 関連 + +- [references/cli-codex.md](references/cli-codex.md) — Codex CLI 固有の手順 +- [references/cli-gemini.md](references/cli-gemini.md) — Gemini CLI 固有の手順 +- `/ndf:cross-review` — codex / gemini 両方を並列起動して APPROVE 収束まで回す +- `/ndf:review` — 第二引数に `codex` / `gemini` を指定すると本スキルの手順へ委譲する +- Claude Code 版 `corder` エージェント — 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 +- 他の AI CLI(`claude`, `ollama` 等)も同じパターンで利用できる diff --git a/plugins/ndf-codex/skills/external-ai/references/cli-codex.md b/plugins/ndf-codex/skills/external-ai/references/cli-codex.md new file mode 100644 index 00000000..295edf0c --- /dev/null +++ b/plugins/ndf-codex/skills/external-ai/references/cli-codex.md @@ -0,0 +1,210 @@ +# Codex CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Codex CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which codex && codex --version +codex login # 初回のみ。未ログインだと即座に失敗する + +# 未インストールの場合 +npm install -g @openai/codex +codex exec --help +``` + +## サンドボックス制約(最重要) + +Codex の既定サンドボックスは `bubblewrap (bwrap)` に依存する。次の環境では bwrap が動作せず、 +`exec` で実行するシェルコマンドがすべて失敗する。 + +- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) +- **一部の devcontainer / Docker 環境**(user namespace 非対応) + +該当環境では `--dangerously-bypass-approvals-and-sandbox` を付けて起動する。 + +```bash +# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) +codex exec -s read-only -C "$PWD" + +# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" +``` + +**判断基準**: Docker / devcontainer / VM / CI ランナー等で外部的に隔離済みなら実用上安全。 +ホスト直接実行でコードを全書き換えされたくない場合はフラグを付けず、下記の bwrap 代替で対処する。 +`-s read-only` / `-s workspace-write` も bwrap を使うため、フラグなしでは同じ失敗になる点に注意。 + +### bwrap 代替の有効化(ホスト直接実行時) + +```bash +# Debian/Ubuntu 系でホスト user namespace を有効化 +sudo sysctl kernel.unprivileged_userns_clone=1 + +# 永続化 +echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf +``` + +## 起動コマンド + +プロンプトは **stdin へ流す**。`-C` で作業ディレクトリを明示する。 + +```bash +codex exec --dangerously-bypass-approvals-and-sandbox \ + --config reasoning.effort=medium \ + -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +``` + +| オプション | 用途 | +|---|---| +| `-C ` | 作業ディレクトリ。指定しないと cwd が想定と異なりファイルを読めなくなる | +| `--dangerously-bypass-approvals-and-sandbox` | bwrap 非対応環境で必須。外部隔離環境内でのみ使用する | +| `--config reasoning.effort=medium` | `high` だと思考へ偏り最終 message を返さない頻度が上がるため、既定で `medium` を推奨 | +| `--json` | JSON Lines でイベントを出力。`event.type=assistant_message` を grep すれば確実に本文を取れる | +| `codex resume` | 長時間ジョブで親エージェントが再起動した場合にセッションを再開する | + +## 出力ストリーム + +| ストリーム | 内容 | +|---|---| +| **stdout** | 最終 assistant message のみ(Markdown 本文)。**空になることがある**(下記) | +| **stderr** | プロンプトのエコー + 実行コマンドと結果 + 思考プロセス + `^tokens used$` sentinel。数千行になる | + +## 最終出力をファイル経由で保証する(必須) + +Codex CLI(特に `gpt-5-codex` / 高 `reasoning_effort`)は、長時間調査の末に +**最終 assistant message を返さずセッションを終えることがある**。このとき stdout は空のまま、 +stderr のイベントログにはコードを読んだ痕跡だけが残る(`^tokens used$` は出ているのに stdout が空)。 + +**根本対策**: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。 +Codex は最終 message を返さなくても `apply_patch` でファイルを作成できるため、ファイル経由なら確実に回収できる。 + +```markdown +## 出力先(必須) + +最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: + +`/tmp/codex-output-タスク名.md` + +書き出しは `apply_patch` で新規ファイル作成してください。 +**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 +書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 +``` + +補助策として `--config reasoning.effort=medium` へ下げる、`--json` でイベントを採取する、 +プロンプト末尾に「tool 呼び出しのみで終了しないこと」を明記する、の 3 つを併用する。 + +回収は **ファイル → stdout → stderr** の順(共通手順の三段フォールバック、Codex は `OUTPUT_FILE` 優先)。 + +## 完了検知 + +`ps -p $PID` は zombie (defunct) にも 0 を返すため、**PID watch は永久ループになりうる**。 +stderr 末尾の sentinel を脱出条件にする。 + +```bash +# ❌ 永久ループ化しうる +until ! ps -p $PID; do sleep 30; done + +# ✅ zombie 安全 +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +進捗を覗くときは `tail -30 /tmp/codex-err.log`。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +echo "codex PID: $PID" + +# === 3. 完了確認(^tokens used$ sentinel を待つ) === +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル優先 → stdout フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./review-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/codex-err.log + exit 1 +fi +``` + +## Codex 固有のトラブルシューティング + +### Q1. stdout が空で stderr に大量の exec ログだけある + +**原因**: まだ最終回答を出す前に停止した、または最終 assistant message を出さずにセッションが終わった。 + +**対処**: `grep -q '^tokens used$' /tmp/codex-err.log` で sentinel を確認する。 +未出力なら実行中なので追加待機。出ているのに stdout が空なら「最終出力をファイル経由で保証する」の +パターンでリトライする(`apply_patch` 指示の追加 + `reasoning.effort=medium`)。 + +### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 + +**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 + +**対処**: フラグを追加して再実行する。ホストで有効化する方法は「サンドボックス制約」節を参照。 + +### Q3. 「ファイルを読めません」と返ってくる + +**原因**: サンドボックス有効で読み取りに失敗、またはプロンプトの相対パスと cwd の不一致。 + +**対処**: `--dangerously-bypass-approvals-and-sandbox` を追加し、プロンプトには絶対パス、`-C` で cwd を明示する。 + +### Q4. タスク完了通知が来たのに出力が空 / 待機ループが抜けない + +**原因**: `&` で起動したラッパーシェルだけが終了した、または zombie を `ps -p` が生存と誤判定している。 + +**対処**: 検知を PID ではなく `^tokens used$` sentinel で行う(「完了検知」節)。 + +### Q5. 認証エラー(`Unauthorized` / `token expired`) + +```bash +codex logout +codex login +``` diff --git a/plugins/ndf-codex/skills/external-ai/references/cli-gemini.md b/plugins/ndf-codex/skills/external-ai/references/cli-gemini.md new file mode 100644 index 00000000..6440b067 --- /dev/null +++ b/plugins/ndf-codex/skills/external-ai/references/cli-gemini.md @@ -0,0 +1,221 @@ +# Gemini CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Gemini CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which gemini && gemini --version + +# 初回ログイン(OAuth): 対話モードで起動して /auth を叩きブラウザ認証する +gemini + +# 未インストールの場合 +npm install -g @google/gemini-cli +gemini -p "hello" --output-format text +``` + +## 承認モード(最重要) + +Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには +`--yolo` か `--approval-mode` を指定する。指定しないと承認待ちでハングする。 + +| モード | 用途 | +|---|---| +| `default` | 対話で都度承認(非対話では止まる) | +| `auto_edit` | 編集系のみ自動承認。シェル実行は都度承認 | +| `yolo`(`--yolo`) | 全 tool 自動承認 | +| `plan`(`--approval-mode plan`) | 読み取り専用。編集系 tool は走らない | + +- **レビュー / 調査タスク**: `--approval-mode plan`(編集事故を防ぐ) +- **コード生成タスク**: `--yolo`(実ファイル編集が必要) +- **`gh api -X POST` などシェル実行を伴うタスク**: `--yolo` 必須(`plan` / `auto_edit` ではブロックされる) + +指定した承認モードは trusted directory 判定で覆される。untrusted なパスで起動すると +`--yolo` が `default` へ降格し、非対話では承認待ちのままハングする。headless 実行では +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず併用すること(「起動コマンド」節参照)。 + +> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / +> 任意のファイル編集を**無確認で許可**する。Docker コンテナ / devcontainer / VM / CI ランナー / +> 隔離された worktree のいずれかの**外部隔離環境内でのみ**使用すること。ホスト直接実行や +> 本番リポジトリ作業中の `--yolo` は厳禁で、その場合は `--approval-mode auto_edit` への降格を検討する。 +> プロンプトで「リポジトリ編集禁止」を明示することは有効だが、sandbox の代替にはならない。 + +## 起動コマンド + +プロンプトは `-p "$(cat ...)"` で渡すか、stdin へパイプする。 + +> ⚠️ **非対話実行では `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず両方付ける**。 +> Gemini CLI は未登録のディレクトリ(worktree のような新規パスを含む)を untrusted と判定し、 +> `--yolo` を `default` へ降格させる。降格すると tool ごとの承認待ちになり、非対話では +> そのままハングする。片方だけでは降格を防げないため、環境変数とフラグの両方が必要。 + +```bash +GEMINI_CLI_TRUST_WORKSPACE=true gemini --approval-mode plan --skip-trust --output-format text \ + -p "$(cat /tmp/gemini-prompt.md)" \ + > /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! + +# stdin パイプでも可 +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text -p "" \ + < /tmp/gemini-prompt.md \ + > /tmp/gemini-stdout.md 2> /tmp/gemini-err.log & +``` + +| オプション | 用途 | +|---|---| +| `--output-format text` | 最終 response の本文をそのまま stdout へ出す | +| `--output-format json` | `{session_id, response, stats}` の JSON 1 オブジェクトを出す | +| `--include-directories ` | ワークスペース外のディレクトリを参照対象へ追加する | +| `--skip-trust` | trusted directory 判定を飛ばす。`--yolo` が無効化されるのを防ぐ | +| `GEMINI_CLI_TRUST_WORKSPACE=true`(環境変数) | 実行ディレクトリを trusted 扱いにする。`--skip-trust` と併用必須 | +| `-m ` | モデルを明示指定する(既定モデルは時期により変動する) | + +`/ndf:cross-review` の `scripts/launch-gemini.sh` も同じ組み合わせで起動している。 + +## 出力ストリーム + +| ストリーム | `--output-format text` | `--output-format json` | +|---|---|---| +| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | `{session_id, response, stats}` | +| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)。通常数行で無害 | 同左 | + +```bash +# 成果物だけ取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text \ + -p "$(cat prompt.md)" > out.md + +# 統計(トークン数・tool 呼び出し履歴)込みで取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format json \ + -p "$(cat prompt.md)" > out.json +jq -r '.response' out.json > out.md +jq '.stats' out.json > stats.json +``` + +Gemini には Codex のような「最終 message を返さずに終わる」既知挙動は確認されていないため、 +**回収は stdout 優先**(共通手順の三段フォールバックで `STDOUT` を `PRIMARY` にする)。 +ただし長尺タスクの途中エラーに備え、保険として `write_file` での書き出しをプロンプトに加えておく。 + +```markdown +## 出力先(推奨) + +最終結果を `/tmp/gemini-output-タスク名.md` にも `write_file` で書き出してください。 +(stdout には同内容をそのまま出力すれば冪等で問題ありません。) +``` + +## 完了検知 + +Gemini は `^tokens used$` のような sentinel を吐かないため、stderr の grep では完了判定できない。 +**プロセスの終了**を見るのが正しい。 + +```bash +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "exit=$?" +``` + +進捗を覗くときは `tail -30 /tmp/gemini-err.log`(実行中の stdout 出力は限定的)。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し === +FINAL=/tmp/gemini-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! +echo "gemini PID: $PID" + +# === 3. 完了確認(プロセス終了を待つ) === +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "DONE exit=$?" + +# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === +if [ -s /tmp/gemini-stdout.md ]; then + cp /tmp/gemini-stdout.md ./review-result.md +elif [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md + echo "WARN: ファイルからフォールバック回収" >&2 +else + echo "ERROR: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 + tail -200 /tmp/gemini-err.log + exit 1 +fi +``` + +## Gemini 固有のトラブルシューティング + +### Q1. 非対話モードなのにプロセスがハングする + +**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` のまま)。 +指定したはずの `--yolo` が trusted directory 判定で `default` へ降格しているケースも同じ症状になる。 + +**対処**: `--yolo` または `--approval-mode plan` を付けたうえで、 +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を併用する。レビュー / 調査なら `plan` が安全。 + +### Q2. stdout に思考のような余計な出力が混ざる + +**原因**: `--output-format text` でも進捗 / モデル切替メッセージが混ざる場合がある。 + +**対処**: `--output-format json` にして `jq -r '.response'` で本文だけ抽出する。 +あわせてプロンプトへ「最終結果のみを出力すること、思考や前置きは不要」と明記する。 + +### Q3. ワークスペース外のファイルを読めない / 止まる + +**対処**: `--include-directories /path/to/extra` で対象ディレクトリを追加し、プロンプトには絶対パスを書く。 +それでも止まる場合は `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` を併用する。 + +### Q4. `--yolo` を付けたのに承認待ちになる + +**原因**: trusted directory 判定によって YOLO が無効化され、承認モードが `default` へ降格している。 +worktree のような新規パスは既定で untrusted 扱いになる。 + +**対処**: `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を **両方** 付けて起動する。 +片方だけでは降格を防げない。 + +### Q5. `Error in: mcpServers.` の警告が毎回出る + +**原因**: `.gemini/settings.json` に `disabled: false` などの非互換キーがある。 + +**対処**: 該当キーを除去するか、起動前に設定を sanitize する +(`/ndf:cross-review` の `launch-gemini.sh` は v4.7.2 以降でこれを自動化している)。 + +### Q6. 認証エラー(`Authentication required` / `token expired`) + +**原因**: OAuth セッション失効。 + +**対処**: 対話モードで `gemini` を起動し、`/auth` を叩いてブラウザ認証をやり直す。 diff --git a/plugins/ndf-codex/skills/review/SKILL.md b/plugins/ndf-codex/skills/review/SKILL.md index 983c4e4a..2afd42e2 100644 --- a/plugins/ndf-codex/skills/review/SKILL.md +++ b/plugins/ndf-codex/skills/review/SKILL.md @@ -225,8 +225,9 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ 第二引数が指定された場合、上記「観点」「具体的なチェックポイント」「PR モードの手順」の 内容を **レビュー指示プロンプト** として組み立て、指定された CLI に渡す。 -呼び出し手順の詳細は、利用 runtime に `/ndf:codex` / `/ndf:gemini` skill が同梱されて -いる場合はその skill に従う。同梱されていない runtime では以下の要点に従う。 +呼び出し手順の詳細は、利用 runtime に `/ndf:external-ai` skill が同梱されている場合は +その skill の `references/cli-codex.md` / `references/cli-gemini.md` に従う。 +同梱されていない runtime では以下の要点に従う。 **`codex` 指定時** @@ -239,6 +240,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ > ⚠️ `--dangerously-bypass-approvals-and-sandbox` は codex のサンドボックスを完全に無効化し、 > 任意のシェル実行・ファイル編集を無確認で許可する。**必ず Docker / devcontainer / VM / CI ランナー等の > 外部隔離環境内** でのみ使用すること。ホスト直接実行や本番リポジトリでは使わない。 +> 背景・代替策は `/ndf:external-ai` skill の `references/cli-codex.md`「サンドボックス制約」節を参照。 **`gemini` 指定時** @@ -250,7 +252,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ - 成果物は stdout サマリ + `/tmp/gemini-review-pr<番号>-result.json` で回収 > ⚠️ `--yolo` も同様に外部隔離環境内でのみ実行する。プロンプトでの「リポジトリ編集禁止」明示は必須だが、 -> sandbox の代替にはならない。 +> sandbox の代替にはならない。詳細は `/ndf:external-ai` skill の `references/cli-gemini.md` を参照。 ### プロンプト組み立て @@ -351,6 +353,5 @@ PR モードではレビュー結果が **PR 上に投稿済み** であるこ - `/ndf:fix` — レビュー指摘の分類と修正対応 - `/ndf:cross-review` — codex + gemini の収束レビュー -- `/ndf:codex` — Codex CLI の呼び出し手順(同梱 runtime のみ) -- `/ndf:gemini` — Gemini CLI の呼び出し手順(同梱 runtime のみ) +- `/ndf:external-ai` — Codex / Gemini CLI の呼び出し手順(同梱 runtime のみ) - `/ndf:logging-guidelines` — ログ設計 diff --git a/plugins/ndf-kiro/prompts/codex.md b/plugins/ndf-kiro/prompts/codex.md index ada0330d..ddb3b52d 100644 --- a/plugins/ndf-kiro/prompts/codex.md +++ b/plugins/ndf-kiro/prompts/codex.md @@ -1,3 +1,4 @@ Codex CLIにコード生成・レビュー・調査を委譲してください。 -codexスキルの手順に従って実行してください。引数があればそのまま使用します。 +external-aiスキルの手順に従って実行してください。Codex CLI 固有の呼び出し方法は +`external-ai` スキルの `references/cli-codex.md`(Kiro では `.kiro/skills/external-ai/references/cli-codex.md`)を参照します。引数があればそのまま使用します。 diff --git a/plugins/ndf-kiro/skills/codex/SKILL.md b/plugins/ndf-kiro/skills/codex/SKILL.md deleted file mode 100644 index 80060a83..00000000 --- a/plugins/ndf-kiro/skills/codex/SKILL.md +++ /dev/null @@ -1,473 +0,0 @@ ---- -name: codex -description: "Delegate coding, review, or research to Codex CLI." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" ---- - -# Codex 外部AI委譲スキル - -## 概要 - -`codex` CLI(OpenAI Codex、通常は `/usr/bin/codex` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 - -ローカルファイルの逐語照合レビューや大規模コードベース調査に向いている。 - -## NDFとの関係 - -- NDFプラグインの `corder` エージェントはこの skill の手順に従って Codex CLI を呼び出す -- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない -- 使い分け: 軽量な独立レビュー → `corder` エージェントに委譲。手順の詳細を自分で制御したい or 複雑なプロンプトを出したい → 本 skill を参照して直接 `codex exec` 起動 - -## いつ使うか - -### 使うべきケース -- **独立第二意見レビュー**: 設計書・PR・仕様書を外部AIにレビューさせる(メインエージェントの思考バイアスを避ける) -- **コードベース逐語照合**: 「行番号・関数名・重複箇所の件数」を正確に突き合わせる必要がある場合 -- **長時間の調査タスク**: 複数ファイル横断で5〜10分以上かかる調査 -- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを codex に走らせたい場合 - -### 使わないべきケース -- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 -- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める -- 単純な質問回答 → WebFetch / WebSearch で足りる -- 機密情報を含むコード → 外部API送信の可否を確認してから - -## 前提条件 - -```bash -# インストール確認 -which codex -codex --version - -# ログイン状態確認(初回のみ必要) -codex login -``` - -未インストールの場合は以下でセットアップ: - -```bash -# npm 経由 -npm install -g @openai/codex - -# 動作確認 -codex exec --help -``` - -## 基本実行パターン - -### 1. サンドボックス制約(重要) - -codex のデフォルトサンドボックスは `bubblewrap (bwrap)` に依存する。以下の環境では bwrap が動作せず、`exec` で実行するシェルコマンドがすべて失敗する: - -- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) -- **一部の devcontainer / Docker 環境**(user namespace 非対応) - -該当環境では **`--dangerously-bypass-approvals-and-sandbox` を付けて起動**する必要がある。 - -```bash -# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) -codex exec -s read-only -C "$PWD" - -# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" -``` - -**判断基準**: 既にDocker / devcontainer / VM / CIランナー等で外部的にサンドボックスされているなら `--dangerously-bypass-approvals-and-sandbox` は実用上安全。ホスト直接実行でコード全書き換えされたくない場合はフラグを付けずに対処(後述「bwrap代替」)。 - -#### bwrap 代替の有効化(ホスト直接実行時) - -```bash -# Debian/Ubuntu 系でホスト user namespace を有効化 -sudo sysctl kernel.unprivileged_userns_clone=1 - -# 永続化 -echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf -``` - -### 2. プロンプトは一時ファイル経由で渡す - -長いプロンプトをシェル引数に渡すとエスケープ地獄になるので、**一時ファイル経由でstdinに流す**のが基本。 - -```bash -# Step 1: プロンプトを一時ファイルに書く -cat > /tmp/codex-prompt.md <<'EOF' -## タスク -以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 - -## 対象ファイル(絶対パスで指定) -/absolute/path/to/design.md - -## 出力形式 -Markdown で標準出力に吐いてください。 -EOF - -# Step 2: codex exec に stdin で流す(バックグラウンド実行) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & -``` - -**エージェントからの書き方**: ファイル書き込みツールで `/tmp/codex-prompt.md` を作ってから、シェル実行ツールの「バックグラウンド実行」オプションで codex を起動する。 - -### 3. 出力ストリームの扱い - -codex CLI の出力構造: - -| ストリーム | 内容 | -|---|---| -| **stdout** | **最終 assistant message のみ**(Markdown本文)。出ないことがある(後述) | -| **stderr** | プロンプトのエコー + 実行したコマンドと結果 + codexの思考プロセス + `^tokens used$` sentinel | - -**実務上の扱い**: -- 最終成果物が欲しい → `stdout` をそのまま採用…**ただし stdout が空になるケースがあるので必ずファイル出力も併用**(下記 3.5 参照) -- codexが何を調べたか追跡したい → `stderr` をデバッグ用に保存 - -```bash -codex exec ... > /tmp/codex-output.md 2> /tmp/codex-err.log -# 成果物 = /tmp/codex-output.md(stdout が空でないことを必ず確認) -# デバッグ = /tmp/codex-err.log(大きめ、数千行になる) -``` - -### 3.5 最終出力をファイル経由で保証する(重要) - -**Codex CLI(特に `gpt-5-codex` / 高 reasoning_effort)は、長時間調査の末に** -**最終 assistant message を返さずにセッションを終えることがある**。 -このとき stdout は空のままになり、stderr のイベントログ(数十万バイト)には -コードを実際に読んだ痕跡だけが残る。`^tokens used$` は出ているのに stdout が空、という状態。 - -**根本対策: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。** -Codex は最終 message を返さなくても `apply_patch` ツールでファイルを作成できるため、 -ファイル経由なら確実に結果を回収できる。 - -#### プロンプトに必ず含める指示(テンプレート) - -```markdown -## 出力先(必須) - -最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: - -`/tmp/codex-output-.md` - -書き出しは `apply_patch` で新規ファイル作成してください。 -**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 -書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 -``` - -#### 回収側の安全パターン - -```bash -# 1. ファイルが存在するかを最優先で確認(stdout が空でもこちらに本文が残る) -OUTPUT_FILE=/tmp/codex-output-pr13734-review.md -if [ -s "$OUTPUT_FILE" ]; then - cat "$OUTPUT_FILE" -elif [ -s /tmp/codex-stdout.md ]; then - # 2. ファイルがなければ stdout フォールバック - cat /tmp/codex-stdout.md -else - # 3. どちらも空なら stderr の末尾から拾う最後の手段 - echo "WARN: Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log -fi -``` - -#### 補助対策 - -- **`reasoning_effort` を `medium` に下げる** (`--config reasoning.effort=medium`) - `high` だと思考に偏って最終 message を返さなくなる頻度が上がる -- **`--json` モードでイベント採取** (`codex exec --json`) - JSON Lines で `event.type=assistant_message` を grep すれば確実に取れる -- **強制 summary 指示**: プロンプト末尾に「最後に必ず assistant message として 1 回出力すること、tool 呼び出しのみで終了しないこと」を明記 - -### 4. バックグラウンド実行 + 待機パターン - -codex は **5〜10分かかることが普通**。多くのエージェントハーネスはシェル実行に2〜3分のタイムアウトを課すので、**必ずバックグラウンド実行**する。 - -```bash -# 1. プロンプトファイル書き出し(ファイル書き込みツール) -# -> /tmp/codex-prompt.md - -# 2. codex をバックグラウンドで起動(`&` でシェル自体は即時終了) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & - -# 3. PID を控える -echo "PID: $!" - -# 4. 待機(他の作業を進める or スケジューラで再開) - -# 5. 完了検知 — ps -p は zombie に騙される。stderr の "tokens used" sentinel を見る -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -**⚠️ 罠**: `&` でバックグラウンド実行するとラッパーシェルは即終了し「タスク完了通知」が発火するが、codex 本体はまだ動いている。**`ps -p $PID` は zombie (defunct) も 0 を返す** ため `until ! ps -p $PID` は永久ループになりうる。`grep -q '^tokens used$' /tmp/codex-err.log` を脱出条件にする (codex が最終回答を吐き終わると stderr 末尾に必ず出る sentinel)。 - -### 5. 待機間隔のチューニング - -エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: - -- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) -- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) -- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) - -codex の典型実行時間(5〜10分)に対しては **270秒ポーリング** か **1200秒一括待ち** の二択。 - -### 6. プロセス確認・ログ追跡 - -```bash -# 完了したか (stderr 末尾の "tokens used" が最も信頼できる) -grep -q '^tokens used$' /tmp/codex-err.log && echo DONE - -# 最新の作業内容を覗く -tail -30 /tmp/codex-err.log -``` - -## プロンプト設計のコツ - -### 必須要素 -1. **対象ファイルの絶対パス**(codexは `nl -ba`, `sed -n`, `rg` 等でファイルを読むため) -2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) -3. **出力形式の指定**(Markdownテンプレートを提示) -4. **スコープ外の明示**(codexが脱線しないため) -5. **最終出力先ファイルの指定(必須)**: `/tmp/codex-output-.md` のような明示パスへ - **`apply_patch` で必ず書き出させる**。stdout だけに頼ると最終 message が落ちて空になる事故が起きる(3.5 節参照) -6. **stdout にも同内容を吐く指示**: ファイル書き出し後、念のため stdout にもエコーさせる(冪等) - -### レビュー依頼テンプレート - -```markdown -あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 -以下をレビューしてください。 - -## 対象ファイル(必ず最初に読むこと) -`/absolute/path/to/target.md` - -## 観点 -1. <観点1: 例「仕様とコードの整合性」> -2. <観点2: 例「既存APIとの後方互換性」> - -## 調査対象コード(必要に応じて読む) -- `src/...` -- `lib/...` - -## 背景コンテキスト -- <プロジェクト概要> -- <関連PR / Issue番号> -- <既存レビューで対応済みの事項(重複指摘を避けるため)> - -## 出力形式 - -以下を Markdown で**`/tmp/codex-output-.md` に必ず書き出してください** -(`apply_patch` で新規ファイル作成)。書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため): - -# <タイトル> - -## 総評 -## 1. <観点1> に関する指摘 -### 1.1 正確な主張 -### 1.2 訂正推奨 -## 2. <観点2> に関する指摘 -## 3. 追加提案 -## 4. 承認可否 - -**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 -**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -### コード生成依頼テンプレート - -```markdown -以下の実装タスクを実行してください。 - -## タスク -<具体的な実装内容> - -## 制約 -- <技術制約: 言語バージョン、依存ライブラリ> -- <コーディング規約: ESLint / Prettier / rustfmt等> -- <テスト要件: ユニットテスト必須等> - -## 対象ファイル -- <既存ファイルのパス> -- <新規ファイルのパス案> - -## 背景 -<なぜこの実装が必要か、設計判断の経緯> - -## 完了基準 -- [ ] テストがパスする -- [ ] 型チェック / lint がパスする -- [ ] <追加の受け入れ条件> - -**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を -`/tmp/codex-output-.md` に書き出してください(`apply_patch` で新規作成)。 -書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため)。 -tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -## 実例: レビュー依頼の完全フロー - -```bash -# === 1. プロンプト書き出し === -# ポイント: 最終出力先ファイルをプロンプト内で明示し、apply_patch で書かせる -FINAL=/tmp/codex-output-api-v2-review.md - -cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ - 2> /tmp/codex-err.log & - -PID=$! -echo "codex PID: $PID" - -# === 3. 完了確認(^tokens used$ sentinel を待つ) === -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -echo DONE - -# === 4. 成果物を安全に回収(ファイル優先 → stdout fallback) === -if [ -s "$FINAL" ]; then - cp "$FINAL" ./review-result.md - echo "✅ Codex 書き出しファイルから回収" -elif [ -s /tmp/codex-stdout.md ]; then - cp /tmp/codex-stdout.md ./review-result.md - echo "⚠ stdout からフォールバック回収(ファイル書き出しなし)" -else - echo "❌ Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log - exit 1 -fi -``` - -## トラブルシューティング - -### Q1. stdoutが空でstderrに大量のexecログだけある -**原因**: codex がまだ最終回答を出す前に停止した、または **最終 assistant message を出さずにセッションが終わった**(gpt-5-codex の高 reasoning_effort で発生しやすい既知挙動)。 - -**対処**: -- `grep -q '^tokens used$' /tmp/codex-err.log` で終了 sentinel が出ているか確認(まだなら動作中なので追加待機) -- 出ているのに stdout が空 → セッション終了で最終 message が失われたケース。**3.5 節「最終出力をファイル経由で保証する」のパターンでリトライ必須**: - - プロンプトに `apply_patch` で `/tmp/codex-output-.md` へ必ず書き出させる指示を追加 - - 回収側は「ファイル → stdout → stderr」の三段フォールバックで取りこぼしを防ぐ - - 補助で `--config reasoning.effort=medium` も付けると最終 message を返す傾向が上がる - -### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 -**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 - -**対処**: -- フラグを追加して再実行 -- `-s read-only` / `-s workspace-write` も bwrap を使うので同じ結果になる点に注意 -- ホストで user namespace を有効化する方法は「サンドボックス制約」節を参照 - -### Q3. codexが「ファイルを読めません」と返してくる -**原因**: -- サンドボックス有効でファイル読み取りに失敗 -- プロンプトで相対パスを指定し、codexの cwd が想定と違った - -**対処**: -- `--dangerously-bypass-approvals-and-sandbox` を追加 -- プロンプトには**絶対パス**を書く -- `-C ` で cwd を明示 - -### Q4. タスク完了通知が来たのに出力が空 / wait loop が抜けない -**原因**: `&` で起動したラッパーシェルが先に終了して通知が出ているだけで、codex 本体は動作中。または既に終わっているが zombie (defunct) として残っており `ps -p $PID` が 0 を返し続けている。 - -**対処**: 検知を「PID の存在」ではなく **stderr の `^tokens used$` sentinel** で行う。codex は最終回答を吐き終えると必ずこの行を stderr に書く。 - -```bash -# ❌ 永久ループ化しうる -until ! ps -p $PID; do sleep 30; done - -# ✅ zombie 安全 -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -### Q5. codex実行が15分以上かかる -**原因**: プロンプトで広すぎる調査範囲を指定した、または codex が探索ループに入った。 - -**対処**: -- プロンプトで「読むべきファイル」を明示リスト化 -- スコープ外を明記(「〇〇には踏み込まない」) -- 必要なら `kill ` で打ち切り、プロンプトを絞り込んで再実行 - -### Q6. stdoutの末尾が途切れている -**原因**: codex がトークン上限に達した可能性。 - -**対処**: プロンプトで「400行以内」など出力サイズを指定。または観点を絞って再実行。 - -### Q7. 認証エラー (`Unauthorized` / `token expired`) -**原因**: ログインセッション失効。 - -**対処**: -```bash -codex logout -codex login -``` - -## corder エージェント経由との使い分け - -本スキルは CLI を直接呼び出す詳細手順を記述している。簡易に独立レビューを取りたいだけなら `corder` エージェントに委譲した方が手間が少ない: - -| 観点 | corder エージェント | 本スキルで直接 CLI 起動 | -|---|---|---| -| 使い勝手 | `Agent(subagent_type: "corder", ...)` で委譲するだけ | プロンプト書き出し・バックグラウンド起動・PID 管理を自分で制御 | -| プロンプト制御 | corder 側で整形 | 自由に設計可 | -| バックグラウンド実行 | agent 側が制御 | `&` で非同期化、他作業と並列 | -| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | - -**指針**: 迷ったら corder 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ本スキルの手順で直接起動。 - -## 既知の制約とコスト - -1. **サンドボックス非対応環境**: `--dangerously-bypass-approvals-and-sandbox` で回避必須 -2. **stderrに全思考が書かれる**: 数千行になりうるので必ず `2> /tmp/...` にリダイレクト -3. **ログイン状態**: 初回は `codex login` が必要。未ログインだと即座に失敗する -4. **セッション復旧**: 長時間ジョブで親エージェントが再起動した場合、`codex resume` でセッション再開可能 -5. **APIコスト**: トークン従量課金のため、短時間で済むタスクには使わない。1セッションで数千〜数万トークン消費することがある -6. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと - -## 関連 - -- **NDF `corder` エージェント**: 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 (v4.0.0 以降は MCP ではなく CLI 経由) -- **OpenAI Codex CLI公式ドキュメント**: `codex --help` / `codex exec --help` -- **他のAI委譲方法**: `gemini`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf-kiro/skills/cross-review/SKILL.md b/plugins/ndf-kiro/skills/cross-review/SKILL.md index b355bff2..676c381e 100644 --- a/plugins/ndf-kiro/skills/cross-review/SKILL.md +++ b/plugins/ndf-kiro/skills/cross-review/SKILL.md @@ -469,8 +469,7 @@ pint / larastan / test / build などは **中断** を原則とする。 - `/ndf:review` — 単発レビュー(AI 直接投稿対応) - `/ndf:fix` — 指摘の分類・修正・返信・Resolve(サブエージェント起動対応) -- `/ndf:codex` — codex CLI 呼び出し手順 -- `/ndf:gemini` — gemini CLI 呼び出し手順 +- `/ndf:external-ai` — codex / gemini CLI 呼び出し手順(CLI 別の差分は `references/cli-codex.md` / `references/cli-gemini.md`) - `/ndf:issue-plan-strategy` — multi-PR ワークフローでは **個別 PR ごとに本 cross-review が原則必須**。 `/ndf:review` 単発や Claude Code の `code-reviewer` は代替にせず、release ブランチへ merge する前に codex + gemini の APPROVE 収束を確認する (Step 6) diff --git a/plugins/ndf-kiro/skills/external-ai/SKILL.md b/plugins/ndf-kiro/skills/external-ai/SKILL.md new file mode 100644 index 00000000..9684e739 --- /dev/null +++ b/plugins/ndf-kiro/skills/external-ai/SKILL.md @@ -0,0 +1,285 @@ +--- +name: external-ai +description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." +when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +--- + +# 外部 AI 委譲スキル (Codex / Gemini) + +## 概要 + +`codex` CLI(OpenAI Codex)と `gemini` CLI(Google Gemini)をローカルから直接起動し、 +コード生成・独立第二意見レビュー・大規模コードベース調査を外部 AI に委譲する。 + +**手順の大半は 2 つの CLI で共通**であり、本ファイルはその共通手順を規定する。 +起動フラグ・完了検知・出力回収など **CLI 固有の差分は補助ファイルに分離** している。 + +| 補助ファイル | 内容 | +|---|---| +| [references/cli-codex.md](references/cli-codex.md) | Codex CLI のインストール、サンドボックス制約、`codex exec` の起動、sentinel 完了検知、最終 message 欠落対策 | +| [references/cli-gemini.md](references/cli-gemini.md) | Gemini CLI のインストール、承認モード、`--output-format` の使い分け、プロセス終了による完了検知 | + +## NDF との関係 + +- Claude Code 版の `corder` エージェントは本スキルの手順で Codex CLI を呼び出す +- `/ndf:review codex` / `/ndf:review gemini` の委譲先として利用される +- `/ndf:cross-review` は codex / gemini を**並列に起動**して両者の APPROVE 収束を待つ +- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない +- Gemini 専用エージェントは未整備。委譲時はメインエージェントから本スキルを参照して直接 CLI を起動する + +## いつ使うか + +### 使うべきケース + +- **独立第二意見レビュー**: 設計書・PR・仕様書を外部 AI にレビューさせ、メインエージェントの思考バイアスを避ける +- **コードベース逐語照合**: 行番号・関数名・重複箇所の件数を正確に突き合わせる +- **長時間の調査タスク**: 複数ファイル横断で 5〜10 分以上かかる調査 +- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを外部 AI に走らせる +- **長文生成**: ドキュメント生成・要約・翻訳 + +### 使わないケース + +- 短時間(1〜2 分以内)で済むタスク → メインエージェントで直接対応 +- ユーザとの対話が必要な設計相談 → Plan Mode 等で対話しながら進める +- 単純な質問回答 → WebFetch / WebSearch で足りる +- 機密情報を含むコード → 外部 API へ送信されるため、可否を組織ポリシーで確認してから + +## どちらの CLI を選ぶか + +| 観点 | Codex | Gemini | +|---|---|---| +| stdout の信頼性 | 最終 message が落ちることがある(ファイル書き出し必須) | stdout に response が直接出る | +| サンドボックス | WSL2 / 一部コンテナで `--dangerously-bypass-approvals-and-sandbox` が必須 | bwrap 非依存。ただし trusted directory 判定があり `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` が必須 | +| 非対話実行 | `codex exec` で完結 | `--yolo` か `--approval-mode plan` に加えて trust 解除が必須 | +| 完了判定 | stderr の `^tokens used$` sentinel | プロセス終了(`kill -0` / `wait`) | +| 出力フォーマット | Markdown 本文のみ | `text` / `json`(json は統計付き) | +| 典型実行時間 | 5〜10 分 | 数十秒〜5 分 | +| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | +| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | + +**指針**: + +- 行番号・件数の逐語確認が要る → Codex +- 短時間で済む独立レビュー、横断調査、長文生成 → Gemini +- 第二意見を確実に取りたい → 両方を走らせてクロスチェック(`/ndf:cross-review` が自動化している) +- Codex がレート制限・サンドボックス制約に当たった → Gemini へ代替 + +`corder` エージェントとの使い分けは次のとおり。 + +| 観点 | `corder` エージェント経由 | 本スキルで直接 CLI 起動 | +|---|---|---| +| 使い勝手 | エージェントに委譲するだけ | プロンプト書き出し・起動・PID 管理を自分で制御 | +| プロンプト制御 | corder 側で整形 | 自由に設計可 | +| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | + +迷ったら `corder` 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ直接起動する。 + +## 共通の実行手順 + +CLI 固有のコマンドラインは補助ファイルを参照し、流れは以下で統一する。 + +### 1. 前提確認 + +インストールとログイン状態を確認する。未インストール時のセットアップ手順は補助ファイルに記載。 + +```bash +which codex && codex --version +which gemini && gemini --version +``` + +### 2. プロンプトを一時ファイルへ書き出す + +長いプロンプトをシェル引数へ直接渡すとエスケープが破綻する。**必ず一時ファイル経由**にする。 + +```bash +cat > /tmp/external-ai-prompt.md <<'EOF' +## タスク +以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 + +## 対象ファイル(絶対パスで指定) +/absolute/path/to/design.md +EOF +``` + +エージェントから実行する場合は、ファイル書き込みツールでプロンプトを作ってから、 +シェル実行ツールのバックグラウンド実行オプションで CLI を起動する。 + +### 3. バックグラウンドで起動する + +多くのエージェントハーネスはシェル実行に 2〜3 分のタイムアウトを課す。 +外部 AI は数分〜10 分かかるため、**フォアグラウンド実行は禁止**。`&` で必ず非同期化し、 +stdout と stderr を別ファイルへリダイレクトする。 + +```bash + \ + > /tmp/external-ai-stdout.md \ + 2> /tmp/external-ai-err.log & +PID=$! +``` + +stderr には思考ログや警告が出る。Codex では数千行になるため、必ずファイルへ逃がす。 + +### 4. 完了を検知する + +検知方法は CLI で異なる。**PID の存在だけで判定しない**(Codex は zombie 化して `ps -p` が +0 を返し続けることがある)。 + +| CLI | 脱出条件 | +|---|---| +| Codex | stderr に `^tokens used$` が現れる([references/cli-codex.md](references/cli-codex.md)) | +| Gemini | プロセスが終了する([references/cli-gemini.md](references/cli-gemini.md)) | + +### 5. 成果物を三段フォールバックで回収する + +外部 AI の最終出力は、CLI とモデルの都合で欠落しうる。**stdout だけに依存しない**。 +プロンプト側で「最終結果を指定ファイルへ書き出すこと」を必ず指示し(手順 6 のテンプレート参照)、 +回収側は次の順で拾う。 + +```bash +# STDOUT = CLI の `>` リダイレクト先 +# OUTPUT_FILE = プロンプト指示でツールに書き出させた保険ファイル(task ごとに固有名) +STDOUT=/tmp/external-ai-stdout.md +OUTPUT_FILE=/tmp/external-ai-output-pr13734-review.md + +# PRIMARY / SECONDARY は CLI ごとに下表の順で割り当てる +PRIMARY="$OUTPUT_FILE"; SECONDARY="$STDOUT" # Codex の場合 +# PRIMARY="$STDOUT"; SECONDARY="$OUTPUT_FILE" # Gemini の場合 + +if [ -s "$PRIMARY" ]; then + cp "$PRIMARY" ./result.md +elif [ -s "$SECONDARY" ]; then + cp "$SECONDARY" ./result.md +else + echo "WARN: 外部 AI の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/external-ai-err.log +fi +``` + +| CLI | 優先 (`PRIMARY`) | 次点 (`SECONDARY`) | 最後の手段 | +|---|---|---|---| +| Codex | `OUTPUT_FILE` | `STDOUT` | stderr 末尾 | +| Gemini | `STDOUT` | `OUTPUT_FILE` | stderr | + +Codex は最終 assistant message を返さずにセッションを終える既知挙動があるため、 +ファイルを優先する。Gemini は stdout が信頼できるため stdout を優先する。 + +### 6. 待機間隔のチューニング + +エージェントの context cache TTL は通常 5 分。これを超えると prompt cache がミスして +再送料金が発生する。 + +- **短い間隔**: 60〜270 秒(TTL 内に収まる、軽量) +- **長い間隔**: 1200 秒以上(1 回のキャッシュミスを長時間で償却) +- **避ける**: 300 秒前後(キャッシュミス + 短時間待機の最悪の組み合わせ) + +Codex(5〜10 分)は 270 秒ポーリングか 1200 秒一括待ち、Gemini(数十秒〜5 分)は +60〜270 秒ポーリングでよい。 + +## プロンプト設計 + +### 必須要素 + +1. **対象ファイルの絶対パス**(外部 AI は `nl -ba` / `sed -n` / `rg` 等でファイルを読む) +2. **調査観点を具体化**(箇条書きで 3〜5 項目に絞る) +3. **出力形式の指定**(Markdown テンプレートを提示) +4. **スコープ外の明示**(脱線防止) +5. **出力サイズの目安**(例: 400〜500 行) +6. **最終出力先ファイルの指定**: `/tmp/-output-タスク名.md` のような明示パスへ書き出させる。 + Codex は `apply_patch`、Gemini は `write_file` を使う。**stdout のみへの出力は不可** +7. **assistant message の強制**: 「tool 呼び出しのみで終了せず、最後に必ず 1 回出力すること」 + +### レビュー依頼テンプレート + +```markdown +あなたは(役割: 例 シニアバックエンドエンジニア / セキュリティレビュアー)として、 +以下をレビューしてください。 + +## 対象ファイル(必ず最初に読むこと) +`/absolute/path/to/target.md` + +## 観点 +1. (観点1: 例「仕様とコードの整合性」) +2. (観点2: 例「既存 API との後方互換性」) + +## 調査対象コード(必要に応じて読む) +- `src/...` + +## 背景コンテキスト +- プロジェクト概要 / 関連 PR・Issue 番号 +- 既存レビューで対応済みの事項(重複指摘を避けるため) + +## 出力先(必須) +最終結果を `/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 + +## 出力形式 +# タイトル +## 総評 +## 1. 観点1 に関する指摘 +## 2. 観点2 に関する指摘 +## 3. 追加提案 +## 4. 承認可否 + +**必須**: 行番号・ファイルパスに紐付けて具体的に指摘すること。400〜500 行、日本語。 +**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +### コード生成依頼テンプレート + +```markdown +以下の実装タスクを実行してください。 + +## タスク +(具体的な実装内容) + +## 制約 +- 技術制約(言語バージョン、依存ライブラリ) +- コーディング規約(ESLint / Prettier / rustfmt 等) +- テスト要件(ユニットテスト必須 等) + +## 対象ファイル +- 既存ファイルのパス / 新規ファイルのパス案 + +## 背景 +(なぜこの実装が必要か、設計判断の経緯) + +## 完了基準 +- [ ] テストがパスする +- [ ] 型チェック / lint がパスする + +**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を +`/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 +tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +## 共通のトラブルシューティング + +CLI 固有の症状(サンドボックス失敗、承認モードによるハング等)は補助ファイルを参照。 + +| 症状 | 原因 | 対処 | +|---|---|---| +| 完了通知が来たのに出力が空 | `&` で起動したラッパーシェルだけが終了し、本体はまだ実行中 | 手順 4 の脱出条件で待ち直す。PID の存在で判定しない | +| 出力の末尾が途切れる | モデルの出力トークン上限 | プロンプトで「400 行以内」など出力サイズを指定、または観点を絞って分割実行 | +| 実行が 15 分以上終わらない | 調査範囲が広すぎる、探索ループに入った | 読むべきファイルを明示リスト化し、スコープ外を明記。必要なら `kill` して再実行 | +| 「ファイルを読めません」と返る | 相対パス指定で cwd が想定と違う | プロンプトには**絶対パス**を書き、CLI 側でも作業ディレクトリを明示する | +| 認証エラー | ログインセッション失効 | 各 CLI のログイン手順をやり直す(補助ファイル参照) | +| ハーネスのシェルタイムアウトで kill される | フォアグラウンド実行のまま長尺タスクを走らせた | 手順 3 のとおり必ずバックグラウンド化する | + +## 既知の制約とコスト + +1. **ログイン状態**: 初回はログインが必要。未ログインだと即座に失敗する +2. **stderr の肥大**: 思考ログや警告が出るため必ず `2> /tmp/...` へリダイレクトする +3. **API コスト**: トークン従量課金。1 セッションで数千〜数万トークン消費することがあり、短時間で済むタスクには使わない +4. **機密情報**: コードが外部 API へ送信される。社外秘コードの扱いは組織ポリシーに従う +5. **モデル選択**: 既定モデルは時期により変動する。安定性が要るときは明示指定する +6. **サンドボックス無効化フラグ**: Codex の `--dangerously-bypass-approvals-and-sandbox` と Gemini の + `--yolo` は、任意のシェル実行とファイル編集を無確認で許可する。**Docker / devcontainer / VM / + CI ランナー / 隔離 worktree などの外部隔離環境内でのみ使用**し、ホスト直接実行や本番リポジトリでは使わない + +## 関連 + +- [references/cli-codex.md](references/cli-codex.md) — Codex CLI 固有の手順 +- [references/cli-gemini.md](references/cli-gemini.md) — Gemini CLI 固有の手順 +- `/ndf:cross-review` — codex / gemini 両方を並列起動して APPROVE 収束まで回す +- `/ndf:review` — 第二引数に `codex` / `gemini` を指定すると本スキルの手順へ委譲する +- Claude Code 版 `corder` エージェント — 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 +- 他の AI CLI(`claude`, `ollama` 等)も同じパターンで利用できる diff --git a/plugins/ndf-kiro/skills/external-ai/references/cli-codex.md b/plugins/ndf-kiro/skills/external-ai/references/cli-codex.md new file mode 100644 index 00000000..295edf0c --- /dev/null +++ b/plugins/ndf-kiro/skills/external-ai/references/cli-codex.md @@ -0,0 +1,210 @@ +# Codex CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Codex CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which codex && codex --version +codex login # 初回のみ。未ログインだと即座に失敗する + +# 未インストールの場合 +npm install -g @openai/codex +codex exec --help +``` + +## サンドボックス制約(最重要) + +Codex の既定サンドボックスは `bubblewrap (bwrap)` に依存する。次の環境では bwrap が動作せず、 +`exec` で実行するシェルコマンドがすべて失敗する。 + +- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) +- **一部の devcontainer / Docker 環境**(user namespace 非対応) + +該当環境では `--dangerously-bypass-approvals-and-sandbox` を付けて起動する。 + +```bash +# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) +codex exec -s read-only -C "$PWD" + +# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" +``` + +**判断基準**: Docker / devcontainer / VM / CI ランナー等で外部的に隔離済みなら実用上安全。 +ホスト直接実行でコードを全書き換えされたくない場合はフラグを付けず、下記の bwrap 代替で対処する。 +`-s read-only` / `-s workspace-write` も bwrap を使うため、フラグなしでは同じ失敗になる点に注意。 + +### bwrap 代替の有効化(ホスト直接実行時) + +```bash +# Debian/Ubuntu 系でホスト user namespace を有効化 +sudo sysctl kernel.unprivileged_userns_clone=1 + +# 永続化 +echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf +``` + +## 起動コマンド + +プロンプトは **stdin へ流す**。`-C` で作業ディレクトリを明示する。 + +```bash +codex exec --dangerously-bypass-approvals-and-sandbox \ + --config reasoning.effort=medium \ + -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +``` + +| オプション | 用途 | +|---|---| +| `-C ` | 作業ディレクトリ。指定しないと cwd が想定と異なりファイルを読めなくなる | +| `--dangerously-bypass-approvals-and-sandbox` | bwrap 非対応環境で必須。外部隔離環境内でのみ使用する | +| `--config reasoning.effort=medium` | `high` だと思考へ偏り最終 message を返さない頻度が上がるため、既定で `medium` を推奨 | +| `--json` | JSON Lines でイベントを出力。`event.type=assistant_message` を grep すれば確実に本文を取れる | +| `codex resume` | 長時間ジョブで親エージェントが再起動した場合にセッションを再開する | + +## 出力ストリーム + +| ストリーム | 内容 | +|---|---| +| **stdout** | 最終 assistant message のみ(Markdown 本文)。**空になることがある**(下記) | +| **stderr** | プロンプトのエコー + 実行コマンドと結果 + 思考プロセス + `^tokens used$` sentinel。数千行になる | + +## 最終出力をファイル経由で保証する(必須) + +Codex CLI(特に `gpt-5-codex` / 高 `reasoning_effort`)は、長時間調査の末に +**最終 assistant message を返さずセッションを終えることがある**。このとき stdout は空のまま、 +stderr のイベントログにはコードを読んだ痕跡だけが残る(`^tokens used$` は出ているのに stdout が空)。 + +**根本対策**: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。 +Codex は最終 message を返さなくても `apply_patch` でファイルを作成できるため、ファイル経由なら確実に回収できる。 + +```markdown +## 出力先(必須) + +最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: + +`/tmp/codex-output-タスク名.md` + +書き出しは `apply_patch` で新規ファイル作成してください。 +**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 +書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 +``` + +補助策として `--config reasoning.effort=medium` へ下げる、`--json` でイベントを採取する、 +プロンプト末尾に「tool 呼び出しのみで終了しないこと」を明記する、の 3 つを併用する。 + +回収は **ファイル → stdout → stderr** の順(共通手順の三段フォールバック、Codex は `OUTPUT_FILE` 優先)。 + +## 完了検知 + +`ps -p $PID` は zombie (defunct) にも 0 を返すため、**PID watch は永久ループになりうる**。 +stderr 末尾の sentinel を脱出条件にする。 + +```bash +# ❌ 永久ループ化しうる +until ! ps -p $PID; do sleep 30; done + +# ✅ zombie 安全 +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +進捗を覗くときは `tail -30 /tmp/codex-err.log`。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +echo "codex PID: $PID" + +# === 3. 完了確認(^tokens used$ sentinel を待つ) === +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル優先 → stdout フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./review-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/codex-err.log + exit 1 +fi +``` + +## Codex 固有のトラブルシューティング + +### Q1. stdout が空で stderr に大量の exec ログだけある + +**原因**: まだ最終回答を出す前に停止した、または最終 assistant message を出さずにセッションが終わった。 + +**対処**: `grep -q '^tokens used$' /tmp/codex-err.log` で sentinel を確認する。 +未出力なら実行中なので追加待機。出ているのに stdout が空なら「最終出力をファイル経由で保証する」の +パターンでリトライする(`apply_patch` 指示の追加 + `reasoning.effort=medium`)。 + +### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 + +**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 + +**対処**: フラグを追加して再実行する。ホストで有効化する方法は「サンドボックス制約」節を参照。 + +### Q3. 「ファイルを読めません」と返ってくる + +**原因**: サンドボックス有効で読み取りに失敗、またはプロンプトの相対パスと cwd の不一致。 + +**対処**: `--dangerously-bypass-approvals-and-sandbox` を追加し、プロンプトには絶対パス、`-C` で cwd を明示する。 + +### Q4. タスク完了通知が来たのに出力が空 / 待機ループが抜けない + +**原因**: `&` で起動したラッパーシェルだけが終了した、または zombie を `ps -p` が生存と誤判定している。 + +**対処**: 検知を PID ではなく `^tokens used$` sentinel で行う(「完了検知」節)。 + +### Q5. 認証エラー(`Unauthorized` / `token expired`) + +```bash +codex logout +codex login +``` diff --git a/plugins/ndf-kiro/skills/external-ai/references/cli-gemini.md b/plugins/ndf-kiro/skills/external-ai/references/cli-gemini.md new file mode 100644 index 00000000..6440b067 --- /dev/null +++ b/plugins/ndf-kiro/skills/external-ai/references/cli-gemini.md @@ -0,0 +1,221 @@ +# Gemini CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Gemini CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which gemini && gemini --version + +# 初回ログイン(OAuth): 対話モードで起動して /auth を叩きブラウザ認証する +gemini + +# 未インストールの場合 +npm install -g @google/gemini-cli +gemini -p "hello" --output-format text +``` + +## 承認モード(最重要) + +Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには +`--yolo` か `--approval-mode` を指定する。指定しないと承認待ちでハングする。 + +| モード | 用途 | +|---|---| +| `default` | 対話で都度承認(非対話では止まる) | +| `auto_edit` | 編集系のみ自動承認。シェル実行は都度承認 | +| `yolo`(`--yolo`) | 全 tool 自動承認 | +| `plan`(`--approval-mode plan`) | 読み取り専用。編集系 tool は走らない | + +- **レビュー / 調査タスク**: `--approval-mode plan`(編集事故を防ぐ) +- **コード生成タスク**: `--yolo`(実ファイル編集が必要) +- **`gh api -X POST` などシェル実行を伴うタスク**: `--yolo` 必須(`plan` / `auto_edit` ではブロックされる) + +指定した承認モードは trusted directory 判定で覆される。untrusted なパスで起動すると +`--yolo` が `default` へ降格し、非対話では承認待ちのままハングする。headless 実行では +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず併用すること(「起動コマンド」節参照)。 + +> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / +> 任意のファイル編集を**無確認で許可**する。Docker コンテナ / devcontainer / VM / CI ランナー / +> 隔離された worktree のいずれかの**外部隔離環境内でのみ**使用すること。ホスト直接実行や +> 本番リポジトリ作業中の `--yolo` は厳禁で、その場合は `--approval-mode auto_edit` への降格を検討する。 +> プロンプトで「リポジトリ編集禁止」を明示することは有効だが、sandbox の代替にはならない。 + +## 起動コマンド + +プロンプトは `-p "$(cat ...)"` で渡すか、stdin へパイプする。 + +> ⚠️ **非対話実行では `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず両方付ける**。 +> Gemini CLI は未登録のディレクトリ(worktree のような新規パスを含む)を untrusted と判定し、 +> `--yolo` を `default` へ降格させる。降格すると tool ごとの承認待ちになり、非対話では +> そのままハングする。片方だけでは降格を防げないため、環境変数とフラグの両方が必要。 + +```bash +GEMINI_CLI_TRUST_WORKSPACE=true gemini --approval-mode plan --skip-trust --output-format text \ + -p "$(cat /tmp/gemini-prompt.md)" \ + > /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! + +# stdin パイプでも可 +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text -p "" \ + < /tmp/gemini-prompt.md \ + > /tmp/gemini-stdout.md 2> /tmp/gemini-err.log & +``` + +| オプション | 用途 | +|---|---| +| `--output-format text` | 最終 response の本文をそのまま stdout へ出す | +| `--output-format json` | `{session_id, response, stats}` の JSON 1 オブジェクトを出す | +| `--include-directories ` | ワークスペース外のディレクトリを参照対象へ追加する | +| `--skip-trust` | trusted directory 判定を飛ばす。`--yolo` が無効化されるのを防ぐ | +| `GEMINI_CLI_TRUST_WORKSPACE=true`(環境変数) | 実行ディレクトリを trusted 扱いにする。`--skip-trust` と併用必須 | +| `-m ` | モデルを明示指定する(既定モデルは時期により変動する) | + +`/ndf:cross-review` の `scripts/launch-gemini.sh` も同じ組み合わせで起動している。 + +## 出力ストリーム + +| ストリーム | `--output-format text` | `--output-format json` | +|---|---|---| +| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | `{session_id, response, stats}` | +| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)。通常数行で無害 | 同左 | + +```bash +# 成果物だけ取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text \ + -p "$(cat prompt.md)" > out.md + +# 統計(トークン数・tool 呼び出し履歴)込みで取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format json \ + -p "$(cat prompt.md)" > out.json +jq -r '.response' out.json > out.md +jq '.stats' out.json > stats.json +``` + +Gemini には Codex のような「最終 message を返さずに終わる」既知挙動は確認されていないため、 +**回収は stdout 優先**(共通手順の三段フォールバックで `STDOUT` を `PRIMARY` にする)。 +ただし長尺タスクの途中エラーに備え、保険として `write_file` での書き出しをプロンプトに加えておく。 + +```markdown +## 出力先(推奨) + +最終結果を `/tmp/gemini-output-タスク名.md` にも `write_file` で書き出してください。 +(stdout には同内容をそのまま出力すれば冪等で問題ありません。) +``` + +## 完了検知 + +Gemini は `^tokens used$` のような sentinel を吐かないため、stderr の grep では完了判定できない。 +**プロセスの終了**を見るのが正しい。 + +```bash +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "exit=$?" +``` + +進捗を覗くときは `tail -30 /tmp/gemini-err.log`(実行中の stdout 出力は限定的)。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し === +FINAL=/tmp/gemini-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! +echo "gemini PID: $PID" + +# === 3. 完了確認(プロセス終了を待つ) === +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "DONE exit=$?" + +# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === +if [ -s /tmp/gemini-stdout.md ]; then + cp /tmp/gemini-stdout.md ./review-result.md +elif [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md + echo "WARN: ファイルからフォールバック回収" >&2 +else + echo "ERROR: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 + tail -200 /tmp/gemini-err.log + exit 1 +fi +``` + +## Gemini 固有のトラブルシューティング + +### Q1. 非対話モードなのにプロセスがハングする + +**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` のまま)。 +指定したはずの `--yolo` が trusted directory 判定で `default` へ降格しているケースも同じ症状になる。 + +**対処**: `--yolo` または `--approval-mode plan` を付けたうえで、 +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を併用する。レビュー / 調査なら `plan` が安全。 + +### Q2. stdout に思考のような余計な出力が混ざる + +**原因**: `--output-format text` でも進捗 / モデル切替メッセージが混ざる場合がある。 + +**対処**: `--output-format json` にして `jq -r '.response'` で本文だけ抽出する。 +あわせてプロンプトへ「最終結果のみを出力すること、思考や前置きは不要」と明記する。 + +### Q3. ワークスペース外のファイルを読めない / 止まる + +**対処**: `--include-directories /path/to/extra` で対象ディレクトリを追加し、プロンプトには絶対パスを書く。 +それでも止まる場合は `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` を併用する。 + +### Q4. `--yolo` を付けたのに承認待ちになる + +**原因**: trusted directory 判定によって YOLO が無効化され、承認モードが `default` へ降格している。 +worktree のような新規パスは既定で untrusted 扱いになる。 + +**対処**: `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を **両方** 付けて起動する。 +片方だけでは降格を防げない。 + +### Q5. `Error in: mcpServers.` の警告が毎回出る + +**原因**: `.gemini/settings.json` に `disabled: false` などの非互換キーがある。 + +**対処**: 該当キーを除去するか、起動前に設定を sanitize する +(`/ndf:cross-review` の `launch-gemini.sh` は v4.7.2 以降でこれを自動化している)。 + +### Q6. 認証エラー(`Authentication required` / `token expired`) + +**原因**: OAuth セッション失効。 + +**対処**: 対話モードで `gemini` を起動し、`/auth` を叩いてブラウザ認証をやり直す。 diff --git a/plugins/ndf-kiro/skills/review/SKILL.md b/plugins/ndf-kiro/skills/review/SKILL.md index 983c4e4a..2afd42e2 100644 --- a/plugins/ndf-kiro/skills/review/SKILL.md +++ b/plugins/ndf-kiro/skills/review/SKILL.md @@ -225,8 +225,9 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ 第二引数が指定された場合、上記「観点」「具体的なチェックポイント」「PR モードの手順」の 内容を **レビュー指示プロンプト** として組み立て、指定された CLI に渡す。 -呼び出し手順の詳細は、利用 runtime に `/ndf:codex` / `/ndf:gemini` skill が同梱されて -いる場合はその skill に従う。同梱されていない runtime では以下の要点に従う。 +呼び出し手順の詳細は、利用 runtime に `/ndf:external-ai` skill が同梱されている場合は +その skill の `references/cli-codex.md` / `references/cli-gemini.md` に従う。 +同梱されていない runtime では以下の要点に従う。 **`codex` 指定時** @@ -239,6 +240,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ > ⚠️ `--dangerously-bypass-approvals-and-sandbox` は codex のサンドボックスを完全に無効化し、 > 任意のシェル実行・ファイル編集を無確認で許可する。**必ず Docker / devcontainer / VM / CI ランナー等の > 外部隔離環境内** でのみ使用すること。ホスト直接実行や本番リポジトリでは使わない。 +> 背景・代替策は `/ndf:external-ai` skill の `references/cli-codex.md`「サンドボックス制約」節を参照。 **`gemini` 指定時** @@ -250,7 +252,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ - 成果物は stdout サマリ + `/tmp/gemini-review-pr<番号>-result.json` で回収 > ⚠️ `--yolo` も同様に外部隔離環境内でのみ実行する。プロンプトでの「リポジトリ編集禁止」明示は必須だが、 -> sandbox の代替にはならない。 +> sandbox の代替にはならない。詳細は `/ndf:external-ai` skill の `references/cli-gemini.md` を参照。 ### プロンプト組み立て @@ -351,6 +353,5 @@ PR モードではレビュー結果が **PR 上に投稿済み** であるこ - `/ndf:fix` — レビュー指摘の分類と修正対応 - `/ndf:cross-review` — codex + gemini の収束レビュー -- `/ndf:codex` — Codex CLI の呼び出し手順(同梱 runtime のみ) -- `/ndf:gemini` — Gemini CLI の呼び出し手順(同梱 runtime のみ) +- `/ndf:external-ai` — Codex / Gemini CLI の呼び出し手順(同梱 runtime のみ) - `/ndf:logging-guidelines` — ログ設計 diff --git a/plugins/ndf-shared/manifests/claude-skills.txt b/plugins/ndf-shared/manifests/claude-skills.txt index acb86c81..a94a7a37 100644 --- a/plugins/ndf-shared/manifests/claude-skills.txt +++ b/plugins/ndf-shared/manifests/claude-skills.txt @@ -14,8 +14,7 @@ logging-guidelines cherry-pick-pr deploy playwright-authoring -codex -gemini +external-ai statusline issue-plan-strategy plan-to-spec diff --git a/plugins/ndf-shared/manifests/codex-skills.txt b/plugins/ndf-shared/manifests/codex-skills.txt index 62de56a5..46047cd8 100644 --- a/plugins/ndf-shared/manifests/codex-skills.txt +++ b/plugins/ndf-shared/manifests/codex-skills.txt @@ -2,6 +2,7 @@ cherry-pick-pr cross-review deploy docker-container-access +external-ai fix implementation-plan investigation-rules diff --git a/plugins/ndf-shared/manifests/kiro-skills.txt b/plugins/ndf-shared/manifests/kiro-skills.txt index e4bb9b19..a94a7a37 100644 --- a/plugins/ndf-shared/manifests/kiro-skills.txt +++ b/plugins/ndf-shared/manifests/kiro-skills.txt @@ -14,7 +14,7 @@ logging-guidelines cherry-pick-pr deploy playwright-authoring -codex +external-ai statusline issue-plan-strategy plan-to-spec diff --git a/plugins/ndf-shared/skills/codex/SKILL.md b/plugins/ndf-shared/skills/codex/SKILL.md deleted file mode 100644 index 80060a83..00000000 --- a/plugins/ndf-shared/skills/codex/SKILL.md +++ /dev/null @@ -1,473 +0,0 @@ ---- -name: codex -description: "Delegate coding, review, or research to Codex CLI." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" ---- - -# Codex 外部AI委譲スキル - -## 概要 - -`codex` CLI(OpenAI Codex、通常は `/usr/bin/codex` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 - -ローカルファイルの逐語照合レビューや大規模コードベース調査に向いている。 - -## NDFとの関係 - -- NDFプラグインの `corder` エージェントはこの skill の手順に従って Codex CLI を呼び出す -- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない -- 使い分け: 軽量な独立レビュー → `corder` エージェントに委譲。手順の詳細を自分で制御したい or 複雑なプロンプトを出したい → 本 skill を参照して直接 `codex exec` 起動 - -## いつ使うか - -### 使うべきケース -- **独立第二意見レビュー**: 設計書・PR・仕様書を外部AIにレビューさせる(メインエージェントの思考バイアスを避ける) -- **コードベース逐語照合**: 「行番号・関数名・重複箇所の件数」を正確に突き合わせる必要がある場合 -- **長時間の調査タスク**: 複数ファイル横断で5〜10分以上かかる調査 -- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを codex に走らせたい場合 - -### 使わないべきケース -- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 -- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める -- 単純な質問回答 → WebFetch / WebSearch で足りる -- 機密情報を含むコード → 外部API送信の可否を確認してから - -## 前提条件 - -```bash -# インストール確認 -which codex -codex --version - -# ログイン状態確認(初回のみ必要) -codex login -``` - -未インストールの場合は以下でセットアップ: - -```bash -# npm 経由 -npm install -g @openai/codex - -# 動作確認 -codex exec --help -``` - -## 基本実行パターン - -### 1. サンドボックス制約(重要) - -codex のデフォルトサンドボックスは `bubblewrap (bwrap)` に依存する。以下の環境では bwrap が動作せず、`exec` で実行するシェルコマンドがすべて失敗する: - -- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) -- **一部の devcontainer / Docker 環境**(user namespace 非対応) - -該当環境では **`--dangerously-bypass-approvals-and-sandbox` を付けて起動**する必要がある。 - -```bash -# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) -codex exec -s read-only -C "$PWD" - -# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" -``` - -**判断基準**: 既にDocker / devcontainer / VM / CIランナー等で外部的にサンドボックスされているなら `--dangerously-bypass-approvals-and-sandbox` は実用上安全。ホスト直接実行でコード全書き換えされたくない場合はフラグを付けずに対処(後述「bwrap代替」)。 - -#### bwrap 代替の有効化(ホスト直接実行時) - -```bash -# Debian/Ubuntu 系でホスト user namespace を有効化 -sudo sysctl kernel.unprivileged_userns_clone=1 - -# 永続化 -echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf -``` - -### 2. プロンプトは一時ファイル経由で渡す - -長いプロンプトをシェル引数に渡すとエスケープ地獄になるので、**一時ファイル経由でstdinに流す**のが基本。 - -```bash -# Step 1: プロンプトを一時ファイルに書く -cat > /tmp/codex-prompt.md <<'EOF' -## タスク -以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 - -## 対象ファイル(絶対パスで指定) -/absolute/path/to/design.md - -## 出力形式 -Markdown で標準出力に吐いてください。 -EOF - -# Step 2: codex exec に stdin で流す(バックグラウンド実行) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & -``` - -**エージェントからの書き方**: ファイル書き込みツールで `/tmp/codex-prompt.md` を作ってから、シェル実行ツールの「バックグラウンド実行」オプションで codex を起動する。 - -### 3. 出力ストリームの扱い - -codex CLI の出力構造: - -| ストリーム | 内容 | -|---|---| -| **stdout** | **最終 assistant message のみ**(Markdown本文)。出ないことがある(後述) | -| **stderr** | プロンプトのエコー + 実行したコマンドと結果 + codexの思考プロセス + `^tokens used$` sentinel | - -**実務上の扱い**: -- 最終成果物が欲しい → `stdout` をそのまま採用…**ただし stdout が空になるケースがあるので必ずファイル出力も併用**(下記 3.5 参照) -- codexが何を調べたか追跡したい → `stderr` をデバッグ用に保存 - -```bash -codex exec ... > /tmp/codex-output.md 2> /tmp/codex-err.log -# 成果物 = /tmp/codex-output.md(stdout が空でないことを必ず確認) -# デバッグ = /tmp/codex-err.log(大きめ、数千行になる) -``` - -### 3.5 最終出力をファイル経由で保証する(重要) - -**Codex CLI(特に `gpt-5-codex` / 高 reasoning_effort)は、長時間調査の末に** -**最終 assistant message を返さずにセッションを終えることがある**。 -このとき stdout は空のままになり、stderr のイベントログ(数十万バイト)には -コードを実際に読んだ痕跡だけが残る。`^tokens used$` は出ているのに stdout が空、という状態。 - -**根本対策: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。** -Codex は最終 message を返さなくても `apply_patch` ツールでファイルを作成できるため、 -ファイル経由なら確実に結果を回収できる。 - -#### プロンプトに必ず含める指示(テンプレート) - -```markdown -## 出力先(必須) - -最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: - -`/tmp/codex-output-.md` - -書き出しは `apply_patch` で新規ファイル作成してください。 -**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 -書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 -``` - -#### 回収側の安全パターン - -```bash -# 1. ファイルが存在するかを最優先で確認(stdout が空でもこちらに本文が残る) -OUTPUT_FILE=/tmp/codex-output-pr13734-review.md -if [ -s "$OUTPUT_FILE" ]; then - cat "$OUTPUT_FILE" -elif [ -s /tmp/codex-stdout.md ]; then - # 2. ファイルがなければ stdout フォールバック - cat /tmp/codex-stdout.md -else - # 3. どちらも空なら stderr の末尾から拾う最後の手段 - echo "WARN: Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log -fi -``` - -#### 補助対策 - -- **`reasoning_effort` を `medium` に下げる** (`--config reasoning.effort=medium`) - `high` だと思考に偏って最終 message を返さなくなる頻度が上がる -- **`--json` モードでイベント採取** (`codex exec --json`) - JSON Lines で `event.type=assistant_message` を grep すれば確実に取れる -- **強制 summary 指示**: プロンプト末尾に「最後に必ず assistant message として 1 回出力すること、tool 呼び出しのみで終了しないこと」を明記 - -### 4. バックグラウンド実行 + 待機パターン - -codex は **5〜10分かかることが普通**。多くのエージェントハーネスはシェル実行に2〜3分のタイムアウトを課すので、**必ずバックグラウンド実行**する。 - -```bash -# 1. プロンプトファイル書き出し(ファイル書き込みツール) -# -> /tmp/codex-prompt.md - -# 2. codex をバックグラウンドで起動(`&` でシェル自体は即時終了) -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ - < /tmp/codex-prompt.md \ - > /tmp/codex-output.md \ - 2> /tmp/codex-err.log & - -# 3. PID を控える -echo "PID: $!" - -# 4. 待機(他の作業を進める or スケジューラで再開) - -# 5. 完了検知 — ps -p は zombie に騙される。stderr の "tokens used" sentinel を見る -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -**⚠️ 罠**: `&` でバックグラウンド実行するとラッパーシェルは即終了し「タスク完了通知」が発火するが、codex 本体はまだ動いている。**`ps -p $PID` は zombie (defunct) も 0 を返す** ため `until ! ps -p $PID` は永久ループになりうる。`grep -q '^tokens used$' /tmp/codex-err.log` を脱出条件にする (codex が最終回答を吐き終わると stderr 末尾に必ず出る sentinel)。 - -### 5. 待機間隔のチューニング - -エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: - -- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) -- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) -- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) - -codex の典型実行時間(5〜10分)に対しては **270秒ポーリング** か **1200秒一括待ち** の二択。 - -### 6. プロセス確認・ログ追跡 - -```bash -# 完了したか (stderr 末尾の "tokens used" が最も信頼できる) -grep -q '^tokens used$' /tmp/codex-err.log && echo DONE - -# 最新の作業内容を覗く -tail -30 /tmp/codex-err.log -``` - -## プロンプト設計のコツ - -### 必須要素 -1. **対象ファイルの絶対パス**(codexは `nl -ba`, `sed -n`, `rg` 等でファイルを読むため) -2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) -3. **出力形式の指定**(Markdownテンプレートを提示) -4. **スコープ外の明示**(codexが脱線しないため) -5. **最終出力先ファイルの指定(必須)**: `/tmp/codex-output-.md` のような明示パスへ - **`apply_patch` で必ず書き出させる**。stdout だけに頼ると最終 message が落ちて空になる事故が起きる(3.5 節参照) -6. **stdout にも同内容を吐く指示**: ファイル書き出し後、念のため stdout にもエコーさせる(冪等) - -### レビュー依頼テンプレート - -```markdown -あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 -以下をレビューしてください。 - -## 対象ファイル(必ず最初に読むこと) -`/absolute/path/to/target.md` - -## 観点 -1. <観点1: 例「仕様とコードの整合性」> -2. <観点2: 例「既存APIとの後方互換性」> - -## 調査対象コード(必要に応じて読む) -- `src/...` -- `lib/...` - -## 背景コンテキスト -- <プロジェクト概要> -- <関連PR / Issue番号> -- <既存レビューで対応済みの事項(重複指摘を避けるため)> - -## 出力形式 - -以下を Markdown で**`/tmp/codex-output-.md` に必ず書き出してください** -(`apply_patch` で新規ファイル作成)。書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため): - -# <タイトル> - -## 総評 -## 1. <観点1> に関する指摘 -### 1.1 正確な主張 -### 1.2 訂正推奨 -## 2. <観点2> に関する指摘 -## 3. 追加提案 -## 4. 承認可否 - -**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 -**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -### コード生成依頼テンプレート - -```markdown -以下の実装タスクを実行してください。 - -## タスク -<具体的な実装内容> - -## 制約 -- <技術制約: 言語バージョン、依存ライブラリ> -- <コーディング規約: ESLint / Prettier / rustfmt等> -- <テスト要件: ユニットテスト必須等> - -## 対象ファイル -- <既存ファイルのパス> -- <新規ファイルのパス案> - -## 背景 -<なぜこの実装が必要か、設計判断の経緯> - -## 完了基準 -- [ ] テストがパスする -- [ ] 型チェック / lint がパスする -- [ ] <追加の受け入れ条件> - -**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を -`/tmp/codex-output-.md` に書き出してください(`apply_patch` で新規作成)。 -書き出し後、stdout にも同内容を出力してください。 -**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため)。 -tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 -``` - -## 実例: レビュー依頼の完全フロー - -```bash -# === 1. プロンプト書き出し === -# ポイント: 最終出力先ファイルをプロンプト内で明示し、apply_patch で書かせる -FINAL=/tmp/codex-output-api-v2-review.md - -cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ - 2> /tmp/codex-err.log & - -PID=$! -echo "codex PID: $PID" - -# === 3. 完了確認(^tokens used$ sentinel を待つ) === -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -echo DONE - -# === 4. 成果物を安全に回収(ファイル優先 → stdout fallback) === -if [ -s "$FINAL" ]; then - cp "$FINAL" ./review-result.md - echo "✅ Codex 書き出しファイルから回収" -elif [ -s /tmp/codex-stdout.md ]; then - cp /tmp/codex-stdout.md ./review-result.md - echo "⚠ stdout からフォールバック回収(ファイル書き出しなし)" -else - echo "❌ Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 - tail -200 /tmp/codex-err.log - exit 1 -fi -``` - -## トラブルシューティング - -### Q1. stdoutが空でstderrに大量のexecログだけある -**原因**: codex がまだ最終回答を出す前に停止した、または **最終 assistant message を出さずにセッションが終わった**(gpt-5-codex の高 reasoning_effort で発生しやすい既知挙動)。 - -**対処**: -- `grep -q '^tokens used$' /tmp/codex-err.log` で終了 sentinel が出ているか確認(まだなら動作中なので追加待機) -- 出ているのに stdout が空 → セッション終了で最終 message が失われたケース。**3.5 節「最終出力をファイル経由で保証する」のパターンでリトライ必須**: - - プロンプトに `apply_patch` で `/tmp/codex-output-.md` へ必ず書き出させる指示を追加 - - 回収側は「ファイル → stdout → stderr」の三段フォールバックで取りこぼしを防ぐ - - 補助で `--config reasoning.effort=medium` も付けると最終 message を返す傾向が上がる - -### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 -**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 - -**対処**: -- フラグを追加して再実行 -- `-s read-only` / `-s workspace-write` も bwrap を使うので同じ結果になる点に注意 -- ホストで user namespace を有効化する方法は「サンドボックス制約」節を参照 - -### Q3. codexが「ファイルを読めません」と返してくる -**原因**: -- サンドボックス有効でファイル読み取りに失敗 -- プロンプトで相対パスを指定し、codexの cwd が想定と違った - -**対処**: -- `--dangerously-bypass-approvals-and-sandbox` を追加 -- プロンプトには**絶対パス**を書く -- `-C ` で cwd を明示 - -### Q4. タスク完了通知が来たのに出力が空 / wait loop が抜けない -**原因**: `&` で起動したラッパーシェルが先に終了して通知が出ているだけで、codex 本体は動作中。または既に終わっているが zombie (defunct) として残っており `ps -p $PID` が 0 を返し続けている。 - -**対処**: 検知を「PID の存在」ではなく **stderr の `^tokens used$` sentinel** で行う。codex は最終回答を吐き終えると必ずこの行を stderr に書く。 - -```bash -# ❌ 永久ループ化しうる -until ! ps -p $PID; do sleep 30; done - -# ✅ zombie 安全 -until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do - sleep 30 -done -``` - -### Q5. codex実行が15分以上かかる -**原因**: プロンプトで広すぎる調査範囲を指定した、または codex が探索ループに入った。 - -**対処**: -- プロンプトで「読むべきファイル」を明示リスト化 -- スコープ外を明記(「〇〇には踏み込まない」) -- 必要なら `kill ` で打ち切り、プロンプトを絞り込んで再実行 - -### Q6. stdoutの末尾が途切れている -**原因**: codex がトークン上限に達した可能性。 - -**対処**: プロンプトで「400行以内」など出力サイズを指定。または観点を絞って再実行。 - -### Q7. 認証エラー (`Unauthorized` / `token expired`) -**原因**: ログインセッション失効。 - -**対処**: -```bash -codex logout -codex login -``` - -## corder エージェント経由との使い分け - -本スキルは CLI を直接呼び出す詳細手順を記述している。簡易に独立レビューを取りたいだけなら `corder` エージェントに委譲した方が手間が少ない: - -| 観点 | corder エージェント | 本スキルで直接 CLI 起動 | -|---|---|---| -| 使い勝手 | `Agent(subagent_type: "corder", ...)` で委譲するだけ | プロンプト書き出し・バックグラウンド起動・PID 管理を自分で制御 | -| プロンプト制御 | corder 側で整形 | 自由に設計可 | -| バックグラウンド実行 | agent 側が制御 | `&` で非同期化、他作業と並列 | -| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | - -**指針**: 迷ったら corder 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ本スキルの手順で直接起動。 - -## 既知の制約とコスト - -1. **サンドボックス非対応環境**: `--dangerously-bypass-approvals-and-sandbox` で回避必須 -2. **stderrに全思考が書かれる**: 数千行になりうるので必ず `2> /tmp/...` にリダイレクト -3. **ログイン状態**: 初回は `codex login` が必要。未ログインだと即座に失敗する -4. **セッション復旧**: 長時間ジョブで親エージェントが再起動した場合、`codex resume` でセッション再開可能 -5. **APIコスト**: トークン従量課金のため、短時間で済むタスクには使わない。1セッションで数千〜数万トークン消費することがある -6. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと - -## 関連 - -- **NDF `corder` エージェント**: 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 (v4.0.0 以降は MCP ではなく CLI 経由) -- **OpenAI Codex CLI公式ドキュメント**: `codex --help` / `codex exec --help` -- **他のAI委譲方法**: `gemini`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf-shared/skills/cross-review/SKILL.md b/plugins/ndf-shared/skills/cross-review/SKILL.md index 21223ddd..2472f576 100644 --- a/plugins/ndf-shared/skills/cross-review/SKILL.md +++ b/plugins/ndf-shared/skills/cross-review/SKILL.md @@ -469,8 +469,7 @@ pint / larastan / test / build などは **中断** を原則とする。 - `/ndf:review` — 単発レビュー(AI 直接投稿対応) - `/ndf:fix` — 指摘の分類・修正・返信・Resolve(サブエージェント起動対応) -- `/ndf:codex` — codex CLI 呼び出し手順 -- `/ndf:gemini` — gemini CLI 呼び出し手順 +- `/ndf:external-ai` — codex / gemini CLI 呼び出し手順(CLI 別の差分は `references/cli-codex.md` / `references/cli-gemini.md`) - `/ndf:issue-plan-strategy` — multi-PR ワークフローでは **個別 PR ごとに本 cross-review が原則必須**。 `/ndf:review` 単発や Claude Code の `code-reviewer` は代替にせず、release ブランチへ merge する前に codex + gemini の APPROVE 収束を確認する (Step 6) diff --git a/plugins/ndf-shared/skills/external-ai/SKILL.md b/plugins/ndf-shared/skills/external-ai/SKILL.md new file mode 100644 index 00000000..9684e739 --- /dev/null +++ b/plugins/ndf-shared/skills/external-ai/SKILL.md @@ -0,0 +1,285 @@ +--- +name: external-ai +description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." +when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +--- + +# 外部 AI 委譲スキル (Codex / Gemini) + +## 概要 + +`codex` CLI(OpenAI Codex)と `gemini` CLI(Google Gemini)をローカルから直接起動し、 +コード生成・独立第二意見レビュー・大規模コードベース調査を外部 AI に委譲する。 + +**手順の大半は 2 つの CLI で共通**であり、本ファイルはその共通手順を規定する。 +起動フラグ・完了検知・出力回収など **CLI 固有の差分は補助ファイルに分離** している。 + +| 補助ファイル | 内容 | +|---|---| +| [references/cli-codex.md](references/cli-codex.md) | Codex CLI のインストール、サンドボックス制約、`codex exec` の起動、sentinel 完了検知、最終 message 欠落対策 | +| [references/cli-gemini.md](references/cli-gemini.md) | Gemini CLI のインストール、承認モード、`--output-format` の使い分け、プロセス終了による完了検知 | + +## NDF との関係 + +- Claude Code 版の `corder` エージェントは本スキルの手順で Codex CLI を呼び出す +- `/ndf:review codex` / `/ndf:review gemini` の委譲先として利用される +- `/ndf:cross-review` は codex / gemini を**並列に起動**して両者の APPROVE 収束を待つ +- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない +- Gemini 専用エージェントは未整備。委譲時はメインエージェントから本スキルを参照して直接 CLI を起動する + +## いつ使うか + +### 使うべきケース + +- **独立第二意見レビュー**: 設計書・PR・仕様書を外部 AI にレビューさせ、メインエージェントの思考バイアスを避ける +- **コードベース逐語照合**: 行番号・関数名・重複箇所の件数を正確に突き合わせる +- **長時間の調査タスク**: 複数ファイル横断で 5〜10 分以上かかる調査 +- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを外部 AI に走らせる +- **長文生成**: ドキュメント生成・要約・翻訳 + +### 使わないケース + +- 短時間(1〜2 分以内)で済むタスク → メインエージェントで直接対応 +- ユーザとの対話が必要な設計相談 → Plan Mode 等で対話しながら進める +- 単純な質問回答 → WebFetch / WebSearch で足りる +- 機密情報を含むコード → 外部 API へ送信されるため、可否を組織ポリシーで確認してから + +## どちらの CLI を選ぶか + +| 観点 | Codex | Gemini | +|---|---|---| +| stdout の信頼性 | 最終 message が落ちることがある(ファイル書き出し必須) | stdout に response が直接出る | +| サンドボックス | WSL2 / 一部コンテナで `--dangerously-bypass-approvals-and-sandbox` が必須 | bwrap 非依存。ただし trusted directory 判定があり `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` が必須 | +| 非対話実行 | `codex exec` で完結 | `--yolo` か `--approval-mode plan` に加えて trust 解除が必須 | +| 完了判定 | stderr の `^tokens used$` sentinel | プロセス終了(`kill -0` / `wait`) | +| 出力フォーマット | Markdown 本文のみ | `text` / `json`(json は統計付き) | +| 典型実行時間 | 5〜10 分 | 数十秒〜5 分 | +| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | +| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | + +**指針**: + +- 行番号・件数の逐語確認が要る → Codex +- 短時間で済む独立レビュー、横断調査、長文生成 → Gemini +- 第二意見を確実に取りたい → 両方を走らせてクロスチェック(`/ndf:cross-review` が自動化している) +- Codex がレート制限・サンドボックス制約に当たった → Gemini へ代替 + +`corder` エージェントとの使い分けは次のとおり。 + +| 観点 | `corder` エージェント経由 | 本スキルで直接 CLI 起動 | +|---|---|---| +| 使い勝手 | エージェントに委譲するだけ | プロンプト書き出し・起動・PID 管理を自分で制御 | +| プロンプト制御 | corder 側で整形 | 自由に設計可 | +| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | + +迷ったら `corder` 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ直接起動する。 + +## 共通の実行手順 + +CLI 固有のコマンドラインは補助ファイルを参照し、流れは以下で統一する。 + +### 1. 前提確認 + +インストールとログイン状態を確認する。未インストール時のセットアップ手順は補助ファイルに記載。 + +```bash +which codex && codex --version +which gemini && gemini --version +``` + +### 2. プロンプトを一時ファイルへ書き出す + +長いプロンプトをシェル引数へ直接渡すとエスケープが破綻する。**必ず一時ファイル経由**にする。 + +```bash +cat > /tmp/external-ai-prompt.md <<'EOF' +## タスク +以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 + +## 対象ファイル(絶対パスで指定) +/absolute/path/to/design.md +EOF +``` + +エージェントから実行する場合は、ファイル書き込みツールでプロンプトを作ってから、 +シェル実行ツールのバックグラウンド実行オプションで CLI を起動する。 + +### 3. バックグラウンドで起動する + +多くのエージェントハーネスはシェル実行に 2〜3 分のタイムアウトを課す。 +外部 AI は数分〜10 分かかるため、**フォアグラウンド実行は禁止**。`&` で必ず非同期化し、 +stdout と stderr を別ファイルへリダイレクトする。 + +```bash + \ + > /tmp/external-ai-stdout.md \ + 2> /tmp/external-ai-err.log & +PID=$! +``` + +stderr には思考ログや警告が出る。Codex では数千行になるため、必ずファイルへ逃がす。 + +### 4. 完了を検知する + +検知方法は CLI で異なる。**PID の存在だけで判定しない**(Codex は zombie 化して `ps -p` が +0 を返し続けることがある)。 + +| CLI | 脱出条件 | +|---|---| +| Codex | stderr に `^tokens used$` が現れる([references/cli-codex.md](references/cli-codex.md)) | +| Gemini | プロセスが終了する([references/cli-gemini.md](references/cli-gemini.md)) | + +### 5. 成果物を三段フォールバックで回収する + +外部 AI の最終出力は、CLI とモデルの都合で欠落しうる。**stdout だけに依存しない**。 +プロンプト側で「最終結果を指定ファイルへ書き出すこと」を必ず指示し(手順 6 のテンプレート参照)、 +回収側は次の順で拾う。 + +```bash +# STDOUT = CLI の `>` リダイレクト先 +# OUTPUT_FILE = プロンプト指示でツールに書き出させた保険ファイル(task ごとに固有名) +STDOUT=/tmp/external-ai-stdout.md +OUTPUT_FILE=/tmp/external-ai-output-pr13734-review.md + +# PRIMARY / SECONDARY は CLI ごとに下表の順で割り当てる +PRIMARY="$OUTPUT_FILE"; SECONDARY="$STDOUT" # Codex の場合 +# PRIMARY="$STDOUT"; SECONDARY="$OUTPUT_FILE" # Gemini の場合 + +if [ -s "$PRIMARY" ]; then + cp "$PRIMARY" ./result.md +elif [ -s "$SECONDARY" ]; then + cp "$SECONDARY" ./result.md +else + echo "WARN: 外部 AI の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/external-ai-err.log +fi +``` + +| CLI | 優先 (`PRIMARY`) | 次点 (`SECONDARY`) | 最後の手段 | +|---|---|---|---| +| Codex | `OUTPUT_FILE` | `STDOUT` | stderr 末尾 | +| Gemini | `STDOUT` | `OUTPUT_FILE` | stderr | + +Codex は最終 assistant message を返さずにセッションを終える既知挙動があるため、 +ファイルを優先する。Gemini は stdout が信頼できるため stdout を優先する。 + +### 6. 待機間隔のチューニング + +エージェントの context cache TTL は通常 5 分。これを超えると prompt cache がミスして +再送料金が発生する。 + +- **短い間隔**: 60〜270 秒(TTL 内に収まる、軽量) +- **長い間隔**: 1200 秒以上(1 回のキャッシュミスを長時間で償却) +- **避ける**: 300 秒前後(キャッシュミス + 短時間待機の最悪の組み合わせ) + +Codex(5〜10 分)は 270 秒ポーリングか 1200 秒一括待ち、Gemini(数十秒〜5 分)は +60〜270 秒ポーリングでよい。 + +## プロンプト設計 + +### 必須要素 + +1. **対象ファイルの絶対パス**(外部 AI は `nl -ba` / `sed -n` / `rg` 等でファイルを読む) +2. **調査観点を具体化**(箇条書きで 3〜5 項目に絞る) +3. **出力形式の指定**(Markdown テンプレートを提示) +4. **スコープ外の明示**(脱線防止) +5. **出力サイズの目安**(例: 400〜500 行) +6. **最終出力先ファイルの指定**: `/tmp/-output-タスク名.md` のような明示パスへ書き出させる。 + Codex は `apply_patch`、Gemini は `write_file` を使う。**stdout のみへの出力は不可** +7. **assistant message の強制**: 「tool 呼び出しのみで終了せず、最後に必ず 1 回出力すること」 + +### レビュー依頼テンプレート + +```markdown +あなたは(役割: 例 シニアバックエンドエンジニア / セキュリティレビュアー)として、 +以下をレビューしてください。 + +## 対象ファイル(必ず最初に読むこと) +`/absolute/path/to/target.md` + +## 観点 +1. (観点1: 例「仕様とコードの整合性」) +2. (観点2: 例「既存 API との後方互換性」) + +## 調査対象コード(必要に応じて読む) +- `src/...` + +## 背景コンテキスト +- プロジェクト概要 / 関連 PR・Issue 番号 +- 既存レビューで対応済みの事項(重複指摘を避けるため) + +## 出力先(必須) +最終結果を `/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 + +## 出力形式 +# タイトル +## 総評 +## 1. 観点1 に関する指摘 +## 2. 観点2 に関する指摘 +## 3. 追加提案 +## 4. 承認可否 + +**必須**: 行番号・ファイルパスに紐付けて具体的に指摘すること。400〜500 行、日本語。 +**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +### コード生成依頼テンプレート + +```markdown +以下の実装タスクを実行してください。 + +## タスク +(具体的な実装内容) + +## 制約 +- 技術制約(言語バージョン、依存ライブラリ) +- コーディング規約(ESLint / Prettier / rustfmt 等) +- テスト要件(ユニットテスト必須 等) + +## 対象ファイル +- 既存ファイルのパス / 新規ファイルのパス案 + +## 背景 +(なぜこの実装が必要か、設計判断の経緯) + +## 完了基準 +- [ ] テストがパスする +- [ ] 型チェック / lint がパスする + +**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を +`/tmp/-output-タスク名.md` に書き出したうえで、stdout にも同内容を出力すること。 +tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力すること。 +``` + +## 共通のトラブルシューティング + +CLI 固有の症状(サンドボックス失敗、承認モードによるハング等)は補助ファイルを参照。 + +| 症状 | 原因 | 対処 | +|---|---|---| +| 完了通知が来たのに出力が空 | `&` で起動したラッパーシェルだけが終了し、本体はまだ実行中 | 手順 4 の脱出条件で待ち直す。PID の存在で判定しない | +| 出力の末尾が途切れる | モデルの出力トークン上限 | プロンプトで「400 行以内」など出力サイズを指定、または観点を絞って分割実行 | +| 実行が 15 分以上終わらない | 調査範囲が広すぎる、探索ループに入った | 読むべきファイルを明示リスト化し、スコープ外を明記。必要なら `kill` して再実行 | +| 「ファイルを読めません」と返る | 相対パス指定で cwd が想定と違う | プロンプトには**絶対パス**を書き、CLI 側でも作業ディレクトリを明示する | +| 認証エラー | ログインセッション失効 | 各 CLI のログイン手順をやり直す(補助ファイル参照) | +| ハーネスのシェルタイムアウトで kill される | フォアグラウンド実行のまま長尺タスクを走らせた | 手順 3 のとおり必ずバックグラウンド化する | + +## 既知の制約とコスト + +1. **ログイン状態**: 初回はログインが必要。未ログインだと即座に失敗する +2. **stderr の肥大**: 思考ログや警告が出るため必ず `2> /tmp/...` へリダイレクトする +3. **API コスト**: トークン従量課金。1 セッションで数千〜数万トークン消費することがあり、短時間で済むタスクには使わない +4. **機密情報**: コードが外部 API へ送信される。社外秘コードの扱いは組織ポリシーに従う +5. **モデル選択**: 既定モデルは時期により変動する。安定性が要るときは明示指定する +6. **サンドボックス無効化フラグ**: Codex の `--dangerously-bypass-approvals-and-sandbox` と Gemini の + `--yolo` は、任意のシェル実行とファイル編集を無確認で許可する。**Docker / devcontainer / VM / + CI ランナー / 隔離 worktree などの外部隔離環境内でのみ使用**し、ホスト直接実行や本番リポジトリでは使わない + +## 関連 + +- [references/cli-codex.md](references/cli-codex.md) — Codex CLI 固有の手順 +- [references/cli-gemini.md](references/cli-gemini.md) — Gemini CLI 固有の手順 +- `/ndf:cross-review` — codex / gemini 両方を並列起動して APPROVE 収束まで回す +- `/ndf:review` — 第二引数に `codex` / `gemini` を指定すると本スキルの手順へ委譲する +- Claude Code 版 `corder` エージェント — 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 +- 他の AI CLI(`claude`, `ollama` 等)も同じパターンで利用できる diff --git a/plugins/ndf-shared/skills/external-ai/references/cli-codex.md b/plugins/ndf-shared/skills/external-ai/references/cli-codex.md new file mode 100644 index 00000000..295edf0c --- /dev/null +++ b/plugins/ndf-shared/skills/external-ai/references/cli-codex.md @@ -0,0 +1,210 @@ +# Codex CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Codex CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which codex && codex --version +codex login # 初回のみ。未ログインだと即座に失敗する + +# 未インストールの場合 +npm install -g @openai/codex +codex exec --help +``` + +## サンドボックス制約(最重要) + +Codex の既定サンドボックスは `bubblewrap (bwrap)` に依存する。次の環境では bwrap が動作せず、 +`exec` で実行するシェルコマンドがすべて失敗する。 + +- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) +- **一部の devcontainer / Docker 環境**(user namespace 非対応) + +該当環境では `--dangerously-bypass-approvals-and-sandbox` を付けて起動する。 + +```bash +# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) +codex exec -s read-only -C "$PWD" + +# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" +``` + +**判断基準**: Docker / devcontainer / VM / CI ランナー等で外部的に隔離済みなら実用上安全。 +ホスト直接実行でコードを全書き換えされたくない場合はフラグを付けず、下記の bwrap 代替で対処する。 +`-s read-only` / `-s workspace-write` も bwrap を使うため、フラグなしでは同じ失敗になる点に注意。 + +### bwrap 代替の有効化(ホスト直接実行時) + +```bash +# Debian/Ubuntu 系でホスト user namespace を有効化 +sudo sysctl kernel.unprivileged_userns_clone=1 + +# 永続化 +echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf +``` + +## 起動コマンド + +プロンプトは **stdin へ流す**。`-C` で作業ディレクトリを明示する。 + +```bash +codex exec --dangerously-bypass-approvals-and-sandbox \ + --config reasoning.effort=medium \ + -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +``` + +| オプション | 用途 | +|---|---| +| `-C ` | 作業ディレクトリ。指定しないと cwd が想定と異なりファイルを読めなくなる | +| `--dangerously-bypass-approvals-and-sandbox` | bwrap 非対応環境で必須。外部隔離環境内でのみ使用する | +| `--config reasoning.effort=medium` | `high` だと思考へ偏り最終 message を返さない頻度が上がるため、既定で `medium` を推奨 | +| `--json` | JSON Lines でイベントを出力。`event.type=assistant_message` を grep すれば確実に本文を取れる | +| `codex resume` | 長時間ジョブで親エージェントが再起動した場合にセッションを再開する | + +## 出力ストリーム + +| ストリーム | 内容 | +|---|---| +| **stdout** | 最終 assistant message のみ(Markdown 本文)。**空になることがある**(下記) | +| **stderr** | プロンプトのエコー + 実行コマンドと結果 + 思考プロセス + `^tokens used$` sentinel。数千行になる | + +## 最終出力をファイル経由で保証する(必須) + +Codex CLI(特に `gpt-5-codex` / 高 `reasoning_effort`)は、長時間調査の末に +**最終 assistant message を返さずセッションを終えることがある**。このとき stdout は空のまま、 +stderr のイベントログにはコードを読んだ痕跡だけが残る(`^tokens used$` は出ているのに stdout が空)。 + +**根本対策**: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。 +Codex は最終 message を返さなくても `apply_patch` でファイルを作成できるため、ファイル経由なら確実に回収できる。 + +```markdown +## 出力先(必須) + +最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: + +`/tmp/codex-output-タスク名.md` + +書き出しは `apply_patch` で新規ファイル作成してください。 +**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 +書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 +``` + +補助策として `--config reasoning.effort=medium` へ下げる、`--json` でイベントを採取する、 +プロンプト末尾に「tool 呼び出しのみで終了しないこと」を明記する、の 3 つを併用する。 + +回収は **ファイル → stdout → stderr** の順(共通手順の三段フォールバック、Codex は `OUTPUT_FILE` 優先)。 + +## 完了検知 + +`ps -p $PID` は zombie (defunct) にも 0 を返すため、**PID watch は永久ループになりうる**。 +stderr 末尾の sentinel を脱出条件にする。 + +```bash +# ❌ 永久ループ化しうる +until ! ps -p $PID; do sleep 30; done + +# ✅ zombie 安全 +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +進捗を覗くときは `tail -30 /tmp/codex-err.log`。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & +PID=$! +echo "codex PID: $PID" + +# === 3. 完了確認(^tokens used$ sentinel を待つ) === +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル優先 → stdout フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./review-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/codex-err.log + exit 1 +fi +``` + +## Codex 固有のトラブルシューティング + +### Q1. stdout が空で stderr に大量の exec ログだけある + +**原因**: まだ最終回答を出す前に停止した、または最終 assistant message を出さずにセッションが終わった。 + +**対処**: `grep -q '^tokens used$' /tmp/codex-err.log` で sentinel を確認する。 +未出力なら実行中なので追加待機。出ているのに stdout が空なら「最終出力をファイル経由で保証する」の +パターンでリトライする(`apply_patch` 指示の追加 + `reasoning.effort=medium`)。 + +### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 + +**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 + +**対処**: フラグを追加して再実行する。ホストで有効化する方法は「サンドボックス制約」節を参照。 + +### Q3. 「ファイルを読めません」と返ってくる + +**原因**: サンドボックス有効で読み取りに失敗、またはプロンプトの相対パスと cwd の不一致。 + +**対処**: `--dangerously-bypass-approvals-and-sandbox` を追加し、プロンプトには絶対パス、`-C` で cwd を明示する。 + +### Q4. タスク完了通知が来たのに出力が空 / 待機ループが抜けない + +**原因**: `&` で起動したラッパーシェルだけが終了した、または zombie を `ps -p` が生存と誤判定している。 + +**対処**: 検知を PID ではなく `^tokens used$` sentinel で行う(「完了検知」節)。 + +### Q5. 認証エラー(`Unauthorized` / `token expired`) + +```bash +codex logout +codex login +``` diff --git a/plugins/ndf-shared/skills/external-ai/references/cli-gemini.md b/plugins/ndf-shared/skills/external-ai/references/cli-gemini.md new file mode 100644 index 00000000..6440b067 --- /dev/null +++ b/plugins/ndf-shared/skills/external-ai/references/cli-gemini.md @@ -0,0 +1,221 @@ +# Gemini CLI 固有の手順 + +共通手順(プロンプトの書き出し、バックグラウンド起動、三段フォールバック回収、待機間隔、 +プロンプトテンプレート)は [../SKILL.md](../SKILL.md) を参照。本ファイルは Gemini CLI に固有の差分だけを扱う。 + +## インストールとログイン + +```bash +which gemini && gemini --version + +# 初回ログイン(OAuth): 対話モードで起動して /auth を叩きブラウザ認証する +gemini + +# 未インストールの場合 +npm install -g @google/gemini-cli +gemini -p "hello" --output-format text +``` + +## 承認モード(最重要) + +Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには +`--yolo` か `--approval-mode` を指定する。指定しないと承認待ちでハングする。 + +| モード | 用途 | +|---|---| +| `default` | 対話で都度承認(非対話では止まる) | +| `auto_edit` | 編集系のみ自動承認。シェル実行は都度承認 | +| `yolo`(`--yolo`) | 全 tool 自動承認 | +| `plan`(`--approval-mode plan`) | 読み取り専用。編集系 tool は走らない | + +- **レビュー / 調査タスク**: `--approval-mode plan`(編集事故を防ぐ) +- **コード生成タスク**: `--yolo`(実ファイル編集が必要) +- **`gh api -X POST` などシェル実行を伴うタスク**: `--yolo` 必須(`plan` / `auto_edit` ではブロックされる) + +指定した承認モードは trusted directory 判定で覆される。untrusted なパスで起動すると +`--yolo` が `default` へ降格し、非対話では承認待ちのままハングする。headless 実行では +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず併用すること(「起動コマンド」節参照)。 + +> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / +> 任意のファイル編集を**無確認で許可**する。Docker コンテナ / devcontainer / VM / CI ランナー / +> 隔離された worktree のいずれかの**外部隔離環境内でのみ**使用すること。ホスト直接実行や +> 本番リポジトリ作業中の `--yolo` は厳禁で、その場合は `--approval-mode auto_edit` への降格を検討する。 +> プロンプトで「リポジトリ編集禁止」を明示することは有効だが、sandbox の代替にはならない。 + +## 起動コマンド + +プロンプトは `-p "$(cat ...)"` で渡すか、stdin へパイプする。 + +> ⚠️ **非対話実行では `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を必ず両方付ける**。 +> Gemini CLI は未登録のディレクトリ(worktree のような新規パスを含む)を untrusted と判定し、 +> `--yolo` を `default` へ降格させる。降格すると tool ごとの承認待ちになり、非対話では +> そのままハングする。片方だけでは降格を防げないため、環境変数とフラグの両方が必要。 + +```bash +GEMINI_CLI_TRUST_WORKSPACE=true gemini --approval-mode plan --skip-trust --output-format text \ + -p "$(cat /tmp/gemini-prompt.md)" \ + > /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! + +# stdin パイプでも可 +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text -p "" \ + < /tmp/gemini-prompt.md \ + > /tmp/gemini-stdout.md 2> /tmp/gemini-err.log & +``` + +| オプション | 用途 | +|---|---| +| `--output-format text` | 最終 response の本文をそのまま stdout へ出す | +| `--output-format json` | `{session_id, response, stats}` の JSON 1 オブジェクトを出す | +| `--include-directories ` | ワークスペース外のディレクトリを参照対象へ追加する | +| `--skip-trust` | trusted directory 判定を飛ばす。`--yolo` が無効化されるのを防ぐ | +| `GEMINI_CLI_TRUST_WORKSPACE=true`(環境変数) | 実行ディレクトリを trusted 扱いにする。`--skip-trust` と併用必須 | +| `-m ` | モデルを明示指定する(既定モデルは時期により変動する) | + +`/ndf:cross-review` の `scripts/launch-gemini.sh` も同じ組み合わせで起動している。 + +## 出力ストリーム + +| ストリーム | `--output-format text` | `--output-format json` | +|---|---|---| +| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | `{session_id, response, stats}` | +| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)。通常数行で無害 | 同左 | + +```bash +# 成果物だけ取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format text \ + -p "$(cat prompt.md)" > out.md + +# 統計(トークン数・tool 呼び出し履歴)込みで取りたい +GEMINI_CLI_TRUST_WORKSPACE=true gemini --yolo --skip-trust --output-format json \ + -p "$(cat prompt.md)" > out.json +jq -r '.response' out.json > out.md +jq '.stats' out.json > stats.json +``` + +Gemini には Codex のような「最終 message を返さずに終わる」既知挙動は確認されていないため、 +**回収は stdout 優先**(共通手順の三段フォールバックで `STDOUT` を `PRIMARY` にする)。 +ただし長尺タスクの途中エラーに備え、保険として `write_file` での書き出しをプロンプトに加えておく。 + +```markdown +## 出力先(推奨) + +最終結果を `/tmp/gemini-output-タスク名.md` にも `write_file` で書き出してください。 +(stdout には同内容をそのまま出力すれば冪等で問題ありません。) +``` + +## 完了検知 + +Gemini は `^tokens used$` のような sentinel を吐かないため、stderr の grep では完了判定できない。 +**プロセスの終了**を見るのが正しい。 + +```bash +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "exit=$?" +``` + +進捗を覗くときは `tail -30 /tmp/gemini-err.log`(実行中の stdout 出力は限定的)。 + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し === +FINAL=/tmp/gemini-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ + 2> /tmp/gemini-err.log & +PID=$! +echo "gemini PID: $PID" + +# === 3. 完了確認(プロセス終了を待つ) === +until ! kill -0 $PID 2>/dev/null; do + sleep 30 +done +wait $PID +echo "DONE exit=$?" + +# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === +if [ -s /tmp/gemini-stdout.md ]; then + cp /tmp/gemini-stdout.md ./review-result.md +elif [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md + echo "WARN: ファイルからフォールバック回収" >&2 +else + echo "ERROR: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 + tail -200 /tmp/gemini-err.log + exit 1 +fi +``` + +## Gemini 固有のトラブルシューティング + +### Q1. 非対話モードなのにプロセスがハングする + +**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` のまま)。 +指定したはずの `--yolo` が trusted directory 判定で `default` へ降格しているケースも同じ症状になる。 + +**対処**: `--yolo` または `--approval-mode plan` を付けたうえで、 +`GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を併用する。レビュー / 調査なら `plan` が安全。 + +### Q2. stdout に思考のような余計な出力が混ざる + +**原因**: `--output-format text` でも進捗 / モデル切替メッセージが混ざる場合がある。 + +**対処**: `--output-format json` にして `jq -r '.response'` で本文だけ抽出する。 +あわせてプロンプトへ「最終結果のみを出力すること、思考や前置きは不要」と明記する。 + +### Q3. ワークスペース外のファイルを読めない / 止まる + +**対処**: `--include-directories /path/to/extra` で対象ディレクトリを追加し、プロンプトには絶対パスを書く。 +それでも止まる場合は `GEMINI_CLI_TRUST_WORKSPACE=true` + `--skip-trust` を併用する。 + +### Q4. `--yolo` を付けたのに承認待ちになる + +**原因**: trusted directory 判定によって YOLO が無効化され、承認モードが `default` へ降格している。 +worktree のような新規パスは既定で untrusted 扱いになる。 + +**対処**: `GEMINI_CLI_TRUST_WORKSPACE=true` と `--skip-trust` を **両方** 付けて起動する。 +片方だけでは降格を防げない。 + +### Q5. `Error in: mcpServers.` の警告が毎回出る + +**原因**: `.gemini/settings.json` に `disabled: false` などの非互換キーがある。 + +**対処**: 該当キーを除去するか、起動前に設定を sanitize する +(`/ndf:cross-review` の `launch-gemini.sh` は v4.7.2 以降でこれを自動化している)。 + +### Q6. 認証エラー(`Authentication required` / `token expired`) + +**原因**: OAuth セッション失効。 + +**対処**: 対話モードで `gemini` を起動し、`/auth` を叩いてブラウザ認証をやり直す。 diff --git a/plugins/ndf-shared/skills/gemini/SKILL.md b/plugins/ndf-shared/skills/gemini/SKILL.md deleted file mode 100644 index e2156ed8..00000000 --- a/plugins/ndf-shared/skills/gemini/SKILL.md +++ /dev/null @@ -1,444 +0,0 @@ ---- -name: gemini -description: "Delegate coding, review, or research to Gemini CLI." -when_to_use: "外部 AI (Gemini)へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'geminiで調査', 'geminiレビュー', '第二意見レビュー (Gemini)', 'gemini exec', 'external AI review (Gemini)'" ---- - -# Gemini 外部AI委譲スキル - -## 概要 - -`gemini` CLI(Google Gemini、通常は `/usr/bin/gemini` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 - -`codex` skill と同等の用途だが、Gemini CLI は以下の点で扱いやすい: - -- **stdout に最終 response が直接出る**(text/json いずれも空にならない既知挙動なし) -- **bwrap サンドボックスに依存しない**(WSL2 でも追加フラグ不要) -- **プロセス exit で完了判定可能**(sentinel grep が不要) - -## NDFとの関係 - -- `/ndf:review gemini` のように、`review` skill の第二引数 `gemini` 指定時の委譲先として利用される -- 専用エージェント(`corder` 相当)は未整備。委譲時はメインエージェントから本 skill を参照して直接 CLI を起動する -- Codex との使い分けは「既知制約とコスト」節を参照 - -## いつ使うか - -### 使うべきケース -- **独立第二意見レビュー**: 設計書・PR・仕様書を Gemini にレビューさせる(Codex とのクロスチェックに有用) -- **コードベース横断調査**: Gemini はワークスペース全体を走査する設計のため、複数ディレクトリ横断の調査に向く -- **長文生成**: ドキュメント生成・要約・翻訳など -- **Codex でうまくいかない / レート制限に当たったときの代替** - -### 使わないべきケース -- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 -- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める -- 単純な質問回答 → WebFetch / WebSearch で足りる -- 機密情報を含むコード → 外部API送信の可否を確認してから - -## 前提条件 - -```bash -# インストール確認 -which gemini -gemini --version - -# 初回ログイン(OAuth) -gemini # 起動 → /auth でログイン -``` - -未インストールの場合は以下でセットアップ: - -```bash -# npm 経由 -npm install -g @google/gemini-cli - -# 動作確認 -gemini -p "hello" --output-format text -``` - -## 基本実行パターン - -### 1. 承認モード(重要) - -Gemini CLI は対話モードでは tool 実行ごとに承認を求める。非対話で確実に走らせるには `--yolo` か `--approval-mode yolo` を付ける。 - -```bash -# ❌ 非対話モードで tool 承認待ちで止まる -gemini -p "..." - -# ✅ ツール自動承認(外部隔離前提) -gemini --yolo -p "..." - -# ✅ 読み取り専用モード(plan mode、編集系 tool は走らない) -gemini --approval-mode plan -p "..." -``` - -| モード | 用途 | -|---|---| -| `default` | 対話で都度承認(非対話では止まる) | -| `auto_edit` | 編集系のみ自動承認 | -| `yolo` (`--yolo`) | 全 tool 自動承認 | -| `plan` | 読み取り専用(調査・レビュー向け) | - -**レビュー/調査タスクの推奨**: `--approval-mode plan`(編集事故を防ぐ) -**コード生成タスクの推奨**: `--yolo`(実ファイル編集が必要) - -> ⚠️ **`--yolo` のセキュリティ注意**: 全 tool 自動承認は `rm -rf` / 任意のシェル実行 / 任意のファイル編集を **無確認で許可** する。 -> 必ず以下のいずれかの **外部隔離環境** 内でのみ使用すること: -> - Docker コンテナ / devcontainer -> - VM / CI ランナー -> - 隔離された worktree(ホスト本体のリポジトリでは使わない) -> -> ホスト直接実行や本番リポジトリ作業中の `--yolo` は厳禁。コード生成タスクでも、ホスト直接実行なら -> `--approval-mode auto_edit`(編集系のみ自動承認、シェル実行は都度承認)への降格を検討する。 - -### 2. プロンプトは一時ファイル経由で渡す - -長いプロンプトをシェル引数に直接渡すとエスケープが破綻するので、ファイル経由で stdin か `$(cat ...)` 経由にする。 - -```bash -# Step 1: プロンプトを一時ファイルに書く -cat > /tmp/gemini-prompt.md <<'EOF' -## タスク -以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 - -## 対象ファイル(絶対パスで指定) -/absolute/path/to/design.md - -## 出力形式 -Markdown で標準出力に吐いてください。 -EOF - -# Step 2a: stdin 経由(推奨) -gemini --yolo --output-format text -p "$(cat /tmp/gemini-prompt.md)" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log - -# Step 2b: あるいは stdin パイプ -cat /tmp/gemini-prompt.md | gemini --yolo --output-format text -p "" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log -``` - -### 3. 出力ストリームの扱い - -Gemini CLI の出力構造(codex と異なる点に注意): - -| ストリーム | `--output-format text` の内容 | `--output-format json` の内容 | -|---|---|---| -| **stdout** | 最終 assistant response の本文(Markdown / プレーンテキスト) | JSON 1 オブジェクト: `{session_id, response, stats}` | -| **stderr** | 警告のみ(例: `Ripgrep is not available. Falling back to GrepTool.`)— 通常数行 | - -**実務上の扱い**: -- 成果物が欲しい → `--output-format text` の stdout をそのまま採用 -- 統計(トークン数・tool 呼び出し履歴)が欲しい → `--output-format json` で stdout を `jq` 解析 - -```bash -# 成果物だけ取りたい -gemini --yolo --output-format text -p "$(cat prompt.md)" > out.md - -# 統計込みで取りたい -gemini --yolo --output-format json -p "$(cat prompt.md)" > out.json -jq -r '.response' out.json > out.md -jq '.stats' out.json > stats.json -``` - -### 4. 最終出力をファイル経由で保証する(補強策) - -Gemini は codex のような「最終 message を返さずに終わる」既知挙動は今のところ確認されていない。 -ただし長尺タスクで途中エラーが起きた場合の保険として、**`apply_patch` 相当の write_file tool で書き出させる指示** をプロンプトに加えると安全: - -```markdown -## 出力先(推奨) - -最終結果を `/tmp/gemini-output-.md` にも書き出してください。 -(stdout には同内容をそのまま出力すれば冪等で問題ありません。) -``` - -回収側は「stdout → ファイル → stderr」の順でフォールバック: - -```bash -# 命名規約: -# STDOUT = gemini の `> リダイレクト` 先(本 skill では /tmp/gemini-stdout.md で統一) -# OUTPUT_FILE = プロンプト指示で `write_file` させた保険ファイル(task ごとに固有名) -OUTPUT_FILE=/tmp/gemini-output-pr13734-review.md -STDOUT=/tmp/gemini-stdout.md - -if [ -s "$STDOUT" ]; then - cp "$STDOUT" ./result.md -elif [ -s "$OUTPUT_FILE" ]; then - cp "$OUTPUT_FILE" ./result.md -else - echo "WARN: Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 - tail -200 /tmp/gemini-err.log -fi -``` - -### 5. バックグラウンド実行 + 待機パターン - -Gemini も大規模調査タスクでは数分かかる。エージェントハーネスのシェルタイムアウト(通常2〜3分)に引っかかる可能性があるため、**バックグラウンド実行 + 待機** が安全。 - -```bash -# 1. プロンプトファイル書き出し -# -> /tmp/gemini-prompt.md - -# 2. gemini をバックグラウンドで起動 -gemini --yolo --output-format text -p "$(cat /tmp/gemini-prompt.md)" \ - > /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log & -PID=$! -echo "PID: $PID" - -# 3. 完了検知 — Gemini は exit するので PID watch で OK -# (codex の zombie 問題はないが、念のため出力ファイルサイズも併用すると堅牢) -until ! kill -0 $PID 2>/dev/null; do - sleep 30 -done -echo "DONE" - -# 4. 終了コード確認 -wait $PID -EXIT=$? -echo "exit=$EXIT" -``` - -**注意**: -- Gemini は codex と違って `^tokens used$` のような sentinel を吐かないため、stderr grep では完了判定できない -- 代わりに **プロセスの終了** を見るのが正しい(`kill -0` でプロセス存在確認、`wait $PID` で終了コード回収) - -### 6. 待機間隔のチューニング - -エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: - -- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) -- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) -- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) - -Gemini の典型実行時間(数十秒〜5分)に対しては **60〜270秒ポーリング** で十分。 - -### 7. プロセス確認・ログ追跡 - -```bash -# 完了したか -kill -0 $PID 2>/dev/null && echo "RUNNING" || echo "DONE" - -# 進捗を覗く(Gemini は実行中の stdout 出力は限定的なので stderr 側を見る) -tail -30 /tmp/gemini-err.log -``` - -## プロンプト設計のコツ - -### 必須要素 -1. **対象ファイルの絶対パス**(Gemini はワークスペース外のファイルも参照可能だが絶対パスが安全) -2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) -3. **出力形式の指定**(Markdownテンプレートを提示) -4. **スコープ外の明示**(脱線防止) -5. **出力サイズ目安**(例: 400〜500行) - -### レビュー依頼テンプレート - -```markdown -あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 -以下をレビューしてください。 - -## 対象ファイル(必ず最初に読むこと) -`/absolute/path/to/target.md` - -## 観点 -1. <観点1: 例「仕様とコードの整合性」> -2. <観点2: 例「既存APIとの後方互換性」> - -## 調査対象コード(必要に応じて読む) -- `src/...` -- `lib/...` - -## 背景コンテキスト -- <プロジェクト概要> -- <関連PR / Issue番号> -- <既存レビューで対応済みの事項(重複指摘を避けるため)> - -## 出力形式 - -以下を Markdown で **stdout に出力** してください。 -(保険として `/tmp/gemini-output-.md` にも `write_file` で書き出してください。) - -# <タイトル> - -## 総評 -## 1. <観点1> に関する指摘 -### 1.1 正確な主張 -### 1.2 訂正推奨 -## 2. <観点2> に関する指摘 -## 3. 追加提案 -## 4. 承認可否 - -**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 -``` - -### コード生成依頼テンプレート - -```markdown -以下の実装タスクを実行してください。 - -## タスク -<具体的な実装内容> - -## 制約 -- <技術制約: 言語バージョン、依存ライブラリ> -- <コーディング規約: ESLint / Prettier / rustfmt等> -- <テスト要件: ユニットテスト必須等> - -## 対象ファイル -- <既存ファイルのパス> -- <新規ファイルのパス案> - -## 背景 -<なぜこの実装が必要か、設計判断の経緯> - -## 完了基準 -- [ ] テストがパスする -- [ ] 型チェック / lint がパスする -- [ ] <追加の受け入れ条件> - -**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を -stdout に Markdown で出力してください。 -保険として `/tmp/gemini-output-.md` にも `write_file` で書き出してください。 -``` - -## 実例: レビュー依頼の完全フロー - -```bash -# === 1. プロンプト書き出し === -FINAL=/tmp/gemini-output-api-v2-review.md - -cat > /tmp/review-prompt.md < /tmp/gemini-stdout.md \ - 2> /tmp/gemini-err.log & - -PID=$! -echo "gemini PID: $PID" - -# === 3. 完了確認(プロセス終了を待つ) === -until ! kill -0 $PID 2>/dev/null; do - sleep 30 -done -wait $PID -EXIT=$? -echo "DONE exit=$EXIT" - -# === 4. 成果物を回収(stdout 優先 → ファイルフォールバック) === -if [ -s /tmp/gemini-stdout.md ]; then - cp /tmp/gemini-stdout.md ./review-result.md - echo "✅ stdout から回収" -elif [ -s "$FINAL" ]; then - cp "$FINAL" ./review-result.md - echo "⚠ ファイルからフォールバック回収" -else - echo "❌ Gemini の最終出力を回収できませんでした。stderr を確認:" >&2 - tail -200 /tmp/gemini-err.log - exit 1 -fi -``` - -## トラブルシューティング - -### Q1. 非対話モードなのにプロセスがハングする -**原因**: 承認が必要な tool 呼び出しで止まっている(`default` / `auto_edit` モードのまま)。 - -**対処**: `--yolo` または `--approval-mode plan` を付ける。レビュー/調査なら `plan` が安全。 - -### Q2. stdout に思考のような余計な出力が混ざる -**原因**: `--output-format text` でも一部の進捗 / モデル切替メッセージが混ざる場合がある。 - -**対処**: -- `--output-format json` を使い、`jq -r '.response'` で本文だけ抽出する -- プロンプトで「最終結果のみを出力すること、思考や前置きは不要」と明記 - -### Q3. ファイルを読めない / ワークスペース外アクセスで止まる -**原因**: Gemini のワークスペース範囲外のファイル参照、または承認待ち。 - -**対処**: -- `--include-directories /path/to/extra` で対象ディレクトリを追加 -- プロンプトには**絶対パス**を書く -- それでも止まるなら `--yolo` または `--skip-trust` - -### Q4. 出力が途中で切れる / トークン上限 -**原因**: モデルの出力トークン上限に達した。 - -**対処**: -- プロンプトで「400行以内」など出力サイズを指定 -- 観点を絞って分割実行 -- `-m ` でより長い context のモデルを指定(gemini-3-pro 等、利用可能なものに応じて) - -### Q5. 認証エラー (`Authentication required` / `token expired`) -**原因**: OAuth セッション失効。 - -**対処**: -```bash -# 対話モードで再ログイン -gemini -# プロンプト上で /auth を叩いてブラウザ認証 -``` - -### Q6. ハーネスのシェルタイムアウトで kill される -**原因**: フォアグラウンド実行のまま長尺タスクを走らせた。 - -**対処**: 必ず `&` でバックグラウンド化し、`kill -0 $PID` ポーリングで待機する(5節参照)。 - -## 既知の制約とコスト - -1. **承認モード必須**: 非対話実行では `--yolo` か `--approval-mode plan` を必ず付ける -2. **stderr 警告は無害**: `Ripgrep is not available. Falling back to GrepTool.` 等は通常運用上問題なし -3. **ログイン状態**: 初回は対話モードで `/auth` 経由のログインが必要 -4. **APIコスト**: Google AI Studio / Vertex 経由のトークン課金。Codex より安価な傾向だが従量制 -5. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと -6. **モデル選択**: デフォルトモデルは時期により変動。安定性を求めるなら `-m gemini-2.5-pro` 等を明示 - -## Codex との使い分け - -| 観点 | Codex (`/ndf:codex`) | Gemini (本スキル) | -|---|---|---| -| stdout の信頼性 | 最終 message が落ちることがある(要ファイル書き出し) | stdout に response が直接出る | -| サンドボックス | WSL2 で `--dangerously-bypass-approvals-and-sandbox` 必須 | 追加フラグ不要 | -| 完了判定 | `^tokens used$` sentinel | プロセス exit | -| 出力フォーマット | Markdown 本文のみ | text / json 選択可(json は統計付き) | -| 強み | コード逐語照合、長時間の深い調査 | 横断調査、長文生成、軽量タスク | -| 弱み | セットアップ・運用が煩雑 | 高難度コード解析でやや浅くなることがある | - -**指針**: -- 第二意見が欲しい場合、両方走らせてクロスチェックすると最も堅い -- 短時間で済む独立レビュー → Gemini を先に -- 行番号・件数の逐語確認 → Codex を併用 - -## 関連 - -- **`/ndf:codex` skill**: Codex CLI 経由の同等スキル(本スキルと併用してクロスチェック可能) -- **`/ndf:review` skill**: 第二引数 `gemini` 指定時に本スキルの手順を参照 -- **Gemini CLI 公式ドキュメント**: `gemini --help` -- **他のAI委譲方法**: `codex`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf-shared/skills/qa-security-scan/03-report-template.md b/plugins/ndf-shared/skills/qa-security-scan/03-report-template.md index d87bec9f..6ad9f7ec 100644 --- a/plugins/ndf-shared/skills/qa-security-scan/03-report-template.md +++ b/plugins/ndf-shared/skills/qa-security-scan/03-report-template.md @@ -92,11 +92,13 @@ ## Codex CLI 連携 -詳細な独立レビューが必要な場合は `corder` エージェントに委譲するか、`/ndf:codex` skill の手順で `codex exec` を直接起動する。例: +詳細な独立レビューが必要な場合は `corder` エージェントに委譲するか、`/ndf:external-ai` skill の手順で `codex exec` を直接起動する。例: ```bash -# プロンプト書き出し -cat > /tmp/sec-scan-prompt.md <<'EOF' +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-sec-scan.md + +cat > /tmp/sec-scan-prompt.md < /tmp/sec-scan-prompt.md <<'EOF' ## 対象ファイル(絶対パス) /workspace/src/... +## 出力先(必須) +最終的なスキャン結果を **必ず** \`${FINAL}\` に \`apply_patch\` で新規作成してください。 +**stdout への出力だけでは不十分です**。書き出し後、stdout にも同じ内容を出力してください。 + ## 出力形式 -Markdown 標準出力。行番号と該当コードスニペットを明記。 +Markdown。行番号と該当コードスニペットを明記。tool 呼び出しのみで終了せず、 +最後に必ず assistant message として 1 回出力してください。 EOF -# バックグラウンド起動 -codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ +# === 2. バックグラウンド起動 === +codex exec --dangerously-bypass-approvals-and-sandbox \ + --config reasoning.effort=medium \ + -C "$PWD" \ < /tmp/sec-scan-prompt.md \ - > /tmp/sec-scan-output.md \ + > /tmp/sec-scan-stdout.md \ 2> /tmp/sec-scan-err.log & + +# === 3. 完了確認(^tokens used$ sentinel を待つ。`ps -p` は zombie を生存と誤判定する) === +until grep -q '^tokens used$' /tmp/sec-scan-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル → stdout → stderr の三段フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./sec-scan-result.md +elif [ -s /tmp/sec-scan-stdout.md ]; then + cp /tmp/sec-scan-stdout.md ./sec-scan-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/sec-scan-err.log +fi ``` -詳細は `/ndf:codex` skill を参照。 +詳細は `/ndf:external-ai` skill と `references/cli-codex.md` を参照。 diff --git a/plugins/ndf-shared/skills/review/SKILL.md b/plugins/ndf-shared/skills/review/SKILL.md index 983c4e4a..2afd42e2 100644 --- a/plugins/ndf-shared/skills/review/SKILL.md +++ b/plugins/ndf-shared/skills/review/SKILL.md @@ -225,8 +225,9 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ 第二引数が指定された場合、上記「観点」「具体的なチェックポイント」「PR モードの手順」の 内容を **レビュー指示プロンプト** として組み立て、指定された CLI に渡す。 -呼び出し手順の詳細は、利用 runtime に `/ndf:codex` / `/ndf:gemini` skill が同梱されて -いる場合はその skill に従う。同梱されていない runtime では以下の要点に従う。 +呼び出し手順の詳細は、利用 runtime に `/ndf:external-ai` skill が同梱されている場合は +その skill の `references/cli-codex.md` / `references/cli-gemini.md` に従う。 +同梱されていない runtime では以下の要点に従う。 **`codex` 指定時** @@ -239,6 +240,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ > ⚠️ `--dangerously-bypass-approvals-and-sandbox` は codex のサンドボックスを完全に無効化し、 > 任意のシェル実行・ファイル編集を無確認で許可する。**必ず Docker / devcontainer / VM / CI ランナー等の > 外部隔離環境内** でのみ使用すること。ホスト直接実行や本番リポジトリでは使わない。 +> 背景・代替策は `/ndf:external-ai` skill の `references/cli-codex.md`「サンドボックス制約」節を参照。 **`gemini` 指定時** @@ -250,7 +252,7 @@ gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ - 成果物は stdout サマリ + `/tmp/gemini-review-pr<番号>-result.json` で回収 > ⚠️ `--yolo` も同様に外部隔離環境内でのみ実行する。プロンプトでの「リポジトリ編集禁止」明示は必須だが、 -> sandbox の代替にはならない。 +> sandbox の代替にはならない。詳細は `/ndf:external-ai` skill の `references/cli-gemini.md` を参照。 ### プロンプト組み立て @@ -351,6 +353,5 @@ PR モードではレビュー結果が **PR 上に投稿済み** であるこ - `/ndf:fix` — レビュー指摘の分類と修正対応 - `/ndf:cross-review` — codex + gemini の収束レビュー -- `/ndf:codex` — Codex CLI の呼び出し手順(同梱 runtime のみ) -- `/ndf:gemini` — Gemini CLI の呼び出し手順(同梱 runtime のみ) +- `/ndf:external-ai` — Codex / Gemini CLI の呼び出し手順(同梱 runtime のみ) - `/ndf:logging-guidelines` — ログ設計