folio の用語のうち consumer の domain 用語 (例: python project の python 用語) は folio が解説不能だが、 folio architecture の「作法」に固有の用語 (spec / ADR / constitution / EARS / invariant / SSoT / xref / vocabulary / inventory / prime / cluster / dogfood / caller-marker 等) は folio 所有・closed・stable である。 ゆえに folio が canonical 定義を上流で一度 author し、 テンプレートと共に配布すれば、 consumer の architecture/ で hover tooltip 解説を再現性を保って提供できる。 境界は明快: consumer-domain-vocabulary (consumer 所有・folio 解説不能) vs folio-framework-vocabulary (folio 所有・実現可能・全 consumer で再利用)。
前史 (ADR-0034 §2.8 / rules §9.5 REQ-GLOSS-001、 task #110): 「用語 hover tooltip を機械的に全網羅するのは困難 (自然語の全 occurrence 検出は NLP 難問) + 手動リンクは再現性が崩れる」ゆえ glossary は explicit-mark のみ・best-effort tier・auto-detect / gap-lint しないと確立済。 本 ADR の novelty は分割にある: folio-framework 語は closed set かつ folio 所有ゆえ canonical 定義を folio が一度 author→ship → consumer は derive で受け取る (consumer は folio 語を一切書かない)。 これにより #110 が諦めた「全網羅は無理」の問題を、 folio が所有・固定できる部分集合だけ切り出して機械配布することで解く。
貫く 3 層原則 (ADR-0033): 人間 = 意味を author / 機械 = 純構造を derive / 意味の人間向けレンダリングだけ co-author+enforce。 glossary の 定義文は derive 不可 (誰かが author した意味) だが、 folio-framework 語については folio maintainer が上流で一度 author するため、 consumer 視点では derive になる。 本 ADR は companion ADR-0035 (walkable nav) に depends する (glossary.html も歩ける website の一部として nav に載る)。 status = accepted (S5 統合検証 PASS 後 user 承認)。
folio は folio-framework 語の canonical definition を vocabulary.yaml に上流で author し (folio が所有・SSoT)、 これを ship する。 consumer 側は folio-closed 語を derive (自動 mark) で受け取り、 自身では folio 語の定義を書かない。 これは ADR-0034 §2.8 (glossary Class B = vocabulary.yaml SSoT + HTML view は生成 projection) の extend であり、 SSoT model・hybrid architecture をそのまま継承する。
配布機構 (#130 grill 2026-06-02 確定): vocabulary.yaml は plugin-resident SSoT として folio plugin に同梱し (現 architecture/vocabulary.yaml)、 folio build/fix が $CLAUDE_PLUGIN_ROOT の vocabulary.yaml を直読みして consumer 側の glossary を derive/mark する。 consumer には vocabulary.yaml を置かない (ADR-0024 init は seed しない) — folio を唯一の canonical SSoT に保ち (P-5 1 canonical name / P-7 定義二重化禁止)、 consumer 側 copy の drift を構造排除する (copy 配布案は canonical を 2 箇所に分裂させるゆえ却下)。 実装は folio_glossary_map の探索 candidate に $CLAUDE_PLUGIN_ROOT/architecture/vocabulary.yaml の plugin-resident fallback を追加する (現 root_abs + 親探索の後段、 self-host 時は現探索が既に hit するゆえ additive)。
用語を 2 tier に分割し規約化する:
domain: folio-closed) = folio 所有・固定。 folio が canonical 定義を ship し consumer 側で 自動 derive/mark。domain: consumer、 python 等) = consumer 所有・folio 解説不能。 #110 の手動 best-effort のまま (explicit-mark)。vocabulary.yaml schema に terms[].domain: folio-closed | consumer の namespace 区別を ship 前に追加する。 これは P-5 (1 entity = 1 canonical name) の cross-layer 衝突回避規律である: folio-closed 語 (xref 等) と consumer-domain 語 (同綴の別概念) が canonical ID 空間で衝突し自動 mark が誤定義を貼るのを構造排除する。 fix (auto-mark、 §2.3) / build (glossary.html derive) / validate (gate) は domain: folio-closed 語のみを対象とし、 consumer-domain 語への越権 (自動 mark) を起こさない。 現 vocabulary.yaml の語は全て folio-closed。
これは本 ADR の最重要規律である。 「folio-closed は closed set ゆえ機械列挙可能 → NLP 不要で全 occurrence を auto-mark できる」という推論は 非 sequitur である: ADR-0034 §2.8 が auto-detect を却下した理由は 自然語 prose 中の全 occurrence を誤検出なく拾うのが NLP 難問である点 (例: spec が specialist の一部、 SoT が code literal 内、 引用例の中の用語)。 これは集合列挙の問題ではない — closed set は集合を列挙できるだけで occurrence 検出の困難を解かない (現 mask 機構の line-granular hole = task #112/#116/#119 を継承する)。
ゆえに:
domain: folio-closed 語について folio fix が doc 初出の canonical occurrence を best-effort で auto-mark する」。 主語は build でなく fix (#130 grill 2026-06-02 確定): auto-mark = spec body に term mark (<span class="term">、 hover tooltip のみの no-JS span、 click→glossary は §2.4 で撤回) を挿入する spec mutate ゆえ、 ADR-0035 §2.3 の「fix = graph を整える (spec mutate) / build = 派生 view を出す」分離に従い fix の領分とする (既存 fix Pass 3 = xref auto-wrap / Pass 4 = glossary tooltip populate と同系譜、 build が spec を mutate する設計矛盾を回避)。 全 occurrence の no-gaps normative 化はしない (それは ADR-0034 が却下した NLP-hard occurrence 検出を再燃させ REQ-GLOSS-001 の supersede = P-10 risk になる)。すなわち ADR-0035 決定 1 の「機械検証」は glossary については 「ship された定義の consistency / parity を機械検証する」意味であり、 「全 folio-term occurrence が mark 済」を normative 保証する意味ではない。
同じ ship 済 vocabulary.yaml を 2 面に derive する: (1) spec-body の hover tooltip (no-JS CSS-only、 ADR-0034 §2.4 と同機構)、 (2) nav/index から到達する独立辞書 glossary.html ページ。 spec-body の用語 mark から glossary.html へ deep-link はしない (hover-only)。 供給者は artifact 別 (#130 grill 確定): spec-body の marked span (<span class="term">、 hover tooltip のみ) の data-tooltip は fix Pass 4 が plugin-resident vocabulary.yaml の definition から populate し (§2.3 の auto-mark と同 subcommand = spec mutate)、 glossary.html ページは build が同 vocabulary.yaml から derive する生成 projection (view 出力、 二重化回避 = P-7、 definition を 2 箇所に author しない double-SoT 構造排除)。 これは ADR-0034 §2.9 が roadmap (1.x) に置いた「生成 HTML glossary view」を pre-1.0.0 に timing pull-forward するものであり、 §2.9 自身が「非破壊で後付け可」と宣言した項目の timing 変更で決定内容の supersede ではない。
amend (folio-ovi、 2026-06-03): 当初 §2.4 は描画を hover tooltip + click→glossary.html 両方とし、 auto-mark を <a class="term" href="../glossary.html#term-<slug>"> anchor で実装した (S4b-2 SHIP、 commit 6648c11)。 しかし SHIP 後の dogfood で doc 名と被る用語 (constitution / ADR / inventory / prime / vocabulary 等) を glossary へ deep-link すると、 本来その語の実体 doc (例 constitution.html) へ飛ぶべき導線と routing が衝突・冗長化することが判明した。 ゆえに描画を hover-only に転換し、 用語 mark を <span class="term"> (href なし) に統一する。 glossary.html ページは nav/index から到達する独立辞書として存続する (deep-link を失うのみで辞書自体は不変)。 REQ-GLOSS-001/002 は共に span 形に統一され、 区別は manual (001) か auto (002) かのみとなる。
glossary.html 全体が vocabulary.yaml からの regen (folio build emit) と byte 一致 (definition drift + 構造 drift 双方を含む = build derive の証明 + 手編集検出)。 実装は nav-regen-drift gate に畳む (index.html と同型の regen-drift、 §2.5 冒頭の 3 gate に新 gate を増やさず glossary 特化を追加)。 同一 canonical 用語を別途 prose で重複定義しない (P-5 SSoT 唯一性)。glossary.html の term 集合 == vocabulary.yaml の canonical 集合 (過不足の対称差を報告し drift の所在を surface)。data-term resolve + tooltip consistency、 ADR-0034 §2.6) を folio-closed 語彙で再利用。 §2.3 により 非 opt-in は no-op (keystone)、 opt-in でも best-effort tier (no-gaps normative にしない)。slug 化規約 (#term-<canonical>、 canonical 名の space/記号の slug 化) は glossary.html ページ内部の <dt> term id に用いる (nav/index からの直 URL 到達 + in-page 索引用; spec-body の用語 mark は hover-only ゆえ #term- へ deep-link しない)。 実装で確定する (empty-slug fallback + 一意性 gate は S4c)。
vocabulary.yaml SSoT + data-term tooltip + folio_glossary_map / folio_glossary_populate_doc を再利用。 ADR-0034 を supersede せず extend、 constitution 不変。domain field 追加で既存 13 語に tag 付け + parser/gate の対応が要る。spec / ADR / constitution / invariant + inventory / prime / cluster / vocabulary。 残り (EARS / SSoT / xref / dogfood / caller-marker / reverse-relation 等) は S4 author 中 + 1.x で漸進追加 (§2.3 best-effort 方針 = no-gaps normative にしないゆえ starter からの漸増は valid)。glossary.html 内 term id の slug 化規約 / JS rich tooltip (roadmap) は実装/後付け。| 案 | 採否 |
|---|---|
| ship 語彙 + derive (hover-only tooltip + 独立 glossary.html)、 completeness best-effort (採用) | 採用 — folio-closed を folio が author→ship、 consumer derive。 描画は hover tooltip のみ (当初 hover+click 両方で採用したが S4b-2 dogfood で doc 名 routing 衝突が判明し click→glossary を撤回 = §2.4 amend / §5 trace folio-ovi)。 glossary.html ページは nav/index 到達の独立辞書として存続。 completeness は §2.3 で best-effort 保存 (REQ-GLOSS-001 据置 + REQ-GLOSS-002 追加) し ADR-0034 を extend (supersede せず) |
| folio-term completeness を normative 化 (全 occurrence mark を no-gaps で強制) | 却下 — 「closed-set→NLP 不要」は非 sequitur (occurrence 検出が NLP-hard、 集合列挙でない)。 normative 化は ADR-0034 §2.8 が却下した問題を再燃させ REQ-GLOSS-001 supersede = P-10 risk。 best-effort に留める |
hover+click 両方 (用語 mark から glossary.html#term-<slug> へ deep-link) — 当初採用 (S4b-2)、 後に撤回 | 撤回 (folio-ovi、 2026-06-03) — S4b-2 で <a class="term" href> anchor として実装したが dogfood で routing 衝突が判明 (詳細は §2.4 amend / §5 trace folio-ovi 項)。 採用案 (hover-only + 独立 glossary.html 存続) に転換。 hover-only と独立辞書ページの存続は両立し SoT は 1 つ (二重化なし) |
| hover も click も無し (glossary.html ページも作らない) | 不採用 — folio 所有の closed 語は canonical 辞書を再現性付きで配れる (#110 の射程外を切り出す本 ADR の核)。 独立 glossary.html は nav/index 到達の参照価値があるゆえ存続させる |
| glossary を DB / 外部 store を SoT にする | 不採用 (ADR-0034 が DB-as-SSoT を却下、 継承)。 vocabulary.yaml (rules §3 の YAML 例外) を SoT に保ち glossary.html は derive projection |
| nav と 1 ADR に束ねる | 不採用 — supersede risk が glossary 側のみ集中ゆえ nav の clean な extends と混ぜると ADR-0034 への関係が曖昧化。 ADR-0035 (nav) と分離し本 ADR は ADR-0035 に depends |
$CLAUDE_PLUGIN_ROOT 直読み・consumer に vocabulary.yaml を置かない、 §2.1; copy 配布は P-5 分裂ゆえ却下)、 (2) auto-mark 責務 = fix (REQ-GLOSS-002 主語 build→fix、 spec mutate ゆえ ADR-0035 §2.3 の fix/build 分離に従う、 §2.3/§2.4)、 (3) starter set = 中核 8 語 (§3)。 proposed のうちに §2.1/§2.3/§2.4/§3 を amend。<a class="term" href="../glossary.html#term-<slug>"> anchor で SHIP、 commit 6648c11) 後の dogfood grill で、 auto-mark の deep-link が doc 名と被る用語 (constitution / ADR / inventory / prime / vocabulary 等) で実体 doc への本来の導線と routing 衝突すると判明。 描画を hover-only に転換 — §2.4 を hover+click→hover-only に amend、 §2.3/§2.4 の element を <a>→<span> に統一、 §4 採用行を hover-only へ・旧 hover+click を撤回行へ反転。 glossary.html ページは nav/index 到達の独立辞書として存続 (deep-link を失うのみ)。 REQ-GLOSS-001/002 が span 形に統一 (区別は manual/auto のみ)。 verification REQ-VER-019 / rules §9.5 も span 統一に同期。