付録

本付録は、本文で語った事件を再説明する場ではありません。再利用可能な設計パターン、章とADR・コミットの対応関係、用語の定義、参考文献を、検索して参照するための資料としてまとめます。

全体像: 最終的なレイヤー構成と、そこへ至る流れ

各章は一つの事件を追いますが、事件ごとの詳細に入る前に、最終的にawaseがどんな形に 落ち着いたかを俯瞰しておきます。以下の図は主経路(入力から出力まで)・観測と信念の層・ 世代照合・アプリごとの適応層という4つのまとまりと、それぞれが互いにどこで作用を 差し止めているかを示しています。

awaseの最終レイヤー構成: 4つのまとまりがどこで互いの実行・送信を差し止めているか

矢印のラベルが、それぞれの層の役目を表しています。「アプリごとの適応層」は物理キーを 渡すかどうかとTSF側の準備確認を、「観測・信念層」と「世代照合」は4層reducerを通じて 「作用してよいか」の最終判断を、それぞれ主経路に対して差し込みます。主経路自体は 判断(Decision)と実行(Effect)を分離しただけの単純な形のままで、複雑さのほとんどは この3つの周辺層に押し出されています。出力の先には、メモ帳・Word(Win32/UWP)、 Chrome・Edge、Windows Terminal・VS Codeという具体的なアプリ名を置き、その先で実際に かな漢字変換を行うGJI(Google 日本語入力)・MS-IMEという2つの競合IMEへつながる様子も 示しています。フックからIME確定文字までの間、WH_KEYBOARD_LL・IMM32/TSF・ GetProcessIoCountersといったWindows APIのどこに触れているかも矢印に添えました。

最終形はいきなりこの4つのまとまりを持っていたわけではありません。以下は、同じ図法で 描いた3つの中間段階です。

第1段階(第1〜2章): 入力から出力までの素朴な一本道

最初の開発日には、これだけが動いていました。判定はengine一つで完結し、周辺の層は まだ存在しません。

第2段階(第3〜4章): 統計的タイブレークとアプリ別出力の追加

n-gramによる際どい判定の補正と、Decision/Effectモデル、アプリ種別ごとの出力切り替えが 加わりますが、依然として一本の経路の中だけで完結しています。

第3段階(第5〜9章): 観測・信念層とアプリ適応層が経路の外側に新設される

ここで初めて、主経路の外側に別の層が新設されます。「観測は信念を直接上書きしない」 というbeliefの発想(第5〜6章)と、「物理キーを渡すか渡さないか」を制御する適応層 (第7〜9章)です。主経路そのものは変わらず、複雑さが周辺へ押し出され始めているのが 分かります。

第4段階が、冒頭で見た最終形です。第10章で観測・信念層と適応層をあらためて4層reducerに 統合し、第11章で世代照合という型を追加することで、「作用してよいか」を最後に一箇所で 判断する経路が完成します。第12章はこの構造にも残る限界を認め、終章はGo2 Runtimeという 別の系で同じ空白を確認します。以降のパターンカタログ・ADR対応表・用語集は、この大きな 流れの中の個々の事件を検索するための詳細です。

パターンカタログ

本文全体から抽出した9個の設計パターンです。各パターンは「パターン名・文脈・問題・働く力・解決・結果・限界・関連する章とADR」の8項目で統一しています。

1. Observer never overrides desired(観測は信念を上書きしない)

2. Generation/epoch fencing(世代照合による足止め)

3. Own the channel, don't filter the noise(チャネルを断つ、ノイズは濾さない)

4. Side-channel observability(副次観測)

5. Classify at the edge(端で分類する)

6. Confidence-tiered sensor fusion(確信度による観測の融合)

7. Snapshot at capture time, not at drain time(捕捉時にスナップショットする)

8. Shadow-mode migration(並走移行)

9. SSOTモチーフの反復

