Skip to content

fix(sidecar): spawn the sidecar without resolving tsx from the session directory - #23

Merged
smileygames merged 1 commit into
mainfrom
issue-22-sidecar-spawn
Aug 21, 2026
Merged

fix(sidecar): spawn the sidecar without resolving tsx from the session directory#23
smileygames merged 1 commit into
mainfrom
issue-22-sidecar-spawn

Conversation

@smileygames

Copy link
Copy Markdown
Member

Closes #22

観測

.mcp.json へ書く起動コマンドが cmd /c npx tsx <entry> になっていた。npx はカレントディレクトリから tsx を解決するが、サイドカーを spawn するのは CLI であり、その作業ディレクトリはユーザーのプロジェクトである。

実測(作業ディレクトリ = C:\Users\smile\ClaudeCode):

$ npx --no-install tsx --version
npm error npx canceled due to missing packages and no YES option: ["tsx@4.23.12"]

tsx はグローバルにも無い。npx はレジストリからの取得を試み、非対話で spawn されたサイドカーにはその確認へ答える経路が無い。停止するか失敗するかの違いで、どちらでもサイドカーは起動せず部屋には誰も入らない。

直し方

  • command = node
  • args = [絶対パスの tsx/dist/cli.mjs, 絶対パスの entry]

名前で引くものが無くなるため、解決の起点がどこであっても影響しない。node.exe であり直接 spawn できるので、PATHEXT のための cmd /c ラッパーも不要になり Windows 分岐そのものが消えた。

entry と runner は一度の探索で解決する。別々に引くと、片方だけ別ツリーを指す状態が作れてしまうため。環境変数の上書きは両方に用意した。

テストが見ていなかったもの

sidecar/test/round-trip.test.mjs最初からこの形で spawn しており、CI で通っていた。実装側だけが別の経路を使っていて、テストは実装の起動形を見ていなかった。

生成コマンドの形を crates/mcp-config のテストで固定した。npx が再び現れたら落ちる。

検証

  • cargo testcrates/mcp-config、8 pass)
  • cargo check --target x86_64-pc-windows-gnu
  • npx --no-install tsx がセッションの作業ディレクトリで失敗することを実測

release type

patch — 起動不能の修正。

…n directory

.mcp.json に書く起動コマンドが cmd /c npx tsx <entry> になっており、npx は
カレントディレクトリから tsx を解決する。サイドカーを spawn するのは CLI で
あり、その作業ディレクトリはユーザーのプロジェクトであるため、liplus-chat 側に
しか無い tsx がそこで探される。

実測(作業ディレクトリ = C:\Users\smile\ClaudeCode):
  npx --no-install tsx --version
  -> npx canceled due to missing packages and no YES option: ["tsx@4.23.12"]

tsx はグローバルにも無い。npx はレジストリからの取得を試み、非対話で spawn
されたサイドカーにはその確認へ答える経路が無い。停止するか失敗するかの違いで、
どちらでもサイドカーは起動せず部屋には誰も入らない。

command = node、args = [絶対パスの tsx cli, 絶対パスの entry] に変更した。
名前で引くものが無くなるため解決の起点がどこであっても影響しない。node は
.exe であり直接 spawn できるので、PATHEXT のための cmd /c ラッパーも不要に
なり Windows 分岐そのものが消えた。

sidecar/test/round-trip.test.mjs は最初からこの形で spawn しており CI で通って
いた。実装側だけが別の経路を使っていて、テストは実装の起動形を見ていなかった。
生成コマンドの形を crates/mcp-config のテストで固定し、npx が再び現れたら
落ちるようにした。

entry と runner は一度の探索で解決する。別々に引くと片方だけ別ツリーを指す
状態が作れてしまうため。環境変数の上書きは両方に用意した。

#22

@smileygames smileygames left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI self-review (execution_mode = auto)

受け入れ条件の照合(issue #22 完了条件)

条件 結果 根拠
liplus-chat-room エントリが node と絶対パスだけで構成される pass spawn_formnode + [runner, entry] のみを返す。npx / cmd / PATHEXT 依存が消えた
生成コマンドの形がテストで固定されている pass registers_the_room_server_when_no_config_existscommand == "node" と args 配列全体を assert。npx が戻れば落ちる
作業ディレクトリに tsx が無くてもサイドカーが起動できる 実装済 / 実機未確認 解決を伴わない絶対パス指定。実際の spawn は Master の実機でのみ確かめられる

制約の照合

  • 解決の起点をセッションの作業ディレクトリに置かない: pass。名前で引く要素が残っていない。
  • runner を環境変数で上書きできる: pass。LIPLUS_SIDECAR_RUNNER。entry と対称。
  • entry と runner を一度の探索で解決: pass。別々に引くと片方だけ別ツリーを指す状態が作れる。

この欠陥が CI をすり抜けた理由

sidecar/test/round-trip.test.mjs最初からこの正しい形で spawn していた。node_modules/tsx/dist/cli.mjs を絶対パスで指定しており、CI でも通っていた。つまりテストは正しい起動形を実演していながら、実装が使う起動形を一度も見ていなかった。

テストが実装と別の経路を通っていると、テストの緑は実装の緑ではない。今回はテスト側が正しく実装側が誤っていたため、緑が誤りを隠す方向に働いた。生成コマンドの形を assert に入れたのはこの穴を塞ぐため。

検証

  • CI 全ステップ pass(npm run build / sidecar:check / sidecar:test / cargo check / cargo test 8 pass)
  • npx --no-install tsx --version がセッションの作業ディレクトリで missing packages により失敗することを実測。推測ではない。

scope deviation

なし。

次の期待

execution_mode = auto のため人間レビューゲートなし。CI green(CI pass / check pass 2m16s)。self-review pass により squash merge へ進む。

@smileygames
smileygames merged commit a71cd4e into main Aug 21, 2026
2 checks passed
@smileygames
smileygames deleted the issue-22-sidecar-spawn branch August 21, 2026 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(sidecar): spawn the sidecar without resolving tsx from the session directory

1 participant