# 機能設計書 47-Discussionコメント作成イベント

## 概要

本ドキュメントは、GitHubリポジトリでDiscussionにコメントが追加されたときにGiselleワークフローを自動起動するトリガーイベント機能の設計を記述する。

### 本機能の処理概要

GitHubでDiscussionにコメントが追加されたことをWebhookイベントとして受信し、特定のコールサイン（呼び出しキーワード）が含まれる場合にワークフローを自動実行する機能である。

**業務上の目的・背景**：GitHub Discussionsはコミュニティでの質問、アナウンス、アイデア共有などに使用される。Discussionコメントでワークフローを起動することで、Q&Aへの自動回答、ドキュメント参照、関連情報の検索など、コミュニティサポートの自動化を実現する。

**機能の利用シーン**：Discussionに「@giselle-bot この機能の使い方を教えて」などのコールサインを含むコメントを投稿することで、AIがドキュメントを検索し回答する場面で利用される。例えば、FAQへの自動回答や、新機能のドキュメント案内などのワークフローを構築できる。

**主要な処理内容**：
1. GitHubからのWebhook（discussion_comment.created）を受信
2. リポジトリノードIDに基づいてトリガー設定を検索
3. イベント種別（github.discussion_comment.created）との一致を確認
4. コメント内容からコールサインを解析し、条件との一致を確認
5. Discussion情報、コメント内容、親コメント内容をペイロードとして抽出
6. ワークフロータスクを作成・開始
7. 処理進捗をDiscussionコメントとして投稿（オプション）

**関連システム・外部連携**：GitHub API（Webhook受信、リアクション追加、Discussionコメント投稿、親コメント取得）、Giselle Storage（トリガー設定の永続化）

**権限による制御**：GitHub Appのインストール権限が必要。リポジトリへのread/write権限（discussions）が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主画面 | トリガーノードの追加・設定、GitHubイベント種別の選択、コールサイン設定 |
| 28 | インテグレーション設定画面 | 参照画面 | GitHubリポジトリ連携の管理 |

## 機能種別

イベント駆動処理 / Webhook処理 / データ連携 / 条件分岐処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| body | string | Yes | コメント本文（コールサイン除去後） | - |
| discussionNumber | number | Yes | Discussion番号 | 正の整数 |
| discussionTitle | string | Yes | Discussionのタイトル | 空文字列不可 |
| discussionBody | string | Yes | Discussionの本文 | - |
| discussionUrl | string | Yes | DiscussionのURL | URL形式 |
| commentId | number | Yes | コメントID | 正の整数 |
| parentCommentBody | string | Yes | 親コメントの本文 | - |

### 入力データソース

- GitHub Webhook（discussion_comment.createdイベント）
- ペイロードに含まれるDiscussionデータ（discussion.number、discussion.title、discussion.body、discussion.html_url）
- ペイロードに含まれるコメントデータ（comment.id、comment.body）
- GitHub APIから取得する親コメント（getDiscussionComment）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| body | generated-text | コメント本文（コールサイン部分を除いた内容） |
| discussionNumber | generated-text | Discussion番号（文字列として出力） |
| discussionTitle | generated-text | Discussionのタイトル |
| discussionBody | generated-text | Discussionの本文 |
| discussionUrl | generated-text | DiscussionのURL |
| commentId | generated-text | コメントID（文字列として出力） |
| parentCommentBody | generated-text | 親コメントの本文（親がない場合は空文字列） |

### 出力先

- ワークフロー内の次のノードへの入力として接続
- トリガーノードの各出力ポートから接続先ノードへデータを伝播

## 処理フロー

### 処理シーケンス

```
1. Webhook受信
   └─ handleGitHubWebhookV2でHTTPリクエストを受信
2. イベント検証
   └─ Webhookシークレットによる署名検証
3. リポジトリ連携確認
   └─ repository.node_idからトリガー設定を検索
4. トリガー設定取得
   └─ flowTriggerIdからトリガーデータを取得
5. イベント種別照合
   └─ handleDiscussionCommentCreatedでイベント種別を確認
6. コールサイン照合
   └─ parseCommandでコメントからコールサインを抽出
   └─ トリガー設定のconditions.callsignと比較
7. リアクション追加
   └─ コメントにEYESリアクションを追加
8. タスク作成・開始
   └─ createAndStartTaskでワークフロー実行
9. ペイロード解決
   └─ resolveTriggerでDiscussion・コメントデータを出力に変換
   └─ getDiscussionCommentで親コメントを取得（返信の場合）
10. 進捗通知（オプション）
    └─ 処理進捗をDiscussionコメントとして投稿
```

### フローチャート