10. Typed proof is not live proof(型は過去の証明であって現在の証明ではない)

ADR・コミット対応表

章・事件・ADR番号・主要コミットの対応です。本文の再説明はせず、参照先として使う表です。

事件名症状ADR番号主要コミット不変条件破れる条件
第10章IME belief/SSOTモデルの変遷observationがintentを上書きADR-032, 077d2e183f, f8dd8d4, 6baabf9, a4db93e, 604cf99観測は意図を直接書き換えない/generation一致でのみ状態変更admit後・適用前のepoch遷移(TOCTOU)
第4章Windows Terminal/TSFコールドスタートliteral化ローマ字キーストロークのリテラル漏れADR-04983d5707, 4249846, f426297, 9c80975, a3cce29固定待機でなく副作用からreadiness推論344ms超の長時間アイドル再初期化
第8章ImmCross/LINE偽VK_F3/F4 echo物理KANJIキー押下が偽トグル生成要確認(未特定)d99e3f1, 77ccf34, e890a26, f84c74b, 08b8661, 0e364ea対象アプリに物理IMEキーを見せないImmCrossProbe自体の信頼性問題(Qt子ウィジェット)
第8章(補)GJIキーバインド3世代交代F13/F14衝突ADR-034/057/0677f8291f, 81df62c, cfbbd20, b271aee, 098c663idempotentな絶対セットキーを使うMS-IMEはVK_KANJIが必要(ADR-063)
第10章(補)VK/ScanCode混同検知dylintnewtype導入後も取り違え継続ADR-0122dd43f4vk.rs外でmagic hexを直接書かない未確認(現状lintで防御)
第7章捨て打ち機能(旧サクリファイシャル・ウォームアップ)Chrome cold-start中のリテラル化ADR-048, 06226bc0fe, d02ec44, 6c1732d, 22c3905必要操作自体をプローブに転用、Chrome+GJIのみ適用vim等ターミナルアプリとのVK_A衝突(他アプリはVK_IME_OFF→ON方式へ離脱済み)
第9章StepCoro統一増殖したFSM群(5種類)の複雑化ADR-053e548e63, ccd4711, f01d401, b077c3d, 2c756dd, d1d6d17一回限りの手続きはStepCoro、長期生存・外部問い合わせ対象はFSMとして残すウォームパスのLiteralDetectFsmはコルーチン化されず残存(意図的)

注記です。第8章のコミットハッシュとADR番号の一部は、既存調査からの転記であり、リポジトリ側での再確認は未実施です。

拡張用語集

src/toc.mdの用語集をもとに、Go2 Runtime実地検証で見つかった対応語を追記しています。

用語定義Go2 Runtime対応語
awase (awase)本書で描くWindows用日本語入力エンジン(NICOLA親指シフト方式)
NICOLA / 親指シフト親指キーとの同時打鍵タイミングで仮名を確定する日本語入力方式
shadow stateOSが正直に教えてくれないIME状態を、自前で推測・保持する仕組みWorldState(immutableな世界モデル)
belief(信念)観測から導出した「いまのIME状態はこうだろう」という推定値BeliefView<T>(旧称BeliefSnapshot<S,B>)
Observation(観測)probe・pollから届く生の情報。beliefを直接上書きしないStateUpdate(S層が受け取る生観測)
FocusEpochフォーカス変更等を境に単調増加するカウンタ。観測の鮮度を判定する基準TickId(tick単調カウンタ。ただしepoch照合には未使用)
AcceptedObservation世代(epoch)照合(admit)を通らないと構築できない、型で保証された「新鮮な観測」現状Go2に相当機構なし(Go2Cmd<Checked>は過去の証明のみ)
TOCTOU急所admitした時点では新鮮でも、実際に適用する時点では陳腐化している間隙Executor::execute直前のガードがwatchdogのみである間隙(ADR-R009)
捨て打ち機能必要な操作自体をプローブとして転用し、I/Oカウンタ差分で副次観測する技法直接対応なし(SimIo::injectは素朴な注入のみ)
Go2 Runtime著者が別に設計しているロボット(Unitree Go2)向けアプリケーションランタイム
Observed<T>Go2 Runtimeの観測品質型。FreshStaleUnknownBrokenの4値を持つawaseのshadow state・beliefに相当
BeliefQuality観測の信頼度(confidence)と裏付け種別(evidence)を保持する型。鮮度は持たない(INV-OB1)awaseの確信度型に相当
ControlLease / fencing_token複数オペレータ間で、古い命令が新しい命令を誤って上書きしないためのリーダー選出の仕組み(ADR-P005)awaseのFocusEpochとは別問題(対比事例)
Field<T>beliefを介さない素の観測値(odom等)にも、鮮度・品質を必須で添付するラッパ型shadow stateの「何でもbelief化する」思想と相似

