調査: 2026-06-08、OpenAI o3-deep-research / Gemini deep-research-preview / Claude opus を同一プロンプトで実行。生結果は docs/research/rq-100-result-{openai,gemini,claude}.md目的: markdown + frontmatter の ADR リポジトリ (~130 本) で、機械が辿れる ADR 依存グラフ — 型付き辺・双方向整合・supersession ライフサイクル・dangling/orphan 検出 — をどう表現・維持し、下流ツールが「決定 X は実在し、懸念 Y を所有しているか」を確実に引けるようにするか。 背景: 現状の社内表現は Supersedes: ADR-NNNN メタ欄 (supersession のみ) + 参照節の prose (「ADR-0125 — complements」「ADR-0118 — inherits-from」「ADR-β — parallel」)。未検証・片方向あり・retired ADR で dangling し得る。このグラフは RQ-098 の scope-aware critic が「re-home 先 (target_id)」を解決する前提であり、RQ-097 (1 ADR=1 決定 / typed edges 推奨) とも連続する。社内では ADR-0107 が同型の「ADR 索引 + 依存グラフ整備」を Proposed 済。


Executive Summary(横断 key findings)

3モデルが独立して合意した点を優先して 5 つ。

  1. 既存 ADR 規約は「完全な型付きグラフ」を持たない。実質エンコードされている辺は supersession だけで、しかも記法が一貫しない。(3モデル合意) Nygard の status enum (Proposed/Accepted/Deprecated/Superseded by ADR-NNNN) は supersession を status 欄に書くだけ。MADR は逆に進み、4.0 で ## Links 節を ## More Information に改名し bullet を free text に緩めた(人間向きだが lint には敵対的)。Y-Statements は関係語彙を一切持たない。結論: 自前で小さな型付き辺スキーマを定義するしかない。

  2. 記述場所は YAML frontmatter が唯一の現実解。SSoT は frontmatter、下流向けには生成 JSON アーティファクトを別に吐く。(3モデル合意) 3モデルとも frontmatter を第一候補に挙げた(parse 容易・1 箇所・JSON Schema 検証可・diff がきれい)。body 節は読みやすいが drift が常態、sidecar index は単一マージ衝突点になり ADR から乖離する。Claude/OpenAI とも「frontmatter を真実とし、人間向け Related 節や _graph.json生成物にする」を推奨。

  3. 「1 ユーザ操作で双方向 2 辺を書く」が型付き辺の手本。adr-toolsadr link SOURCE LINK TARGET REVERSE-LINK が古典系で唯一の本物の双方向典拠。(Claude が最も明示、OpenAI/Gemini も同型を引用) 作成時に両端を書き、linter で対称性を検証する Option 3(両端宣言 + linter 強制 + 足場スクリプトが両側を書く)が合意推奨。自分が既に踏んだ failure mode(dangling・片方向 supersede・related の欠落)は、両端宣言を必須にして初めて検出可能という論理が決め手(Claude)。

  4. 必須 lint は小さく既知。target 存在・双方向対称・supersession×status 整合・supersede 鎖の非循環・status 別必須辺。クロスファイル検証だけ自前 (~200 行)、per-file schema と link 存在は既製ツール。(3モデル合意) per-file は ajv-cli/check-jsonschema、markdown link 存在は markdown-link-check、style は markdownlint。クロスファイルの不変量(双方向・supersede 整合・循環)は既製ツールに無いので小さな自前スクリプトを書く(Claude/OpenAI 一致、Gemini は EventCatalog Linter / adr-log 等の ecosystem を列挙)。

  5. ~130 本の prose からの bootstrap は「決定論抽出 + LLM 補完 + 人間 PR レビュー + linter を ground truth」とする一発移行で実用可能。(3モデル合意) 既存 Supersedes: 欄と参照節の verb を決定論スクリプトで型付き辺へマップし、残った prose を LLM が候補辺に起こし、PR 単位で人間レビュー。linter (R1–R6) が最終真実なので、抽出ミスは双方向・status・参照整合のいずれかで即 fail する。社内語彙(complements / inherits-from / parallel)は小さな taxonomy に綺麗に乗る。


