コンテンツにスキップ

AI WF2Des — 組み立てアーキテクチャ

計画予算と画像忠実性(2026年9月23日)

screen planning は provider request 20回・inspection 48回の総上限を維持する。 探索は最終出力用に3 requestを予約し、同じ検証済み履歴とusage counterを使ってtoolなしで確定する。 同一inspectionの反復は短い参照を返し、予算超過で未実行のcallを証拠として扱わない。 失敗時のusageも記録する。確定に失敗してもbaselineは保持するが、cannot_verify findingと screen_planning validator warningを残し、見た目の合格とはしない。

hash検証済みsnapshotから、placeholder名を持ちcontainer/rectangleだけで構成される空のicon slotを variantごとに識別する。実vector・image・非表示slotは空扱いしない。空slotで元の画像を置換せず、 証拠がないvariantでは元の画像を保持する。selection stateのguardは推定kindに依存せず実際の checked/selected軸を検査し、buttonやotherに分類されたarrow toggleによるcheck画像の置換も防ぐ。

footerによる隣接navigationの吸収は、native label+glyphの証拠がありoverride後も可視の単一actionに限る。 parserのformラベルだけで判定せず、実入力欄と別の画像は保持する。同じsource ownerとboundsを共有する 単一instance wrapperではpaddingを一度だけ数え、幅による文字折返し後に残りのfootprintを測る。 独立slot・複数の子・明示min height・table trackは変更しない。特定project IDやregistry migrationは不要で、 新しい実renderによる検証を引き続き合格条件とする。

Asset identity と optional-content の証明

registry hygiene は表示名だけで部品を統合しません。異なる capture source の軸と default を独立に保ち、 実在しない variant 組合せを防ぎます。snapshot preflight は master 定義を持たない proxy INSTANCE からも read-only の BOOLEAN/visibility 証拠を導出します。planner に制御を提示し、grounding は override 後の可視 copy を検証して compound replacement と重複 navigation coverage を許可します。proxy の observed 値は master default と誤認せず明示適用します。文字のない atomic mark は primary が button でも secondary media を認めます。 screen/project ID・部品名・provider label の分岐は使いません。test/replay 成功だけでは visual parity とせず、 新しい plugin render を合格条件にします。

生成時は、3つ以上の source label 全体を可視 text multiset で網羅する唯一の compound を優先します。 非表示化は capture 済み optional part のみ、余分な navigation は近接する native action の証拠を要求します。 候補の曖昧性・未解決 variant・独立 image・部分一致では適用しません。actual-render corrective review には この選択を強制しません。identity・property・coverage と決定的な rationale を既存 screen plan に記録します。

意味的セクションレイアウトと権限(section-layout@1)

部品選択は元の内容をどのdesign-system部品で表すかを決める。追加のセクションレイアウト層は、 連続した兄弟のどこまでを意味のある縦方向セクションとし、境界の余白を誰が決めるかを明確にする。 モデルは ScreenPlan.semantic_sections で限定されたグループを要求できるが、適用前に決定的compilerが 元メンバーと順序、現在の出力の網羅性、配置条件を検証する。原文の変更、grid・絶対配置・instanceの横断、 内容の暗黙削除はできない。未対応・曖昧な要求はfindingを残して測定済みの元配置を保持する。

権限の優先順位は、選択部品が自身の内部形状を所有し、適用対象が明確なルールが明示されたセクション間隔と viewport_width_px を決め、元の測定値がfallbackを担う。base_viewport_px は参考値のままであり、 content幅やpaddingから画面幅を創作しない。実効間隔には既存の境界paddingを含める。 塗りのあるコンテナ、chrome境界、意図的な間隔を一律の正規化から保護する。 適用可能なフローのinstanceだけに height_authority="component" を付け、旧wireframe占有高さのspacerを防ぐ。

不変のassembly stateは検証済み layout_plan(version、requests、sections、joints、findings、viewport)を保存する。 生成と実画像の修正レビューは同じ決定的適用処理を使い、修正前に現在の選択による網羅性を再検証する。 変更のないレビューは同一specを再現し、planのない旧stateは旧リプレイ動作を保持する。 specのノード種別は既存5種類のままであり、planの成功は見た目の合格を意味しない。 詳細は I/O 定義 と 回帰テスト を参照。

このページは、WF2Des の生成を支える 直接組み立てエンジン の実装向けの詳細な掘り下げです。 概要 がパイプラインを 8 ステップで概観するのに対し、このページは 境界がどこにあるか を定義します: どの判断が決定的な変換で、どれが LLM のものか、2 つのフェーズがどう受け渡すか、各 spec ノードがどう生成されるか、そしてなぜ全体が再現可能なのか。

