kairos-chain 3.81.0 → 3.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +102 -0
- data/lib/kairos_mcp/version.rb +1 -1
- data/templates/knowledge/html_slide_deck_authoring/html_slide_deck_authoring.md +401 -0
- data/templates/skillsets/kairos_hook_projector/hooks/readable_gate.rb +135 -4
- data/templates/skillsets/kairos_hook_projector/mode_hooks/_EXAMPLE.json +3 -1
- data/templates/skillsets/kairos_hook_projector/skillset.json +1 -1
- data/templates/skillsets/kairos_hook_projector/test/mutation_check_readable_gate.rb +89 -4
- data/templates/skillsets/kairos_hook_projector/test/test_readable_gate.rb +180 -0
- data/templates/skillsets/minimum_nomic/README.md +88 -5
- data/templates/skillsets/minimum_nomic/bin/control_standard_permissive.md +17 -0
- data/templates/skillsets/minimum_nomic/bin/predict_divergence.rb +505 -0
- data/templates/skillsets/minimum_nomic/bin/score_readback.rb +234 -0
- data/templates/skillsets/minimum_nomic/bin/self_recognition.rb +257 -0
- data/templates/skillsets/minimum_nomic/skillset.json +2 -2
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e601238b25375836907f7eec155beb0297e940cd5fd419ea855b7d48a3335993
|
|
4
|
+
data.tar.gz: 1c720eaa88d3204eedc436e38cdabaa3e79df3b9b5aca6260c925ec4173c6e62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d13dbb392110ebc2f5f913bc38e370f7c4c36ee8067d69d060ab4379f1a34cc9db98a37ee09b845d633a4c76821194bb5aa8eaeef6db6c77e43784f7831150f7
|
|
7
|
+
data.tar.gz: 34eca89babce68b01e805b6510967f0d1e2dca0faa0a856d1ec7a8881fd7e4a00cf90932c69ed7685cefe89e482144566ca4733d1efc433c2bf0b0038d9080af
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,108 @@ All notable changes to the `kairos-chain` gem will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [3.83.0] - 2026-09-01
|
|
8
|
+
|
|
9
|
+
### Added — readable_gate measures sentence length
|
|
10
|
+
|
|
11
|
+
`kairos_hook_projector` 0.6.0 → 0.7.0. The gate now reports three sentence
|
|
12
|
+
metrics on every turn (`sentences`, `sentence_p90`, `sentence_max`) and honours
|
|
13
|
+
two new thresholds, both off unless a mode names them:
|
|
14
|
+
`max_sentence_chars_p90` and `sentence_min_count`.
|
|
15
|
+
|
|
16
|
+
Why it was missing: the readable-output norm this gate exists to enforce names
|
|
17
|
+
long sentences as its first observed failure form, and says "split overlong
|
|
18
|
+
sentences" outright. Nothing in `measure()` was sentence-aware. The one symptom
|
|
19
|
+
the norm names by hand was the one nothing measured, while the line cap — which
|
|
20
|
+
the same norm calls a soft target rather than a gate — was enforced as a hard
|
|
21
|
+
block.
|
|
22
|
+
|
|
23
|
+
The cap is on the 90th percentile, not the mean and not the maximum: a mean
|
|
24
|
+
hides the tail that does the damage, and a maximum fails a good answer for its
|
|
25
|
+
one long sentence. Nearest-rank, so the number reported is the length of a
|
|
26
|
+
sentence actually in the message. The length announcement does not clear it,
|
|
27
|
+
for the diagram floor's reason — announcing that a message is long says nothing
|
|
28
|
+
about whether its sentences are.
|
|
29
|
+
|
|
30
|
+
`sentence_min_count` is not a convenience. Nearest-rank puts the 90th
|
|
31
|
+
percentile at the last element for every count under ten, so below that floor
|
|
32
|
+
the cap would be a maximum cap under another name.
|
|
33
|
+
|
|
34
|
+
What counts as a sentence, each rule with a killed mutation behind it:
|
|
35
|
+
|
|
36
|
+
- Sentences never span a line. A bullet with no terminating punctuation is one
|
|
37
|
+
sentence the length of its line, which is what it costs to read rather than
|
|
38
|
+
an artefact of the author's punctuation.
|
|
39
|
+
- Headings, table rows, horizontal rules and blockquotes are not sentences. A
|
|
40
|
+
seven-column table row measured as one reads as a single 200-character
|
|
41
|
+
sentence and takes over every percentile in the message; and a quotation
|
|
42
|
+
cannot be shortened without cutting quoted facts, which a mode's own rewrite
|
|
43
|
+
instruction is likely to forbid — leaving "stop quoting sources" as the only
|
|
44
|
+
compliance.
|
|
45
|
+
- A list marker is stripped rather than skipped. The text after it is prose the
|
|
46
|
+
reader reads, and skipping list items would exempt most bullet-written output.
|
|
47
|
+
- A URL collapses to one character: it is clicked, not read.
|
|
48
|
+
- An ASCII full stop splits only before whitespace. Without that condition
|
|
49
|
+
`readable_gate.rb`, `v0.4.6` and `3.82.0` shatter into fragments and the
|
|
50
|
+
measured tail collapses towards zero — a metric reporting every message as
|
|
51
|
+
readable.
|
|
52
|
+
|
|
53
|
+
Declared and not closed: prose moved inside a fenced block is not measured.
|
|
54
|
+
That is the hole the line count has always had, and closing it for one metric
|
|
55
|
+
only would leave the two disagreeing about what the message contains.
|
|
56
|
+
|
|
57
|
+
The core ships no number. `--report` gained `sent`, `sent_p90` and `sent_max`
|
|
58
|
+
columns and is where a mode's cap comes from; `mode_hooks/_EXAMPLE.json`
|
|
59
|
+
documents both keys and deliberately omits values, since the right one depends
|
|
60
|
+
on what the author writes and in which script.
|
|
61
|
+
|
|
62
|
+
- Cost: 0.9 ms of a 3.2 ms full measurement on a 25,719-character message,
|
|
63
|
+
against the hook's 9.5 s budget.
|
|
64
|
+
- Tests: 168 runs, 997 assertions, 0 failures (was 152 runs; 16 new fixtures).
|
|
65
|
+
Mutation sweep filtered to the new family — 19/19 killed, 0 survived, 0
|
|
66
|
+
anchor-not-found, source restored byte-identical, 11-file baseline green at
|
|
67
|
+
325 runs.
|
|
68
|
+
- One existing mutation anchor (M39) was retargeted: the sentence columns were
|
|
69
|
+
inserted into the argument list it points at, and a stale anchor reports
|
|
70
|
+
ANCHOR NOT FOUND rather than a survivor.
|
|
71
|
+
|
|
72
|
+
## [3.82.0] - 2026-08-31
|
|
73
|
+
|
|
74
|
+
### Added — L1 knowledge: html_slide_deck_authoring
|
|
75
|
+
|
|
76
|
+
New gem-bundled L1 knowledge entry `html_slide_deck_authoring` (v1.0), written
|
|
77
|
+
by the operator from the 2026-08 build of a bilingual lab-meeting deck: 24 main
|
|
78
|
+
slides plus a 58-slide appendix, ja/en generated from one source, click-driven
|
|
79
|
+
builds, a searchable index, and a handout PDF.
|
|
80
|
+
|
|
81
|
+
Contents: the five-module split (`kit` / `txt_*` / `viz_*` / `make_*` /
|
|
82
|
+
`check_*`) and why kit and viz must not merge — they constrain different units
|
|
83
|
+
(viewport height vs SVG user units); the one-slide budget; the rule that every
|
|
84
|
+
number on a slide is read from the same context the report reads, never written
|
|
85
|
+
into prose, with the sibling deck that still said "sweep in progress" after the
|
|
86
|
+
sweep finished as the counter-example; the three ways a number was actually
|
|
87
|
+
misread on the day (missing denominator, two axes in one sentence, a range
|
|
88
|
+
whose span was not named); inline SVG rather than rasterised PNG (CJK fonts,
|
|
89
|
+
scaling, tooltips); the animation safety direction — draw the finished state
|
|
90
|
+
and animate backwards from it, so print, `prefers-reduced-motion`, CSS-off and
|
|
91
|
+
JS-off all render something true; two checkers with different jurisdictions
|
|
92
|
+
(inside the SVG vs the slide's vertical budget); the handout-PDF variant and
|
|
93
|
+
the values a JS-free build leaves blank; and a searchable index whose filter
|
|
94
|
+
must listen on the `input` event, since CJK IME text never reaches `keydown`.
|
|
95
|
+
|
|
96
|
+
- Shipped to both `knowledge/` and `templates/knowledge/`, byte-identical, so
|
|
97
|
+
the next `system_upgrade` on the authoring instance reports UNCHANGED rather
|
|
98
|
+
than `user_modified` — a divergent instance copy wins silently over every
|
|
99
|
+
later template update.
|
|
100
|
+
- Two neighbouring entries (`frontend_design`, `html_to_pdf_conversion`) are
|
|
101
|
+
instance-local and do not ship, so the `[[...]]` links to them dangle on a
|
|
102
|
+
fresh install. Same convention as `loop_engineering_patterns`.
|
|
103
|
+
- Not multi-LLM reviewed. This is a record of what was measured while building,
|
|
104
|
+
not a design under review. It ships as written apart from a `version` field,
|
|
105
|
+
a folded-scalar fix (`>` to `>-`) so the description does not carry a
|
|
106
|
+
trailing newline into the `knowledge_list` table, and one paragraph stating
|
|
107
|
+
the boundary against the two neighbours.
|
|
108
|
+
|
|
7
109
|
## [3.81.0] - 2026-08-27
|
|
8
110
|
|
|
9
111
|
### Changed
|
data/lib/kairos_mcp/version.rb
CHANGED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: html_slide_deck_authoring
|
|
3
|
+
description: >-
|
|
4
|
+
Use when building a presentation deck as generated HTML — a self-contained, CDN-free,
|
|
5
|
+
16:9 deck with inline-SVG figures, two languages from one source, PowerPoint-style
|
|
6
|
+
click-driven builds, mechanical layout checkers, a searchable slide index for a large
|
|
7
|
+
appendix, and a handout PDF. Covers the module split, the one-slide budget, the
|
|
8
|
+
"numbers come from the reader, never the prose" rule, how a number on a slide gets
|
|
9
|
+
misread, the animation safety direction, why a regex checker over your own output
|
|
10
|
+
fails silently, and the traps that cost real time. NOT for Markdown slide tools
|
|
11
|
+
(Marp/reveal.js) or for writing the talk's content.
|
|
12
|
+
version: "1.0"
|
|
13
|
+
tags: [slides, presentation, html, svg, bilingual, i18n, ime, animation, pdf, playwright, checker, search, authoring]
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# HTML スライドデッキの作り方
|
|
17
|
+
|
|
18
|
+
生成 HTML でプレゼン資料を作るときの設計方針と手順。2026-08 にラボミーティング用
|
|
19
|
+
デッキ(本編 24 枚+Appendix 58 枚、日英 2 言語、クリック送り、索引、配布 PDF)を
|
|
20
|
+
作り切った経験から。
|
|
21
|
+
|
|
22
|
+
## いつ使うか
|
|
23
|
+
|
|
24
|
+
- 図が主役で、**数値が別の成果物(レポート・解析結果)と一致していないと困る**とき
|
|
25
|
+
- **同じ内容を2言語**で出すとき
|
|
26
|
+
- 発表用と**配布用 PDF** の両方が要るとき
|
|
27
|
+
- PowerPoint を開けない環境で作るとき、あるいは図をコードで生成したいとき
|
|
28
|
+
|
|
29
|
+
使わない場合: Marp / reveal.js で足りるとき。話す内容そのものを考える段階。
|
|
30
|
+
|
|
31
|
+
隣の entry: [[frontend_design]] は見た目の原則と JSON から組む簡易デッキ生成器
|
|
32
|
+
(枚数が少なく図が単純なとき)。[[html_to_pdf_conversion]] は Playwright で PDF に
|
|
33
|
+
焼く手順だけ。ここは**図をコードで生成し、枚数が数十枚に育つ場合**を扱う。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 1. モジュールの分け方
|
|
38
|
+
|
|
39
|
+
5 つに分ける。**混ぜると必ず壊れる。**
|
|
40
|
+
|
|
41
|
+
kit.py CSS・JS・1枚を組む関数(slide / table / tiles / panes / figure)
|
|
42
|
+
txt_*.py 本文。1枚ずつ並べるだけ。ここに geometry を書かない
|
|
43
|
+
viz_*.py 図。インライン SVG を返す関数の集まり
|
|
44
|
+
make_*.py 入口。context を作り、言語を切り替えて両方を出す
|
|
45
|
+
check_*.py 機械検査(後述)
|
|
46
|
+
|
|
47
|
+
**kit と viz を混ぜないこと。** kit は「1枚に置けるもの」を構造として制限する係で、
|
|
48
|
+
viz は「1つの図の中の座標」を持つ係。制限が違う(前者は vh、後者は SVG ユーザー単位)。
|
|
49
|
+
|
|
50
|
+
### 1枚の予算
|
|
51
|
+
|
|
52
|
+
**要点1行 + 図か表1つ + 断片3つまで。** それ以上は Appendix に回す。
|
|
53
|
+
`slide()` で 4 個目の断片を受けたら例外で落とす、くらい強制してよい。制限が無いと
|
|
54
|
+
必ず溢れる。Appendix は枚数無制限にしておくと、本編の圧が逃げる。
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 2. 数値を地の文に書かない
|
|
59
|
+
|
|
60
|
+
**成果物が2つ以上あるなら、数値は必ず共通の reader から来させる。**
|
|
61
|
+
|
|
62
|
+
from make_report import build_context # レポートと同じ reader
|
|
63
|
+
C = build_context()
|
|
64
|
+
... f"偶然の {C['B']['gf_lo']:.1f} 倍"
|
|
65
|
+
|
|
66
|
+
こうすると「レポートだけ更新してスライドが古いまま」が構造的に起こらない。
|
|
67
|
+
|
|
68
|
+
失敗例が実在する: 同じ repo の別デッキは地の文ハードコードで、解析が終わった後も
|
|
69
|
+
「掃引中」と書いたままになっていた。**同じ轍を踏まない。**
|
|
70
|
+
|
|
71
|
+
派生値もヘルパにする。「約 100 倍」と手で書いた箇所が、実際にはモデルごとに
|
|
72
|
+
71〜1,101 倍と桁が違っていた(元資料のモデル横断の丸めを転記していた)。
|
|
73
|
+
`_ratio(C, model)` のような関数にして毎回そこから出す。
|
|
74
|
+
|
|
75
|
+
### 2.1 数値は「軸」と「分母」を言わないと誤読される
|
|
76
|
+
|
|
77
|
+
聞き手は数値を**自分が知っている種類の数値**として読む。実際に起きたこと。
|
|
78
|
+
|
|
79
|
+
- **「53%」を「50% の改善」と読まれた。** 実際は増分の内訳で、追加学習で得た
|
|
80
|
+
0.64 のうち 0.34 がその情報そのもの、という意味。倍率の伸びは +19% だった。
|
|
81
|
+
棒グラフが 50% 伸びて見えないのは正しく、読み手の指摘が正しかった。
|
|
82
|
+
→ タイルの中に**元の3値**(3.40 → 4.05、同じ計算量の対照 3.70)を並べたら通じた。
|
|
83
|
+
- **1つの要点に軸を2つ入れていた。** 「対照の 8.5〜11.7 倍動く」と
|
|
84
|
+
「KEGG は偶然の 2.26 倍」を1文に並べていた。前者は動いた量そのもの、後者は
|
|
85
|
+
その並びの当たり方で、別の軸。単独では何のことか読めない。
|
|
86
|
+
→ 片方を落とし、Appendix に図解で分けた。
|
|
87
|
+
- **「8.5〜11.7 倍」を複数モデルの幅と読まれた。** 実際は**1モデルを2条件で**
|
|
88
|
+
測った幅。もう1つのモデルは 93〜96 倍で、範囲の外にあった。
|
|
89
|
+
|
|
90
|
+
規則にすると:
|
|
91
|
+
|
|
92
|
+
1. **割合を出すなら分母も出す。** 「増分のうち」「最良モデル比」まで書く。
|
|
93
|
+
2. **1文に軸を2つ入れない。**
|
|
94
|
+
3. **範囲を出すなら、何をまたいだ範囲か言う**(モデル/条件/seed)。
|
|
95
|
+
4. 丸めた元値を並べると、聞き手の再計算が**最終桁でずれる**ことがある
|
|
96
|
+
(3.40・3.70・4.05 から計算すると 54%、表示は 53%)。増分の形で出すか、断る。
|
|
97
|
+
|
|
98
|
+
### 2.2 参考文献はその枚のフッターに1回だけ
|
|
99
|
+
|
|
100
|
+
一覧を付録に置くだけだと、聞き手は話を離れて探しに行くことになる。
|
|
101
|
+
**その文献が初めて意味を持つ枚**のフッターに出す。
|
|
102
|
+
|
|
103
|
+
- **出てくるたびに書かない。** ベンチマークの名前は本編の大半の枚に出るので、
|
|
104
|
+
毎回書くと雑音になる。導入する枚に1回だけ。
|
|
105
|
+
- **著者・年までに留める。** 掲載誌まで入れると、注意書きのある枚で行が
|
|
106
|
+
折り返し、ページ番号まで2行に割れる。番号 `[n]` が付録の一覧を指す。
|
|
107
|
+
- 付録にあって本編で使っていない文献は、付録だけに置いたままにする。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 3. 2言語を1つのソースから
|
|
112
|
+
|
|
113
|
+
図のラベルも本文も、同じ `T(ja, en)` を通す。
|
|
114
|
+
|
|
115
|
+
LANG = "ja"
|
|
116
|
+
def set_lang(lang): global LANG; LANG = "en" if lang == "en" else "ja"
|
|
117
|
+
def T(ja, en): return en if LANG == "en" else ja
|
|
118
|
+
|
|
119
|
+
`T` はリストも受けられる(`T(["a","b"], ["x","y"])`)ので、箇条書きにも使える。
|
|
120
|
+
入口は言語ごとに `set_lang()` → 全枚を組む、を繰り返すだけ。
|
|
121
|
+
|
|
122
|
+
**英語は同じ意味でも横に伸びる。** 日本語で収まっても英語で溢れる、が何度も起きた。
|
|
123
|
+
検査は必ず**両言語**に掛ける。最後に `set_lang("ja")` で既定に戻すこと(同じ
|
|
124
|
+
プロセスで他の生成物を作ると英語で出てしまう)。
|
|
125
|
+
|
|
126
|
+
UI 側の文字列(索引の見出しなど)は `document.documentElement.lang` から出す。
|
|
127
|
+
JS に日本語を直書きすると、英語版に日本語が出る。
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 4. 図はインライン SVG
|
|
132
|
+
|
|
133
|
+
matplotlib で PNG に焼かない。理由は3つ。
|
|
134
|
+
|
|
135
|
+
1. **CJK フォントが無い環境では日本語が全部豆腐になる。** SVG ならテキストは
|
|
136
|
+
ブラウザ側のフォントで描かれる。
|
|
137
|
+
2. 拡大しても劣化しない(投影・PDF の両方で効く)。
|
|
138
|
+
3. hover の tooltip を付けられる。
|
|
139
|
+
|
|
140
|
+
代償は「自動レイアウトが無い」こと。折り返しも自分で書く。日本語は文字数、
|
|
141
|
+
英語は単語境界で折る **別々の幅**を持たせないと、どちらかが必ず溢れる
|
|
142
|
+
(CJK 約 1.0em、英小文字 約 0.52em)。
|
|
143
|
+
|
|
144
|
+
### 図を大きく見せる
|
|
145
|
+
|
|
146
|
+
表示高は `min(余白の高さ, 横幅 × h/w)` で決まる。**viewBox の h を詰めると、
|
|
147
|
+
同じ表示高でも中の文字が大きく描かれる。** 断片を削って情報を捨てるより、
|
|
148
|
+
viewBox を詰めるほうがよい。要点(take)を削るのも余白が増えて効く。
|
|
149
|
+
|
|
150
|
+
図を2枚並べたいときは、本文の器を `display:flex` にして `figure{flex:1}` に
|
|
151
|
+
しておけば `figure(a) + figure(b)` で半分ずつになる。1枚に詰めるより文字が
|
|
152
|
+
1.4 倍ほど大きくなる。
|
|
153
|
+
|
|
154
|
+
### 図の中の説明箱は縦の予算を使わない
|
|
155
|
+
|
|
156
|
+
スライドの縦は常に足りない。**説明を1行足したいとき、図の中の箱に入れれば
|
|
157
|
+
図の高さも断片の数も変わらない。** 枚の外に足すと図が縮む。
|
|
158
|
+
逆に、図の中の箱を差し替えるのは「無料」の変更になる。
|
|
159
|
+
|
|
160
|
+
### 図を2つの文書で共有する
|
|
161
|
+
|
|
162
|
+
同じ図をスライドと文書(レポート)で共有していると、片方だけ変えたいときに困る。
|
|
163
|
+
**図を複製せず、変えたい部分を引数にする。**
|
|
164
|
+
|
|
165
|
+
def fig_pipeline(..., box="rank"): # 既定は文書側のまま
|
|
166
|
+
if box == "cooc": ... # スライドだけ差し替える
|
|
167
|
+
|
|
168
|
+
複製すると、次に数値が変わったとき片方だけ古くなる。§2 と同じ理屈。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 5. アニメーション
|
|
173
|
+
|
|
174
|
+
2つの方式を用意し、**同じ図で混ぜない**。
|
|
175
|
+
|
|
176
|
+
### ループ(CSS のみ、JS を使わない)
|
|
177
|
+
|
|
178
|
+
.anim-fade{...}
|
|
179
|
+
.slide.on .anim-fade{animation:... infinite; animation-delay:var(--d,0s)}
|
|
180
|
+
|
|
181
|
+
`--d` で段差をつける。`.slide.on` の中だけで回す(裏で全枚ぶん回さない)。
|
|
182
|
+
|
|
183
|
+
### クリック送り(PowerPoint 風)
|
|
184
|
+
|
|
185
|
+
図側: <g data-step="auto"> ← 番号は書かない
|
|
186
|
+
枚側: slide(..., build=True) ← 出現順に採番し、断片はその続き
|
|
187
|
+
JS: next() が段を1つ進め、出しきってから次の枚へ
|
|
188
|
+
|
|
189
|
+
`tiles` / `panes` / `table` にも `build=True` を通して、タイル・対比・表の行を
|
|
190
|
+
1つずつ出せるようにしておくとよい。**要点(take)は段に載せない** — その枚の
|
|
191
|
+
主張なので最初から出ていないと聞き手が迷う。
|
|
192
|
+
|
|
193
|
+
締めの一段落のように「表を読み終えてから出したいもの」は、段の最後に置く。
|
|
194
|
+
結論が最初から画面にあると、表を追う意味が無くなる。
|
|
195
|
+
|
|
196
|
+
### 両方に共通する安全の向き(最重要)
|
|
197
|
+
|
|
198
|
+
**図は「終わった状態」を描く。アニメは始点にずらして戻すだけ。**
|
|
199
|
+
|
|
200
|
+
こうしておけば、印刷・`prefers-reduced-motion`・CSS 無効・JS 無効のどれでも
|
|
201
|
+
静止画が正しい。逆向き(始点を描いてアニメで終点に持っていく)にすると、
|
|
202
|
+
効かない環境で**間違った図**が出る。
|
|
203
|
+
|
|
204
|
+
クリック送りも、隠すのは JS が `body.built` を付けてから。JS が落ちたら
|
|
205
|
+
全部見えたままになる。
|
|
206
|
+
|
|
207
|
+
### 隠すのは opacity だけ
|
|
208
|
+
|
|
209
|
+
`display:none` にすると段が進むたびに版が動く。`opacity` なら場所は取ったまま
|
|
210
|
+
なので、レイアウトが跳ねない。縦の予算も「全段出した状態」で一度測れば済む。
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 6. 機械検査を2本用意する
|
|
215
|
+
|
|
216
|
+
ブラウザで目視できない環境では、検査が唯一の防壁になる。**性質の違う2本**が要る。
|
|
217
|
+
|
|
218
|
+
| 検査 | 見るもの | 捕まえるもの |
|
|
219
|
+
|---|---|---|
|
|
220
|
+
| geometry | SVG の**内側** | テキストのはみ出し、要素どうしの重なり |
|
|
221
|
+
| fit | スライドの**箱** | 本文がタイトル・フッターに被る、図が小さくなりすぎ |
|
|
222
|
+
|
|
223
|
+
実際に起きた崩れは geometry では**1件も捕まらなかった**。縦の予算を数える
|
|
224
|
+
fit のほうが必要だった。逆に fit は SVG の中身を見ない。両方要る。
|
|
225
|
+
|
|
226
|
+
太字は幅 ×1.06 で見積もる。これを入れた途端に実在の欠陥が 11 件出た。
|
|
227
|
+
|
|
228
|
+
**検査が見ないもの**も明示しておく: 段(アニメ)の動き、色、実フォントの字幅。
|
|
229
|
+
|
|
230
|
+
### 6.1 自分の出力を正規表現で読む検査は、黙って壊れる(最重要)
|
|
231
|
+
|
|
232
|
+
**生成側のマークアップを変えた日に、検査が静かに測らなくなる。**
|
|
233
|
+
|
|
234
|
+
実例。断片を `<li class="hi">` から `<li class="hi" data-step="2">` に変えたところ、
|
|
235
|
+
検査の正規表現 `<li class="[^"]*">` が当たらなくなり、**本編 24 枚の断片 42 個が
|
|
236
|
+
縦の予算に 0 として入り続けた。** それでも ALL CLEAR は出ていた。
|
|
237
|
+
同じ日に、`class="slide title"` の表題枚も `<section class="slide"` に当たらず、
|
|
238
|
+
まるごと検査対象から漏れていた。**どちらも数か月ぶん気づかれなかった。**
|
|
239
|
+
|
|
240
|
+
対策は2つ。
|
|
241
|
+
|
|
242
|
+
1. **数えた個数を検査自身に出させる。** 「断片 0 個」が異常だと分かるように
|
|
243
|
+
する。生成側が出した個数と突き合わせるのが理想。
|
|
244
|
+
2. **属性やクラスを1つ足したら、検査の正規表現を見に行く。** 手順に入れる。
|
|
245
|
+
|
|
246
|
+
### 6.2 ALL CLEAR は「見た」ことにならない
|
|
247
|
+
|
|
248
|
+
ブラウザが使える環境でも同じ。矢印の右に置いた注記が viewBox の右端で切れて
|
|
249
|
+
いたのに、幾何の検査は通した。近似モデルは境界で外す。
|
|
250
|
+
**枚を触ったら必ず1枚撮って目で見る。** そのために「この枚だけ撮る」機能を
|
|
251
|
+
先に作っておく(後述)。
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 7. PDF にする
|
|
256
|
+
|
|
257
|
+
### 配布用の変種を作る
|
|
258
|
+
|
|
259
|
+
発表用デッキとは別に、**JS を積まない1枚1ページの HTML** を出す。
|
|
260
|
+
|
|
261
|
+
- `.slide{display:flex!important; page-break-after:always}`
|
|
262
|
+
- `[data-step]` と `.anim-*` は全部見せて止める
|
|
263
|
+
- Appendix を入れるかは選べるようにする(配布は本編だけ、が多い)
|
|
264
|
+
|
|
265
|
+
同じ `main(C)` から作れば、発表用と中身がずれない。
|
|
266
|
+
|
|
267
|
+
### JS が埋める値は、配布版では生成時に埋める
|
|
268
|
+
|
|
269
|
+
画面版のページ番号を JS で入れていると、**JS を積まない配布版は空欄のまま**
|
|
270
|
+
印刷される。配布用を組む関数の中で埋めてしまうのが確実(配布は本編だけなので
|
|
271
|
+
通し番号でよい)。画面版は JS が上書きするので二重にならない。
|
|
272
|
+
|
|
273
|
+
同じ罠は「JS で入れている表示」すべてに当てはまる。配布版を作ったら、
|
|
274
|
+
**空になっている要素が無いか出力を数える。**
|
|
275
|
+
|
|
276
|
+
### ヘッドレス Chromium で焼く
|
|
277
|
+
|
|
278
|
+
playwright + chromium → page.pdf(width=..., height=..., print_background=True)
|
|
279
|
+
|
|
280
|
+
**紙もスライドと同じ 16:9 にする。** A4 に入れると上下に余白が出るだけ。
|
|
281
|
+
|
|
282
|
+
共有環境に入れないこと。`pip install --user` と `~/.cache` に閉じる。root が無くて
|
|
283
|
+
`playwright install-deps` が使えない場合は、足りない共有ライブラリを他の環境から
|
|
284
|
+
**home にコピー**して `LD_LIBRARY_PATH` を通す。他人の環境を直接参照すると、
|
|
285
|
+
その環境が消えた日に黙って壊れる。
|
|
286
|
+
|
|
287
|
+
**CJK フォントが無いホストでは日本語版を PDF にできない**(豆腐になる)。
|
|
288
|
+
版組みの確認には使える(箱の位置と行数は正しく出る)。配布が要るなら
|
|
289
|
+
`~/.fonts` にフォントを置くか、operator のブラウザで印刷してもらう。
|
|
290
|
+
|
|
291
|
+
### 「この枚だけ撮る」を最初に作る
|
|
292
|
+
|
|
293
|
+
1枚ずつ直す作業では、毎回これを使う。
|
|
294
|
+
|
|
295
|
+
render.py <html> -o out.png --png --slide 12
|
|
296
|
+
|
|
297
|
+
中では `?still` で全段を出した状態に固定し、**枚送りの関数を直接呼ぶ**。
|
|
298
|
+
ハッシュ(`#12`)を変えて `goto` するだけでは same-document navigation になり、
|
|
299
|
+
JS が再実行されず1枚目のまま撮れる。
|
|
300
|
+
|
|
301
|
+
配布用 HTML には枚送りの JS が無いので、`--slide` は使えない。
|
|
302
|
+
**何が違うのかを1行で言って止める**(`ReferenceError` を出さない)。
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 8. 大きな Appendix を引く索引
|
|
307
|
+
|
|
308
|
+
Appendix が数十枚になると、矢印で送って探すのは実用にならない。
|
|
309
|
+
**キー1つで一覧を出し、語で絞り込んで飛ぶ**仕組みを入れる。
|
|
310
|
+
|
|
311
|
+
### サムネイルは選ばない
|
|
312
|
+
|
|
313
|
+
reveal.js 風に全枚を縮小して並べる案は、**図が主体のデッキでは機能しない。**
|
|
314
|
+
82 枚を1画面に入れるには 1/6 前後まで縮める必要があり、本文が 3px 相当になって
|
|
315
|
+
読めない。結果、見分けのつかない矩形が並ぶだけになる。
|
|
316
|
+
**探しているのは語**なので、番号・見出し・題名の一覧+絞り込みのほうが速い。
|
|
317
|
+
|
|
318
|
+
### 実装で外せない4点
|
|
319
|
+
|
|
320
|
+
1. **絞り込みは `<input>` の `input` イベントで受ける。**
|
|
321
|
+
`keydown` の `e.key` を拾う実装は **CJK の IME で動かない** — 確定前の文字は
|
|
322
|
+
`e.key` に来ず、composition イベントを経由する。英語版だけ絞り込みが効いて
|
|
323
|
+
日本語版で 0 件、という形で出る。**2言語のデッキなら必ず両方で試す。**
|
|
324
|
+
2. **探すのは題名ではなく、その枚の全文。** 題名だけだと、本文で論じている語で
|
|
325
|
+
見つからない(ある語で 1 枚しか出ず、それを扱う本編 4 枚が漏れた。全文なら
|
|
326
|
+
12 枚出た)。表示は題名のままでよい。索引だけ全文にする。
|
|
327
|
+
3. **既存のハンドラに触らない。** 新しいハンドラを **capture 段**で登録し、
|
|
328
|
+
一覧が開いている間だけ `stopPropagation` する。クリックは既に「次へ進む」に
|
|
329
|
+
割り当てられているので、これをしないと選ぶ操作が枚送りになる。
|
|
330
|
+
4. **一覧は grid にする。** CSS の段組み(`column-count`)は高さが尽きると
|
|
331
|
+
**右へ**伸びるので、行数が多いと横スクロールになる。grid なら溢れは縦。
|
|
332
|
+
|
|
333
|
+
### 操作の細部
|
|
334
|
+
|
|
335
|
+
- **矢印は並んで見えている位置で動かす。** 文書順にすると3段の格子で ↓ が
|
|
336
|
+
右隣に飛ぶ。段数は書かずに `offsetTop` が揃う要素を数えて**実測**する
|
|
337
|
+
(スタイルシートの段数を変えても追従する)。
|
|
338
|
+
- `←→` を格子の移動に使うなら、入力欄のカーソル移動は諦める。絞り込みの語は
|
|
339
|
+
短いので `Backspace` で足りる。
|
|
340
|
+
- **閉じるのは Esc だけ。** 開くキーで閉じられるようにすると、その文字から
|
|
341
|
+
始まる語("ortholog" の o)を打った瞬間に閉じる。
|
|
342
|
+
- 見出しの接頭辞(「付録 —」)は一覧では落とす。番号が言っているので重複で、
|
|
343
|
+
残すと見出し列が全部同じ文字で埋まって省略記号で切れる。
|
|
344
|
+
- 該当0件で Enter を押しても何も起きないようにする。
|
|
345
|
+
- 配布用 HTML は JS を積まないので索引も入らない。PDF の頁数は変わらない。
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 9. 実際に踏んだ罠
|
|
350
|
+
|
|
351
|
+
| 罠 | 症状 | 対処 |
|
|
352
|
+
|---|---|---|
|
|
353
|
+
| 表の折り返しの既定が逆 | 文字列の列だけが最小幅に潰れる | 折り返しを既定にし、**数値セルだけ** nowrap |
|
|
354
|
+
| 図の高さが縛れていない | 図が箱から溢れてタイトルの上に描かれる | SVG を包む箱に `width/height:auto` + `max-*:100%` |
|
|
355
|
+
| フッターがページ基準に置かれる | 1枚目だけ偶然合っている | 枚の器に `position:relative` |
|
|
356
|
+
| 横棒グラフのラベル欄 | 長いラベルが**左に**はみ出す(右揃えなので) | 欄幅から字数上限を決める。長い説明は tooltip か断片へ |
|
|
357
|
+
| 関数名の衝突 | `TypeError: 'int' object is not callable` | ドメイン語(`step`=窓の刻み幅)と被らない名前にする |
|
|
358
|
+
| **CSS クラス名の衝突** | 指定した font-size と色が効かない | 後ろの規則が勝つ。名前を付ける前に**スタイルシートを grep** |
|
|
359
|
+
| **本文の器が flex 行** | 表と段落を渡すと左右に割れる | 縦に積む器で包む。`flex:1;min-width:0` が無いと `table{width:100%}` が解決しない |
|
|
360
|
+
| **フッターにもう1行足す** | 行が折り返し、ページ番号が「6 /」「24」に割れる | 番号に `white-space:nowrap`。中身は1行に収まる短さに切る |
|
|
361
|
+
| **`::before` の区切り記号** | 地のテキストがあるのに最初の1つだけ区切りが出ない | 地のテキストは要素ではないので `:first-child` が当たる。区切りは生成側で入れる |
|
|
362
|
+
| **`column-count` の溢れ** | 行数が多いと**横**スクロールになる | 高さが尽きると右へ伸びる。縦に溢れさせたいなら grid |
|
|
363
|
+
| **矢印キーを文書順に割り当てる** | 3段の格子で ↓ が右隣に飛ぶ | 並んで見えている位置で動かす。段数は `offsetTop` から実測 |
|
|
364
|
+
| **CJK の IME を keydown で受ける** | 英語版だけ絞り込みが動き、日本語版で 0 件 | 確定前の文字は `e.key` に来ない。`<input>` の `input` イベントで受ける |
|
|
365
|
+
| **JS が埋める要素** | JS 無しの配布版で空欄になる(ページ番号) | 生成時に埋める。画面版は JS が上書きするだけ |
|
|
366
|
+
| ハッシュだけ変えて `goto` | ヘッドレスで撮ると全部1枚目になる | same-document navigation で JS が再実行されない。関数を直接呼ぶ |
|
|
367
|
+
| 段番号を手で振る | 図を1つ足すと以降が全部ずれる | `"auto"` の印だけ置いて、組むときに一括採番 |
|
|
368
|
+
| 生成後の grep をしない | 分割された文字列リテラルが grep に掛からない | ソースではなく**出力 HTML** を grep して確認 |
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 10. 進め方
|
|
373
|
+
|
|
374
|
+
operator が1枚ずつ見て指示する形が一番回った。そのとき効いたこと。
|
|
375
|
+
|
|
376
|
+
- **枚数表を引き継ぎ資料に置く。** 枚を出し入れすると番号がずれ、口頭の
|
|
377
|
+
「S18 が」が指すものが変わる。番号はその表で確認する約束にする。
|
|
378
|
+
- **本編とスライド番号で相互参照しない。** 「S12 と同じ」ではなく
|
|
379
|
+
「先ほどの KEGG 採点と同じ」と内容で指す。番号は必ずずれる。
|
|
380
|
+
- **落とした情報の行き先を記録する。** 「本編から削除」ではなく
|
|
381
|
+
「Appendix のどこへ移した」。あとで必ず聞かれる。
|
|
382
|
+
- **本編で語らないことは結論スライドにも出さない。** 文脈の無い数値が
|
|
383
|
+
まとめに残ると、そこだけ質問が集中する。
|
|
384
|
+
- **前方参照を作らない。** まだ説明していない実験の数値を先の枚で使わない。
|
|
385
|
+
- **「この数値はどこから出たのか」と聞かれたら、それは枚の欠陥である。**
|
|
386
|
+
聞かれた場所を直し、根拠は Appendix に図解で1枚足す。使われていない図が
|
|
387
|
+
ソースに眠っていることがある(書いたが置き忘れた図が実際にあった)。
|
|
388
|
+
- **1枚直したら、ビルド → 検査2本 → その枚を撮る、まで回す。** 直した枚だけ
|
|
389
|
+
でなく検査は全枚に掛ける(1箇所の変更が他の枚の余白を変えることがある)。
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## 11. 最小の骨格
|
|
394
|
+
|
|
395
|
+
kit.py CSS(vh 単位・明色固定)、JS(枚送り+段送り+索引)、slide()/table()/tiles()
|
|
396
|
+
txt_deck.py main(C) が本編、appendix(C) が付録。slide() を並べるだけ
|
|
397
|
+
viz_deck.py 図。T() でラベルを2言語に
|
|
398
|
+
make_deck.py build_context() → set_lang → 両言語 → 配布 HTML
|
|
399
|
+
check_geom.py SVG の内側
|
|
400
|
+
check_fit.py 枚の縦の予算(**生成側を変えたら正規表現を見る**)
|
|
401
|
+
render_pdf.py ヘッドレス Chromium(`--slide N` で1枚だけ)
|