コンテンツにスキップ

uLoop 導入の進捗表示とカードの情報負荷 (2026-08-12)

ユーザー報告: (1) 導入ボタンを押してから導入されるまでタイムラグがあるが、その間表示が 変わらず何が起きているか分からない。(2) 押したときに展開される UI が説明過多で情報負荷が 高い。

ラグ: 実測済みの既知値。OpenUPM の解決は実エディタで 30.5 秒(2026-08-04 の初回導入 実行)。Apply は Client.Add を投函した時点で成功を返し、AddRequest は UloopInstallApplyResult.ClientAddRequest に載っているが、UI は誰もポーリングして いない(v0.18.1 のレビュー対応で「UI はまだ読まない。ポーラの配線が次の一歩」と 明記した宿題)。その間、状態ラベルは「未導入」のまま静的な文が1行出るだけ。

カード(合成プランで実カードを構築して計測): 全体 222px。内訳は タイトル 13px / フルパス2本入りの経路文 27px(約100字) / 常時展開の生 JSON 差分 TextField 124px(207字) / ボタン行。「説明過多」の実体は、パス2本を本文に埋めた文章と、 畳めない生 JSON である。

2a. 進捗の実表示(AddRequest のポーリング)

Section titled “2a. 進捗の実表示(AddRequest のポーリング)”

Apply 成功後、返ってきた ClientAddRequest を EditorApplication.update で監視する:

  • 未完了: 「導入中… {0}秒」(経過秒を更新)。Apply は無効のまま。
  • Status == Failure: request.Error.message を添えた失敗表示(非同期失敗が初めて パネル内で見える — v0.18.1 の caveat の正式な解消)。
  • Status == Success: 解決完了。検出器が依存キーを見て「導入済み」に切り替わる。

ドメインリロード横断: 解決成功はパッケージ取り込み→再コンパイル→リロードを引き起こし、 AddRequest オブジェクトはそこで消える。SessionState に「導入進行中」フラグ+開始時刻を 置き、リロード後の RefreshUloopSection は (a) 検出器が導入済み→フラグ解除、 (b) フラグが新しい(5分未満)→「導入中…」を出し続ける、(c) 古い→ 「Package Manager で状態を確認してください」。ポーラを持たない旧状態への退行はない (現状がまさに (b)(c) 無しの世界)。

2b. カードの整理(v0.19.0 と同じ原則)

Section titled “2b. カードの整理(v0.19.0 と同じ原則)”
  • 経路文: パスを本文から抜き、1行に。「manifest.json に OpenUPM レジストリを追加し、 Package Manager にパッケージを要求します。」フルパス2本はカードのツールチップへ。
  • 差分: 折りたたみ(Foldout)で既定は閉。差分が安全装置であることは変わらない — 見たい人が1クリックで開ける。開いた状態の中身は従来どおり。
  • caveat(警告)は画面に残す(v0.19.0 の規則: ホバーしないと読めない警告は警告でない)。
  • 「導入を要求しました。〜約30秒〜」という長い静的文は、ライブの進捗表示に置き換わるので 不要になり削除。
  • 進捗バー(パーセント表示): Client.Add は進捗率を公開しない。偽の進捗を描くのは 「観測していない成果を報告しない」原則に反する。経過秒数が正直な最大限。
  • 差分を完全にツールチップへ: 207字の JSON はホバー表示に不向きで、 等幅・選択可能であるべき差分の性質にも合わない。折りたたみが正解。
  • ポーリング状態機械は純クラスに切り出して EditMode でテーブルテスト。
  • 使い捨てプロジェクトを再作成して実際の導入をもう一度実行し、 Pending→Success の実遷移と経過表示、成功後の「導入済み」切り替えを実測する。
  • カードは合成プランで再構築して高さを before/after 比較する。

カード(同じ合成プランで再計測): 222px → 99px。差分は Foldout で既定閉 (開くまで 0px)、経路文は1行、フルパス2本は経路ラベルのツールチップに載っていることを リフレクションで直接確認。caveat と ボタン行は不変。

実導入(使い捨てプロジェクトで2回実行):

  • 1回目: Apply 成功 → 26.5秒後に本物の解決失敗(UPM の「manifest.json への アクセスが拒否されました」— 一過性のファイルロック)。状態機械は Installing → FailedAsync を正しく導出。従来この失敗は完全に不可視だった (成功と同じ「開始しました」だけが出て、状態は永遠に「未導入」のまま)。 仕込んだ失敗ではなく、偶発した本物の失敗で FailedAsync 経路が検証されたことになる。
  • 2回目(再試行): Installing(0.2秒)→ Succeeded(21.8秒)。 このとき AddRequest.IsCompleted はまだ False のまま検出器が先に立った — 「Succeeded は常に検出器(manifest の依存キー)から導出し、リクエストの成功 ステータスからは導出しない」という設計判断そのものが実測で裏付けられた。 リクエスト完了を待っていたら、実際より遅く成功を報告していた。

サンドボックス 2038 tests / 0 failed(進捗状態機械のテーブルテスト19件を含む)。