{
  "$schema": "https://yukihamada.github.io/openformats/article/v1.json",
  "spec_version": "1.1.0",
  "kind": "article",
  "id": "bim-deterministic-scoring-2026-11",
  "title": "LLMに「何点ですか」と聞くのをやめた — 決定論スコアで測った建築設計AIの改善と方式比較",
  "lang": "ja",
  "license": "all-rights-reserved",
  "created_at": "2026-11-03T00:00:00+09:00",
  "updated_at": "2026-11-03T00:00:00+09:00",
  "authors": [
    {
      "name": "濱田優貴",
      "role": "author",
      "url": "https://teai.io"
    }
  ],
  "provenance": {
    "generator": {
      "name": "teai-blog",
      "version": "2026.11"
    },
    "human_involvement": "ai-assisted",
    "history": [
      {
        "at": "2026-11-03T00:00:00+09:00",
        "action": "create",
        "by": "yuki",
        "note": "bim.house の決定論採点に関する実測記事。元原稿は ~/workspace/teai-blog/2026-11-03-bim-deterministic-scoring.md。"
      }
    ]
  },
  "access": {
    "visibility": "public",
    "embeddable": true,
    "derivatives": "ask"
  },
  "meta": {
    "slug": "bim-deterministic-scoring-2026-11",
    "excerpt": "LLMに採点させず、法規・構造を決定論エンジンで計算した建築設計AIの改善記録。442件の配置改善で平均64.4→73.0、方式比較の全試行費用は$0.675。",
    "tags": [
      "bim",
      "llm",
      "evaluation",
      "deterministic",
      "architecture"
    ],
    "published_at": "2026-11-03T00:00:00+09:00",
    "reading_time_min": 12
  },
  "blocks": [
    {
      "type": "paragraph",
      "text": "建築設計AIを作っていると、必ずこの問いにぶつかる。**「この設計案は良くなったのか？」**"
    },
    {
      "type": "paragraph",
      "text": "LLMに「100点満点で採点してください」と頼むのは簡単だ。だがその数字は、プロンプトの語尾を変えただけで5点動く。同じ案を2回採点させれば違う点が返る。ましてや「改良前と改良後、どちらが良いか」をLLMに判定させれば、**改良した側を褒める方向に引っ張られる**。評価者が生成者を兼ねているのだから、当然といえば当然である。"
    },
    {
      "type": "paragraph",
      "text": "だから私たちは、採点をLLMから取り上げた。法規（建築基準法・斜線・建蔽率・容積率・採光・省エネUA値）と構造（ASD偏心率・N値・必要耐力）は、決定論エンジンで計算する。LLMには**案を出すことだけ**をさせる。点数は毎回、同じ入力に対して同じ値が返る。"
    },
    {
      "type": "paragraph",
      "text": "これは建築に限った話ではない。**LLMに自分の出力を採点させているプロダクトは、すべて同じ罠を踏んでいる。** 生成と評価を同じモデルに持たせた瞬間、改善の効果は測れなくなる（LLM審査が自分の生成物を優遇する self-preference は [arXiv:2404.13076](https://arxiv.org/abs/2404.13076)、2026-11-03取得、で実証されている）。この記事は、その罠を外したあとに何が見えるか、という2つの実験の記録だ。"
    },
    {
      "type": "list",
      "ordered": true,
      "items": [
        "**MCP生成物442件の品質改善** — 太陽光パネル・雨水タンク・吹抜の配置を変えただけで、平均点が64.4→73.0、中央値が74.9→84.9になった話",
        "**LLM設計方式の比較** — 単発（＋決定論ポリッシュ）／best-of-N／敵対ループ／役割分離を、同じ敷地・同じテーマ・同じ採点で並べた話（全試行の実測合計 $0.675）"
      ]
    },
    {
      "type": "paragraph",
      "text": "どちらも「LLMの賢さ」ではなく「測り方」と「幾何」の話である。"
    },
    {
      "type": "divider"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "実験1: 配置を対称にしただけで、中央値が75点から85点になった"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "前提: MCPの生成経路"
    },
    {
      "type": "paragraph",
      "text": "bim.house のMCPサーバには `create_house` というツールがある。住所と言葉を渡すと、住宅のBIM（壁・窓・屋根・階段・家具・設備の要素集合）を自動生成する。要素が明示されない場合、`src/mcp.rs` の `gen_shell_elements` が寸法からBIMを組み立て、`enrich_shell_features` が「薪ストーブ」「ロフト」「サウナ」といった言葉を拾って要素を注入する。"
    },
    {
      "type": "paragraph",
      "text": "標準装備として、太陽光パネル（4kW）と雨水タンク（200L）は以前から生成されていた。ただし配置はこうだった。"
    },
    {
      "type": "code",
      "text": "// 変更前（src/mcp.rs:1834, 1837）\npush(..., \"太陽光パネル (4kW)\", w * 8 / 100, d * 6 / 100, roof_z, w * 42 / 100, d * 18 / 100, 80);\npush(..., \"雨水タンク (200L)\", -1100, d * 22 / 100, 0, 900, 900, 1600);"
    },
    {
      "type": "paragraph",
      "text": "太陽光パネルは南帯の左端に寄り、雨水タンクは建物の外側（x = -1100mm）に固定。**どちらも建物の重心からずれている。** そして吹抜（ボイド）は存在しなかった。"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "測り方"
    },
    {
      "type": "paragraph",
      "text": "評価母集団は、2026年10月以降にMCP経由で生成された実物件 **442件**。DBのコピー上で、現行コードの出力と変種の出力を同じ採点エンジン（`evolve::score_spec_with`）に通した。採点は法規・構造・5軸（機能・美しさ・環境・楽しさ・コスト）で、LLMは一切使わない。"
    },
    {
      "type": "paragraph",
      "text": "建築に馴染みのない読者のために、出てくる指標を一行で言っておく。**建蔽率**は敷地に対する建物の投影面積の割合、**容積率**は延床面積の割合で、どちらも上限が法律で決まっている。**ASD偏心率**は、建物の重心と剛性中心（地震力に抵抗する壁の中心）がどれだけズレているかを表す指標で、大きいほどねじれに弱い。**UA値**は断熱性能（小さいほど良い）。これらはすべて、同じBIMを入れれば同じ数値が返る。"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "結果"
    },
    {
      "type": "table",
      "rows": [
        [
          "変種",
          "内容",
          "平均",
          "中央値",
          "85点以上",
          "95点以上",
          "法規退行",
          "構造退行"
        ],
        [
          "現行",
          "PV=南帯片寄せ、雨水=西側、吹抜なし",
          "64.4",
          "74.9",
          "5",
          "4",
          "—",
          "—"
        ],
        [
          "v_pv",
          "PVの配置のみ調整",
          "64.9",
          "75.3",
          "17",
          "4",
          "0",
          "0"
        ],
        [
          "v_rain",
          "雨水タンクの配置のみ調整",
          "64.7",
          "75.1",
          "8",
          "4",
          "0",
          "0"
        ],
        [
          "v_void",
          "吹抜の追加のみ",
          "65.0",
          "75.3",
          "20",
          "4",
          "0",
          "0"
        ],
        [
          "v_sym",
          "PV・雨水を**対称配置**",
          "65.8",
          "75.3",
          "**60**",
          "4",
          "0",
          "0"
        ],
        [
          "probe",
          "3要素追加（吹抜は**屋根の外**）",
          "71.5",
          "84.1",
          "206",
          "5",
          "**4**",
          "**8**"
        ],
        [
          "probe2",
          "3要素追加（配置調整）",
          "72.4",
          "84.9",
          "219",
          "5",
          "2",
          "5"
        ],
        [
          "v_symall",
          "対称配置＋吹抜",
          "72.7",
          "84.9",
          "219",
          "5",
          "2",
          "0"
        ],
        [
          "**v_sym4**",
          "**吹抜を屋根の内側に**",
          "**73.0**",
          "**84.9**",
          "**220**",
          "**5**",
          "**0**",
          "**0**"
        ]
      ]
    },
    {
      "type": "heading",
      "level": 3,
      "text": "読み取れること"
    },
    {
      "type": "paragraph",
      "text": "**第一に、対称配置だけで85点以上が5件→60件に増えた。** PVも雨水タンクも、単独で配置をいじっただけでは（v_pv, v_rain）平均はほぼ動かない。ところが両方を建物の重心に対して対称に置くと、85点以上の帯が12倍になる。理由は構造スコアだ。片寄せ配置は質量偏心を増やし、ASDの偏心率を悪化させる。対称配置はその逆で、**要素を足しているのに構造が良くなる**。"
    },
    {
      "type": "paragraph",
      "text": "**第二に、吹抜は単独では効かない。** v_void は平均 +0.6点しか動かない。しかし対称配置と組み合わせると大きく効く（v_sym 65.8 → v_symall 72.7）。吹抜は「楽しさ」軸の加点対象だが、それだけでは点にならない。**構造を壊さずに足せて初めて点になる。**"
    },
    {
      "type": "paragraph",
      "text": "**第三に、置き場所を間違えると法規・構造が壊れる。** 吹抜を屋根の外側に置いた probe は、平均点は高いのに法規4件・構造8件が退行した。屋根の外にボイドを作ると、建蔽率・容積率の算定と構造モデルが破綻する。屋根の内側に収めた v_sym4 では退行がゼロになった。"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "点数の分布——改善の実体は「中央値帯の底上げ」"
    },
    {
      "type": "paragraph",
      "text": "ここは正直に書いておきたい。改善前の442件は**二峰性**で、大半が40〜85点に沈む一方、99.2点の塊が4件あった。改善後もその4件はそのまま残り、95点以上は98.3点が1件加わって5件になるだけだ。**新たな高得点を作ったわけではない**。動いたのは中央値帯だ。"
    },
    {
      "type": "table",
      "rows": [
        [
          "点数帯",
          "改善前",
          "改善後"
        ],
        [
          "0–40",
          "71",
          "44"
        ],
        [
          "40–60",
          "76",
          "73"
        ],
        [
          "60–75",
          "75",
          "50"
        ],
        [
          "75–85",
          "215",
          "55"
        ],
        [
          "85–95",
          "1",
          "215"
        ],
        [
          "95–101",
          "4",
          "5"
        ]
      ]
    },
    {
      "type": "paragraph",
      "text": "つまり「75〜85点の山（215件）が85〜95点へ1段上がった」のが実態で、平均 +8.5点・中央値 +10.0点はこの移動を反映している。**「88点以上が35倍」のような言い方は、しきい値の選び方ひとつで数字が激変するので使わない**（同じデータでも ≥85 なら5→220、≥95 なら4→5）。改善の主張は平均・中央値・分布の移動で行うのが妥当だ。"
    },
    {
      "type": "paragraph",
      "text": "最終案の仕様はこうなる。"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "太陽光パネル: 既存屋根と同高さ・建物重心に対して対称配置",
        "雨水タンク: 同じく対称配置（西側固定をやめる）",
        "吹抜: 屋根面の範囲内（屋根を貫通させない）"
      ]
    },
    {
      "type": "paragraph",
      "text": "考え方は単純で、建物の重心 `(cx, cy) = (w/2, d/2)` を軸に、PVと雨水タンクの**質量モーメントが打ち消し合う**位置へ置く。実験で走った変種コードは一時スクリプトでリポジトリに残っていないため、以下は仕様を再現するための**概念式**であり、実際の定数ではない。"
    },
    {
      "type": "code",
      "text": "重心 (cx, cy) = (w/2, d/2)\nPV  : 中心 (cx + a, cy - b) に置く        # a, b > 0\n雨水: 中心 (cx - a', cy + b') に置く      # a', b' > 0（PVと逆象限）\n吹抜: z を屋根面の内側に収める（roof_z を貫通させない）"
    },
    {
      "type": "paragraph",
      "text": "質量の偏心モーメントが逆象限で相殺されるため、要素を足しても ASD 偏心率が悪化しない。吹抜は屋根の内側に置くことで、建蔽率・容積率の算定範囲を変えない。"
    },
    {
      "type": "paragraph",
      "text": "平均 +8.5点、中央値 +10.0点、85点以上の帯が5→220件。**LLMのモデルを替えずに、幾何だけでここまで動く。**"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "注意"
    },
    {
      "type": "paragraph",
      "text": "これはスクラッチDB上の実験で、`src/mcp.rs` には未反映だ。変種の実装差分は一時スクリプトで、リポジトリには残っていない。再現するには該当2行を上記仕様に変え、同じ442件で採点し直す必要がある。母集団も2026年10月以降のMCP生成物442件に限られ、curated物件や他の生成経路は含まない。そしてこの点数は決定論エンジンの値であって、意匠や居住性の人間評価ではない。"
    },
    {
      "type": "divider"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "実験2: LLM設計方式を、同じ採点で並べる"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "比較した5方式"
    },
    {
      "type": "table",
      "rows": [
        [
          "記号",
          "方式",
          "LLM呼出"
        ],
        [
          "A",
          "単発生成",
          "1"
        ],
        [
          "A+",
          "単発生成 + 決定論ポリッシュ",
          "1"
        ],
        [
          "B",
          "best-of-N（N=4〜6、決定論で最良案を選抜）",
          "4〜6"
        ],
        [
          "C",
          "敵対ループ（設計→審査→裁定→修正）",
          "4〜7"
        ],
        [
          "Cx",
          "C の役割分離（設計=gemini-flash、審査/裁定=glm-flash）",
          "4"
        ]
      ]
    },
    {
      "type": "paragraph",
      "text": "条件は固定した。規定敷地（198㎡・第一種中高層住居専用地域・建蔽率60%・容積率200%・前面道路6m）、テーマは「光と風の自邸」、採点は実験1と同じ決定論エンジン。LLMは案の生成・欠陥指摘・裁定だけを担い、**数値は絶対に捏造させない**。接続は teai のAPI（`openai:<model>@https://api.teai.io`）、費用は `/api/v1/pricing` の単価で実トークン数から換算した。"
    },
    {
      "type": "paragraph",
      "text": "総費用は **$0.675**（全試行合計）。方式ごとの上限$100に対して、2桁以上小さい。**この合計は保存した `*.jsonl` の各行のトークン数に、その行のモデルの単価（`/api/v1/pricing`、2026-11-03取得）を掛けて再計算した値**だ。Cx は設計=gemini-flash・審査/裁定=glm-flash の混在なので、行ごとに単価を適用している。"
    },
    {
      "type": "table",
      "rows": [
        [
          "試行群",
          "実測費用"
        ],
        [
          "初期スモーク（3モデル × A/B/C）",
          "$0.0867"
        ],
        [
          "A+（単発＋ポリッシュ、3モデル）",
          "$0.0071"
        ],
        [
          "最終 A（3回）",
          "$0.0179"
        ],
        [
          "最終 A+（3回）",
          "$0.0212"
        ],
        [
          "最終 Cx（2回、2モデル混在）",
          "$0.0298"
        ],
        [
          "反復 B/C（各3回）",
          "$0.2592"
        ],
        [
          "gemini-2.5-pro（A/B/C）",
          "$0.2272"
        ],
        [
          "アブレーション",
          "$0.0258"
        ],
        [
          "**合計**",
          "**$0.6750**"
        ]
      ]
    },
    {
      "type": "heading",
      "level": 3,
      "text": "結果"
    },
    {
      "type": "paragraph",
      "text": "**A 単発（3回）**: 58.0（法規0%）、58.0（法規0%）、83.1（法規100%）\n→ 分散が大きい。単発は法規不適合を引くことがある。"
    },
    {
      "type": "paragraph",
      "text": "**A+ 単発＋決定論ポリッシュ（3回）**: ポリッシュ前 85.1 / 85.1 / 85.1 → ポリッシュ後 **98.7 / 98.7 / 98.7**\n→ 1呼出・約$0.007で最高水準。しかも3回とも同じ値。ポリッシュが外形・階数・素材・断熱・しかけという仕様レバーを決定論で詰めるため、再現する。"
    },
    {
      "type": "paragraph",
      "text": "**B best-of-6（3回）**: pass@1 = 90.3 / 90.3 / 90.3、best = 90.3、失敗0、$0.032〜0.037\n→ 安定して90点台。ただしポリッシュ無しでは天井が90.3付近で止まる。"
    },
    {
      "type": "paragraph",
      "text": "**C 敵対ループ（3回、gemini-flash単一）**: ポリッシュ前 94.6 / 90.3 / 85.1、ポリッシュ後 98.7、$0.044〜0.061（実測 0.0441 / 0.0508 / 0.0608）\n→ ポリッシュ前で最も高い回がある。ただし分散あり、呼出4〜7回。"
    },
    {
      "type": "paragraph",
      "text": "**Cx 役割分離（2回）**: ポリッシュ前 85.1 / 90.3、ポリッシュ後 98.7、$0.0142〜0.0156、呼出4\n→ 審査/裁定を安価な glm-flash に置いても品質は維持。**費用はC単一モデル（$0.044〜0.061）の約1/3。** 素点はCより低め（Cx平均87.7、C平均90.0）なので、Cxの利点は費用と分散の小ささにある。"
    },
    {
      "type": "paragraph",
      "text": "**gemini-2.5-pro（参考）**: A 83.1、B(N=4) pass@1 79.0・best 90.3・法規適合75%、C 前90.3→後98.7。実測費用は A $0.0198、B $0.0928、C $0.1146 で、flash の約3倍。**今回の小標本では flash に対する明確な優位は確認できなかった。**"
    },
    {
      "type": "paragraph",
      "text": "**他モデル（スモーク）**: gpt-4o-mini は A 84.8（法規100%）・B 89.5・C 前86.5→後98.7で $0.0003〜0.0019。z-ai/glm-5.3-flash は A 58.0（法規0%）・B 90.3・C 前85.1→後98.7で $0.0001〜0.0004（この2モデルの中では最安）。"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "アブレーション: ヒントを消すと壊れる"
    },
    {
      "type": "paragraph",
      "text": "敵対ループには、決定論エンジンが計算した「この敷地で到達可能な天井」を設計役へのヒントとして渡している（最良構成そのものは渡さない。渡すとLLMが丸写しして設計も敵対ループも意味を失う）。"
    },
    {
      "type": "paragraph",
      "text": "`MU_NO_HINT=1` でこれを切ると:"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "A-nohint: 83.1 / 83.1",
        "A-hint: 58.0 / 83.1",
        "**C-nohint: 1呼出で出力が得られなかった**（保存ログに停止理由の記録はなく、原因は未特定）"
      ]
    },
    {
      "type": "paragraph",
      "text": "単発の分散はヒントの有無ではなく、モデルのサンプリング分散が主因だった。一方、**ヒント無しでは敵対ループが完走しなかった**（n=2のうち1回は0呼出）。原因は未特定で、比較の主軸には使えない。"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "結論（暫定）"
    },
    {
      "type": "list",
      "ordered": true,
      "items": [
        "**費用対効果の最良は A+（単発＋決定論ポリッシュ）**。1呼出・約$0.007で98.7、3回とも同値。設計意図を保ったまま仕様だけ詰めるので再現性が高い。",
        "**品質の安定性を最優先するなら Cx（敵対ループ＋役割分離）**。ポリッシュ前の素点はCより低めだが、$0.015/件と安く、2回とも98.7に到達した。",
        "**B best-of-N は中間**。6呼出で90.3に安定するが、ポリッシュ前提ならA+に費用で劣る。",
        "**ポリッシュを適用した方式（A+・C・Cx）は98.7に収束する。** Bはポリッシュ無しなので90.3のまま。だから方式差は「ポリッシュ前スコア」「法規適合率」「分散」で評価するのが妥当だ。"
      ]
    },
    {
      "type": "heading",
      "level": 3,
      "text": "制約"
    },
    {
      "type": "paragraph",
      "text": "サンプル数が少ない（各方式2〜3回、1テーマ・1敷地）。モデルの一般的優劣の結論には使えない。ポリッシュが天井付近へ収束するため方式差の分解能が低い。次段は複数敷地で法規適合率と素点分布を測るべきだ。Claude系はアカウント側の upstream blocked で未比較。"
    },
    {
      "type": "divider"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "2つの実験から言えること"
    },
    {
      "type": "paragraph",
      "text": "実験1と実験2は、別々の話に見えて同じことを示している。"
    },
    {
      "type": "paragraph",
      "text": "**実験1**: LLMを一切変えず、幾何の配置だけで平均+8.5点・中央値+10点。対称配置という単純な制約が、構造スコアを通じて効いた。"
    },
    {
      "type": "paragraph",
      "text": "**実験2**: モデルを上位に替えても（gemini-2.5-pro、費用3倍）明確な優位は出なかった。一方、**決定論ポリッシュという後処理を1つ足すだけで、flash の単発（$0.007）が flash の敵対ループ（$0.052）と同じ98.7に到達した。**"
    },
    {
      "type": "paragraph",
      "text": "つまり、この領域では**「賢いモデルを選ぶ」より「決定論で詰められる部分を決定論で詰める」方が費用対効果が高い**。少なくとも、この1テーマ・1敷地・各2〜3回の範囲ではそう見えた。LLMにしかできないのは、主題から構成を導くこと、意図を言語化すること、欠陥を言語で指摘することだ。点数を決めることでも、仕様レバーを最適化することでもない——というのが今回の作業仮説で、次段の複数敷地実験で検証する。そこを分離できれば、品質は再現可能になり、費用は1桁下がる。"
    },
    {
      "type": "paragraph",
      "text": "そして、この分離が成立するのは**採点が決定論である場合に限る**。LLMに採点させていたら、ポリッシュの効果も、対称配置の効果も、測れなかっただろう。「良くなった気がする」以上のことは言えず、A+とCxのどちらが得かも判断できなかった。"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "次にやること"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "実験1の最終案（v_sym4）を `src/mcp.rs` に反映し、同じ442件で再検証する",
        "方式比較を複数敷地・複数テーマに広げ、法規適合率と素点分布で評価する",
        "C-nohint が完走しなかった原因を特定する（`MU_NO_HINT` は実験用なので実運用では使わない）"
      ]
    },
    {
      "type": "heading",
      "level": 2,
      "text": "自分で試す"
    },
    {
      "type": "paragraph",
      "text": "bim.house（https://bim.house）の `/build` では、ブラウザ内の WebLLM で設計案を生成し、同じ決定論エンジンで採点できる。MCPの `create_house` も同じ採点系に乗っている。手元で再現するなら、リポジトリの `scripts/method_bench.py` に `BENCH_THEME` と `BENCH_CAP_USD` を渡せば、この記事と同じ方式比較が走る。"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "再現用データ"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "MCP品質改善: `docs/mcp-feature-sweep-2026-11-03/`（442件 × 10変種の採点結果 `scores-442.json` と手順 `README.md`）",
        "方式比較: `docs/method-bench-2026-11-03.md` と生データ `docs/method-bench-2026-11-03/raw/`",
        "方式比較ハーネス: `scripts/method_bench.py`（`BENCH_OUT` / `BENCH_THEME` / `BENCH_CAP_USD` で条件を指定）"
      ]
    }
  ],
  "citations": [
    {
      "label": "Self-preference in LLM judges (arXiv:2404.13076)",
      "url": "https://arxiv.org/abs/2404.13076",
      "retrieved_at": "2026-11-03"
    },
    {
      "label": "bim.house",
      "url": "https://bim.house",
      "retrieved_at": "2026-11-03"
    }
  ],
  "content_hash": "032125d41e6c658ac166987379b203e7e5facc49673f4c359e6e5941ee4d1cc5",
  "signatures": [
    {
      "alg": "Ed25519",
      "public_key": "f/NPZdENXk1dAVXqB+QWn1mIx6LUdhoJWuYWA4hnTPY=",
      "signature": "fzYSQ+c+x2Xp3Zn2xpsATPjZ+wC+k24zbcfLG1o+e4YDMdnLzOBs0rFx4qnPe5FUNUPO/yUJaLD3K/TMbxWUAA==",
      "signer": "openformats-maintainer",
      "signed_at": "2026-11-09T12:46:59Z"
    }
  ]
}
