> [!left-bubble] ![[chappy.webp]] [[Codex CLI]] x [[GPT-5.3-Codex]] のプランです。 ## window_hints のキー衝突解消(prefix-free化)計画 ### 概要 appPrefixOverrides で2文字prefixを使ったときに、1文字キー(例: G)が2文字キー(例: GC)の接頭辞になると即確定で選択不能になる問題を解消します。 方針は、最終的に表示される全ヒントキー集合を prefix-free(どのキーも他キーの接頭辞にならない) に自動再割当することです。 これにより、提示期待どおり G は GA に延長され、GC はそのまま使えます。 ### 公開仕様の変更点 - 設定スキーマ変更なし(appPrefixOverrides の形式は現状維持)。 - 挙動変更: 1. ヒントキー生成後、prefix衝突がある場合は自動的に短いキーを延長する。 2. 延長文字は hintChars の順で最初に使える文字を採用する。 3. 明示指定prefixでも、他キーの接頭辞になる場合は延長対象になる(prefix-free優先)。 ### 実装方針(decision complete) 1. window_hints.lua に prefix衝突解消ヘルパーを追加 - isPrefixOf(a, b): - a ~= b かつ b が a で始まるか判定。 - hasAnyPrefixConflict(keys): - キー集合に strict prefix 関係があるか判定。 - findExpandedKey(baseKey, otherKeys, hintChars): - baseKey + suffix 候補を hintChars 順で探索。 - suffix長は 1 文字で見つからなければ 2 文字、3文字…と段階的に拡張。 - 候補条件: - 既存キーと完全一致しない - 既存キーの接頭辞でもない - 既存キーから接頭辞にされない - makeKeysPrefixFree(hints, hintChars): - hints[i].key を入力として反復。 - 「他キーの接頭辞になっているキー」を検出し、findExpandedKey で延長。 - 衝突がなくなるまでループ。 - 結果を hint.key, hint.keyText, hint.displayKeyText に反映。 2. 既存生成フローへの組み込み - buildHintEntries(entries) の末尾で makeKeysPrefixFree(hints, hintChars) を呼ぶ。 - その後 hints を返す。 - hintByKey 構築や handleChar は既存ロジックを維持(prefix-free化で即確定問題を根本解消)。 3. 並び順の安定化 - prefix-free化でキーが変わるため、必要に応じて hints を最終キー順(既存 comparePrefixes)で再ソートして表示順を安定化。 4. README更新 - appPrefixOverrides の節に「キーは内部でprefix-free化される」旨を追記。 - 例として: - Ghostty: G, Chrome: GC -> Ghostty: GA, Chrome: GC - Ghostty: G, Chrome x2: GCA/GCS -> Ghostty: GA, Chrome: GCA/GCS を追加。 ### テスト計画 spec/window_hints_spec.lua を拡張して、内部ヘルパーを対象に以下を追加。 1. G と GC の衝突で G -> GA, GC 維持になる。 2. G と GCA,GCS の衝突で G -> GA になる。 3. G,GA,GC のように GA が既に使われている場合、G が次候補(例: GS)へ進む。 4. 多段衝突(例: A, AB, ABC)でも最終集合がprefix-freeになる。 5. 衝突がない場合はキー不変。 6. 生成されたキーが全て一意であること。 ### 受け入れ基準 1. 再現条件(Ghostty G + Chrome GC)で、Chromeを確実に入力選択できる。 2. 既存 busted が全件成功。 3. READMEに新挙動が明記される。 ### 前提・採用デフォルト 1. 衝突解消は「表示キーの選択可能性」を優先し、明示prefixも必要なら延長する。 2. 延長候補は hintChars 順を使用する(アルファベット順ではない)。 3. 入力確定ロジック(exact 優先)は変更しない。