3モデル横断の合意 / 相違(設問別)

設問1 — 辺の型タクソノミー

合意点(3モデル)

  • supersedes が唯一普遍的に実装される辺。それ以外(depends_on / refines / relates / conflicts / follow-up)は規約が名付けるだけで実装は informal。
  • 型は小さい閉じた語彙 + catch-all に絞るべき。各型が実際の運用ユースケースに対応する時だけ追加する(OpenAI「relation type ごとに real use-case を要求」、Claude「closed vocabulary + relates_to」)。
  • 方向性の区別が必須: supersedes は対象を retire するが、amends/refines は対象を accepted のまま残す(Claude が表で明示、Gemini も supersedes(temporal) と refines/complements(hierarchical) を分離)。

相違・固有の指摘

  • OpenAI: 6 型(supersedes/superseded_by, depends_on, refines, related/complements, conflicts_with(任意), delegates_to/follow_up)。conflicts は「nice-to-have」で多くのチームは不要と明言。delegates_to は「将来 ADR への先送り」を表し、未実現の dangling future reference を linter が警告できると提案。
  • Gemini: より広い 7 型でトレーサビリティ辺を追加 — affects(下流の blast radius), implements(コード/IaC/Jira へ), verifies(テスト/fitness function へ)。ADR を「能動的ガバナンス機構」に格上げする立場。ISO/IEC 25010 の品質特性を architecture_drivers に構造化し、辺と合わせて「Security を Performance に犠牲にした決定群」を SPARQL で横断照会する将来像を描く。
  • Claude: 8 型を inverse・semantics・source への lifecycle 効果まで含む表で定義(下記推奨スキーマの骨格)。amends/refines/follows_up_on を supersedes と明確に分け、社内 prose 語彙への写像(complements→relates_to, inherits-from→refines, parallel→relates_to, follow-up spike→follows_up_on)まで提示。applies_to/owns_concerns を「critic の所有判定用」に切り出した点が固有。

設問2 — 機械可読な記述場所

合意点(3モデル)

  • YAML frontmatter を SSoT にする(3モデル一致)。triple-dash で本文と分離、全ツールが parse 可、JSON Schema 検証可、diff が行単位。
  • body 節は読みやすいが free-text drift が常態(Claude が Log4brains の slug bug を反例に引用)。sidecar index は単一マージ衝突点・ADR から乖離・発見性低下で SSoT 不適(OpenAI/Claude 一致。ただし生成物としての sidecar/_graph.json は推奨)。
  • 双方向辺は両端宣言を基本とし、有向辺(depends_on 等)は子側だけ宣言してツールで逆引きする。

相違・固有の指摘

  • OpenAI: supersedes は「新 ADR 側を authoritative」にして linter が旧側の status/back-link を検証する手も提示(adr-tools の自動書換に整合)。frontmatter から人間向け Related 節を生成して二重管理を避ける CI/pre-commit を推奨。
  • Claude: 3 案(A frontmatter / B body 節 / C sidecar)を明記しA を SSoT + 生成 decisions/_graph.json。両端宣言の決定的論拠を「自分が踏んだ failure mode は両端必須でのみ検出可能」と接地。具体 frontmatter 例に applies_to(type/id) と owns_concernsrollback を含め、critic 照会まで一気通貫。
  • Gemini: frontmatter を「pragmatic standard」とし、エンタープライズ横断では JSON-LD / Turtle (RDF) へ昇格して @context で語彙を URI に固定し triple store (Neo4j/AllegroGraph) で SPARQL する道を別途提示。~130 本・solo の本件には過剰だが、将来のマルチリポ統合時の選択肢として記録に値する(Claude も「graph DB/MCP は 130 本では overkill、consumption 層でのみ可」と同旨)。

設問3 — 整合 lint

合意点(3モデル)

  • 必須チェックの中核は共通: (a) dangling 参照(target 不在)、(b) 双方向対称(A.supersedes B ⇔ B.superseded_by A、related の相互)、(c) supersession×status 整合(superseded なら superseded_by 非空・対象 status=superseded)、(d) supersede 鎖の非循環、(e) status 別の必須辺
  • per-file の schema/style と link 存在は既製ツールで賄い、クロスファイル不変量だけ自前で書く。
  • CI(GitHub Actions on PR + push)+ pre-commit で多層に回す。