決定的な性質はここで一度だけ述べ、全体を通じて成り立ちます: retrieval なし、embedding なし、 ベクトル検索なし、学習コーパスなし。 エンジンはプロジェクト自身のコンポーネントレジストリとルールセットを 直接読み込み、そこから組み立てます。これは des2code との構造的な対比です — des2code はインデックス化された ベクトルから広めの候補プールを retrieval してリランクします。WF2Des はインデックス化せず、類似度で採点せず、 コーパスに対してランク付けもしません — その候補ステップはストレートでテナントスコープの フィルタ です。


LLM フェンス

エンジンは 決定的優先 です。LLM はフェンスの内側で、境界された、エビデンス pin 済みの判断のみを行います。 フェンスの反対側にあるものはすべて再現可能な変換です。フェンスはこのワーカーにおいて最も重要なアーキテクチャの 線であるため、ここで明示的に描きます。

フェンスの内側 — 唯一の 2 つの生成 LLM 呼び出し:

フェーズ LLM が決定 LLM は決して決定しない
Parse(fast tier) 各 WFNode の role(共有の要素タイプ語彙から — WFNode role 値の閉じた集合。prompts.py の ROLE_VOCABULARY に固定)と intent(OPEN memo + variant ラベルから) ツリー形状 — WFNode 抽出は決定的
Assemble(strong tier) セクションごと: ケース(instance / compose / unmatched)、component key、variant props、text-slot 塗り candidate admissibility、投票に対する決定的ガード、縫合、検証、confidence

これらは 2 つの 生成時 呼び出しです。これらに加えて、ルールの取り込みがガイドラインボードごとの vision 抽出呼び出し (rule_process、vision tier)を行います — ルールリビジョン上のガイドラインボード 参照。

フェンスの外側 — それ以外はすべて決定的:

  • WFNode 抽出 — wireframe snapshot は固定ルールによって WFNode ツリーに walk されます (可視の FRAME / GROUP / INSTANCE / TEXT の各子孫 + 画像塗りの矩形。vector/shape の葉は親に 折りたたむ。隠しレイヤーはスキップ)。ツリー形状は snapshot の関数であり、モデルの関数ではありません。
  • Memo ステータス — 取込済フレーム内部の memo は包含により resolved になります。resolved の memo は ライブ intent から除外されます。純粋な幾何 / 包含であり、モデルはありません。
  • screen_id 文法 — wf_parse における決定的な名前文法([A-Z]{2,3}_[A-Z0-9]+、アンカーなし)。 生成時の screen_id はリクエストから来ます。variation_label は決定的なフレーム名分割です。
  • 候補セット — project registry を dedup / hygiene 折りたたみした後、決定的な role→admissible-kind gate が section ごとに絞り込みます。size は model evidence であり gate ではありません。scoring / similarity は ありません(候補セット 参照)。
  • 投票に対する決定的ガード — LLM の選択エコーは、信頼される前に固定プログラムによってクランプされ スコープチェックされます(投票に対する決定的ガード 参照)。
  • 決定台帳 — design_resolution は選択の前に参照され、ガードの後に決定的ルールで書き戻されます (design_resolution 決定台帳 参照)。
  • Spec 縫合 — セクションごとの判断は固定変換によって DesignSpec に組み立てられます (決定的縫合 参照)。
  • Rules validator — コンパイルされたルールセットが縫合された spec に対してプログラムとして実行されます (The Rules Validator 参照)。
  • 計算された confidence — 構造的シグナルに対する数式。決してモデルの自己申告ではありません (計算された Confidence 参照)。

フェンスにはハードな帰結があります: LLM が決定するすべては、そのエビデンス(source、 lineage_wf_node_ids、pin 済みの inputs)と共に保存され、LLM が 決定しない すべては再計算できます。 パイプラインのどこにも、類似度スコア、embedding、コーパスルックアップが入り込む場所はありません — それらは このエンジンには単純に存在しません。


二フェーズパイプライン

生成は confirm チェックポイントで区切られた 2 つのフェーズで実行されます。Parse は parse された wireframe を 生成し、(インタラクティブでは)待機するか、(auto-confirm では)そのまま連鎖します。Assemble は pin された 入力を再水和し、ターミナルな DesignSpec を生成します。

