つまり「プラグイン化できないもの」の一覧が、そのまま Harnessの定義(=最小のHarness) になる。 現在のHarnessが含む LivePage・MCPアダプタ・ensure/reloadの オーケストレーション等は不可還元ではなく、その不可還元な核の 周りに集まった便益層である(/api/*・/mcp越しに任意言語で 再実装できる)。Harnessは「消せない外側+便利だから置いた外側」の 2層でできている、と読むと正確。

すでにプラグイン側にあるもの

コマンドdispatch・ファイルJSONL・REST・MCP・レジストリ・stdio shimは 全て qgis_live_driver 内にあるため、輸送層としての外側スクリプト (live-drive.mjs/qgis-mcp.mjs相当)は原理的には不要。

さらに以下はnamedコマンドとしてDriverに実装済み:

コマンド 吸収した元の機能
reload_plugin qgis-session.mjs がクライアント側で生成していたreloadコード(sys.modules掃除+reloadPlugin+open_dialog)。自己リロードも可
open_plugin startup.py+WEBENGINE_AUTOOPEN によるダイアログ自動オープン(コマンド呼び出し型に置換)
bridge_call JS経由 BridgeClient.callJson のbridge呼出しをプロセス内直接呼出しに。WebChannelのwedge/飢餓の影響を受けない
status pyeval("1") による間接的な生存probeを正式コマンド化
plugin_id ルーティング eval/pyeval/screenshot/devreload を他プラグインのドライバへ転送。Driverのlive dir/HTTPポート1本が全プラグインの統一制御点になる

さらに内側へ移せるもの

機能 方法
他プラグインのdeploy(ファイル配置) pyevalでファイル配置・junction・QGIS4.iniまで完結可能(reload側は reload_plugin 化済み)。ただし現行の規約ではdeploy系の書込みはUI操作のみと定めているため、導入する場合もその制約を引き継ぐ
LivePage相当のクライアント /api/*を叩くだけのstdlibクライアントに置換可能(mcp_stdio.pyがほぼそれ)
QTWEBENGINE_CHROMIUM_FLAGSの設定 classFactory時点ではQWebEngine未初期化のためプラグイン内でos.environ設定できる可能性(他が先に初期化すると破綻。要検証)
WEBENGINE_LIVE_DIR のゲート QgsSettingsや ~/.qgis-live/ の設定ファイルで有効化判定すればenv無し起動QGISへもアタッチ可能(任意コード実行の常時有効化になるためopt-in必須)

構造上外に残るもの(不可逆)

残るもの 理由 最小化策
プラグイン自身の初回インストール 自己deployの鶏卵問題 通常のプラグインzip/プラグインマネージャ配布
QGISプロセスの起動 プラグインは起動済みQGIS内でしか動かない envを永続化するかlive dir既定パス化すれば「普通に起動」で済む
クラッシュ監視・再起動 ホスト死亡時にドライバも死ぬ(自己監視不可) クライアント側タイムアウト+レジストリstale検出で代替
L1(Playwright)/pytest QGIS無しでの検証が目的なので外が正しい そのまま(Nodeは任意依存に退化)

QGIS_PLUGINPATHをrepoの qgis-plugin/ に恒久的に向ければ deploy自体も不要になる可能性がある(QGIS 4.0.1での動作は要検証)。

決定: ハイブリッド構造を固定方針とする

上記の分析から「全部プラグインにできる」わけだが、実運用の安定性を 考えて「プラグイン内の薄いプリミティブ + 外側のオーケストレーション」の ハイブリッド構造を固定方針とした。

理由(いずれも実測): dispatchはGUIスレッドで動くため、待機や多段処理を インプロセスに入れるとQGIS UIをブロックしてドライバ自身も無応答になる (pyeval内のdriver.submit自己デッドロック等)。加えて、検証側の障害で QGISを巻き込まないクラッシュ分離、実行中コマンドを打ち切る手段が クライアント側の放棄しかない、という理由から、タイムアウトと リトライは構造上外側でしか制御できない。

エラー処理の契約もこの境界で固定する: プリミティブは失敗を {error} で返して例外を漏らさない、境界のHTTP/接続エラーは クライアント側で例外化する、オーケストレーションは個別失敗を集約して 続行する(test:liveのcheck()/WARNパターン)。新コマンドは 「即応答・error返却・GUIブロック禁止」を満たすこととし、長時間処理は 状態付きコマンド(start→poll→result)に分割して待機を外側に置く。

留保