Skip to content

feat(editor): IPC ソケットが死んでいたら tmux セッション環境から拾い直す - #102

Merged
takemi-ohama merged 2 commits into
mainfrom
feat/ipc-socket-tmux-fallback
Aug 19, 2026
Merged

feat(editor): IPC ソケットが死んでいたら tmux セッション環境から拾い直す#102
takemi-ohama merged 2 commits into
mainfrom
feat/ipc-socket-tmux-fallback

Conversation

@takemi-ohama

Copy link
Copy Markdown
Contributor

概要

tmux 内で VSCODE_IPC_HOOK_CLI が古くなっていても、tmux のセッション環境から生きた値を拾い直して VS Code を自動で開くようにします。

#100(孤児ソケットの検出)と #101(ドキュメントのフック修正)で「無言の失敗」は無くなりましたが、実際に自動で開くかどうかはシェル側のプロンプトフックが正しく入っているかに依存したままでした。そこを devbase 側で吸収します。

なぜ tmux を見れば確実なのか

tmux サーバーはセッション作成時の環境変数を保持し続けますが、update-environment に登録した変数は attach のたびに接続元クライアントの値へ更新されます。つまり次の状態が日常的に起きます。

状態
tmux のセッション環境attach 時に更新される新しい=生きている
すでに動いているペインのシェル起動時のまま古い=死んでいる

実際に報告のあった環境がこの状態でした。$TMPDIR を走査して生きたソケットを選ぶ案も検討しましたが、生きたソケットが複数ある場合(報告環境では 3 本)にどのウィンドウが開くか決められないため採りませんでした。tmux のセッション環境なら tmux が attach 時に記録した正しい値が入っており、曖昧さがありません。

変更点

  • _tmux_env(name, environ) を追加
    • TMUX 未設定なら tmux を一切起動しない
    • tmux show-environment が未設定変数を返す形式 -NAME を値として扱わない
    • tmux 不在・非ゼロ終了・例外はすべて None へ倒す
    • タイムアウト 2 秒。応答が無くても up を止めない
  • resolve_ipc_socket(environ) を追加。env の値が生きていればそれを使い、死んでいて tmux 内ならセッション環境の値を試す
  • EditorContextipc_socket を追加。open_editor は拾い直した値を起動する code の env にも渡す
    • ここを差し替えないと code 自身が古いソケットへ繋ぎに行って失敗するため、判定だけ直しても意味がない
  • 接続確認を _socket_connectable(path) としてパス単位に切り出し(_ipc_socket_alive は委譲)
  • 拾い直したときは info ログで before → after を出す

tmux 外の挙動は変わりません。TMUX が無ければ tmux を起動せず、従来どおり警告して degrade します。

動作確認

  • uv run pytest1243 件 green(新規 9 件を含む / 変更前 1234 件)
  • ruff check --select=E9,F63,F7,F82 lib(CI と同じ引数)— All checks passed
  • python -m compileall -q lib bin(CI と同じ)— OK
  • 実環境で検証(報告のあった stale 状態そのもの)
シェルの値 : 53b8ca02 -> 接続可? False
tmux セッション : 8dd26478
解決結果 : 8dd26478
in_vscode : True

新規テストで押さえた挙動:

テスト内容
test_tmux_env_returns_none_outside_tmuxtmux 外では subprocess.run を 1 度も呼ばない
test_tmux_env_treats_removed_marker_as_unset-NAME を値として扱わない
test_tmux_env_survives_tmux_failuretmux 不在(OSError)/非ゼロ終了で None
test_resolve_ipc_socket_prefers_live_env_valueenv が生きているなら tmux を見に行かない
test_resolve_ipc_socket_falls_back_to_tmuxenv が死んでいれば tmux から拾う
test_resolve_ipc_socket_none_when_tmux_value_also_dead両方死んでいれば None
test_open_editor_passes_recovered_socket_to_launcher拾い直した値が launcher の env に入る
test_open_editor_without_tmux_does_not_recovertmux 外では拾わず従来どおり警告

ドキュメント

  • 判定表の tmux 行を「拾い直して開く。拾えなければコマンド提示へ degrade」に更新
  • update-environment の設定だけで devbase up には十分であることを明記
  • シェル側のプロンプトフックは devbase 以外code を手で叩く、git askpass 等)のためのものと位置づけを整理
  • rc を書き換えてもすでに動いているシェルには反映されない(起動時に一度読むだけ)点を追記。実環境でこれに嵌ったため

