第6話 キャッシュに残る指先
消したはずのものが残る。
それは、バグの中でもかなり嫌な部類に入る。
午前九時を過ぎた。NEXTPULSE への暫定報告は、三枝さんが社内確認へ回している。俺の手元には、別管理にした観測ログと、薄い痕の残ったレシートがあった。
空中キーは消した。
画面外座標の生成も止めた。
当たり判定も外した。
専用エディタの入力経路も閉じた。
それなのに、レシートには一センチ四方の痕が残っている。
現場の言葉に直せば、こうだ。
画面から消したボタンの跡が、紙の上に残っている。
「MICA、通常候補」
「紙の凹み、指先接触、照明角度、録画圧縮、表示残り、入力状態のキャッシュ」
「最後だけ毛色が違うな」
「あなたの好みに合わせました」
「俺の好みを嫌な方向に学習するな」
キャッシュ。
一度使ったものを、すぐ取り出せるよう近くに置いておく仕組みだ。
店で言えば、毎回倉庫まで取りに行く代わりに、よく売れる商品をレジ横に置いておくようなもの。便利だが、古い商品を置きっぱなしにすれば、もう売ってはいけないものまで出てくる。
プログラムでも同じだ。
消したはずの表示が残る。更新したはずの値が古いまま見える。押した状態が、離した後も残る。
今回の困りごとは、それが紙の上に見えていることだった。
「状態を分ける」
俺はメモを三つに切った。
表示。
入力状態。
現実側の痕跡。
表示は、白い点や仮想キーの見た目だ。
入力状態は、指が枠に入ったか、s を入れたか、離れたかという内部の記録だ。
現実側の痕跡は、レシートに残った薄い跡だ。
この三つを一緒に消したつもりになっていたから、何が残ったのか分からない。
バグ修正で一番やってはいけないのは、よく分からないまま全部を消すことだ。
消えてしまえば気持ちはいい。だが、それでは何が原因だったか分からない。次に同じものが出たとき、また祈るしかなくなる。
俺は祈る仕事を高額では受けない。
「MICA、消去処理を三系統に分ける。表示だけ、入力だけ、座標対応だけ」
「作成します。確認します。あなたが今やろうとしているのは、現実側の痕跡に対するキャッシュ無効化ですか」
「名前を付けるならな」
「現実側にキャッシュがある前提は未証明です」
「だから仮名だ。仮名は便利だぞ。間違っていたら捨てられる」
「あなたは仮名を気に入りすぎる傾向があります」
「それはある」
MICA が三つの小さなスクリプトを出した。中身は地味だ。表示用のオブジェクトを消す。入力履歴の配列を空にする。画面外座標と机上座標を結びつけた表を捨てる。
地味な処理ほど、失敗したときに怖い。
ログアウトしたはずなのにログイン状態が残る。古い権限が残って、見えてはいけない情報が見える。買い物かごから消したはずの商品が決済にだけ残る。
どれも、見た目より中身が遅れているときに起きる。
この部屋で起きているのは、その現実版かもしれなかった。
「まず表示だけ消す」
画面外座標の生成を止める。白い点は出ない。仮想キーも出ない。
レシートの痕は残った。
「表示キャッシュではない」
「断定には不足します」
「少なくとも表示を止めても消えない」
「記録しました」
次に、入力状態を消す。
専用エディタの内部記録を空にする。最後に指が入った位置、最後に発火した時刻、デバウンスの待ち時間。全部捨てる。
「入力状態を破棄しました」
レシートを見る。
痕は、少し薄くなった。
「動いたな」
「照明角度の可能性があります」
「角度を変える」
ライトを右へ動かす。左へ動かす。レシートを回す。
薄くなった跡は、どの角度でも薄いままだった。
「入力状態と関係してる」
「相関あり。因果は未確定」
「それでいい」
ここで焦って結論を出すと、たぶん負ける。
俺はレシートをスマホで撮り、ファイル名に時刻を入れた。机の端に置いた照明の位置も、マスキングテープで印を付ける。光の角度が変わっただけで、紙の凹みは別物に見える。
「あなたにしては慎重です」
「俺にしては、は余計だ」
「訂正します。高額案件中のあなたとしては通常です」
「それならいい」
本当はよくない。MICA の言い方はだいたい正しい。
面白い現象を見つけたとき、俺は早く触りたくなる。だが、触ったせいで壊したら観測できない。バグは、逃げる。再現条件を雑に扱う人間からは特によく逃げる。
俺は自分が作った痕を、もう一度作ることにした。
ただし、今度は場所を変える。
方眼紙の上で、左の枠を A、右の枠を B と呼ぶ。A に仮想キーを置き、s を一文字だけ入れる。すぐに消す。B は触らない。
実行。
空ファイルに s が入る。
A の位置に、薄い痕が残る。
B には何もない。
「ここまでは想定内」
「想定内という表現に不安があります」
「俺もある」
入力状態を消す。
A の痕が薄くなる。
さらに、入力状態の記録だけでなく、画面外座標の最後の値も捨てる。方眼紙と画面外座標の対応表も捨てる。
A の痕は、ほとんど見えなくなった。
「自分の痕は薄められる」
「はい」
「じゃあ、元のレシートは」
俺は、仮想キーを最初に消したときのレシートを戻した。
一センチ四方の痕がある。
入力状態を消す。
座標対応を消す。
表示を消す。
痕は薄くならなかった。
「おかしい」
「紙の個体差があります」
「新しい紙でもう一度」
同じ手順で、自分の痕を作る。消す。薄くなる。
古いレシートの痕だけが残る。
俺は目を細めた。
残っているのは、一つではなかった。
自分が置いた一センチ四方の痕の端に、細い半月形の跡が重なっている。
俺の枠とは位置がずれている。
指先を近づけた場所とも違う。
「MICA、画像差分」
「実行します」
最初の録画、現在のレシート画像、新しく作った痕の画像を並べる。
自分の痕は、枠の形に近い。
知らない痕は、指先を横から押し当てたような半月形だ。
「これ、俺のじゃない」
「根拠」
「座標が合わない。俺が置いた枠はここ。指を近づけた軌道はここ。残っている半月は、そのどちらにも乗っていない」
「センサー誤差、紙のしわ、過去画像の混入、照明条件の差を候補に残します」
「残せ」
俺は半月形の端を、画面上でなぞった。
なぞるといっても、答えが出るわけじゃない。画像の上に赤い線を引き、座標を読むだけだ。けれど、形を見るより数字を見る方が嘘をつきにくい。
自分の痕の中心は、仮想キーの枠から二ミリ以内に収まっている。
半月形の中心は、そこから七ミリ外れている。
指先の軌道は、逆側を通っている。
「紙がずれた可能性」
「テープで固定していた」
「固定前にずれていた可能性」
「録画の一フレーム目で位置を取る」
「過去画像の混入」
「撮影時刻とハッシュを見る」
MICA は嫌になるほど普通の可能性を並べる。
その普通さが役に立つ。
現実離れしたものを見つけたときほど、普通の失敗を潰す必要がある。レンズの汚れ、紙のしわ、手の影、ファイルの取り違え。そういうものを無視して大発見に飛びつくと、だいたい恥をかく。
「撮影ファイルのハッシュは一致。時刻は連続。照明位置の変化なし。紙の固定も変化なし」
「では、未知の痕跡として扱います。ただし名称は控えめにしてください」
「知らない痕」
「控えめです」
そのとき、三枝さんから追加ログが届いた。
件名は短い。
照度ログ追加分です。
俺は通話ではなく、テキストで返した。
「受領しました。確認します」
向こうのログには、表示ズレの瞬間に小さな照度低下がある。だが、その後にもう一つ、説明しづらい揺れがあった。
表示ズレより、二フレーム遅い。
俺のレシートで、知らない半月形の痕が写った時刻と近い。
「MICA、莉央側ログとこちらの画像時刻を相関」
「時刻同期の精度が不足しています」
「誤差込みでいい」
「相関候補を作成します」
結果は弱い。
断定できない。
だが、無視するには嫌な場所に並んでいた。
「外部由来候補を追加します」
MICA が言った。
俺は手を止めた。
MICA がその言葉を使うのは初めてだった。
「確率は」
「低いです。かなり低い」
「理由」
「時刻同期が弱い。莉央側環境に物理痕跡はない。こちらの痕跡も紙由来の可能性が残ります」
「それでも追加した」
「除外できません」
俺はレシートを見た。
自分が作った痕は薄くなる。
知らない痕だけが残る。
それが何かは分からない。
誰かのものかも分からない。
敵だとか、外部参照だとか、そんな名前を付けるには早すぎる。
だから、今はただこう呼ぶことにした。
知らない痕。
「外部由来の可能性は低いが、除外できません」
MICA がもう一度言った。
「低いままでいい」
俺はレシートを透明な袋に入れた。
「残せ」
■ 技術メモ
【キャッシュ】
キャッシュは、一度使った情報をすぐ使える場所に一時保存する仕組みです。
便利ですが、古い情報が残ると、消したはずの表示や入力状態が残って見えることがあります。
【表示キャッシュ】
表示キャッシュは、画面に出すための見た目の情報が残る状態です。
画面を更新したつもりでも、古い表示が一瞬残ることがあります。
【入力キャッシュ】
入力キャッシュは、押した、離した、最後に触れた位置など、入力に関する古い状態が残ることです。
作中では、入力状態を消すと自分の痕が薄くなるため、入力状態と現実側の痕跡に関係がある可能性が出ています。
【状態分離】
状態分離は、複数の状態を一緒に扱わず、分けて確認する考え方です。
表示、入力状態、現実側の痕跡を分けることで、どの状態が残り続けているのか調べやすくなります。