flowchart TD
  subgraph PARSE["Phase 1 — Parse"]
    P0["PIN inputs into the result doc<br/>(first act — the pinning moment)"]
    P1{"parse cache hit?<br/>composite _id + same wf_content_hash"}
    P2["DETERMINISTIC WFNode extraction<br/>visible FRAME / GROUP / INSTANCE / TEXT<br/>+ image-fill rects; vectors collapse; hidden skipped"]
    P3["DETERMINISTIC memo status<br/>取込済 containment ⇒ resolved (excluded from intent)"]
    P4[["LLM · fast tier · roles + intent ONLY<br/>never the tree shape"]]
    P5["copy prior parse artifacts<br/>(no LLM)"]
    P6["write wireframe cache doc (LWW)<br/>+ parse block + immutable parse.json (CAS)"]
    P0 --> P1
    P1 -->|miss| P2 --> P3 --> P4 --> P6
    P1 -->|hit| P5 --> P6
  end
  P6 --> CONF{"confirm checkpoint<br/>auto_confirm?"}
  CONF -->|"no · interactive"| PARK["park at awaiting_confirm<br/>plugin previews → designer confirms"]
  CONF -->|"yes · auto"| CHAIN["assemble in the same invocation"]
  PARK --> A0
  CHAIN --> A0
  subgraph ASM["Phase 2 — Assemble"]
    A0["REHYDRATE pins from result doc inputs<br/>FAIL CLOSED on any hash mismatch"]
    A1["DETERMINISTIC candidate set<br/>registry hygiene + per-section role/kind gate<br/>(no scoring / no similarity; size is a signal)"]
    AL0["DECISION-LEDGER consult (design_resolution)<br/>mined or score ≥ trust → LOCK (no LLM)<br/>weaker entry → FLOOR (re-vote)"]
    A2[["LLM · strong tier · SECTION-PARALLEL selection<br/>K-SAMPLE self-consistency vote per section<br/>instance / compose / unmatched · component key ·<br/>variant props · text-slot fills"]]
    AG["DETERMINISTIC guards over the vote<br/>variant clamp · symmetric scope guards ·<br/>dup-claim dedupe · kit-name override ·<br/>variant + screen-facts resolution"]
    A3["DETERMINISTIC stitch → DesignSpec<br/>spec tree · spec_nodes_flat · style_bindings"]
    A4["DETERMINISTIC rules validator<br/>auto-fix where safe, else flag"]
    A5["COMPUTED confidence<br/>never model self-report"]
    AL1["DECISION-LEDGER write-back (design_resolution)<br/>deterministic score · ratchet-fenced"]
    A6["result doc spec/selection/validator/confidence (CAS)<br/>+ S3 result artifact + manifest"]
    A0 --> A1 --> AL0 --> A2 --> AG --> A3 --> A4 --> A5 --> AL1 --> A6
  end

ダブルブラケットのノード([[…]])が生成パイプラインにおける唯一の 2 つの LLM 呼び出しです。 ダイアグラムのそれ以外はすべて 決定的な変換です。そのレンズでパイプラインをもう一度読むと、フェンスが形として見えてきます: 長い決定的な背骨に 埋め込まれた 2 つの狭い LLM ステップ。

Phase 1 — Parse

呼び出しの最初の行為は、結果ドキュメントの inputs ブロックへ 入力を pin する ことです(wireframe アイデンティティ + source_hash、加えて assemble が再水和する rule/component/LLM の pin)。最初に pin する ことが実行を再現可能にします: 下流のすべてはライブ状態ではなく pin を参照します。

Parse は次に parse キャッシュ をチェックします — wireframe コレクションにおける複合 _id = {project_id}_{figma_file_key}_{node_id} による主キールックアップで、メッセージの wf_content_hash と照合します。ヒット時は前回実行の parse アーティファクトをこの実行自身の parse.json に LLM 呼び出しなし でコピーします。ミス時は snapshot をダウンロードして決定的抽出を実行し、その後 role + intent のための単一の fast-tier LLM ステップを実行します。キャッシュは却下後のリトライでは意図的に スキップ されます — それらのケースでは新規 parse がその目的だからです。

Parse は wireframe キャッシュドキュメント(LWW フェンス済み)と、結果ドキュメントの parse ブロック、加えて イミュータブルな parse.json を書き込みます。parse.json アーティファクトが正式です: wireframe コレクションの ドキュメントは後続の再 parse で上書きされる可能性があるため、プレビューおよび memo レビューのサーフェスは 結果ドキュメント + parse.json を読み込み、上書き可能なキャッシュドキュメントは決して読み込みません。

Confirm チェックポイント

フェーズの間に confirm チェックポイントが位置します。インタラクティブでは、parse が parse_done を POST し、 行は phase = awaiting_confirm で待機します。plugin が parse をプレビューし、デザイナーが confirm(または reject) します。Confirm は awaiting_confirm + attempt を CAS チェックして assemble をエンキューするバックエンド エンドポイントです。auto_confirm 経路では待機はありません — assemble が同一呼び出し内で連続実行され、 ターミナルな Webhook のみが発火します。チェックポイントが存在するのは、parse が memo intent を解釈する場所だから です。コンポーネント選択にコミットする前にデザイナーに 解釈 を confirm させることで、高価な strong-tier ステップが誤読された wireframe に対して動作するのを防ぎます。

Phase 2 — Assemble

Assemble の最初の行為は、結果ドキュメントの inputs ブロックから pin を再水和 し、いずれかのハッシュ 不一致で fail close する ことです — pin されたルールリビジョンまたはコンポーネント snapshot が そのハッシュにもはや一致しない場合、より新しいバージョンに静かにフォールバックするのではなく実行を中止します。 再水和した pin から、決定的なセクションごとの admissible な候補セットを構築し、design_resolution 決定台帳を 参照し、単一の strong-tier セクション並列選択ステップ(K サンプル自己一貫性投票)を実行し、投票に対する決定的 ガードを適用し、その後 決定的な縫合、validator、confidence の数式、台帳の書き戻しを実行し、ターミナルな結果 ドキュメント + S3 アーティファクト + マニフェストを書き込みます。