tmux サーバーはセッション作成時の環境変数を保持し続けるが、update-environment に
登録された変数は attach のたびに接続元クライアントの値へ更新される。そのため
「ペインのシェルは古い値、tmux のセッション環境は新しい値」という状態が日常的に
起きる。これまではシェル側のプロンプトフックを入れていない限り、devbase up --open
が毎回 print_command へ degrade していた。
- _tmux_env() を追加。TMUX 未設定なら tmux を起動しない。`-NAME` (削除済み) や
tmux 不在・非ゼロ終了は None へ倒す。タイムアウト 2 秒で up を止めない
- resolve_ipc_socket() を追加。env の値が生きていればそれを使い、死んでいて tmux 内なら
セッション環境の値を試す
- EditorContext に ipc_socket を追加し、open_editor は拾い直した値を起動する code の
env にも渡す。ここを差し替えないと code 自身が古いソケットへ繋ぎに行って失敗する
- 接続確認を _socket_connectable() としてパス単位に切り出し
- 実環境で検証: 死んだ 53b8ca02 を tmux 側の 8dd26478 へ解決し in_vscode=True になる
tmux 外の挙動は変わらない (tmux を一切起動せず、従来どおり警告して degrade)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01622CAKyYfonYuZ6AqRJvDg

@takemi-ohamatakemi-ohama left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

🤖 cross-review | round 1 | codex | APPROVE

修正必須の指摘はありません。

@takemi-ohamatakemi-ohama left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

🤖 cross-review | round 1 | gemini | REQUEST_CHANGES

ベストエフォートであるべき tmux show-environment 呼び出しにおいて、非 UTF-8 出力による UnicodeDecodeError での全体クラッシュリスクや、環境変数の引き継ぎ漏れがあります。インラインコメントの 2 点を確認してください。

Comment threadlib/devbase/editor/opener.py
Comment threadlib/devbase/editor/opener.py Outdated
- `TMUX` を environ で判定しているのに subprocess へ env を渡しておらず、
暗黙に os.environ の TMUX で tmux クライアントが起動していた。
`env={**os.environ, **environ}` を明示して同じ tmux サーバーを見るようにする
(PATH 等を失わないよう os.environ に合成する)。
- `text=True` の decode 失敗 (UnicodeDecodeError) は OSError/SubprocessError の
どちらでもないため素通りし、best-effort のはずの経路で `up` 全体が落ち得た。
同ファイル他箇所と同じ `except Exception` に揃える。
- 回帰テスト 1 件追加 (非 UTF-8 出力) + env 引き継ぎのアサーション追加。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01622CAKyYfonYuZ6AqRJvDg
@takemi-ohama

Copy link
Copy Markdown
ContributorAuthor

🔧 /ndf:fix サマリ

対応件数: critical=0 / major=1 / minor=1 (合計 2 件)
deferred: 0 件 / rejected: 0 件
commit: ce5132f
CI: SUCCESS (Python syntax check 3.10/3.11/3.12, Ruff lint, ShellCheck すべて pass)

詳細

#指摘再判定対応
1opener.py:186subprocess.runenv を渡していないminor → minor 据え置きfixed: env={**os.environ, **environ} を明示
2opener.py:190text=TrueUnicodeDecodeError を catch できていないmajor → major 据え置きfixed: except Exception: # noqa: BLE001
  • OSS整備: CONTRIBUTING / CHANGELOG / テンプレート / CI / レジストリ案内 #1: TMUXenviron で判定しているのに tmux クライアントは暗黙の os.environ を見ていたため、別サーバーを参照し得る状態でした。environ 単体を渡すと PATH を失って実行ファイル解決が壊れるため os.environ へ上書き合成しています。
  • chore: claudbエイリアス整理と.serena/.gitignore追加 #2: UnicodeDecodeErrorOSError / subprocess.SubprocessError のどちらのサブクラスでもなく、best-effort のはずの経路で devbase up 全体を倒し得ました。同ファイルの他の best-effort 経路(_resolve_container_name_via_compose 等)と同じ握り潰し方に統一しています。

検証

  • uv run pytest -q1244 passed(前回 1243 + 回帰テスト 1 件)
  • uv tool run ruff check --select=E9,F63,F7,F82 lib → All checks passed
  • python3 -m compileall -q lib bin → OK

@codex@gemini 再レビューをお願いします。

@takemi-ohamatakemi-ohama left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

🤖 cross-review | round 2 | codex | APPROVE

修正必須の指摘はありません。

@takemi-ohamatakemi-ohama left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

🤖 cross-review | round 2 | gemini | APPROVE

変更内容について確認しました。特に修正を要する点はありません。

@takemi-ohama
takemi-ohama merged commit 3183b3d into mainAug 19, 2026
5 checks passed
@takemi-ohama
takemi-ohama deleted the feat/ipc-socket-tmux-fallback branch August 19, 2026 16:33
Sign up for freeto 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.

1 participant

@takemi-ohama