ADR-0036 — folio-vocabulary glossary derive + partition

Status: accepted · Date: 2026-06-01 · folio v0.5.0-draft · folio が folio-framework 語の canonical 定義を上流で author→ship、 consumer は derive (自動 mark)、 描画は hover tooltip のみ (glossary.html は nav/index から到達する独立辞書、 用語 mark から直接 deep-link しない)。 closed (folio 所有・自動 derive) / open (consumer-domain・#110 手動 best-effort) の分割を明文化。 completeness は ADR-0034 §2.8 の best-effort tier を保存し新 REQ で extend (supersede しない)。 companion ADR-0035 (nav) に depends

§1. Context

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 承認)

§2. Decision

§2.1 folio が canonical folio-vocabulary を author→ship、 consumer は derive (ADR-0034 §2.8 を extend)

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.yamlplugin-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.2 分割ルールの明文化 + vocabulary.yaml domain namespace (P-5 cross-layer)

用語を 2 tier に分割し規約化する:

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。

§2.3 completeness は best-effort を保存 (REQ-GLOSS-001 据置 + 新 REQ-GLOSS-002 追加、 ADR-0034 を supersede しない)

これは本 ADR の最重要規律である。 「folio-closed は closed set ゆえ機械列挙可能 → NLP 不要で全 occurrence を auto-mark できる」という推論は 非 sequitur である: ADR-0034 §2.8 が auto-detect を却下した理由は 自然語 prose 中の全 occurrence を誤検出なく拾うのが NLP 難問である点 (例: specspecialist の一部、 SoT が code literal 内、 引用例の中の用語)。 これは集合列挙の問題ではない — closed set は集合を列挙できるだけで occurrence 検出の困難を解かない (現 mask 機構の line-granular hole = task #112/#116/#119 を継承する)。

ゆえに:

すなわち ADR-0035 決定 1 の「機械検証」は glossary については 「ship された定義の consistency / parity を機械検証する」意味であり、 「全 folio-term occurrence が mark 済」を normative 保証する意味ではない

§2.4 描画 = hover tooltip のみ (single-SoT derive、 旧 click→glossary.html は S4b-2 dogfood で routing 衝突が判明し撤回)

同じ 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-tooltipfix 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) かのみとなる。

§2.5 enforcement = folio validate に glossary gate 追加

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)。

§3. Consequences

Positive

Negative

Neutral / TODO

§4. Alternatives Considered

採否
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

§5. Trace