diff --git a/docs/0-requirements.md b/docs/0-requirements.md index 4c61065..97ca0bd 100644 --- a/docs/0-requirements.md +++ b/docs/0-requirements.md @@ -18,16 +18,24 @@ GitHub Webhook イベントを受信・永続化し、MCP プロトコル経由 GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist──> events.json ^ | - MCP Server (stdio) ──read/write - ^ - | - AI Agent (Claude) + ┌─────────────────────────────┴─────────────────────────────┐ + | | + | trigger-events/.json + | ^ + | | + MCP Server (stdio) ──read/write direct trigger queue + ^ | + | | + AI Agent (Codex / Claude) optional trigger command ``` 二つのプロセスモードを持つ単一エントリポイント: - `python main.py webhook` — HTTP 受信サーバー - `python main.py mcp` — MCP ツールサーバー +Webhook モードは、イベント永続化に加えて optional な direct trigger queue を持つ。 +trigger command が設定されている場合、保存済みイベントごとに直列実行される。 + ## Functional Requirements ### F1. Webhook 受信 @@ -71,6 +79,8 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist | F3.2 | 各イベントは id, type, payload, received_at, processed フィールドを持つ | | F3.3 | ファイルエンコーディングは UTF-8 で書き込む | | F3.4 | レガシーエンコーディング(cp932, shift_jis, utf-8-sig)からの自動マイグレーションを行う | +| F3.5 | trigger 実行を行う場合、イベントに `trigger_status`, `trigger_error`, `last_triggered_at` を追記できる | +| F3.6 | trigger 実行用に `trigger-events/.json` を保存できる | **イベント構造:** @@ -80,7 +90,10 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist "type": "issues", "payload": {}, "received_at": "ISO8601+timezone", - "processed": false + "processed": false, + "trigger_status": "succeeded|failed|skipped|null", + "trigger_error": "", + "last_triggered_at": "ISO8601+timezone|null" } ``` @@ -102,6 +115,8 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist "type": "issues", "received_at": "ISO8601", "processed": false, + "trigger_status": "succeeded|failed|skipped|null", + "last_triggered_at": "ISO8601|null", "action": "opened", "repo": "owner/repo", "sender": "username", @@ -111,7 +126,43 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist } ``` -### F5. 推奨ポーリングフロー +### F5. Direct Trigger Execution + +| ID | 要件 | +|----|------| +| F5.1 | webhook モードは optional な trigger command を受け付ける | +| F5.2 | trigger command は保存対象イベントごとに 1 件ずつ直列実行する | +| F5.3 | trigger command にはイベント JSON 全体を stdin で渡す | +| F5.4 | trigger command には `GITHUB_WEBHOOK_*` 環境変数でイベント要約を渡す | +| F5.5 | trigger command 成功時はデフォルトでイベントを `processed=true` にする | +| F5.6 | `keep_pending_on_trigger_success` 指定時は成功しても pending のまま残す | +| F5.7 | trigger command 失敗時はイベントを pending のまま残し、`trigger_status=failed` を記録する | +| F5.8 | trigger command が notify-only fallback を選んだ場合は `trigger_status=skipped` を記録し、pending のまま残す | + +**trigger command へ渡す環境変数:** + +- `GITHUB_WEBHOOK_EVENT_ID` +- `GITHUB_WEBHOOK_EVENT_TYPE` +- `GITHUB_WEBHOOK_EVENT_ACTION` +- `GITHUB_WEBHOOK_EVENT_REPO` +- `GITHUB_WEBHOOK_EVENT_SENDER` +- `GITHUB_WEBHOOK_EVENT_NUMBER` +- `GITHUB_WEBHOOK_EVENT_TITLE` +- `GITHUB_WEBHOOK_EVENT_URL` +- `GITHUB_WEBHOOK_EVENT_PATH` +- `GITHUB_WEBHOOK_RECEIVED_AT` + +### F6. Bundled Codex Wrapper + +| ID | 要件 | +|----|------| +| F6.1 | `codex_reaction.py` を bundled helper として提供する | +| F6.2 | helper は `codex exec -C ` による direct execution を行える | +| F6.3 | helper は `codex exec resume ` による resume mode を行える | +| F6.4 | helper は event JSON path を prompt に含め、workspace の `AGENTS.md` を読む前提で起動する | +| F6.5 | workspace に `.codex-webhook-notify-only` がある場合、helper は direct execution を行わず notify-only fallback を返す | + +### F7. 推奨ポーリングフロー | ステップ | 操作 | |---------|------| @@ -137,6 +188,9 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist | N2.1 | ポート | `--port` / 環境変数 | 8080 | | N2.2 | シークレット | `--secret` / `WEBHOOK_SECRET` | なし(検証スキップ) | | N2.3 | イベントプロファイル | `--event-profile` / `WEBHOOK_EVENT_PROFILE` | all | +| N2.4 | trigger command | `--trigger-command` / `WEBHOOK_TRIGGER_COMMAND` | なし | +| N2.5 | trigger working directory | `--trigger-cwd` / `WEBHOOK_TRIGGER_CWD` | なし | +| N2.6 | success 時に pending を維持するか | `--keep-pending-on-trigger-success` | false | 優先順位: CLI 引数 > 環境変数 > デフォルト @@ -147,6 +201,7 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist | N3.1 | イベントはファイル全体をメモリにロードする(大量イベントには不向き) | | N3.2 | イベント検索は線形探索(インデックスなし) | | N3.3 | 単一プロセス想定(webhook と mcp は別プロセスで起動) | +| N3.4 | direct trigger は単一 worker による直列実行であり、同時実行はしない | ## Dependencies @@ -163,3 +218,13 @@ GitHub ──POST──> Cloudflare Tunnel ──> FastAPI :8080 ──persist |---------------|------| | Cloudflare Tunnel | GitHub からのインバウンド HTTPS を localhost に転送 | | GitHub Webhook | イベント送信元 | +| optional trigger command | 保存済みイベントごとの direct reaction | + +## Files + +| パス | 用途 | +|-----|------| +| `events.json` | 永続化された webhook イベント本体 | +| `trigger-events/.json` | trigger command に渡す保存済みイベント JSON | +| `main.py` | webhook receiver / MCP server / direct trigger queue | +| `codex_reaction.py` | Codex direct execution / resume / notify-only fallback helper |