TL;DR(このページは何か・専門語ゼロ): これはすでに役目を終えた古い構成の記録です。かつて「だれかが判断のたたき台を投稿すると、AI が二段階で中身を確かめ、合格したものだけ自動で変更提案を作る」仕組みを、ある外部サービス上で組もうとした初期の設計メモを残しています。実際にはこの方式は作る前に取りやめになり、別の土台に作り直しました。いまから新しく開発する人がこのページを手本にする必要はなく、当時どう考えていたかをたどるための履歴として置いてあります。

⚠️ Status: Retired (2026-05-08, ADR-0019)

本設計書は ADR〔Architecture Decision Record=技術判断の記録〕-0019 (Decision Pipeline 刷新 — LangGraph TS + adr-kit 採用 / Dify〔ディファイ=当時使った外部のワークフロー構築サービス〕 退役) により退役。Phase 2a は未着手のまま終了し、後継として LangGraph〔ランググラフ=判断審査の流れを組む実装基盤〕 TS + Hono on Cloudflare Workers + LiteLLM Gateway 構成へ移行する。

  • 退役理由・代替案検討: docs/adr/0019-drp-migration.md
  • 後継アーキテクチャの実装手順: langgraph_migration/main_workspace_checklist.md
  • 退役対応表(既存 6 本の処遇まとめ): langgraph_migration/migration_overview.md

履歴として保持(Phase 1 投資の Triage v0.2 / Scoring v0.1 プロンプトは LangGraph node に手作業移植予定)。本ファイルの設計内容は LangGraph 構成に置き換わるため、新規開発の参照には使用しないこと。


Status: Retired (2026-05-08) Phase: 2a(GitHub 連携最小動作版) — 未着手のまま退役 前提: Phase 1 完了(Triage v0.2 / Scoring v0.1 確定) スコープ外: Gate〔ゲート=審査の関門。各段で起案を通すか差し戻すかを判定する〕 1 問診(Phase 2b)/ Gate 2 過去整合性(Phase 2c)/ Gate 3 並列レビュー(Phase 3)


1. ゴール

業務委託者が Dify に意思決定ドラフトを投稿すると、

  1. Gate 0(Triage〔トリアージ=そもそも記録に残す価値があるかの選別〕)で ADR 要否・Mode〔モード=起案の重要度区分。合格に必要な点数の高さが変わる〕 判定
  2. Gate 4(Scoring)で 50 点満点採点(40 点未満は差戻し)
  3. 合格起案のみ GitHub Actions に Webhook 送信
  4. GitHub 側で docs/adr/NNNN-slug.md を含むブランチ+ PR を自動作成
  5. オーナー(代表取締役)が PR レビュー → マージで Status: Accepted 確定

エンドツーエンドで動かすことが目標。Gate 1/2/3 はスキップし、Triage/Scoring の 2 ゲート構成のみで運用する。

2. アーキテクチャ全体図

[業務委託者]
    │ ブラウザ
    ▼
┌───────────────────────────────────────┐
│ Dify Workflow                         │
│  [開始] → user_input                  │
│     ↓                                 │
│  [Gate 0: Triage] → JSON              │
│     ├─ is_adr_worthy=false → 終了     │
│     ↓                                 │
│  [Gate 4: Scoring] → JSON             │
│     ├─ pass=false → 起案者に差戻し    │
│     ↓                                 │
│  [HTTP リクエスト]                    │
│     POST → GitHub repository_dispatch │
└───────────────────────────────────────┘
           │ HTTPS POST + GitHub App JWT
           ▼
┌───────────────────────────────────────┐
│ GitHub Actions                        │
│  .github/workflows/decision-pr.yml    │
│   on: repository_dispatch             │
│       types: [decision_submission]    │
│   ├─ payload schema 検証              │
│   ├─ 連番採番(ls docs/adr/)         │
│   ├─ ブランチ作成                     │
│   ├─ ADR ファイル作成                 │
│   ├─ コミット & push                  │
│   └─ PR 作成(タイトル/本文/ラベル)  │
└───────────────────────────────────────┘
           │
           ▼
