@aiquants/daily-report 0.24.0 → 0.26.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,100 @@
2
2
 
3
3
  All notable changes to `@aiquants/daily-report` are documented here.
4
4
 
5
+ ## 0.26.0 (2026-10-04)
6
+
7
+ 0.25.0 の続き: 位置の変化ごとの錨の記録、行と面の 4 px の格子、読み込みの画面の枠とエラーの文言の色、コメントの節の 1 つの規則、添付の配信とサムネイルの生成の締め付け、共有 SSE リーダーの位置の固定。どれも README の該当の節が今の契約を記す。
8
+
9
+ ### Changed
10
+
11
+ - **錨は位置のどの変化の後にも記録する**: DetailList の行の測り直しはスクロールの口の `resizeRow` (VirtualScroll の `updateItemSize` の直後に錨を記録する) を通る。`updateItemSize` は可視の先頭より上の行の高さが変わるとその差だけ位置を自分でずらす (レイアウトのずれの補正) ので、直後の記録は補正の後の状態を読む。
12
+ VirtualScroll が自分で位置を動かしたとき (測り直した行の補正・描画の後の高さの照合・保留中の揃えの留め直し・クランプされた補正の再発行) は、`@aiquants/virtualscroll` 3.9.0 の `onScrollAdjust` で同期に知らされ、両ビューは錨をその場で記録し直す。
13
+ 以前は次のフレームの可視範囲の知らせまで錨が古いままで、その間に確定した一覧の変化 (SSE の挿入・削除) が、先頭に見えている日報を補正の差だけずらすか隣の日報に置き換えた。
14
+ キーボード操作とビューが受け取るハンドルは読み取りの関数だけの型 (`ListNavigationHandle`) になり、位置を動かす関数 (`scrollToIndex`・`scrollBy`・`scrollTo`・`applyWheel`・`updateItemSize`) を口の外で呼ぶと型検査で落ちる。利用者のスクロールの後の錨の進め方は、一様な高さの行 (List) では算術で 1 回、実測の高さの行 (DetailList) では通り過ぎた行だけをたどる。
15
+ - **ビューの高さはどの値も `ResizeObserver` から**: 最初の値も観測の最初の配達から受け取り、その配達は `flushSync` で描く前に確定させる (配達まではビューの中身を描かないので、推測の高さでは描かない)。0.25.0 は最初の値を計算済みの `block-size` から読み、有効数字 6 桁の文字列 (743.65625 が 743.656) のために端数のある高さを 2 回確定させた。
16
+ 箱を持たない根要素は、Chromium では最初の配達の 0、仕様どおり 0 × 0 から観測を始める描画エンジンでは箱を持つまで値が無い (VirtualScroll を描かない)。
17
+ - **行の枠と面は 4 px の格子の上**: List の行の枠の高さ P は 52 px + 6.75 rem を 4 px の倍数へ切り上げる (根 16 px は 160 のまま。根 12・20・24 px は 133・187・214 から 136・188・216 になり、カードの余裕が 4 px 未満だけ増える)。DetailList の測る前の行の見積もりは 352 px (以前の 350 は、窓より上の測っていない行 1 つごとに下の行を 2 px ずらした)。
18
+ DetailList の行の本体 (カード・スケルトン・編集の枠・エラー) は中身の高さを 4 px へ切り上げる (`calc-size(auto, round(up, size, 4px))`。根 16 px では変わらない。持たない描画エンジンは中身の高さのまま)。
19
+ 画像の添付のタイルは最後の行の下に 0〜3 px の寄せ (`round(up, h, 4px) − h`) を持ち、どのタイルも ⌈h / 4⌉ · 4 + 48 px になる (枠の高さ h(t) = round(2t / 3) と 3 : 2 の画像の埋まり方は変えない)。タイルの `100cqi` の容器はタイルの根になり、枠の包みは容器でなくなった。
20
+ 以前は k 段のタイルを持つ面が k · h(t) (mod 4) だけ格子を外れ、その下の DetailList の行は画素密度 1.25 で装置の画素の半分ずれて、枠線・選択の輪・アウトラインがにじんだ。
21
+ - **端に揃えた面は G より端へ寄らない**: `@aiquants/virtualscroll` 3.9.0 の装置の画素への揃えが揃えた端を守るので、下端・上端に揃えた行の面は端から G = 8 px より近づかず (足されるのは 1 装置画素未満)、ビューの高さと行の枠が装置の画素の整数ならちょうど G になる。以前はビューの高さが端数だと、下端に揃えた行の余白が最大で装置の画素の半分削られた (比 1 で高さ 705.5 px のビューの最後の行の余白が 7.5 px)。
22
+ - **読み込み中と読み込みの失敗の画面も同じページの枠と列**: どの画面もページの枠 (`VIEW_PAGE_FRAME_CLASS_NAME`。明 slate-50・暗 slate-950) と中央の列 (`VIEW_COLUMN_CLASS_NAME`。4 px の格子の原点を含む) を使う。以前の読み込み中と失敗の画面は明るい slate-50 の枠を直に書いたので、暗色では読み込みが終わるまで明るいページで、終わると切り替わった。
23
+ エラーの文言の色は 1 つのトークン (`ERROR_TEXT_CLASS_NAME`。明 red-700・暗 red-400) で、載るパッケージの面のどれにも明暗とも 6.17:1 以上。以前は失敗の画面の文言 (red-600) が暗色の面の上で 1.42:1、側面ペインの日報の読み込みの失敗 (red-500) が白の上で 3.81:1 だった。
24
+ - **コメントの節は 1 つの規則**: DetailList の行・側面ペイン・モバイルのオーバーレイは、コメントがあるか投稿できる間だけ、見出しごとコメントの節を描く。以前の側面ペインとオーバーレイは常に描き、投稿できない種別でコメントの無い日報に空の見出しを残した。
25
+ 削除を確定した後のフォーカスの行き先は残る構造から決める: 次のゴミ箱、前のゴミ箱、節が残るなら節の見出し、残らなければ日報自身の目印 (DetailList は行、側面ペインとオーバーレイはペインの日報の見出し)。以前の DetailList では、投稿できない種別の最後のコメントを消すと、フォーカスを移した見出しが節ごと消え、フォーカスが `body` へ落ちた。
26
+ - **営業日の吹き出しは `transform` で付いていく**: スクロールバーのつまみの営業日の吹き出しは一定の位置に置き、つまみの中心へは `transform` だけで動かす (遷移は付けない)。以前は `top` / `left` を書いたので、吹き出しを見せている間のスクロールの 1 段ごとに文書の根からのレイアウトを 1 回足した。
27
+ - **sharp を起動する前のたどりに歩数の上限**: JPEG の区切りと走査の読み飛ばしと WebP のチャンクのたどりは同期でイベントループを止めるので、訪れる 0xFF 1 つと WebP のチャンク 1 つを 1 歩と数え、`maxWalkSteps` = ⌊16 ms × 10⁶ ÷ (50 ns × 2)⌋ = 160,000 歩を超える原本は sharp を起動せずに `unsupported` (内容で決まる失敗として記録) にする。符号化済みのデータの 0xFF の連なりは 1 つの JS のループで読む。
28
+ 以前は 32 MiB の原本で、符号化済みのデータが 0xFF の連なりならイベントループを 0.97〜1.11 秒、`FF 00` や再同期の連なりなら 0.50〜0.59 秒止め、そのうえ sharp を起動した。上限までのたどりは、測ったホストで最も重い形 (`FF 00` の組を 3〜209 バイトおきに散らした原本) でも 5.0〜7.0 ms、ほかの形は 1〜2.4 ms。
29
+ - **添付のどの応答にも `Cross-Origin-Resource-Policy` と `nosniff`**: 失敗の応答 (400・401・403・404・405・413・429・500・502・503。GET と HEAD) も `Cross-Origin-Resource-Policy: same-origin` と `X-Content-Type-Options: nosniff` を持つ。どの応答の経路も 1 つのヘッダーの組を最後に広げる。
30
+ 0.25.0 は成功の応答 (原本の 200 と縮小画像の 200・304) にだけ方針を付けたので、同じサイトのページが no-cors の `fetch` で、見える添付と見えない添付をトークンごとに見分けられた。
31
+ - **内容キーごとに展開は 1 つ**: 描画の締め切りを過ぎても続く描画がある間、同じ内容の次の生成は枠を取らずにその決着を待ち、結論が記録されていればキャッシュから答える (締め切りの後の描画の待ちと枠の待ちを合わせて `queueWaitMs` の内。尽きたら展開を重ねずに 503 `queue`)。以前は既定の 2 枠のもう 1 つで、締め切りを越えさせた混雑の中で同じ原本をもう一度読んで展開した。
32
+ 描画の結果は締め切りの前に決着しても後に決着しても同じ 1 つの分類で決め、オブジェクトでない結果は 500 (`port_contract` / `code=result`) になる (以前は例外)。
33
+ - **共有 SSE リーダーは `$` から読まない**: 読み取り位置はいつも具体 ID で、ストリームの末尾を読めないときは `ready()` が拒否する (失敗した読取りは残さず、次の呼び出しが読み直す)。同梱の SSE ハンドラはその接続を閉じ (`producer-failed`)、クライアントはカーソルがあればそれで開き直して追いつく。位置を固定できない run は、ほかの失敗した run と同じく全購読者の `onError` を呼ぶ。
34
+ 以前は末尾を読めないと `"$"` へ縮退し、2 回の XREAD の合間に足されたエントリを誰にも届けない窓が残った (`"$"` は XREAD のたびにその時点の末尾へ解決される)。
35
+
36
+ ### Added
37
+
38
+ - server の `DAILY_REPORT_SHARP_THUMBNAIL_DECODE_WORK_MODEL`: 描画の段の締め切り `renderMs` (10,000) と、展開の仕事の上限 (`nanosecondsPerBlockVisit`・`margin`・`maxBlockVisits`) とたどりの上限 (`walkBudgetMs`・`nanosecondsPerWalkStep`・`walkMargin`・`maxWalkSteps`) を持つ凍結した表。ホストの適合の検査は締め切りを書き写さずにここから読む。
39
+ - **開発者向け**: 公開のスクリプトは `pnpm run verify` の直後に `node scripts/check-bundle-size.mjs --exact` を走らせる。測った大きさが基準の項目と 1 バイトでも違えば (大きくても小さくても) 落とし、そのビルドを記録する `--write --accept` のコマンドを示すので、公開する版はどれも自分のビルドの基準を持つ。SQL の結果のキャッシュのキーは 1 つのモジュール (`cache-keys.ts`) が組み、誰も書かないキーを消す無効化の呼び出しを除いた。
40
+
41
+ ### Removed
42
+
43
+ - server の `SqlResultCache` の `invalidate` と `flush` (同じ処理の 2 つの名前)。完全一致のキーで消す呼び出しはどこにも無い (詳細のキーは利用者と可視性で区切るので、完全一致のキーは誰も書かないキーを指していた)。消すのは `invalidatePrefix` と `clearAll` の 2 つだけ。
44
+
45
+ ### Breaking
46
+
47
+ - `DailyReportSseReader.ready()` はストリームの末尾を読めないとき拒否する (0.24.0 と 0.25.0 は `"$"` へ縮退して解決した)。Migration: 自前の SSE ハンドラで共有リーダーを使うホストは、`ready()` の拒否で接続を閉じてクライアントに開き直させる (同梱のハンドラはそうしている)。リーダーを自前で差し替えるホストの `ready()` も、位置を具体 ID に固定できないときは拒否する。
48
+ - ピアの `@aiquants/virtualscroll` の下限を 3.9.0 へ上げる。両ビューは 3.9.0 の `onScrollAdjust` で錨を記録し直し、揃えた端を守る装置の画素への揃えに頼る。Migration: `@aiquants/virtualscroll` を 3.9.0 以降へ上げる。
49
+ - server の `SqlResultCache` から `invalidate` と `flush` を外した。Migration: 1 つのキーを消していた呼び出しは、そのキーを接頭辞とする `invalidatePrefix(<キー>)` か、全部を消す `clearAll()` へ置き換える。
50
+
51
+ ## 0.25.0 (2026-10-03)
52
+
53
+ 0.23.0 のキーボード操作とサムネイルの仕上げの続きと、共有 SSE リーダーの取りこぼしの修正。どれも README の該当の節が今の契約を記す。
54
+
55
+ ### Changed
56
+
57
+ - **スクロールの錨はスクロールの直後に記録する**: ビュー自身のスクロール (キーの移動と長押しのフレームごとの移動・キーボードのフォーカスを見せるスクロール・List のモバイルのオーバーレイを閉じた後の揃えと行の枠の高さ P が変わったときの位置の直し・DetailList の選択の揃えとコメントの投稿の後の見せ方) はどれも 1 つのスクロールの口を通り、口はスクロールの直後に VirtualScroll のハンドルから錨を記録する。以前は次のフレームの可視範囲の知らせで記録したので、キーと次のフレームの間に確定した SSE の挿入・削除が位置をキーの前へ戻した (End・PageDown・長押しが巻き戻り、DetailList ではフォーカスが body へ落ちた)。
58
+ 利用者のスクロール (ホイール・ドラッグ・スクロールバー・慣性) は今までどおり可視範囲の知らせで記録し、知らせの前の 1 フレームに一覧が変わったときは、記録してからスクロールした距離だけ錨を前の一覧の行の高さで進めてから戻す (利用者のスクロールを巻き戻さず、1 行もずらさない)。錨が譲るのは、日報の到着を待つ DetailList の選択の見せ方だけ。
59
+ - **キャッシュに無い日報の最初の読み込みはすぐ始める**: `useDailyReportDetail` はキャッシュに無い日報の要求を効果の中で始める。以前は 0 ms のタイマーを挟んだので、キーの長押しが続く間ずっと後回しにされ、キーを離すまで要求が出なかった。間を置く (120 ms) のは期限切れのキャッシュの日報の再取得だけ。id が変わった後とアンマウントの後に届いた結果は捨て、同じ営業日の要求は 1 つにまとまる。
60
+ - **ビューの高さの最初の値も配置の px**: ビューの箱の高さは最初の値も根要素の計算済みの `block-size` (配置の px) から読み、以後の `ResizeObserver` の値と同じ単位になった (以前の最初の値は `getBoundingClientRect` の見た目の px で、祖先が変形・拡大縮小しているときだけ 1 フレーム後の観測で直った)。祖先の変形・拡大縮小で 2 回目の確定は起きない (ただし端数のある高さは、計算済みのスタイルが長さを有効数字 6 桁の文字列にするので、最初の値 (743.656) と観測の値 (743.65625) が食い違って 2 回確定する)。内部のフックの名前も測るものに合わせた (`useViewBoxHeight`)。
61
+ - **空のビューの文言は 1 つ**: 空の List と DetailList は VirtualScroll の空の文言 (`noItems`。en "No items"・ja 「項目がありません」) だけを描く。以前はパッケージの `listEmpty` の文言と 2 つが一覧の上端で 8 px 重なった。文言の上下の寄せ 16 px と色 (明 slate-500・暗 slate-400。ページに対して 4.55:1・7.66:1。エンジンの既定の灰は暗色のページで 4.17:1) はビューが与える。
62
+ - **両ビューの行の枠は配置の境界**: DetailList の行の枠も List と同じく大きさ・配置・スタイルを閉じ込め (`contain: size layout style`)、VirtualScroll の行の箱を埋める。行の高さは本体 (枠の直下の子) を測って 2G を足した値。行の中の変化 (後回しにした本体の描画・読み込みの完了・選択とフォーカスの表示) の配置はその行から始まり、キーの移動の配置は変わる行の中に留まる (以前の DetailList は、長押しのフレームごとに文書の根から配置し直した)。
63
+ - **側面ペインの見出しと本文は同じ端で終わる**: 営業日と作成者の列とタブの並びは、本文と同じスクロールバーの溝を取る箱に入る (以前は古典的なスクロールバーで、本文の列が見出しより 10 px 手前で終わった)。
64
+ - **List のパネルの終わりに G**: 一覧のパネルはスクロールバーの後に G = 8 px を取り、側面ペインとの間は 2G = 16 px の溝になる。境界の中央に置かれるリサイズの取っ手 (当たり 10 px・目印 6 px) はスクロールバーにもペインの縁にも掛からない (以前は目印がスクロールバーのトラックの 3 px を覆った)。
65
+ - **選ばれたタブの印はまっすぐな 2 px の線**: 下の枠線をやめ、トリガーの角の半径 (`--radius-lg`) だけ左右を内側へ入れた `::after` の棒にした。角の丸い箱の下の枠線は丸みに沿って細りながら持ち上がり、画素密度 3 では中ほどで 6 装置画素の三日月だった。棒は流れの外なので場所を取らず、文言は 24 px のトリガーの中央に来る (以前は透明な枠線の分だけ 1 px 上)。強制配色では `Highlight` の棒。
66
+ - **ビューの列の原点は 4 px の格子の上**: 中央に寄せた列の始まりを 4 px の倍数へ切り下げる (`round()` を持たないエンジンは `mx-auto` の中央のまま)。画素密度 1.25・1.5・1.75 でも、左右の縁の 2 px の輪・隙間・アウトラインがどれも整数の装置の画素で描かれ、枠線は自分の色で描かれる (以前は列が 0.5 px に来ることがあり、1.25 で線と枠線がにじんだ)。
67
+ - **スクロールを伴うキーの行の描き直しは VirtualScroll の窓のずらしのもの**: 描画済みの行を描き直すのは、VirtualScroll が描画の窓をずらす段だけ (このパッケージの変更は要らない)。
68
+ 行をマウントしない段はラッパーの `transform` だけを書き、どの行も描き直さない。
69
+ 行をマウントする段ではラッパーの層 (`will-change: transform`) が描き直しを要するので、Chromium が描く範囲 (表示領域を 4000px 広げた範囲) をヒステリシス無しで今の位置へ置き直し (`CullRectUpdater::ShouldProactivelyUpdate`)、中身が自分のはみ出しを切る残る行 (`kMayBeClippedByCullRect`) を描き直す。両ビューの行はどちらもこれに当たる。
70
+ `@aiquants/virtualscroll` の計測 (Chromium 148・1280×800・比 1・overscan 15。20 段 × 3 回の中央値) では、1 行ずらす段が 160px の行で 36 層 (Paint 0.99ms、Paint・PrePaint・Layerize の和 2.6ms、ラスター 3.7ms)、448px の行で 26 層 (0.66ms・1.9ms・2.6ms)。
71
+ 描く範囲を外させる `perspective` は層を 6 に減らすが、行を 2D の平行移動でない変換の下で合成させ、比 1.25 の明色で選択の輪とフォーカスの輪の間の帯を混ぜるので、virtualscroll は使わない (ラッパーは 3.8.1 と同じ層)。
72
+ `@aiquants/virtualscroll` 3.8.2 の配布 CSS が、動きを減らす設定 (`prefers-reduced-motion: reduce`) で、パッケージが動かす部品 (タップスクロールサークルとその中のすべての要素・バーのサークルの器・矢印ボタン・スクロールバーのつまみ・端へ戻るボタンとその覆い) の遷移とアニメーションを止める (3.8.2 をピアの下限にした。Breaking を参照)。
73
+ - **JPEG の展開の仕事の上限**: sharp の描画ポートは、sharp を起動する前に JPEG の展開の仕事 (EOI までの走査ごとに、符号化する成分のブロックの数の和) をフレームヘッダーと同じ 1 回のたどりで見積もり、描画の締め切りから導いた上限 (2,000 万回の訪問) を超える原本と、仕事を見積もれない原本 (算術符号と階層のフレーム、規格の上限を超える走査の数、崩れた区切り) を `unsupported` (内容で決まる失敗として記録) で断る。以前は 0.2 MB で 2,647 走査の 4,096² のプログレッシブの JPEG が、画素数と作業領域の上限を通って描画 1 回に CPU 13〜25 秒をかけ、締め切りを越えても何も記録しないので表示のたびに展開し直した。可逆 (SOF3) のフレームは受け付ける。
74
+ - **締め切りの後の描画の結果を残す**: 描画の締め切り (`render_timeout` の 502) の後に描画ポートが決着したら、出力の検証を通った縮小画像と `unsupported` は、同一性を確かめた生成ならキャッシュに記録してから枠を返す (以前は捨てた)。遅いが正当な原本の超過は 1 回で済み、次の表示はキャッシュから答える。生成は枠を渡されたときにキャッシュを見直すので、超過した描画の後ろで待っていた要求はもう 1 度展開しない。sharp の描画ポートは展開を始めた後に中断されても、展開の結果をそのまま返す (以前は `failed` に変えたので、残す結果が無かった)。
75
+ - **添付の応答は同じオリジンだけが読み込める**: 原本の 200 (インラインとダウンロード、GET と HEAD) とサムネイルの 200・304 は `Cross-Origin-Resource-Policy: same-origin` を持つ。セッションの Cookie は同じサイトの別オリジンからの読み込みにも付くので、無いと同じサイトのページが推測したトークンを画像として読み込み、読めたかどうかから閲覧者の可視性を 1 件ずつ知りえた。失敗の応答 (404 など) は方針を持たないので、no-cors の `fetch` では、見える添付 (方針を持つ応答をブラウザーが塞ぐ) と見えない添付 (404 が opaque な応答として解決する) をまだ見分けられる。
76
+ - **開発者向け**: バンドルの予算は書かずに導く: `bundle-baseline.json` (パッケージの根) が入口ごとの gzip-9 の大きさと余裕 `headroomPercent` (3) を記録し、予算は ⌈基準 × (100 + 余裕) ÷ 100⌉ (整数の計算)。手で書いた `package.json#bundleBudget` は拒否する。`pnpm run bundle:ratchet` (`--write`) が新しいビルドの大きさを記録し、下げるのと古い項目を消すのは自由、増やすのと項目を足すのは `--write --accept` だけ。
77
+ ビューのスクロールの口を通らないハンドルのスクロールを落とす守り (`view-scroller.spec.ts`)、VirtualScroll の代役と本物を同じ props で比べる適合の spec (空の出力・矢印の Tab の止まり先・ビューが呼ぶハンドル)、`utils/constants.ts` が export するどの定数にも出荷するコードの読み手があることの守り (読み手の無かった `EMPTY_DETAIL` も消した) を加えた。
78
+
79
+ ### Fixed
80
+
81
+ - **末尾を読めなかった共有リーダーの取りこぼし**: プロセス最初の run でストリームの末尾を読めないと、リーダーは `"$"` で読み始める。
82
+ その後に別の接続の `ready()` が末尾を読めて位置を固定しても、動いている run は `"$"` のまま再武装を続け、BLOCK の合間に足されたエントリを
83
+ 読まなかった (その位置を見て `connected` を受け取った接続にも届かない)。run は XREAD のたびに、まだ `"$"` なら固定された位置へ移る。
84
+
85
+ ### Removed
86
+
87
+ - client の `DEFAULT_ITEM_HEIGHT` と `TAP_SCROLL_CIRCLE_OPTIONS` (消費側が読み込まない)。公開名を足すのは消費側 (ホストのアプリ・examples) が読み込むときだけで、README に書くことは公開の理由にならない。
88
+ - ラベル `listEmpty` (固有キーは 83、全 90 キー)。
89
+
90
+ ### Breaking
91
+
92
+ - `DEFAULT_ITEM_HEIGHT` と `TAP_SCROLL_CIRCLE_OPTIONS` を外した。行の幾何はホストとの契約ではない: List は根の文字サイズから行の枠の高さ P = 52px + 6.75rem を求めるので、P は根が 16 px のときにしか 160 にならない。0.23.0 の Breaking の Migration の「行の計算は `DEFAULT_ITEM_HEIGHT` で行う」は、この項で置き換える。
93
+ Migration: 行は `[data-daily-report-row="<id>"]` か、テスト用のハンドル (`__virtualScroll` の `findReportIndex` / `getReportItem`) で探し、index × 行の高さで求めない。タップスクロールサークルの設定はホストが自分で持つ。
94
+ - ラベル `listEmpty` を外した (上書きに渡すと、未知のキーとして `RangeError`)。空の一覧の文言は `noItems` の 1 つ。Migration: `labels` から `listEmpty` を外し、空の一覧を「データがありません」/ "No data" で待っていたテストは `noItems` の文言 (「項目がありません」/ "No items") で待つ。
95
+ - 描画ポートの契約: 中断で打ち切った描画は `unsupported` を返してはならない (締め切りの後の `unsupported` は内容で決まる失敗として記録する)。Migration: 自前の描画ポートは、中断で打ち切った描画を `{ ok: false, reason: "failed" }` で返す。
96
+ - ピアの `@aiquants/virtualscroll` の下限を 3.8.2 へ上げた (`peer-floors.json`)。3.8.2 の配布 CSS が、動きを減らす設定で VirtualScroll 自身の部品の遷移とアニメーションを止める (3.8.0 と 3.8.1 ではタップスクロールサークルが動く)。
97
+ Migration: `@aiquants/virtualscroll` を 3.8.2 以降へ上げる。
98
+
5
99
  ## 0.24.0 (2026-10-03)
6
100
 
7
101
  共有 SSE リーダーを `@aiquants/sse` の `createSharedSource` へ載せ替え、接続の直後に足されたエントリが配られないことのある順序の誤りを直す。