相違・固有の指摘

  • OpenAI: orphan(どこからも参照されない ADR)は低優先で、初期 ADR は incoming 0 が正常なので「dangling > orphan」と明言。transitive supersede(C→B→A の二段陳腐化)を warning でレポート。depends_on 先が superseded/proposed なら警告。
  • Claude: R1–R12 の severity 付きルール表を提示し、自前グラフ linter は ~200 行と見積。EventCatalog Linter(Zod schema 検証 + reference validation = R1 の実在実装)を最も近い手本に挙げ、Structured MADR は per-file JSON Schema 止まりでクロスファイル不変量を表現できないと指摘。transitive supersession 解決を critic の current_form(id) として superseded_by 鎖を前進歩行し、分岐/deprecated 終端なら no-owner を返す設計を明示。
  • Gemini: linter ecosystem(adr-log/adr-check/linkml-lint)と双方向自動同期(PR の supersedes 宣言を CI が旧 ADR の frontmatter に reciprocal superseded_by を注入)を強調。AI critic(mcp-adr-analysis-server)で EC-ADR / ISO 25010 に対する品質採点、AST で実装ドリフト検出という AI 拡張像。

設問4 — ライフサイクルと bootstrap

合意点(3モデル)

  • status は Proposed → Accepted → (Deprecated | Superseded) が最小 4 状態。Accepted は実質 immutable。Rejected は「却下した道」の記録として残す。
  • Accepted→Superseded 時に「後継 ADR の PR が」supersedes:[self] を足し、旧 ADR の status を superseded に変え back-edge を書く(旧 ADR を触るのは後継が強制する時だけ → 保守を有界化)。
  • bootstrap は一発移行が最も簡単。決定論抽出(既存 Supersedes 欄・status 行・References bullet)→ verb を taxonomy へ写像 → 両端を同一 commit で書く。

相違・固有の指摘

  • OpenAI: proposal 段階の supersedes は「提案上の supersession」として旧 ADR を accepted のまま許容し、後継の accept 時に旧側を flip。reverted は「revert 専用の新 ADR が旧を supersede」で同一機構に乗せる。retired は status: Retired + superseder なしを linter が許容。7 フェーズ移行計画(解析→schema→自動挿入→手動 cleanup→linter report-only→旧節除去→ドキュメント化)。
  • Claude: status DAG を図示(Superseded は terminal で superseded_by 必須)。6 ステップ bootstrap(schema freeze + advisory → 決定論抽出 → LLM 補完 → linter を波状に解消 → blocking 化 + pre-commit → new.sh 足場で持続)。「LLM 抽出が許容できるのは PR で人間レビューされ linter が ground truth だから」と明言。./decisions/new.sh が宣言した全辺の両側を書くのが adr-tools の実証パターンの再現。
  • Gemini: legacy prose からの bootstrap を NLP/関係抽出(rule-based → LSTM/Transformer、syntactic search by example)として一般論で展開。抽出辺を中間ノードで Neo4j に格納しソーステキストへの監査トレイルを残し人間が検証、という重装備。本件規模には過剰だが「抽出元への traceability を残す」原則は採用価値あり。

設問5 — 下流ツール向け最小スキーマ

合意点(3モデル)

  • ノードの最小属性は id / status / 型付き辺 / 懸念(concerns・drivers・tags)。これで「存在するか」「現行か」「懸念 Y を所有するか」を answer 可能。
  • 存在照会は superseded ID を後継へ alias する(supersede 鎖を前進して終端の現行 ADR を返す)。
  • 懸念照会は ADR の concerns/drivers/applies_to と Y を突合。所有が確認できなければ no-owner(critic は保守的に finding を keep)。