[オーナー(代表取締役)]
   PR レビュー → マージ

3. 確定した設計判断

#論点決定根拠
1スコープ範囲C: 段階的(Phase 2a → 2b → 2c → Phase 3)Gate 1/2 の必要性は実運用で見極める
2認証方式GitHub App中長期運用での権限委譲・退職時継続性
3ADR 命名連番 + slug(NNN_slug.md、3桁 + アンダースコア)既存 ADR (001〜009) との一貫性を優先
4PR タイトル[ADR-NNN] 要旨 (Mode)一覧で Mode が即視認可能
5PR 本文起案入力原文 + Scoring サマリ + ADR リンクトレーサビリティ最優先
6ラベルadr / mode:* / status:* / auto-generated(4 系統)フィルタ性最大化
7起案者身元Dify 認証 + payload に名前同梱最シンプル、運用負荷小

4. Dify Webhook Payload Schema

4.1 スキーマ定義(v1.0)

{
  "schema_version": "1.0",
  "submitter": {
    "name": "string",                // 業務委託者の表示名(PR 本文に表示)
    "dify_user_id": "string"         // Dify 内部 user id(追跡用)
  },
  "user_input": "string",            // 起案テキスト原文(Markdown 可)
  "triage": {
    "is_adr_worthy": true,
    "mode": "Light | Standard | Critical",
    "title_summary": "string",       // 30 字以内(Triage v0.2 制約)
    "reason": "string"               // 60 字以内
  },
  "scoring": {
    "scores": {
      "1_problem_definition":   { "score": 0, "comment": "string" },  // 0-5
      "2_alternatives":         { "score": 0, "comment": "string" },
      "3_decision_criteria":    { "score": 0, "comment": "string" },
      "4_past_adr_consistency": { "score": 0, "comment": "string" },
      "5_impact_scope":         { "score": 0, "comment": "string" },
      "6_operational_pitfalls": { "score": 0, "comment": "string" },
      "7_rollback_strategy":    { "score": 0, "comment": "string" },
      "8_cost_estimate":        { "score": 0, "comment": "string" },
      "9_completion_criteria":  { "score": 0, "comment": "string" },
      "10_long_term_impact":    { "score": 0, "comment": "string" }
    },
    "total": 0,                      // 0-50(10 項目 × 5 点)
    "mode": "Light | Standard | Critical",
    "threshold": 40,                 // Light=35 / Standard=40 / Critical=45
    "pass": true,                    // total >= threshold
    "weakest_items": ["string"],
    "feedback_for_user": "string",
    "score_summary_md": "string"     // PR 本文に貼る整形済み Markdown
  },
  "adr_draft": {
    "slug": "string",                // snake_case、英数字 + アンダースコア、20 字以内
    "body_md": "string"              // ADR テンプレートに沿った本文
  },
  "submitted_at": "string"           // ISO 8601
}

4.2 schema_version の運用ルール

  • メジャー番号変更(1.0 → 2.0)= 破壊的変更。Actions 側で旧バージョン拒否
  • マイナー番号変更(1.0 → 1.1)= 後方互換あり。新フィールド追加など
  • Actions 側は schema_version の major 部分が一致しない payload を 400 で拒否

4.3 必須/オプションフィールド

フィールド必須欠落時の挙動
schema_version400 拒否
submitter.name400 拒否
triage.is_adr_worthy=truefalse の場合は Dify 側で Webhook 送信しない
scoring.pass=truefalse の場合は Dify 側で Webhook 送信しない
adr_draft.slug400 拒否(slug 採番ロジックは Dify 側責務)
submitted_at⚪️欠落時は Actions 受信時刻を記録

5. GitHub Actions ワークフロー

5.1 ファイル配置