```mermaid
flowchart TD
    A[Webhook受信] --> B{署名検証}
    B -->|失敗| Z[処理終了]
    B -->|成功| C[リポジトリ連携確認]
    C --> D{トリガー設定存在?}
    D -->|No| Z
    D -->|Yes| E[トリガー設定取得]
    E --> F{イベント種別一致?}
    F -->|No| Z
    F -->|Yes| G{コメント存在?}
    G -->|No| Z
    G -->|Yes| H[コールサイン抽出]
    H --> I{コールサイン一致?}
    I -->|No| Z
    I -->|Yes| J[EYESリアクション追加]
    J --> K[タスク作成・開始]
    K --> L[ペイロード解決]
    L --> M{親コメント存在?}
    M -->|Yes| N[親コメント取得]
    M -->|No| O[空文字列設定]
    N --> P[ワークフロー実行]
    O --> P
    P --> Q[進捗通知]
    Q --> R[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | イベント種別照合 | Webhookイベントがdiscussion_comment.createdかつトリガー設定がgithub.discussion_comment.createdの場合のみ処理を実行 | 常時 |
| BR-47-02 | コールサイン照合 | コメント内のコールサインがトリガー設定のconditions.callsignと一致する場合のみ処理を実行 | 常時 |
| BR-47-03 | リアクション追加 | 処理開始時にコメントにEYESリアクションを追加して処理中であることを示す | トリガーが有効な場合 |
| BR-47-04 | コールサイン除去 | 出力のbodyフィールドにはコールサイン部分を除いたコメント内容を設定 | 常時 |
| BR-47-05 | 親コメント取得 | parent_idが設定されている場合、親コメントの本文を取得 | 返信コメントの場合 |
| BR-47-06 | 進捗コメント | shouldPostInProgressCommentがtrueの場合、処理進捗をDiscussionコメントとして投稿 | 設定に基づく |

### 計算ロジック

- コールサイン解析: `parseCommand(comment.body)` でコールサインと内容を分離
- 親コメント取得: `getDiscussionComment(parent_id)` で親コメントを取得

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| トリガー設定取得 | Storage（JSON） | SELECT | flow-triggers/{triggerId}.jsonからトリガー設定を取得 |
| リポジトリ連携確認 | Storage（JSON） | SELECT | github-integration-indexes/{repositoryNodeId}.jsonから連携情報を取得 |

### テーブル別操作詳細

#### flow-triggers/{triggerId}.json

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, workspaceId, nodeId, configuration | triggerId一致 | トリガー設定全体を取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-47-01 | 認証エラー | GitHub認証情報が未設定 | integrationConfigsのgithub.authV2を確認 |
| E-47-02 | トリガー未設定 | リポジトリに対応するトリガーが存在しない | ワークフローエディタでトリガーを設定 |
| E-47-03 | 署名検証失敗 | Webhookシークレットが不一致 | Webhookシークレットの再設定 |
| E-47-04 | コールサイン不一致 | コメントに設定されたコールサインが含まれない | 正しいコールサインを使用 |
| E-47-05 | 親コメント取得失敗 | GitHub APIからの親コメント取得に失敗 | API権限とレート制限を確認 |

### リトライ仕様

- Webhook処理自体にリトライ機構はなし
- GitHub側のWebhook再送機能に依存（最大3回、指数バックオフ）

## トランザクション仕様

- 各処理ステップは独立して実行
- タスク作成・生成処理はStorage操作として個別にコミット
- エラー発生時は該当トリガーの処理のみスキップし、他のトリガーは継続処理

## パフォーマンス要件

- Webhook応答: 10秒以内（GitHub推奨）
- ペイロード解決: 3秒以内（親コメント取得含む）
- 複数トリガー並列処理: Promise.allによる並列実行

## セキュリティ考慮事項

- Webhookシークレットによる署名検証必須
- GitHub App認証（Installation Token）による安全なAPI呼び出し
- プライベートキーの安全な管理（環境変数経由）
- コールサインによるアクセス制御（不正な起動を防止）

## 備考

- コメント本文（body）はコールサイン部分を除去した内容が出力される
- parentCommentBodyは親コメントの内容（会話のコンテキスト把握用）
- 親がない場合（新規スレッド開始）はparentCommentBodyは空文字列
- Discussionコメントへの返信はGraphQL APIを使用（REST APIでは対応不可）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、Discussionコメント作成イベントのペイロード定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | github.ts | `packages/trigger-registry/src/github.ts` | githubDiscussionCommentCreatedEventの定義（117-135行目）、ペイロードスキーマ |
| 1-2 | trigger.ts | `packages/protocol/src/node/operations/trigger.ts` | TriggerContentの型定義、トリガー状態の管理 |

**読解のコツ**: Discussion特有のフィールド（discussionUrl、commentId、parentCommentBody）に注目。IssueやPRとは異なる構造。

#### Step 2: エントリーポイントを理解する

Webhook受信からイベント処理への流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handle-webhook-v2.ts | `packages/giselle/src/github/handle-webhook-v2.ts` | handleGitHubWebhookV2関数（39-93行目）、サポートイベント一覧（36行目：discussion_comment.created） |

**主要処理フロー**:
1. **46-49行目**: GitHub認証情報の取得と検証
2. **50-75行目**: dispatch関数の定義（イベント処理のメインロジック）
3. **88-92行目**: handleWebhookでWebhook署名検証とイベントディスパッチ

#### Step 3: イベントハンドラーを理解する

Discussionコメント作成イベントの具体的な処理ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | handleDiscussionCommentCreated関数（438-461行目）、コールサイン照合ロジック |
| 3-2 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | processEvent関数（478-813行目）、タスク作成とコールバック処理 |

**主要処理フロー**:
- **441-446行目**: Webhookイベントとトリガー設定のイベント種別照合
- **448-451行目**: コメント存在確認
- **453行目**: parseCommandでコールサイン抽出
- **454-458行目**: conditions.callsignとの照合
- **460行目**: リアクションNodeIdとしてcomment.node_idを返す

#### Step 4: コールサイン解析を理解する

コメントからコールサインを抽出する処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utils.ts | `packages/giselle/src/github/utils.ts` | parseCommand関数、コールサイン形式の解析 |

#### Step 5: ペイロード解決を理解する

Discussion・コメントデータをワークフロー出力に変換する処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | trigger-utils.ts | `packages/giselle/src/github/trigger-utils.ts` | resolveDiscussionCommentCreatedTrigger関数（815-935行目）、ペイロード各フィールドの処理 |
| 5-2 | resolve-trigger.ts | `packages/giselle/src/triggers/resolve-trigger.ts` | resolveTrigger関数（15-193行目）、トリガー解決のメインロジック |

**主要処理フロー**:
- **818-833行目**: イベント種別、トリガー設定、コールサインの検証
- **837-845行目**: bodyフィールドの出力生成（command.content）
- **882-889行目**: commentIdフィールドの出力生成（comment.id.toString()）
- **891-927行目**: parentCommentBodyフィールドの出力生成（getDiscussionComment呼び出し）

### プログラム呼び出し階層図

```
handleGitHubWebhookV2 (handle-webhook-v2.ts)
    │
    ├─ handleWebhook (github-tool)
    │      └─ Webhook署名検証
    │
    └─ process (handle-webhook-v2.ts:125-192)
           │
           ├─ getGitHubRepositoryIntegrationIndex
           │      └─ リポジトリ連携情報取得
           │
           └─ processEvent (event-handlers.ts:478-813)
                  │
                  ├─ handleDiscussionCommentCreated (event-handlers.ts:438-461)
                  │      │
                  │      ├─ parseCommand (utils.ts)
                  │      │      └─ コールサイン抽出
                  │      │
                  │      └─ コールサイン照合
                  │
                  ├─ addReaction
                  │      └─ EYESリアクション追加
                  │
                  └─ createAndStartTask
                         │
                         └─ resolveTrigger (resolve-trigger.ts)
                                │
                                └─ resolveDiscussionCommentCreatedTrigger
                                       │
                                       └─ getDiscussionComment
                                              └─ 親コメント取得
