criterion-c (1.0.0 「実用に耐える」判断) で user が公開 architecture の folio-self-spec 図5 の subgraph 多行タイトル (「7 並列固定」等) が枠/子ノードに overlap しているのを発見した。 この種の視覚欠陥は過去の mermaid 問題 (#121 / #123) も全て人間の目視で発見されており、 folio validate の機械 gate を素通りしていた。
根本原因は構造的である: folio validate は pure-bash で動き、 mermaid が render した後の DOM 幾何 (getBoundingClientRect 座標) を観測できない。 link-integrity / jsonld / EARS 等の構造は検査できるが、 「render しないと存在しない」テキスト-ブロック overlap は static 解析の原理的死角である。 floor (REQ-VER-021 render-safety gate、 Slice B) は既知の overlap-prone パターン (<pre class="mermaid"> 内の subgraph 多行タイトル) を static pattern-lint するに留まり、 「任意の」幾何 overlap は捕捉できない。
一方 ADR-0028 は「ceiling (Phase F の LLM review agent) は非決定的ゆえ CI gate に不適 = authoring advisory」と定義していた。 render geometry の検査は LLM でなく 決定的 (vendored mermaid + pinned browser を固定すれば座標は再現する) であり、 ADR-0028 の「ceiling」語が想定した非決定 LLM ceiling とは別カテゴリである。 ゆえに render-safety の上層 (ceiling) を CI に搭載するには、 「ceiling = CI 不可」 framing の射程を明確化する必要がある。
render-safety verification を二層で構成する:
folio validate の render-safety gate (bash、 REQ-VER-021)。 全 consumer に配布。 render 後 DOM を見れないため既知の overlap-prone パターン (subgraph 多行タイトル) を deterministic に static pattern-lint する。tests/render-gate/)。 browser 依存ゆえ consumer の folio validate には入れず、 folio 自身の CI で dogfood する (CI-only)。floor は「既知パターンを全 consumer に安価に配る」/ ceiling は「任意の幾何 overlap を folio 自身で網羅的に検査する」の役割分担で、 floor が原理的に拾えない欠陥を ceiling が埋める (REQ-VER-021 の二層 prose を機構として実現する)。
ADR-0028 は ceiling を一貫して「LLM ceiling」 (Phase F の spec-review-* agent) と限定して定義済で、 それが「CI gate に不適」とした根拠は LLM agent の非決定性 (出力が再現しない) であった。 本 ADR は「ceiling」を 2 種に明示分割し、 この CI 不適格根拠が決定的 ceiling に及ばない点を clarify する:
spec-review-* agent)。 非決定的ゆえ CI 非搭載・authoring advisory (ADR-0028 のまま不変)。すなわち ADR-0028 の CI 不適格根拠は (a) LLM ceiling の非決定性に紐づき、 (b) 決定的 visual ceiling を排除しない。 CI 採用の唯一の基準は「決定的か」であり、 LLM/render の別ではない (frozen な ADR-0028 本文は不変、 本 §2.2 はその適用解釈を clarify (明示化) する — ADR-0028 が広く ceiling=CI 不可と述べていたのを狭めるのではなく、 元から LLM 限定だった射程の外に決定的 ceiling が在ることを示す)。
visual ceiling を blocking merge gate にする正当化は決定性である。 三重 pin で render を固定する:
architecture/assets/mermaid.min.js、 rules §8 REQ-DA-JS-2) — layout アルゴリズムを固定。requirements.txt で版固定) — chromium revision を固定。fonts-noto-cjk を install) — text shaping を固定。 spec 図は CJK label を含むため font 環境が text 幅に効く。detector の主軸 (多行 cluster-label の height) は font-size 駆動で行数に比例するため font 差に頑健。 面積比 detector は text 幅依存だが mermaid dagre layout が node box を label 幅に self-normalize するため conservative threshold を跨ぎにくい (font 摂動の実測で交差比は不変)。 三重 pin により render は再現的で、 blocking が正当化される。
<pre class="mermaid"> 数 (HTML コメント内は除外) で導出する。constitution.html は編集禁止の不変資産 (P-10 amendment は user 承認必須) ゆえ、 blocking gate で overlap を検出しても救済不能 (frozen deadlock) になる。 これを advisory (表示のみ・非 blocking) で扱う。 判定は doc 自身の @type==FolioConstitution で行い (mention するだけの README/relations は blocking のまま)、 floor (folio validate) が FolioConstitution を scan 除外するのと同基準とする。ceiling が検出するのは flowchart/graph の 3 class: (1) 多行 cluster-label (subgraph タイトルの縦 overflow)、 (2) label-over-foreign-node (text が自分以外の node 矩形と交差)、 (3) node-over-node (layout collision)。 非 flowchart 図 (sequence/state) は .node/.cluster を出さず vacuous、 横溢れ / viewport clip は未対応 (follow-up folio-w5z)。 「任意 overlap の完全網羅」は normative 化しない (best-effort tier): render 環境差 + 図 type 多様性ゆえ no-gaps 保証は過大で、 floor/ceiling の二層分業 (REQ-VER-021) を精緻化するに留める (完全網羅を約束する supersede ではない)。
ceiling の WHAT は REQ-VER-021 の二層 prose (「任意 overlap の網羅は browser-render を要する ceiling の領分」) を anchor とし、 専用 REQ-VER-022 は defer する: folio の既存 ceiling (Phase F spec-review-fidelity) も独立 REQ を持たず floor REQ の prose 内に位置づけられる先例に倣う (HOW = tests/render-gate/ は P-11 隔離・executable、 P-13 WHAT↔HOW 分離)。
tests/render-gate/README.md で部分 trace)。 将来 ceiling を spec REQ で formalize するか判断する際は、 本 ceiling が blocking merge gate である点 (authoring-advisory な spec-review-fidelity ceiling とは非対称) を材料に含める — blocking gate は verification.html §3.7 coverage RTM の被覆対象外で gap 可視化の網から外れるため、 REQ trace の要否判断が advisory ceiling とは異なりうる。| 案 | 採否 |
|---|---|
| 二層 (static floor 全配布 + deterministic browser ceiling CI-only blocking、 採用) | 採用 — floor が原理的に見れない render 幾何を ceiling が実ブラウザで埋める。 決定的ゆえ blocking、 browser 依存ゆえ consumer 非配布の folio dogfood。 完全網羅は best-effort (flowchart 3-class) で REQ-VER-021 を精緻化 |
| ceiling も全 consumer に配布 (browser gate を consumer validate に同梱) | 不採用 — browser + chromium download は consumer の bash/yq/jq stack に重く、 folio の「pure-bash floor を全配布」の軽量性を壊す。 ceiling は folio dogfood に留め、 consumer には floor (static lint) のみ配る |
| ceiling を advisory (report-only、 non-blocking) にする | 不採用 — render geometry は決定的ゆえ ADR-0028 の CI gate 基準を満たし blocking 可能。 advisory に格下げすると視覚欠陥を merge block できず検出力を活かせない。 fail-closed + 三重 pin + constitution carve-out で blocking を安全化 (§2.3/§2.4) |
| floor (static lint) だけで完結させる (ceiling を作らない) | 不採用 — pure-bash は render 後 DOM 幾何を原理的に見れず、 既知パターン以外の任意 overlap (図5 以外) を捕捉できない。 criterion-c の視覚欠陥クラスは static 解析の死角ゆえ browser ceiling が要る |
| 任意 overlap の完全網羅を normative 化 (全図 type・横溢れ含め no-gaps 強制) | 不採用 — render 環境差 + 図 type 多様性ゆえ no-gaps 保証は過大で、 REQ-VER-021 の floor/ceiling 二層分業を逸脱。 flowchart 3-class の best-effort に留め generality は folio-w5z へ漸進 (§2.5) |
| ADR-0028 を改訂して「ceiling」定義を直接書き換える | 不採用 — ADR-0028 は frozen (CLAUDE.md §2、 P-10 隣接の historical record)。 本文を触らず、 本 ADR が「ceiling 語を二分し CI 基準=決定性を render ceiling に適用」の適用解釈を授権する (reverse-link + prose で trace) |
folio validate の gate 化 (REQ-VER-021 + rules §4.5 authoring rule + sandbox) / Slice C (be58ef4) ceiling = playwright 視覚 render gate を CI 追加 (tests/render-gate/、 CI 初実走 green 実証)。tests/render-gate/) / P-13 (WHAT↔HOW 分離 = ceiling は executable HOW、 WHAT は REQ-VER-021 prose) / P-10 (constitution immutability = advisory carve-out の根拠)。 本 ADR は constitution を touch しない。