.github/
└── workflows/
    └── decision-pipeline-pr.yml

5.2 トリガー設計

repository_dispatch を採用。Dify から event_type: "decision_submission" で呼び出す。

on:
  repository_dispatch:
    types: [decision_submission]

理由:

  • workflow_dispatch は inputs サイズ制限(10 入力まで)で payload を運べない
  • repository_dispatch は payload を client_payload として丸ごと受け取れる
  • Webhook URL: POST /repos/BizLinkPartners/bizlp-gas-accounting/dispatches

5.3 ステップ一覧

  1. Checkout main
  2. Payload 検証schema_version major / 必須フィールド / pass=true の三段チェック
  3. 連番採番ls docs/adr/ | grep -E '^[0-9]{3}_' | sort -r | head -1 で次番号算出(3桁ゼロパディング)
  4. ブランチ作成claude/decision-NNN-slug
  5. ADR ファイル作成docs/adr/NNN_slug.md に payload を流し込み
  6. コミット & push — Bot identity で(GitHub App の bot[bot] ユーザ)
  7. PR 作成 — タイトル/本文/ラベル/Reviewer を一括設定
  8. 失敗時の通知 — Slack/Discord webhook で #dev-alerts に通知(オプション、Phase 2a 末で検討)

5.4 連番採番の同時実行衝突対策

  • Phase 2a: 業務委託者は 1 人ずつ起案する運用とし、衝突対策はしない
  • Phase 2b 以降: optimistic concurrency で実装(push 失敗時に番号取り直してリトライ)
    • 候補1: GitHub Actions の concurrency group で直列化
    • 候補2: ADR ファイル名にハッシュサフィックスを付与
    • 設計判断は Phase 2b で行う

6. GitHub App セットアップ仕様

6.1 App 名

bizlp-decision-pipeline-bot

6.2 権限スコープ(最小権限の原則)

Permissionレベル用途
ContentsRead & Writeブランチ作成 + ADR ファイル作成 + コミット
Pull requestsWritePR 作成 + ラベル付与 + Reviewer 指定
MetadataReadデフォルト(必須)
Issues不要
Workflows不要(自分のワークフロー定義は触らない)

6.3 インストール先

BizLinkPartners/bizlp-gas-accounting のみ。Org 全体には install しない。

6.4 認証フロー

Dify ← App ID + Private Key + Installation ID
  ↓ JWT 生成(10 分有効)
  ↓ POST /app/installations/{id}/access_tokens
  ↓ Installation Access Token (1 時間有効)
  ↓ POST /repos/.../dispatches
  ↓
GitHub

Dify 側で App Private Key を扱う必要があるため、

  • Phase 2a 暫定: Dify の HTTP リクエストノードで JWT を生成(Dify が JWT 署名できるか要検証)
  • Phase 2a 暫定の代替案: Cloudflare Worker を中継 — Dify → Worker(JWT 生成 → GitHub 認証)→ repository_dispatch

推奨は Cloudflare Worker 中継。理由:

  • Dify でプライベートキーを保持・署名生成する責務を持たせるとセキュリティ要件が増える
  • Worker なら GitHub App の private key を Cloudflare の secret に格納
  • Worker URL に Dify からの payload を HMAC で検証して中継できる

ただし Phase 2a の MVP 性を重視するなら、PAT (Personal Access Token) で先に動かして検証 → Phase 2a 完了前に GitHub App + Worker に置き換える、という二段構えも可。

6.5 Phase 2a の認証実装方針(暫定)

ステップ認証方式期間
Step 1: 動作検証PAT(オーナー個人)1〜2 週間
Step 2: Worker 中継 + GitHub AppCloudflare Worker + GitHub AppStep 1 動作確認後

Step 2 完了をもって Phase 2a 完了とする。

7. ADR テンプレート設計

7.1 ファイル配置