```

### データフロー図

```
[入力]                           [処理]                              [出力]

GitHub Webhook ───────▶ handleGitHubWebhookV2 ───────▶ Giselle Task
(discussion_comment.        │                           │
 created)                   │                           │
      │                      │                           │
      ▼                      ▼                           ▼
┌─────────────┐      ┌─────────────────┐       ┌────────────────────┐
│discussion   │      │ processEvent    │       │ outputId: body     │
│ .number     │      │ handleDiscussion│       │ outputId: discussionNumber│
│ .title      │  ──▶ │ CommentCreated  │  ──▶ │ outputId: discussionTitle │
│ .body       │      │ parseCommand    │       │ outputId: discussionBody │
│comment.body │      │ getDiscussionComment│   │ outputId: parentCommentBody│
│parent_id    │      │                 │       │ outputId: commentId│
└─────────────┘      └─────────────────┘       └────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| github.ts | `packages/trigger-registry/src/github.ts` | ソース | GitHubイベント定義（ペイロードスキーマ） |
| handle-webhook-v2.ts | `packages/giselle/src/github/handle-webhook-v2.ts` | ソース | Webhook受信エントリーポイント |
| event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | ソース | イベントハンドラー群 |
| utils.ts | `packages/giselle/src/github/utils.ts` | ソース | コールサイン解析ユーティリティ |
| trigger-utils.ts | `packages/giselle/src/github/trigger-utils.ts` | ソース | トリガーペイロード解決 |
| resolve-trigger.ts | `packages/giselle/src/triggers/resolve-trigger.ts` | ソース | トリガー解決メインロジック |
| utils.ts | `packages/giselle/src/triggers/utils.ts` | ソース | トリガー設定の読み書き |
| trigger.ts | `packages/protocol/src/node/operations/trigger.ts` | ソース | トリガーノード型定義 |
| index.ts | `packages/trigger-registry/src/index.ts` | ソース | トリガーレジストリエクスポート |