相違・固有の指摘

  • OpenAI: find_by_topic(keyword) + get_ADR(id) の最小 2 関数。concerns は Context/Decision Drivers から抽出。LLM へ全 130 本を渡すのでなく ID/topic で関連分だけ retrieve させる用途を想定。
  • Claude: lint 時に生成する単一 decisions/_graph.json(nodes に status / current_form / owns_concerns / applies_to / has_rollback / edges_out / edges_in)と最小 4 コール API exists(id) / current_form(id) / owns_concern(id, concern_id) / has_rollback(id)。null/false で critic が保守 fallback。130 本ならメモリ常駐で O(1)(current_form は O(鎖長))、graph DB/MCP は consumption 層でのみ妥当と明言。
  • Gemini: triple store + SPARQL で「2024 以前に Performance>Security を選んだ ADR に依存する全 microservice」級の横断照会を描く。MCP(Model Context Protocol)で AI agent が ADR グラフを「永続メモリ」として参照し、macro ADR 違反(同期 REST を非同期 Kafka 必須に反する等)を実行前にブロックする agentic governance 像。本件の最小 IF には過剰だが将来像として記録。

合意度サマリ: 設問1=(supersession 中核は合意・追加型の数と種類は割れる)、設問2=(frontmatter SSoT で一致・RDF 昇格は Gemini 固有の将来案)、設問3=、設問4=(一発移行 + status DAG で一致・bootstrap の重装備度は割れる)、設問5=(最小スキーマで一致・graph DB/MCP の位置づけも consumption 層で一致)。


推奨スキーマ(当リポ向け統合案)

Claude の型付き辺表を骨格に、OpenAI の status 整合・移行運用、Gemini のトレーサビリティ辺 (任意) を取り込む。SSoT = 各 ADR の YAML frontmatter。下流向けに lint 時生成の docs/adr/_graph.json を別途吐く(ADR-0107 が掲げる「1 枚の機械可読データ」と整合)。

型付き辺タクソノミー

辺(forward)inverse意味source への lifecycle 効果社内 prose 写像
supersedessuperseded_by旧決定を全面置換対象 status → superseded既存 Supersedes:
amendsamended_by修正するが置換しない対象は accepted のまま(新規・部分 supersede 系: ADR-0031 型)
refinesrefined_by上位決定のスコープ内の子決定対象は accepted のままinherits-from
depends_onrequired_by対象なしには実装不可対象は accepted・被依存中は supersede 不可「follows from / builds on」
relates_torelates_to(対称)緩い相互参照なしcomplements / parallel
conflicts_withconflicts_with(対称)両立不可・要解決両方 accepted なら lint 警告(該当時のみ)
follows_up_onfollowed_up_by具体回答を負う spike/follow-up対象は accepted・re-home 先解決に有用ADR-β — parallel(spike)

任意拡張(Gemini 由来・将来): affects(下流 blast radius) / implements(コード・IaC へ) / verifies(テスト・fitness function へ)。当面は不要。

frontmatter スキーマ例

---
id: ADR-0125
title: "..."
status: accepted            # proposed | accepted | deprecated | superseded | rejected
date: 2026-04-12
deciders: [[email protected]]

# 型付き辺(ADR 間)— 両端宣言・空配列も明示
supersedes: []
superseded_by: []
amends: []
amended_by: []
refines: [ADR-0118]
refined_by: []
depends_on: [ADR-0099]
required_by: []
relates_to: [ADR-0124]
conflicts_with: []
follows_up_on: []
followed_up_by: [ADR-β-0007]

# critic の「懸念 Y を所有するか」用
applies_to:
  - { type: component, id: tenant-db-pool }
  - { type: concern,   id: connection-exhaustion-under-burst }
owns_concerns: [connection-exhaustion-under-burst, pool-sizing]
rollback: "..."             # 非空 or 本文 ## Rollback 節
---

双方向の扱い: 対称辺(relates_to / conflicts_with)と supersede 系は両端宣言を必須にし linter で対称性を強制。有向辺(depends_on)は子側のみ宣言し逆引きはツール側で計算(必要なら required_by を生成)。作成は足場スクリプト decisions/new.sh が宣言した全辺の両側を同一 commit で書く(adr-tools 流)。

adr-lint 検証ルール集