docs/
└── adr/
    ├── README.md          # ADR 運用ガイド(新規)
    ├── _template.md       # テンプレート(新規)
    ├── 001_ssot_invoice.md       # 既存
    ├── ...
    ├── 009_separation_strategy.md # 既存
    └── 010_xxx.md                 # Phase 2a 以降に Decision Pipeline で生成

7.2 テンプレート構造

# ADR-NNN: タイトル要旨

- **Status**: Proposed | Accepted | Superseded by ADR-XXX | Rejected
- **Mode**: Light | Standard | Critical
- **起案者**: 名前
- **起案日**: YYYY-MM-DD
- **承認日**: YYYY-MM-DD(Accepted 時のみ)

## Context(背景)

何を解決しようとしているか。なぜ今この決定が必要か。

## Decision(決定)

採用する方針を 1 段落で。

## Alternatives Considered(検討した代替案)

- 案 A: ...(不採用理由: ...)
- 案 B: ...(不採用理由: ...)

## Consequences(影響)

- 正の影響: ...
- 負の影響: ...
- リスク: ...

## Rollback Plan(撤退条件)

どうなったら元に戻すか。

## References

- 関連 ADR: ADR-XXXX
- 関連 PR/Issue: #NNN

Light Mode の場合は Alternatives Considered と Rollback Plan を省略可とする(Triage v0.2 の Light 定義に準拠)。

7.3 docs/adr/README.md の役割

  • ADR 運用ガイド(命名規則 / Status 遷移 / 連番採番)
  • ADR インデックス(自動生成 or 手動メンテ)
  • Phase 2a 時点では手動メンテ。自動生成は Phase 2c 以降の課題

8. PR タイトル / 本文 / ラベルの仕様

8.1 タイトル

[ADR-NNN] {triage.title_summary} ({triage.mode})

例: [ADR-0010] 領収書 OCR を Claude へ移行 (Standard)

8.2 本文テンプレート

> Decision Pipeline (Dify) 経由で自動生成された PR です。

## 起案者
**{submitter.name}** (Dify: {submitter.dify_user_id})
{submitted_at}

## Triage
- ADR 要否: ✅ 要
- Mode: {triage.mode}
- 理由: {triage.reason}

## Scoring
{scoring.score_summary_md}

## ADR 本文
[`docs/adr/{NNN}_{slug}.md`](../blob/{branch}/docs/adr/{NNN}_{slug}.md) を参照

## 起案入力原文

<details><summary>展開</summary>

{user_input}

</details>

---

このPRをマージすると ADR が `Status: Accepted` として確定します。
差し戻す場合は本 PR を Close してください(`status:rejected` ラベルが自動付与)。

8.3 ラベル設計

ラベル付与タイミング説明
adrPR 作成時ADR 関連 PR の総称タグ
mode:light / mode:standard / mode:criticalPR 作成時Triage の mode に対応
status:proposedPR 作成時デフォルト
status:acceptedPR マージ時GitHub Actions の on: pull_request で自動付け替え
status:rejectedPR Close 時GitHub Actions で自動付け替え
status:superseded後続 ADR の supersedes フィールド経由Phase 2c で実装
auto-generatedPR 作成時人手 PR と区別

8.4 Reviewer 指定

team-reviewers ではなく reviewers で個人指定する。

Reviewers: [t-saitoh-bizlp]

CODEOWNERS の使用は Phase 2b で再検討(業務委託者の範囲が広がった場合)。

9. 起案者の身元保証

9.1 Dify 認証

業務委託者は Dify アカウントでログイン(Dify の SSO 機能で Google 認証を採用)。

9.2 Payload への組み込み

Dify Workflow の開始ノードで、以下の組み込み変数を使用:

{{user.name}}    → submitter.name
{{user.id}}      → submitter.dify_user_id

これらを Webhook payload に同梱して GitHub に送る。

9.3 PR 上の表示

PR 本文の「起案者」セクションに submitter.name をそのまま表示。Phase 2a では GitHub Account とのマッピングは行わない(Phase 2b で検討)。

