TL;DR(このノードは何をする・専門語ゼロ): これまでに作られた決定記録ファイルの中から一番大きい番号を見つけ、それに 1 を足して新しい番号を割り当てるノードです。本文中の番号の仮置き部分を、確定した番号で置き換えます。AI は使わず、ファイル一覧を読んで番号を数えるだけの単純な処理です。複数の起案が同時に走っても番号が重ならないよう、別の仕組みで処理を 1 件ずつ順番に流します。

実装: drp/src/nodes/numbering.ts プロンプト: なし (LLM 呼出なし) テスト: なし 基盤 ADR: ADR-0023 (4 桁ハイフン形式)


1. 役割と位置づけ

docs/adr/ 配下の既存 ADR から 最大番号を取得し +1 して採番〔Numbering=ADR 番号の自動割り当て〕、その番号で adrBody 内の ADR-??? プレースホルダを ADR-NNNN に置換する純データ処理ノード。

  • 解決する課題: ADR 番号の重複・抜け番防止。body_generation 時点では番号未確定のため、後段で確定値を埋め込む二段階方式。
  • 設計思想: 差戻しなし / LLM 呼出なし。GitHub Contents API でファイル一覧を取得し正規表現で番号抽出するだけ。
  • 採番排他制御〔concurrency=同時実行の直列化〕: ノード内では排他制御なし。GitHub Actions 側で concurrency: decision-pipeline (cancel-in-progress: false、Pipeline 全体を直列化) で排他するため、Pipeline が並列起案されても重複しない設計 (.github/workflows/drp-trigger.yml)。

2. フロー図

flowchart LR
    SL[slug] --> N[numbering]
    N -->|GET /contents/docs/adr| GH[(GitHub API)]
    GH --> N
    N --> W[webhook]

3. トリガー条件

無条件で slug の後に実行。


4. 入力 (State)

State フィールド用途
adrBodyADR-??? プレースホルダを含む本文

外部入力:

  • GET /repos/{owner}/{repo}/contents/docs/adr (GitHub REST) でファイル一覧

5. 処理ロジック

1. fetchNextAdrNumber(env):
   a. GET /contents/docs/adr → ファイル名配列
   b. 各 name を /^(\d{4})-/ (新) または /^(\d{3})_/ (旧) でマッチ
   c. 全マッチ番号の最大値を max とする
   d. return max + 1
2. padded = String(adrNumber).padStart(4, '0')   // "0042"
3. adrBody.replace(/ADR-\?\?\?/g, `ADR-${padded}`)
4. { adrNumber, adrBody } を state に返す

正規表現の互換性: ADR-0023 で 4 桁ハイフン形式 (0042-slug.md) に統一済。旧 3 桁アンダースコア形式 (042_slug.md) も互換のため検出するが、改名完了済のため通常は残らない。


6. LLM 設定

なし (LLM 呼出なし)。


7. 副作用

  • GET /repos/{owner}/{repo}/contents/docs/adr — ファイル一覧取得
  • 認証: env.GITHUB_PAT / User-Agent: decision-pipeline/1.0
  • 読み取り専用。書き込み・PR 作成は webhook ノードが担当

8. 出力 (State)

{
  adrNumber: number,   // 例: 42
  adrBody: string,     // ADR-??? → ADR-0042 置換済み
}

9. 分岐 (次ノード)

.addEdge('numbering', 'webhook')        // buildGraphWithWebhook
.addEdge('numbering', END)              // buildGraph (チャット型・webhook なし)

buildGraph (/chat/run) では webhook を持たず END。PR 作成はユーザー操作で別途実行する設計。


10. エラー時の挙動

  • GitHub API 失敗: GitHub API docs/adr: 503 {body} で例外スロー → グラフ全体失敗
  • 空ディレクトリ: max=0 → adrNumber=1。実環境では既に 50+ ADR があるため発生しない
  • ADR-??? プレースホルダ欠落: body_generation が ADR-??? を出力しなかった場合、replace で何も置換されず ADR 番号がメタデータに反映されない (要 body_generation 側の品質保証)

11. 既知の弱点・運用注意

  • 同時起案時の race condition〔競合状態=同時実行で結果が乱れる状態〕: Pipeline 自体は排他制御を持たない。複数起案が同時に実行されると同じ adrNumber が採番されるリスクあり。
    • 緩和策: GitHub Actions ワークフロー側の concurrency: decision-pipeline (cancel-in-progress: false) で pipeline 全体を直列化 → 実質的に PR 作成が直列化される (numbering 自体は並列だが、PR 作成順で番号が決まる) ※運用実績上の race 発生報告なし
  • GitHub API レート制限: PAT で 5000 req/hour。numbering + webhook で 1 起案あたり 4〜6 リクエスト消費。1 日 100 起案でも余裕。
  • 新形式 / 旧形式の混在検知: 両形式とも \d{4} または \d{3} で数値抽出するため、4 桁形式 1000 番台 (例: ADR-0150) と 3 桁形式の旧 ADR (例: 050_xxx) が共存しても max は正しく取れる。ただし旧形式は改名完了済のため検出されない想定。
  • 手動採番との競合: GitHub 上で人間が手動で 0043-xxx.md を追加してから Pipeline が走ると、Pipeline は最大 0043 → 採番 0044 で問題なく動く (実害なし)。

12. テストケース

なし。GitHub API モックが必要 + 純データ処理のため統合テスト (本番採番) で検証。

代替: 番号衝突時の挙動は GitHub Actions concurrency 設定で確認。


13. 過去の設計判断ログ

日時変更経緯
2026-05-11Phase 2a' 初期実装
ADR-0023 採択3 桁→4 桁形式統一正規表現 /^(\d{3,4})/ 両対応で旧 ADR との互換性確保
(設計時)排他制御を Pipeline ではなく GitHub Actions 側に委譲Cloudflare WorkersDurable Objects を使わない方針 (KISS)
(設計時)LLM を使わず純データ処理に採番ロジックに LLM 判断不要 (コスト・レイテンシ削減)

14. 関連リンク

  • 前ノード: 09_slug.md
  • 次ノード: 11_webhook.md
  • GitHub Actions ワークフロー: .github/workflows/drp-trigger.yml (concurrency: decision-pipeline / cancel-in-progress: false)
  • 関連 ADR: ADR-0023