参考文献リスト

文献書誌情報備考
Kleppmann, フェンシングトークン論Martin Kleppmann, "How to do distributed locking", 2016-02-08, https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.htmlfencing tokenの標準的な説明・Redlock批判で知られるブログ記事です。
Chubby (Burrows, OSDI 2006)Mike Burrows, "The Chubby lock service for loosely-coupled distributed systems", 7th USENIX OSDI '06, 2006-11. https://www.usenix.org/conference/osdi-06/presentation/chubby-lock-service-loosely-coupled-distributed-systemsPDF直リンクは要検索です。書誌情報としては確認済みです。
Firefox OS/Gaia bug 1110030Bugzilla@Mozilla, Bug 1110030, "Routing hardware key events to keyboard app when an input field is focusing", https://bugzilla.mozilla.org/show_bug.cgi?id=1110030IsSynthesizedByTIPフラグへの言及箇所は要検索です(バグ番号・タイトルのみ確認済み)。
NIOSH Hierarchy of ControlsCDC/NIOSH, "Hierarchy of Controls", https://www.cdc.gov/niosh/hierarchy-of-controls/about/elimination・substitution・engineering・administrative・PPEの5段階を示す公式頁です。
Yaron Minsky, "Make illegal states unrepresentable"原典記事URLは要検索です(OCamlコミュニティで広まった言い回し)。要検索
"Typestate via Revocable Capabilities" (arXiv 2510.08889)arXiv番号のみ確認済みで、URLは要検索です。要検索
Kubernetes resourceVersionKubernetes公式ドキュメント, "API Concepts: Efficient detection of changes", https://kubernetes.io/docs/reference/using-api/api-concepts/オブジェクトの世代を表す文字列で、楽観的排他制御に使われます。
Raftコンセンサスアルゴリズムのterm番号Diego Ongaro, John Ousterhout, "In Search of an Understandable Consensus Algorithm", USENIX ATC 2014第11章で触れた「任期」番号の出典です。
Gaffer On GamesGlenn Fiedler, "Gaffer On Games"(ネットコード分野で広く参照される個人技術ブログ), https://gafferongames.com/URLはトップページのみ確認、個別記事の直リンクは要検索です。
GGPOGGPO開発チーム, "GGPO Rollback Networking SDK", https://github.com/pond3r/ggpoロールバック方式ネットコードの代表的な実装です。
Bevy TickBevy公式ドキュメント, bevy_ecs::component::Tick, https://docs.rs/bevy_ecs/latest/bevy_ecs/component/struct.Tick.htmlRust製ゲームエンジンBevyのECSが持つ、フレームごとに増える世代カウンタです。
crossbeam-epochcrossbeam-rsプロジェクト, https://docs.rs/crossbeam-epoch/「epoch」という語は共通ですが、解いているのはメモリ回収問題であり、第11章の観測の陳腐化とは別問題です(false friend)。
slotmap / generational-arenaそれぞれのcrates.ioページ、https://docs.rs/slotmap/https://docs.rs/generational-arena/世代付きインデックスを持ちますが、値の構築自体を型で制限してはいません。
GhostCell / generativityJoshua Yanovski et al., "GhostCell: Separating Permissions from Data in Rust"(ICFP 2021)、generativity crateドキュメントブランド型・phantomライフタイムで不正な構築を防ぐ技法ですが、世代カウンタとの組み合わせ例は確認できませんでした。
Peter Ferrie, アンチデバッグ手法集Peter Ferrie, "The Ultimate Anti-Debugging Reference", 2011年初出・以降改訂I/Oカウンタ差分によるプロセス挙動の推測が、2013年前後の解説記事に同様の手法として登場します。原典URLは要検索です。
F5/NGINXの受動的ヘルスチェックF5公式ドキュメント「Passive Health Monitoring」、NGINX公式ドキュメント「passive health checks」専用の確認要求を送らず、既存の通信に相乗りして相手の状態を推測する手法です。
チョード式キーボードの特許(US4,680,572)United States Patent 4,680,572 (1987年登録)複数キーの組み合わせで文字を確定させる入力方式の古典的な特許です。
QMKファームウェアのtap-hold機能QMK公式ドキュメント, "Tap-Hold Configuration Options", https://docs.qmk.fm/tap_holdキーを押す長さで異なる動作を割り当てる、自作キーボード向けファームウェアの機能です。
Rodney Brooks, Subsumption ArchitectureRodney A. Brooks, "A Robust Layered Control System for a Mobile Robot", IEEE Journal of Robotics and Automation, 1986知覚・計画・行動という順序そのものに異議を唱えたロボティクスの古典的論文です。
Joint Detection and Estimation理論信号処理分野における、検出(detection)と推定(estimation)を同時に扱う理論の総称。個別の代表論文は要検索です。逐次処理(先に検出、後で推定)の劣位性を形式的に扱う理論分野です。
Gary Bernhardt, "Functional Core, Imperative Shell"Gary Bernhardt, "Boundaries"(講演、2012年、Destroy All Software)判断を行う純粋な核と、副作用を実行する薄い外殻を分ける設計思想の呼び名として広まりました。講演URLは要検索です。
Android ANR(Application Not Responding)Android公式ドキュメント, "Keep your app responsive", https://developer.android.com/topic/performance/vitals/anrメインスレッドが一定時間応答しないアプリを検知する仕組みです。URLは要検索です。
Kubernetes readiness/livenessプローブKubernetes公式ドキュメント, "Configure Liveness, Readiness and Startup Probes", https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/固定時間ではなく実際の応答確認によって、通信を回してよいかを判断する仕組みです。
TCP再送タイマーとKarnのアルゴリズムPhil Karn, Craig Partridge, "Improving Round-Trip Time Estimates in Reliable Transport Protocols", ACM SIGCOMM 1987実測した往復時間をもとに再送までの待ち時間を更新し続ける手法です。
ReduxRedux公式ドキュメント, https://redux.js.org/一回限りの処理と、アプリ全体が持ち続ける状態を意図的に分離するフロントエンド向け状態管理ライブラリです。
JavaScript/Python/Rustのasync/await各言語公式ドキュメント(ECMAScript async functions、PEP 492、Rust async book)コンパイラが一直線に書かれた手続きを、中断・再開可能な状態機械へ変換する仕組みです。個別URLは要検索です。
フライバイワイヤとフライトエンベロープ保護例: Airbus公式資料「Fly-by-wire」解説等操縦桿の意図・センサーの観測・保護則の最終判断を分離する航空機の設計です。個別の一次資料URLは要検索です。
CWE-367 (Time-of-check Time-of-use Race Condition)MITRE, "CWE-367", https://cwe.mitre.org/data/definitions/367.html確認時点と使用時点のずれによる脆弱性の分類項目です。

未確認・要確認事項