10. 失敗ケースと運用設計

10.1 Dify 側の失敗

ケース挙動
LLM API レート制限Dify の自動リトライに任せる(最大 3 回)
GitHub Webhook 送信失敗Dify ログに記録、起案者に「再送信してください」を表示
Triage で is_adr_worthy=falseフィードバック表示して終了(Webhook 送信しない)
Scoring で pass=falseスコア詳細をフィードバック表示して終了

10.2 GitHub Actions 側の失敗

ケース挙動
Payload schema 不正core.setFailed でジョブ失敗、起案者には通知されない(運用で検出)
連番採番衝突Phase 2a では発生しない前提(運用で 1 人ずつ起案)
Slug 重複Actions ジョブ失敗、Slack 通知(Phase 2a 末)
ブランチ作成失敗Actions ジョブ失敗
PR 作成失敗ブランチは作成されているが PR がない状態に。手動で PR を立てる

10.3 失敗時のオブザーバビリティ

  • GitHub Actions ジョブ失敗ログを Slack #dev-alerts チャンネルに送る(Phase 2a 末で実装)
  • Dify ログは Dify 標準のログビューワで確認

11. Phase 2a 完了基準

以下のすべてを満たした時点で Phase 2a 完了とする:

  1. ✅ Dify Workflow に Triage / Scoring / Webhook 送信ノードが配線済み
  2. ✅ GitHub App bizlp-decision-pipeline-bot が作成・install 済み
  3. ✅ Cloudflare Worker(または同等の中継)が動作
  4. .github/workflows/decision-pipeline-pr.yml が main にマージ済み
  5. docs/adr/README.md docs/adr/_template.md が main に配置済み
  6. ✅ TC-07 入力(高品質起案)を Dify に流すと、自動で PR が立つ
  7. ✅ TC-06 入力(雑なドラフト)を流すと、Webhook 送信されず Dify 側で差戻し表示される
  8. ✅ Phase 2a の operator_guide.md が公開され、業務委託者にアカウント発行可能な状態

12. Phase 2a 実装タスク一覧

実装担当: main スペース(GAS 実装担当)/ ドキュメント担当: sub スペース。

#タスク担当依存
1docs/adr/README.md docs/adr/_template.md 作成sub
2docs/_internal/05_how-to/operator_guide.md 作成sub
3docs/_internal/decision_pipeline/dify_workflow_spec.md 作成sub
4prompts/06_adr_body.md prompts/07_slug.md 新規プロンプト作成sub3
5GitHub App bizlp-decision-pipeline-bot 作成・installオーナー
6Cloudflare Worker 実装(HMAC 検証 + JWT 生成 + repository_dispatch 中継)main5
7.github/workflows/decision-pipeline-pr.yml 実装main1, 6
8Dify Workflow に N2〜N13 ノード追加(仕様: dify_workflow_spec.md)オーナー4, 6
9TC-07 / TC-06 / TC-01 でエンドツーエンド動作確認オーナー1〜8
10Phase 2a 振り返り / Phase 2b 着手判定オーナー9

完了済みタスクは ✅ 列でマーク。タスク #4 は本 PR とは別途、追加作業が必要。

13. 残課題(Phase 2a → 2b 候補)

  • 並行起案時の連番衝突対策
  • ADR インデックス自動生成
  • Slack/Discord 通知の実装
  • Dify から GitHub Account へのマッピング
  • CODEOWNERS 導入
  • Status: Superseded の自動付与(後続 ADR が supersedes フィールドを持つ場合)

変更履歴

日時変更内容
2026-05-07初版作成(Phase 1 完了直後の設計セッションで決定事項を確定)
2026-05-07ADR 命名を NNN_slug.md に統一(既存規則に整合)
2026-05-07Scoring schema を 10 項目 × 5 点に修正(実プロンプトとの不整合解消)/§12 にタスク #3, #4 追加