#ルールseverity検出する failure mode根拠
R1全辺配列の各 ID が実在 ADR ファイルに解決するerrordangling 参照(retired ADR への参照)adr-tools / EventCatalog Linter (Zod reference validation)
R2非対称辺は target に逆辺が存在(supersedes⇔superseded_by 等)error片方向 supersede(A→B だが B が沈黙)adr-tools adr link ... REVERSE-LINK(両端を同時生成)
R3対称辺(relates_to / conflicts_with)は両端に出現errorrelated の欠落EventCatalog 双方向 appliesTo
R4status: supersededsuperseded_by 非空 かつ対象に back-edgeerror半適用 supersessionNygard status 規約
R5supersedes:[X] ⇒ X.status=superseded かつ X.superseded_by に selferroraccepted のまま superseded と主張Nygard / MADR ADR-0013
R6supersede 部分グラフが非循環(DAG)error作成ミス・current_form の停止保証
R7superseded ADR へ accepted から depends_on の inboundwarning暗黙の依存腐敗OpenAI depends-on 健全性
R8ADR id がファイル名規約に一致erroridentity drift
R9status 遷移が lifecycle DAG に従うerror不正 statusNygard 4 状態
R10applies_to の target が既知 component/concern に解決warningcatalog drift
R11本文の ADR-NNNN 参照が frontmatter 辺に反映warningprose 限定参照(機械不可視)Log4brains slug bug の教訓
R12どの辺からも参照される ADR ファイルが欠落していないerrorsoft delete

実装: per-file schema = ajv-cli/check-jsonschema、link 存在 = markdown-link-check、style = markdownlint(MD051)。R1–R12 のクロスファイル不変量だけ自前 ~200 行スクリプト(同スクリプトが _graph.json も emit)。CI(GitHub Actions on PR + push)+ pre-commit。当リポは ADR-0107 (Proposed) が「全 ADR 1 回読取 → 機械可読データ → 索引/絞り込み/関係図/AI 書き出し」を掲げており、本スキーマ + linter はその「関係図 + AI 書き出し」部分の具体化に相当する。


bootstrap 手法(~130 本の prose → 型付きグラフ)

3モデル統合(Claude の 6 ステップを骨格に OpenAI の cleanup フェーズと Gemini の「抽出元への監査トレイル」を採用)。

  1. schema freeze + advisory: JSON Schema と linter を commit。最初は report-only で回しベースラインのエラー数を取る。
  2. 決定論抽出: 既存 Supersedes: 欄 / status 行「Superseded by ADR-XXXX」/ References 節 bullet を読み、verb を taxonomy へ写像。
    • complements / related / parallel → relates_to
    • inherits-from / extends → refines
    • depends on / requires → depends_on
    • amends / modifies → amends
    • follow-up / spike → follows_up_on
    • parallel は relates_to + 人間レビュー用コメント 各辺の両側を同一 commit で書く。
  3. LLM 補完: 残った prose(References 節 + 末尾本文)を LLM に渡し候補辺を出力、PR 単位で人間レビュー。許容理由は「linter が ground truth で、抽出ミスは R1–R6 で即 fail するから」。抽出元テキストへの参照をコメントで残す(Gemini の監査トレイル原則)。
  4. 波状解消: linter の error を R8+R12 → R1 → R2/R5/R6 の順で潰す。ADR-β のような非数値プレースホルダは本物の ID 付与か削除を判断(dangling 解消の好機)。
  5. cutover: CI を blocking に切替、pre-commit hook 追加、decisions/README.md に schema を記載。旧 References 節は外部リンク専用に縮退し ADR 相互参照は frontmatter へ一本化(OpenAI フェーズ 6)。
  6. 持続: decisions/new.sh 足場が宣言した全辺の両側を書く。以後 Accepted ADR を触るのは後継 ADR が supersede/amend を強制する時だけ(保守を有界化)。

移行は cross-cutting なので「frontmatter 一括追加」→「supersede の旧側 status 更新」のように commit を分けつつ、main 上では常に整合した状態を保つ(OpenAI)。


下流ツール連携(RQ-098 scope-aware critic との IF)

RQ-098 の critic は out-of-scope finding の「re-home 先 (target_id)」を解決する際に本グラフを引く(RQ-098 synthesis の不変量 I4「名指し target がグラフで解決し、target が当該懸念をカバーする自分のドライバーを持つ」のグラフ側の実装がこれ)。