再配送時、assemble は 既存の pin を再利用 し、inputs ブロックが不在の場合のみ選択を再実行します — クラッシュリトライが、リトライしている attempt とは異なるコンポーネントまたはルールリビジョンを 静かに選択することは決してありません。


5 つの Spec ノードケース

縫合された DesignSpec は、正確に 5 つのノードケース のツリーです。セクション選択の LLM は、コンテンツ ノードについて instance / compose / unmatched のいずれかを選びます。layout_frame と text は決定的な 構造から導かれます。各ケースは次のように生成されます。

ケース 生成元 フラグ付け? 内容
layout_frame 決定的 — WFNode 構造から導出された auto-layout または座標配置コンテナ いいえ auto_layout {direction, gap, padding, sizing}(重なり合う free-form レイヤーは direction=none)、fill_opacity、clips_content、children、lineage_wf_node_ids
instance LLM がセクションの role/kind admissible なセットから登録済みコンポーネントを選択。縫合が slot を解決 低 confidence のときのみ component_key、platform_design_id(安定した validator キー)、variant_props、text_slots、bbox、source {kind: registry \| wireframe}
compose LLM が単一コンポーネントは適合しないと判断し、子からサブツリーを組み立てる 常にフラグ付け インライン化された children、source {kind: composed}
text 決定的 — スタイルトークンにバインドされたコンテンツを持つ text WFNode 低 confidence のときのみ content、style_token、source
unmatched LLM のセクション選択が confident なマッチを見つけられない → 可視のプレースホルダ 常にフラグ付け placeholder {role, text, bbox}、source {kind: none}

このうち 2 つはエンジンが越えない 明確な線 です:

  • compose は常にフラグ付けされます。 組み立てられたサブツリーは最も根拠が弱い結果です — 登録済み コンポーネントがマッチしなかったため、エンジンがパーツから 1 つを組み立てました。それが confident な結果として 提示されることは決してありません。常にレビューのために表面化されます。
  • unmatched が静かに削除されることは決してありません。 confident なマッチのないノードは、その role、 text、bbox を運ぶ可視のプレースホルダになり、デザイナーのためにフラグ付けされます。デザインの欠落は 隠されるのではなく、可視にされます。

すべてのノード — 5 つのケースすべて — は、それが由来する WFNode まで lineage_wf_node_ids を運び、各コンテンツ ノードはフラットなレビューとフィードバック帰属のために spec_nodes_flat({layer_path, case, component_key, wf_role, confidence, flagged, lineage_wf_node_ids})に一度だけ現れます。


候補セット

LLM が選択する前に、エンジンは候補セットを構築します — これは des2code ではベクトル retrieval であるステップであり、ここではその類のものは一切ありません。

  • ソース — プロジェクトの コンポーネントレジストリ。これは inputs.components に pin された共有 プラットフォーム design テーブル(type=component)です。各候補の assembly/instancing コンテキストは design_component コレクション(_id = {project_id}_{figma_file_key}_{node_id} でキー付け)から読み込みます: variant_properties、text_slots、image_slots、default_size、component_key。
  • Role-aware admissibility。 registry-wide dedupe / hygiene collapse の後、決定的な role→kind map が section を構造上満たせない category を除外します。本番 default は CANDIDATE_KIND_GATE=true で、無効化は controlled evaluation のみです。選択 LLM は admissible な候補を各候補の完全な構造でふるいにかけます。size は signal であり gate ではない ため、default variant の寸法差だけで valid component を除外しません。
  • 採点なし、類似度なし、ランク付けなし。 WF セクションの embedding はなく、コサイン距離もなく、学習された リランカーもありません。セットは、organization_id + project_id でスコープされた、レジストリ metadata に 対するストレートでテナントスコープの読み込みです。
  • 切り詰めは記録され、静かではありません。 セクションごとの候補カウントは selection ブロックの candidates_considered マップに着地し、過大な候補セットの切り詰めはそこにフラグ付けされます。

hygiene と role→kind admissibility はどちらも決定的なので、section ごとの candidate set は再現可能で記録されます。 LLM は project が登録した component の既知で bounded な subset のみを見るため、判断は監査可能です。


選択 — K サンプル投票

選択は strong-tier の assemble 呼び出しであり、単一の完了を信頼しません。セクションごとに K サンプル自己一貫性 投票 を実行します: 同じエビデンス pin 済みの低温プロンプトを K 回サンプリングし、判断は (case, platform_design_id) に対する多数決 です — したがって同じセクション KIND は、単一の抽選ではぶれる 場合でも同じコンポーネントに収束します。これは 1 つの LLM ステップであって K 回のフェンス呼び出しではありません: K サンプルは単一のセクションごとの選択呼び出しに乗るため、LLM フェンス は不変です。 タイと下流のすべての信頼上の懸念は、下記のガードによって決定的に解決されます。 投票が提案し、ガードが処分します。


