TL;DR(このノードは何をする・専門語ゼロ): Socratic が「採用案の弱点は?」「代替案の不採用理由は妥当か?」のような問いを投げる際に使う観点リストの中から、起案ごとに 3 つの観点を選ぶ補助モジュール。同じ起案には毎回同じ 3 観点を返す決定性を持ちつつ、似たヘッダ構造の起案群でシード空間がぶつかっても 3 観点全部が連動して固着しないよう、軸ごとに独立シードで選ぶ。AI は使わず、文字列ハッシュと PRNG の純粋関数だけで決める。

実装: drp/src/nodes/perspective_selector.ts 呼び出し元: drp/src/nodes/socratic.ts (3 観点を pick して socratic プロンプトへ注入) プロンプト: なし (LLM 呼出なし) テスト: drp/test/perspective_selector.test.ts (決定性回帰 + カバレッジ分布) 基盤 ADR: ADR-0109 (§5.2 #6 シード衝突による永続的視点固着の緩和) / ADR-0102 (Light cap / Gate 1 観点選択)


1. 役割と位置づけ

Socratic / Cross-Validation で使う観点リスト CONSTITUTION_PERSPECTIVES (現行 22 項目) から、起案ごとに重複なしで 3 観点を選ぶ。

  • 解決する課題: 観点の固定だけでは「同じ起案には同じ問い」が出ず、Cross-Validation の goalpost が観測しづらかった。決定性を持たせて再現性を確保しつつ、シード衝突 (類似ヘッダ構造の ADR 群が同じ 3 観点に固着する) を緩和する。
  • 設計思想: graph には独立ノードとして addNode されない補助モジュールsocratic.ts 内から selectRandomPerspectives(3, deterministic ? userInput : undefined) の形で呼ばれる pure 関数。langchain 非依存で workerd プールから単体テスト可能。
  • 由来: ADR-0109 Part 3 (決定性 PRNG 導入) + §5.2 #6 緩和 (a) 軸インデックス XOR 混合。

2. フロー図

flowchart LR
    SO[socratic] -->|userInput| PS[selectRandomPerspectives]
    PS -->|3 indices + 3 perspectives| SO
    SO --> LLM[Gate 1 LLM 呼出]

3. トリガー条件

graph の独立ノードではないため graph 上の edge 条件はない。socratic.ts:204 で以下のとき呼ばれる:

呼び出し条件挙動
SOCRATIC_DETERMINISTIC=true (本番既定)selectRandomPerspectives(3, userInput) で決定性 pick
SOCRATIC_DETERMINISTIC=false (旧経路 / 開発時)selectRandomPerspectives(3, undefined)Math.random 単一ストリーム

4. 入力 (引数)

引数用途
countnumberpick する観点数。min(count, 22) でクリップ
seedStrstring | undefinedシード文字列 (本番は起案者の userInput を使う)。undefined なら Math.random 単一ストリーム

外部入力なし。


5. 処理ロジック

1. available = CONSTITUTION_PERSPECTIVES のインデックス配列 [0..21] のコピー
2. n = min(count, 22)
3. seedStr=undefined (旧経路):
   - n 回ループで Math.random から pick → available から splice
4. seedStr!=undefined (決定性経路):
   - base = hashSeed_(seedStr)   // FNV-1a 32bit
   - 各 pick i で rng = mulberry32_((base ^ AXIS_SALTS[i % 5]) >>> 0)
   - pick = floor(rng() * available.length) → available から splice
5. indices と CONSTITUTION_PERSPECTIVES[indices[*]] を返す

AXIS_SALTS (5 個・golden-ratio / SplitMix64 系の撹拌定数):

  • 0x9e3779b9 / 0x7f4a7c15 / 0x94d049bb / 0xbf58476d / 0x2545f491

各 pick を独立シード (base ^ AXIS_SALTS[i]) の PRNG で行うため、類似シード (類似ヘッダ構造の ADR 群) がシード空間でクラスタリングしても pick 系列が相関しない。単一 PRNG ストリームでは base シードの近接が 3 観点全部の近接に直結するが、salt 混合により各軸の選択が独立化する。

ADR の緩和 (a) は「ADR カテゴリタグ・軸インデックス」の XOR を挙げるが、ADR カテゴリの taxonomy が現状未定義 (state にカテゴリフィールドなし) のため、実装可能な軸インデックス混合を先行導入。カテゴリタグ混合は Review After (2026-12-02) で再評価。


6. LLM 設定

LLM 不要 (純粋関数)。FNV-1a と mulberry32 の数値演算だけで決まる。同一 seedStr → 同一 3 観点 (Part 3 決定性の回帰テストで固定)。


7. 副作用

なし。引数のみで結果が決まる pure 関数。


8. 出力

{
  perspectives: string[],   // CONSTITUTION_PERSPECTIVES から重複なしで pick した文字列 (count 個)
  indices: number[],        // pick した index (audit / 分布可視化に使う)
}

socratic.tsperspectives を Gate 1 LLM プロンプトへ注入し、indicestelemetry へ載せる。


9. 分岐 (次の処理)

graph の独立ノードではないため graph edge を持たない。socratic.ts は本モジュールの戻り値を Gate 1 LLM 呼出に渡すだけ。


10. エラー時の挙動

エラー無し (deterministic)

  • count > 22 でも n = min(count, 22) で safe
  • seedStr が空文字列でも hashSeed_2166136261 (FNV-1a offset basis) を返し有効
  • 数値演算のみで例外を投げる経路がない

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

  • 意味的多様性は保証されない: 22 観点の中身は人間が決めた集合で、似た観点 (例: 「コスト試算は最悪ケースか」と「最悪のケースを過小評価していないか」) が同じ起案で同時 pick される可能性がある。CI のカバレッジ分布テストで全軸の出現を検証するが、意味的近接は無視。
  • AXIS_SALTS の周期: 5 個で循環 (i % 5) するため、count>5 では同じ salt が再利用される。現行は count=3 固定で問題なし。count を増やすときは salt 数も増やす。
  • カテゴリ混合は未実装: ADR が示す緩和 (a) のうち「カテゴリタグ XOR」は ADR カテゴリ taxonomy が未定義のため未着手。観測で固着パターンが残るかを 2026-12-02 まで観測し、必要なら追加実装。
  • SOCRATIC_DETERMINISTIC=false 経路の温存: 開発時の挙動検証用に Math.random 経路を残している。本番は常に true 固定。
  • 観点リスト改訂時の互換: CONSTITUTION_PERSPECTIVES 配列順序を変えると同一 seedStr でも違う 3 観点が pick される (= 過去 run との比較が壊れる)。末尾追加 で互換性維持。

12. テストケース

drp/test/perspective_selector.test.ts (vitest workerd プール):

観点期待
同一 seedStr → 同一 3 観点 (Part 3 決定性の回帰)indices と perspectives が一致
異なる seedStr → 異なる 3 観点出現分布のばらつき
合成コーパス (一様 + クラスタ) で全軸の出現22 軸すべてが出現する (カバレッジ分布テスト)
count > 22min(22, count) でクリップ
seedStr=undefinedMath.random 経路で重複なし
hashSeed_FNV-1a 32bit の既知ベクタ

CI ログに分布テーブルを出力 (ADR-0109 §5.2 #6 緩和 (b)(c))。


13. 過去の設計判断ログ

日時変更経緯
ADR-0109 Part 3Math.random → 決定性 PRNG (FNV-1a + mulberry32)sub の goalpost 観測再現性を確保
ADR-0109 §5.2 #6 緩和 (a)軸インデックス XOR salt 混合類似シード起案群で 3 観点固着する盲点に対処
ADR-0109 §5.2 #6 緩和 (b)(c)カバレッジ分布テスト + CI 分布表全軸出現を機械的に検証
Review After 2026-12-02カテゴリタグ混合の再評価taxonomy が定義されたら追加実装を検討

14. 関連リンク

  • 呼び出し元: 02_socratic.md (socratic.ts:204 で 3 観点を pick)
  • 関連 ADR:
    • ADR-0109 — Part 3 決定性 + §5.2 #6 シード衝突緩和
    • ADR-0102 — Light cap と Gate 1 観点選択の併用
  • 観点リスト SSoT: drp/src/nodes/perspective_selector.tsCONSTITUTION_PERSPECTIVES