最小照会 IF(lint 時生成の docs/adr/_graph.json をメモリ常駐、Claude の 4 コール):

exists(id)                    → bool          # R8 + ファイル系
current_form(id)              → id | null     # superseded_by 鎖を前進。分岐/deprecated 終端は null
owns_concern(id, concern_id)  → bool          # applies_to / owns_concerns / drivers と突合
has_rollback(id)              → bool          # rollback 欄 or ## Rollback 節
  • 存在: exists(target_id) が false → critic は finding を keep(保守)。
  • 現行性: current_form で superseded 鎖を前進し終端の現行 ADR を返す。分岐や superseder なし deprecated 終端は null → no-owner → keep。R6(非循環)が O(鎖長) での停止を保証。
  • 所有: owns_concern(target, Y) が true で初めて re-home 可。false → keep。
  • これらが揃った時のみ critic は降格でき、揃わなければ保守的に keep(RQ-098 の I1/I4 と一致)。グラフが不完全/陳腐だと lookup が落ち critic は安全側に倒れる(誤って取りこぼさない)が、その分 re-home の便益が出ない — だから linter による整合維持が前提条件になる。
  • graph DB / MCP server は consumption 層(critic が LLM agent の場合)でのみ妥当。SSoT はあくまで markdown + frontmatter + 生成 _graph.json(3モデル合意)。

未解決・要追加調査

  1. 辺の型の本件最適数: 追加型(depends_on / amends / refines / follows_up_on / conflicts)のどれが当リポで実際に使われるかは未実証。Gemini のトレーサビリティ辺(affects/implements/verifies)採用可否も含め、bootstrap 後の実データで頻度を測って削る(過剰な型は drift 源)。
  2. owns_concern の relevance 判定: 「target のドライバーが当該懸念を本当にカバーするか」の自動判定は RQ-098 でも未解決の再帰問題(小型 scope-classifier を要し、その検証が再帰)。本グラフは ID 解決と concerns 突合までで、意味的 coverage 判定は別レイヤ。
  3. follows_up_on(spike)の時間的妥当性: 委任先 spike が「十分早く」着手されるかの判定は不可。OpenAI は target status をメタに入れ目安にするが確実な機構は未確立。delegates_to 由来の dangling future reference を linter で警告する案(OpenAI)の運用閾値も未決。
  4. RDF / triple store 昇格の閾値: Gemini の JSON-LD/SPARQL/MCP は将来のマルチリポ SaaS で価値が出るが、130 本 solo では過剰。どの規模・どのマルチテナント段階で frontmatter から RDF へ移すべきかは未調査(合意なし)。
  5. ADR-0107 との実装統合: ADR-0107(Proposed)の「4 軸索引 + 横断ビュー + 依存グラフ + AI 書き出し」と本スキーマ/linter をどう 1 実装にまとめるか(メタデータ網羅率の穴 — Scope 59/107 等 — の補完も含む)は起案時に詰める。

References(3モデル統合・重複排除)

ADR 基礎 / status・supersession

MADR / Structured MADR / Y-Statements

ツール — 型付き辺 / 双方向 / linter

汎用 markdown 検証

実務 / 例

品質モデル / 評価(Gemini 由来)

  • ISO/IEC 25010(8 品質特性)— architecture_drivers 分類の基盤。
  • EC-ADR チェックリスト / ATAM・SAAM・ARID — ADR 評価方法論。

セマンティック Web / グラフ DB / AI(Gemini 由来・将来)

  • W3C RDF / JSON-LD / Turtle. https://www.w3.org/ / https://json-ld.org/
  • LinkML(schema 駆動). https://linkml.io/
  • Neo4j / AllegroGraph(triple store), SPARQL — エンタープライズ横断照会。
  • Model Context Protocol (MCP) — AI agent が ADR グラフを永続メモリとして参照(consumption 層)。

agentic / AI 時代の ADR(frontmatter 型付き辺パターン)

完全な URL(Gemini の Vertex grounding redirect 含む)は各生結果 docs/research/rq-100-result-{openai,gemini,claude}.md の References / Sources 節を参照。