投票に対する決定的ガード

投票は提案です。エンジンは LLM の選択エコーを最終として 決して信頼しません: 投票と縫合の間(信頼境界)に 固定プログラムが位置し、正確でなければならないすべてを再導出します。各ガードは決定的で記録されます — どれも 2 回目のモデル呼び出しではありません。

  • Variant クランプ。 variant props は、何かが読む前に レジストリの軸にクランプ されます: モデルが 捏造した値や drop した軸はコンポーネントの実際の variant_properties にスナップバックされるため、下流のどの ステップも軸外の variant を見ることは決してありません。
  • 対称スコープガード。 適合は両方向でチェックされます。主張するセクションより 著しく大きい コンポーネントは unmatched に降格され(可視のプレースホルダ。静かな不適合は決して発生しません)、マルチユニットのセクションを 主張する小さなコンポーネント は compose に降格され、そのユニットが 1 つの誤った instance に折りたたまれる のではなく、レジストリに対して個別に 再選択 されます。
  • 重複主張の dedupe。 2 つのセクションが同じコンポーネントを主張する場合、タイは wireframe 名のエビデンス で解消されます — 自身の wireframe 名が一致するセクションが主張を保持し、もう一方は再解決します。
  • kit 名オーバーライド。 1 つの名前付き kit 要素そのものであるセクションは、投票がドリフトした先ではなく、 その名前 のレジストリコンポーネントを取り、kit 自身の variant 値を引き継ぎます。
  • フォーカスされた variant 解決パス。 仕様不足の instance は、その variant 軸のみの 2 回目の狭い解決を 受けます — セクションとその 1 つの候補のみ、それ以外は何もありません。
  • screen-facts パス。 スクリーンをまたいで共有される variant 軸(ログイン / ログアウト状態、プラットフォーム)は スクリーンごとに 1 回解決 され、一貫して適用されるため、兄弟セクションがスクリーン全体の事実で不一致に なることはありません。

台帳フロア(下記)はこれらのガードの 前 に適用されるため、ガードが常に最終決定権を保ちます: 投票または台帳 フロアが何を提案しようと、クランプされ、スコープチェックされ、dedupe された結果が縫合に到達します。


どのガードがどの選択を判定できるか

ガードは 2 つの層 に分かれ、この区分は実装上の詳細ではなく契約である:

層 ガード 適用対象
サイズ基準 overscoped、underscoped バリアントを指定していない選択のみ
バリアント非依存 kind_mismatched、heading_as_compound すべての instance 選択

サイズ層が限定されるのは default_size を読むためである。これはコンポーネントの デフォルト バリアントのみを表すサイズであり、別のバリアントを指定した選択は正当にそのサイズの一部分であり得る(デフォルトが 786px のフルフッターであるセットにおける細いフッターバリアントなど)。したがってデフォルトの面積で判定すれば正しい選択を捨ててしまう。kind は異なる: button_group はどのバリアントでも button_group であり、バリアント指定がカテゴリ誤りを正当化することはない。

この区別は実際の障害から学ばれた。 kind ガードは当初サイズ層の not selection.variant_props ブロックの 内側 にあり、バリアントを反映した選択に対しては無効化されていた(保存済み instance 選択の 57 件中 33 件、57% で実測)。実画面での結果: ページタイトル 「ログイン」 を保持する header 領域が button container(kind は button_group。header は許可しない)を 確信度 0.9、フラグなし で採用し、生成されたデザインはページ見出しを入力欄の上の 2 つ目の大きな暗いログインボタンとして描画した。これほど確信度が高くなった原因はコンテンツの整合性である — タイトル文字列がログインボタン自身のデフォルトラベルと完全に一致し、スロット充填ガードは逆の失敗(どのスロットにも適合しないテキスト)しか検出しない。

other はカテゴリ誤りではない。 記録された kind が other のコンポーネントは、kind が存在しない場合とまったく同様に「セマンティクスタガーが判断できなかった」ことを意味し、ROLE_CANDIDATE_KINDS はどのロールに対しても other を列挙していない。これを不一致として扱えば、該当するすべてのコンポーネントがあらゆる場所で拒否される — レジストリ 279 件のうち 19 件が other であり、logo、icon-slot、list dot などが含まれる。ガードはこれを判定対象外とする。(実測: kind ガードがバリアント指定済みの選択に対して動作し始めた直後、ロゴが当然属する header 領域で logo が拒否された。)

レジャーもバリアント非依存層を再検証する。 保存された判断は参照時にこれらのガードで再チェックされる。これにより、ガードが存在する以前に、あるいは修正済みのバグの下で書かれたエントリがそのまま固定されることはない。この再チェックに kind が欠落していたことが、上記の不具合を固定化させた原因である: 誤った選択はスコア 0.88 で信頼閾値を超え、3 つ のセクションをロックし、連続する 2 回の実行がバイト単位で同一の出力を生成した。投票経路のみを修正しても何も変わらなかった — 選択が再投票されなかったためである。拒否は ledger_entry_misselected として、該当ガードを示す reason 付きで記録される。


