unified slash menu skill invocation_ja - kkamegawa/vsextensionforcodex GitHub Wiki
日付: 2026-08-11
追跡: Issue #140
ベースライン: main の 249b2c4
実装: codex/140-unified-slash-menu の 6aee497
目標は ChatGPT app と同じように、組み込みコマンドとローカルで利用可能な Codex スキルを一つのインライン Slash メニューへ表示することです。Worker は既に skills/list でスキルを検出しており、本計画では Extension の表示、構造化された turn の受け渡し、永続的なローカルカタログキャッシュを定義します。
ADR-009 は元の v15 呼び出し設計の記録として残します。ADR-010 は、Extension 側のスキル表示20件上限と揮発キャッシュのみという前提だけを置き換えます。Worker の安全上限、平坦化カタログ、完全な同一性検証、欠損耐性、固定 glyph のアイコンフォールバックは維持します。
- コンポーザーの index 0 にある
/で一つのインライン・非Popup候補リストを開きます。//、途中の Slash、/skill、/skills、$skillは対象外です。 - 組み込み候補を先に表示し、上限は8件のままです。同じ仮想化
ListBoxの後半に Skills を表示し、Worker が安全に受理した異なる(Name, Scope, Path)identity を、Worker の安全上限200件まで全て表示します。 - スキルを選ぶと独立した削除可能な
PendingSkillチップを作り、SetComposerText("")で/...の検索文字列だけを消します。通常のコンポーザーは表示したままです。別のスキルを選ぶと置き換え、polite live region で通知します。 - 無効、stale、受動的な状態行は表示しますが、キーボード選択の対象外です。キャッシュカタログは cached と明示し、live generation が届くまで選択不可です。
- Busy または
WaitingForApproval中も選択・置換・削除を許可します。スキルが保留中は Send/steer を無効化し、待つかチップを外すよう案内します。チップを外すと既存の text-only steer を再開できます。 - Ready 状態ではコンポーザーが空でもスキルだけで
turn/startを開始できます。一致するturn/startが成功した後だけチップを消し、更新失敗、stale 検証、送信中の置換、steer、review、compact では保持します。 -
#ファイル候補は Slash 候補と排他的です。Up/Down/Home/End/PageUp/PageDown、Enter/Tab、Escape、Ctrl+Enter の既存キー操作とアクセシビリティを維持します。
- Worker 契約 v15 に nullable な
StartTurnRequest.Skill、SkillInvocationInfo { Name, Scope, Path }、検証済みメタデータ、SkillsChanged { Generation }、bridge の一覧操作を追加します。アイコン DTO/RPC は Remote UI の spike が成功するまで追加しません。 - Extension が Remote UI に公開するのは不透明な選択 ID、安全化済み表示名、固定変換した scope label だけです。raw
Path、URL、command、依存関係の transport 値、defaultPrompt全文は data member にしません。 - 全ての
turn/start直前に Worker がskills/listを force reload します。選択したName + Scope + Pathは、現在の enabled カタログ項目と完全一致しなければなりません。app-server へ送るのは{ "type": "skill", "name": "...", "path": "..." }だけで、Scopeとskill_approvalはシリアライズしません。 - 未知のスキル固有 approval request は fail-closed とし、既存の grant へ流しません。
-
skills/changed通知、接続、再起動、切断で generation を進めます。古い完了結果が新しい snapshot を上書きすることはありません。
Worker は既存の60秒のメモリ正本キャッシュに加えて、versioned な stale-while-revalidate snapshot を %LOCALAPPDATA%\\Kkamegawa.CodexForVisualStudio\\skill-catalog\\v1 に保存します。
- キャッシュキーは正規化した workspace path の SHA-256 です。format version、Codex version、保存 UTC、generation 非依存の truncation 状態、検証済み表示/identity レコード最大200件を保存します。
- hard expiry は24時間、workspace ごと4 MiB、全体64 MiBです。atomic な一時ファイル置換、LRU eviction、名前付き cross-process mutex、欠落・破損・過大・ロック中ファイルから live へ移る fail-open を適用します。
- 保存するのは
Name、Description、ShortDescription、DisplayName、Scope、Path、Enabled、正規化済みBrandColorだけです。DefaultPrompt、依存関係の値、errors、raw app-server JSON、icon path、Remote UI ID は保存しません。 - 有効なディスクレコードは
IsStale=trueで直ちに返し、Extension では cached・選択不可として表示します。single-flight とTimeProviderによるバックグラウンド更新後、最新 generation だけを公開します。選択と turn 開始の正本は常に liveskills/listです。 - Extension は generation 付き表示 snapshot を保持し、Worker への取得はメニューを開くとき、TTL 切れ、通知受信時に限定します。キー入力ごとの RPC は行いません。
一つの仮想化リストに、組み込み行、Skills header、スキル行、loading/empty/unsupported/failed/cached/truncated の受動的な状態行を平坦化します。組み込みは既存の先頭 token 順位と8件上限を維持し、スキルは / 以降全体を検索して空白と dot を保持します。
スキルの順位は Name完全一致、DisplayName完全一致、Name前方一致、DisplayName前方一致、単語境界一致、Name/DisplayName部分一致、説明部分一致の順です。同順位は enabled、repo/user/system/admin/unknown の scope 順、表示名、Name、Path で安定化します。Worker の201件目以降は Worker-truncated 行として表示し、表示側の別上限とは混同しません。同名・同scope・別path は raw path を表示せず、Repository 1 of 2 のような安全な suffix で区別します。
メタデータは表示専用でフィールド単位に検証します。BrandColor は大文字の厳密な #RRGGBB で、小さな accent だけに使い High Contrast では非表示にします。DefaultPrompt は redaction、制御文字除去、4096文字上限を適用し、安全な preview だけを表示します。コンポーザーが空のときの明示操作でのみ挿入し、自動送信しません。依存関係は最大16件の plain-text badge/tooltip(type/value/descriptionに上限)だけで、実行、導入、readiness check、自動承認を行いません。
アイコン spike は未完了です。Extension 所有 cache URI の Image.Source が Remote UI で初回表示・更新できることを確認するまで固定 glyph を使い、icon RPC/DTO は有効化しません。成功時だけ、Worker の containment/PNG 検証、Extension の decode・metadata 除去・SHA-256 名・atomic publish、32ファイル/8 MiB LRU、複数VS間のlockを適用し、Remote UI へは cache URI だけを渡します。
-
契約と Worker: v15 DTO、厳密な serializer、正本メモリキャッシュ、永続キャッシュストア、invalidation/generation guard、sticky
-32601、force reload、fail-closed identity 検証。 - 統合表示: 一つの仮想化 ListBox、組み込み8件、Worker が安全に受理したスキル最大200件、決定的な順位/衝突表示、状態行。
- コンポーザーのライフサイクル: 独立した一枠チップ、置換/削除、検索文字列だけの消去、Busy steer gate、default prompt の明示操作、アクセシビリティ/live region。
- メタデータとセキュリティ: フィールド別 fallback、SafeMarkdown/ISecretRedactor 境界、raw path 非公開、依存関係実行なし、固定 glyph icon gate。
- 検証と文書: Core/UI/cache/serialization/security テスト、warnings-as-errors の Debug/Release build、成果物と embedded XAML の hash、英日ドキュメントと本Wikiの同期。
- サーバーの0、1、20、21、200、201件を検証します。受理された全 identity がキーボードと UI Automation から到達でき、Worker truncation は明示されます。
- stale から live への置換、TTL 境界、force reload、single-flight、通知 race、workspace 分離、破損/期限切れ/過大キャッシュ、atomic concurrent write、LRU cleanup、live fallback を検証します。
- disabled/stale identity 拒否、3フィールドだけの turn serializer、Scope 非シリアライズ、
skill_approval非送信、チップ置換/削除/成功時のみ clear、Busy steer gate、#排他、default prompt 非送信、メタデータ redaction/fallback、raw data member 回帰を検証します。 - Debug/Release build、Core/UI 全テスト、VSIX/DLL/XAML hash、狭い幅と200% DPIの Dark/Light/Blue/High Contrast を確認します。Experimental Instance screenshot と icon spike は手動の後続ゲートです。
別のスキルパネルや mode toggle、新しい NuGet package、途中入力の Slash、iconLarge/SVG、任意の背景色、自動 prompt 送信、依存関係の実行/導入/readiness/自動承認、turn field の skill_approval は対象外です。