design_resolution 決定台帳

design_resolution は 6 番目の DocumentDB コレクション(design_resolution 参照)であり、エンジンの 自律的な品質ラチェット です。これが存在するのは、このワーカーには 人間による修正 ループが存在しない からです — 品質はマシン側で収束しなければならないため、エンジンはセクション KIND ごとに自身の 最良の判断を記憶し、時間とともに、より良い判断がより悪い判断を置き換えることを許します。各エントリは 構造的で LLM フリーな section_signature(sig@1:… — セクションの kit コンポーネント名、正規化された名前、 子タイプの形状、テキスト数に対するバージョン付きハッシュ。決して LLM が割り当てた role ではない)でキー付けされる ため、同じセクション KIND はすべてのスクリーンとすべての再実行で同じエントリにヒットします。

台帳は assemble に 2 点で触れます。

  • 参照、選択の前。 section_signature でキー付けされ、エントリはそのセクションを ロック するか フロア します。provenance = mined(ファイル内のデザイナー製デザインから読み取られたもの — 投票より上位の 唯一の権威)のエントリ、または score ≥ トラストしきい値の voted エントリは、そのセクションを ロックします: LLM は実行されません。 より弱い voted エントリは フロア です — セクションは再投票され、 より高いスコアの判断が勝ちます。フロアは決定的ガードの 前 に適用されるため、フロアが通したものについても ガードが最終決定権を保ちます。
  • 書き戻し、ガードの後。 すべての非 unmatched セクション判断(および各 compose-child)は、決定的スコア (構造的品質 — base + modeled + variant 完全性 + scope 適合。mined = 1.0)とともに design_resolution に upsert されます。書き込みは ラチェットフェンス されます: voted の書き込みは strictly 低いスコアの 非 mined エントリの上にのみ 着地します。mined の書き込みはフェンスされません。同一のエビデンスは同一に スコアリングされるため、再実行がチャーンすることはなく、より良い判断が単調により悪いものを置き換えます。

台帳は両側で決定的です — 参照も書き戻しもプログラムロジックであり、スコアは構造的シグナルの純粋関数です — したがって LLM 呼び出しを追加せず、既存の assemble ステップの内側に乗ります。これがエンジンが人間をループに入れずに改善する メカニズムです。


Native Materialization と Render Review

plugin は self-contained spec から native component instance を作ります。width は planned region に合わせますが、 component height は intrinsic のままです。vertical auto-layout 内で instance が source/spec box より短い場合は、 transparent spacer が minimum footprint を保持し、component や divider を引き伸ばさず後続 sibling の collapse を防ぎます。

variant props、style/variable binding、image、text slot は component と font の解決後に適用します。materializer diagnostic は name_fallback、ordinal_fallback、build_error、font_fallback、prop_rejected、unmatched、 preserved の 7 種です。detail は backend placement flag の変更より先に保存されます。

actual-render correction は意図的に bounded です。plugin は PNG、node/bounds manifest、diagnostic report を hash-derived render_review identity で upload します。最初の review は pass または grounded candidate spec を 1 つ返します。元 output は 保持したまま、candidate を隣に build して再 render します。2 回目は verification-only で、pass なら candidate を in-place promote、fail または evidence を検証できない場合は candidate を削除して元 output を保持します。parent review から追加 correction は作れないため、recursive drift と unbounded model cost は発生しません。


決定的縫合

LLM がセクションごとの判断を返したら、縫合はそれらを 固定変換 によって自己完結型の DesignSpec に組み立てます — 同じ判断は常に同じ spec に縫合されます。

縫合は 3 つのものを生成します:

  1. Spec ツリー(spec.root)— 上記の 5 ケースのノードツリーで、plugin が決定的にアドレス指定できるよう すべてのノードに layer_path が付きます。
  2. spec_nodes_flat — レビューとフィードバックのために、コンテンツノードごとに 1 つのフラットなエントリ。
  3. style_bindings マップ — token → Figma style/variable id。project_figma_file.style_captures(sweep が キャプチャしたファイルレベルのローカル text スタイル + color 変数)から 導出されます。spec はスタイルの トークン を参照します。style_bindings が各トークンを具体的な Figma スタイルに解決するため、plugin は スタイルを自身でルックアップする必要が決してありません。

spec は 設計上自己完結型 です。すべてのノードは自身の layer_path と埋め込み bbox を運び、すべての スタイル参照は style_bindings を通じて解決され、すべての画像プレースホルダはコンポーネント自身が運ぶ構造的な image_slot です。したがって plugin は、レジストリ、ルール、wireframe を再読み込みすることなく、spec のみからデザインを 決定的に マテリアライズできます — 同じ spec、同じキャンバス結果。これがマテリアライゼーションを 2 回目の解釈パスではなく spec の純粋関数にするものです。


The Rules Validator

コンパイルされたルールセットが validator のプログラム です。ルールセットは strict なルールファイルとして 手で執筆されるものではありません: 取り込み時に、プロジェクトの選択された Figma ガイドラインボードから 抽出 されます — ボードごとに 1 回の vision 抽出を行い、ボードごとのフラグメントを決定的に単一の RuleSet にマージし、デザイナーのレビュー待ちとして draft_source: "llm_extracted" で保存します。ルールがどう抽出された かに関わらず、validator 自体は不変です: design_rule ドキュメント((design_rule_id, content_hash) ごとに 1 つのイミュータブルドキュメント)は 4 つのルールクラスを運び、validator は各クラスを縫合された spec に対する決定的なパスとして実行します:

ルールクラス バインド先 強制内容
spacing layout_frame auto-layout 許可された spacing スケール + section gap
typography text ノード 許可されたスタイルトークン + トークンごとの最大行数
color_tokens style bindings 許可されたトークンセット
screen_group_policies layout_frame のジオメトリ 画面ファミリー単位のレイアウト: コンテンツ幅、パディング、セクション/要素間ギャップ、カラム数の範囲 — ポリシーが述べるスコープを画面名に照合して選択
component_specs instance のスロットロール ガイドラインが述べるコンポーネント単位の規則(バリアント、状態、スロット規則)。スロットロール分類器に接続される

違反ごとの validator の結果は 安全な範囲で自動修正、そうでなければフラグ付け です。許可されたスケールに きれいにスナップする spacing 値は自動修正され、エンジンが安全に解決できないジオメトリはフラグ 付けされます。validator_report はすべての違反を {rule, layer_path, action (auto_fixed | flagged), detail} として記録します。

slot_constraints は削除されました。 wf_role を許可された platform_design_id の集合に バインドする設計でしたが、これを生成する抽出パスは存在せず、フィールドは常に空でバインディングは一度も 実行されませんでした。コンポーネント単位の規則は、ガイドラインが実際に記述する component_specs として 到達します。加えて kind ガードが、その領域が取り得ないカテゴリのコンポーネント(装飾バッジに選ばれた 選択コントロールなど)を却下します。

ルールなし経路は明示的です。 プロジェクトにルールが登録されていない場合、validator は no-op となり、 validator_report.status = no_rules を設定し、すべてのノードが rules_unvalidated でフラグ付けされます。 未検証が静かに valid として扱われることは決してありません — ルールセットの不在自体がすべてのノードで表面化されます。

validator は 常に LLM を上書きします。ルールダイジェストは選択ステップに アドバイザリ な入力として渡されますが、 ルールに違反するモデルの選択は、モデルが何を好んだかに関わらず validator によって修正またはフラグ付けされます。 決定的なパスが権威です。


計算された Confidence

Confidence はバージョン付きの数式によって構造的シグナルから 計算 されます。モデルの自己申告は 禁止 です — エンジンは LLM に「どのくらい confident か?」を決して尋ねず、そのような回答を決して記録しません。

数式への入力:

  • Validator 違反 — フラグ付けされた(未修正の)違反は confidence を下げ、自動修正されたものは影響が小さい。
  • Unmatched / composed カウント — unmatched と compose の結果は根拠の弱いシグナルです。
  • Slot の曖昧さ — 登録時に text_slots / image_slots が ambiguous とフラグ付けされたコンポーネントは、 それらを埋めるあらゆる instance に曖昧さを持ち込みます。
  • Component-fit(role 一致) — 選択されたコンポーネントの構造がセクションの WF role とどれだけ 一致するか。

数式自体にハードなルールが存在します: compose は instance より低く上限が設けられます。 組み立てられた サブツリーは、他のシグナルがどう出ようと、クリーンな登録済みコンポーネントの instance ほど confident にスコアリング されることは決してありません。これは「compose は常にフラグ付け」という明確な線の数値的表現です。

出力の confidence ブロックは {min, avg, flag_count, formula_version} です。flag_count はエンジンがレビュー用に flag したすべてのノードを数えます — flag しきい値未満のスコア、compose/unmatched の結果、トラスト境界で クランプされた選択エコー(drop された variant 軸・スロットパス)、そして style_bindings で解決 できないスタイルトークンを持つテキストノード。完了 Webhook を介して wf2des.flag_count にミラーされ、formula_version(cf@0.6)は数式を pin するため、confidence 数値は常に、 それを生成した正確な数式に対して解釈可能です。すべての入力が spec に記録された構造的シグナルであるため、 confidence は spec + pin された数式バージョンから 再現可能 です — validator と同様、記憶されるのではなく 再計算可能です。


フェンシングと再現性

エンジンは pin された判断から再現可能 になるよう構築されています。3 つのメカニズムが組み合わさってそれを 保証します。

1. (_id, attempt) に対する結果ドキュメント CAS。 すべての生成 DocDB 書き込みは、結果ドキュメントの _id(= wf2des 行 id)と attempt に対する compare-and-swap です。取って代わられた attempt のゾンビワーカーは その書き込みをコミットできず、その遅延 Webhook は no-op です — フェンシングのペア (wf2des_id, attempt) が Webhook を通じてエコーバックされ、バックエンドが attempt ガード付きで行を進めます。他に CAS はありません: 内部実行は行を持たず、コンテンツアドレス指定 / LWW の出力ドキュメントによってのみフェンシングされます。

2. Pin された入力、fail-closed。 inputs ブロックは parse の最初の行為として pin され、assemble の最初の 行為として再水和されます。再水和時のいかなるハッシュ不一致も、フォールバックするのではなく 中止 します。 したがって実行は常に、pin した正確なルールリビジョン、コンポーネント snapshot、LLM/prompt バージョンに 対して組み立てます — 決してドリフトした「最新」ではありません。完了した生成は 決して再処理 されてフル置換にはなりません。再実行はコミット済みの人間イベントデータを異なる非決定的な spec で上書きしてしまう ためです。ターミナル行は最終であり、ワイヤーフレームの再実行は新しい行を作成します。

3. 決定的な縫合 + 自己完結型 spec。 同じ LLM 判断が与えられれば、縫合、validator、confidence 数式はすべて 同じ出力を生成します — フェンスされた 2 つの LLM ステップのみが非決定的で、その出力はエビデンスと共に保存されます。 結果の spec は自己完結型(style_bindings、layer_path、埋め込み bbox、image_slots)であるため、plugin は何も再解釈 することなくそれを決定的にマテリアライズします。

まとめると: 生成実行は 2 つの LLM 判断 まで 再現可能であり、それらの判断が供給するすべてはそれらの純粋関数です。 非決定性はフェンスに閉じ込められ、パイプラインの残りはリプレイ可能です。


ルールリビジョン上のガイドラインボード

セクションごとの選択呼び出しは デザインシステムのガイドラインボード画像 を vision リファレンスとして添付します — そして boards は別途キュレーションされたセットではありません。それらは pin された design_rule リビジョンのソースボード です: 取り込み時にルール抽出が読み取ったのと同じガイドラインボードで、リビジョン上に boards[] として保存されます。1 つの pin、2 つの消費者 — assemble 時、pin されたリビジョンの再水和は、マージされた RuleSet(決定的 validator のプログラム)と リビジョンのボード画像(S3 から読み込まれ、すべてのセクション選択呼び出しに vision プレフィックスとして添付)の 両方 を返します。再水和は fail-closed です: pin されたリビジョンドキュメントの欠落 または ボード画像の欠落は ContractFailure であり、pin されたリファレンスなしで組み立てるのではなく実行を中止します。ルールリビジョンが登録されていない場合、boards もルールもありません: pin は None となり、validator は明示的な no_rules 経路を取ります。

boards は各選択プロンプトの先頭に配置され、セクション間で共有されるプロバイダキャッシュのプレフィックスを形成します。そして アドバイザリのみ です: rules digest と同様、選択に影響を与え — LLM はスタイリングと用法がデザインシステムに合うコンポーネント/バリアントを優先できます — が、決定的な縫合・validator・計算された confidence を上書きすることはなく、LLM がそれらを満たすために id や slot を捏造することは決してありません。boards を与える場合、strong tier は vision 対応モデルでなければなりません。再現性に別個の set hash は不要です — boards はルールリビジョンのイミュータビリティに乗るため、pin されたリビジョンがルールとリファレンス画像の両方を固定します。これにより LLM フェンス は保たれます(boards は既存の選択呼び出しに乗り、新しい呼び出しではありません)。

セクション並列性

strong-tier の選択ステップは セクションを独立に並列で 決定します。2 つの帰結が直接続きます。

  • 実時間は最も遅いセクションであり、合計ではありません。 選択中にセクションは互いに依存しないため、並行して 決定されます。フェーズのレイテンシは合計ではなく単一の最も遅いセクションによって境界されます。(ソフト p50 ターゲット: confirm→spec は 2 分未満。)
  • Prompt キャッシュが静的プレフィックスを共有します。 すべてのセクションのプロンプトは同じ静的プレフィックス — 指示と rules digest — を共有し、それがキャッシュ されてセクションリクエスト間で再利用されます。セクションごとのエビデンス(WF セクション、そのフィルタ済み候補セット、memo intent) のみが変わります。これにより多数の小さなセクション判断が 1 つのモノリシックなプロンプトより安価になり、 クリーンなレビュー帰属のために各判断を 1 セクションのエビデンスにスコープしたまま保ちます。

セクション並列性が、エンジンが 1 つの巨大な選択パスではなくセクションごとの 境界された LLM 呼び出しを許容できる 理由です: 並列性がコールごとのレイテンシを隠し、共有されたキャッシュ済みプレフィックスが多数のコールのコストを 1 つのコストに近く保ちます。