Skip to content

feat(PLAN69): tmux のセッションを名指しで移る・調べる・落とすコマンドと prefix S のメニュー(#234) - #264

Merged
takemi-ohama merged 16 commits into
mainfrom
feature/plan69-tmux-named-session
Sep 24, 2026
Merged

takemi-ohama merged 16 commits into
mainfrom
feature/plan69-tmux-named-session

Conversation

@takemi-ohama

@takemi-ohama takemi-ohama commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Closes #234

Summary

  • containers/base/tmux-session を新設。1 つの tmux セッションを名指しで 移る(go)・調べる(peek)・落とす(kill)。tmux-go / tmux-peek / tmux-kill の symlink で呼ぶとそのサブコマンドになる。名前は完全一致、$数字 は ID(名前へ落とさない)
  • /etc/tmux.conf に prefix S を足す。choose-tree で選んだセッションの ID と押した端末名を tmux-session menu へ渡し、「移る / 中身を見る(popup) / 落とす(確認つき)」のメニューを出す
  • Dockerfile の tmux の整理コマンドの節に COPY と symlink 3 つ、CI の ShellCheck に containers/base/tmux-first / tmux-clean / tmux-session の step(severity は既定)を足す
  • 利用者向け文書(docs/user/environment-variables.md「セッションを名指しで扱う」。ホストで使う手順を含む)と CHANGELOG
  • tmux-first / tmux-clean と entrypoint.sh は変えていない

設計: issues/old/PLAN69_tmux-named-session-design.md(#260)。タスク分解と実装で確かめたことは issues/old/PLAN69_tmux-named-session.md。

設計の未確認 3 件の結果:

  • メニューの引用の入れ子: pty から prefix S → 選択 → a / p / k→y を送るテストで、' " $ ; を含む名前でも選んだセッションに効いた
  • 背景の run-shell -b からの display-message -c: 端末へ届いた(設計のまま)
  • shellcheck: 手元の 0.11.0 で 3 ファイルとも既定の severity で 0 件。runner の版の結果はこの PR の CI で見る

並行の #253(PR #262)も containers/base/Dockerfile を触るが、触る節が違う(本件は tmux の整理コマンドの節)。先にマージされた側の上へ載せ直す。

Test plan

ホスト(macOS、tmux 3.7b)で実行。tmux のテストは TMUX_TMPDIR を専用のディレクトリへ向け、利用者の tmux サーバに触れない。

  • env -u DEVBASE_ROOT uv run --locked pytest tests/ -q → 3092 passed、exit=0(受け入れ条件 20)
  • uv run --locked pytest tests/containers/test_tmux_session.py tests/containers/test_tmux_conf.py -q → 75 passed(受け入れ条件 1〜14、16 の Dockerfile の静的な部分)
  • 同じテストを tmux-session の shebang を /bin/dash に差し替えて実行 → 64 passed(Ubuntu の /bin/sh 相当)
  • uvx --from shellcheck-py shellcheck containers/base/tmux-session containers/base/tmux-first containers/base/tmux-clean → exit=0(0.11.0)
  • git diff --stat origin/main -- containers/base/tmux-first containers/base/tmux-clean が空(受け入れ条件 19)
  • CI の ShellCheck ジョブが成功(受け入れ条件 18。runner の版でも 3 ファイルとも指摘 0 件)
  • 作業ツリーの ./bin/devbase build base --no-cache(26637c2 から。構造改善で変わったのはテストだけで tmux-session は同じ)→ exit=0。建ったイメージの /usr/local/bin/tmux-session の sha256 4752cb42…a87e3 が作業ツリーのファイルと一致(受け入れ条件 16)
  • 使い捨ての docker run --rm --entrypoint /bin/bash devbase-base:plan69 /x/check.sh(受け入れ条件 16・17・15)
  • 構造改善(/ndf:cross-refactoring)で現状固定のテストを 8 件足した(tests/containers/test_tmux_session.py、+402 行)。構造の書き換えの提案 4 件はテストの期待を変えるため取り消し、本体は無変更
イメージの中の結果(受け入れ条件 16・17)
lrwxrwxrwx 1 root root    12 Sep 24 03:41 /usr/local/bin/tmux-go -> tmux-session
lrwxrwxrwx 1 root root    12 Sep 24 03:41 /usr/local/bin/tmux-kill -> tmux-session
lrwxrwxrwx 1 root root    12 Sep 24 03:41 /usr/local/bin/tmux-peek -> tmux-session
-rwxr-xr-x 1 root root 13057 Sep 24 03:32 /usr/local/bin/tmux-session
4752cb4239d9f1d1e3dbbbd433da6eb9958e8e72f363e439524cc4d4851a87e3  /usr/local/bin/tmux-session
tmux-go -h exit=0
shellcheck version: 0.11.0
shellcheck exit=0
メニュー(受け入れ条件 15): コンテナの tmux 3.6 で、外側の tmux の pane を利用者の端末に見立て、send-keys で prefix S → 一覧で選ぶ → a / p / k を押した
--- menu (target)
                ┌───────────target───────────┐
                │ 移る(他の端末を外す) (a) │
                │ 中身を見る             (p) │
                │ 落とす                 (k) │
                └────────────────────────────┘
--- p(中身を見る): popup に peek の出力
       │session  target ($1)  windows 1  attached 0
       │clients
       │  (なし)
       │panes
       │  0.0  bash  pid=23  /work
       │    59  sleep 1000
       │screen (0.0 の直近 20 行) ...
       │[Enter で閉じる]
--- k(落とす): 確認が出て n で残る
target を落としますか? (y/n)
after n: a b$1,keep,target,
--- a(移る): 端末が target へ移った
after a (client session): /dev/pts/3 target
--- 名前 `a b$1` を k → y: そのセッションだけ終わる(表示名は安全な文字でないため ID)
$0 を落としますか? (y/n)
after y: keep,target,
  • メニューを人が実際の端末で操作する確認は利用者に残す(send-keys による再現は上のとおり済み。手での確認は未確認)
  • 文書の差分の目視(受け入れ条件 21): docs/user/environment-variables.md「セッションを名指しで扱う」に 3 つのコマンド・prefix S・ホストでの symlink と ~/.tmux.conf の 1 行、CHANGELOG.md [Unreleased] に devbase build base --no-cache が要ること

検査の持ち場の検証結果(b3b9b88)

段階 コマンド 対象範囲 実行時刻 結果
限定的な検証 env -u DEVBASE_ROOT uv run --locked pytest tests/containers/test_tmux_session.py tests/containers/test_tmux_conf.py -q tmux のテスト 2026-09-24 14:14 91 passed / exit=0
全体テスト env -u DEVBASE_ROOT uv run --locked pytest tests/ -q 全体 2026-09-24 14:15 3108 passed / exit=0
静的解析 uvx --from shellcheck-py shellcheck containers/base/tmux-{session,first,clean} 3 ファイル 2026-09-24 14:17 exit=0
CI ShellCheck / Ruff / Pytest 3.10・3.13 / syntax 全体 b3b9b88 すべて success
イメージ ./bin/devbase build base --no-cache → 使い捨て docker run(上の details) base イメージ 2026-09-24 12:41 exit=0。tmux-session の sha256 は b3b9b88 のファイルと一致
  • 実装レビュー(/ndf:cross-review): 2 ラウンドで収束(round 1 codex 1 件 minor + CI の flaky を b3b9b88 で修正、round 2 agy / kiro とも指摘 0)。未解決のスレッド 0
  • 構造改善(/ndf:cross-refactoring): テスト整備 2 ラウンドで現状固定テスト 8 件を追加。構造の書き換え 4 件はテストの期待を変えるため取り消し(改修計画: feat(PLAN69): tmux のセッションを名指しで移る・調べる・落とすコマンドと prefix S のメニュー(#234) #264 (comment) )
  • 受け入れ条件: 1〜21 のうち 15 の「人が実端末で操作する」部分だけ未確認(send-keys での再現は済み)。ほかは満たす
  • 既存の失敗: なし / 範囲外と判断したもの: なし

確定仕様化(37c1c05)

対象 内容
docs/specifications/tmux-named-session.md 確定仕様を新設(前例 PLAN67 / PR #252 の 1d4c3b4 と同じ形)
issues/PLAN69_tmux-named-session*.md → issues/old/ 要求と設計の 2 文書を移した(中身は変えていない)
docs/user/environment-variables.md 新しい確定仕様へのリンク
docs/specifications/kiro-auth-persistence-and-tmux-copy.md 関連リンクに相互リンクを 1 行

env -u DEVBASE_ROOT uv run pytest -q exit=0、CI(37c1c05)すべて success。

🤖 Generated with Claude Code

takemi-ohama and others added 2 commits September 24, 2026 12:33
- containers/base/tmux-session を新設(go / peek / kill / menu)。tmux-go / tmux-peek /
  tmux-kill の symlink で呼ぶとそのサブコマンドになる
- /etc/tmux.conf に prefix S(choose-tree → menu)を足す
- Dockerfile に COPY と symlink、CI の ShellCheck に containers/base/tmux-* の step を足す
- 専用のソケットの tmux で振る舞いを確かめるテストと、利用者向け文書・CHANGELOG

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Keep the invoking client and unrelated clients connected while detaching other clients of the target session, using a stateful tmux stub.

Item-Id: R1-001
Round: 1
Impl-Runtime: codex
Impl-Model: default
@takemi-ohama

takemi-ohama commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/devbase #264

/ndf:cross-refactoring が提案し、適用した改善項目の記録である。
理由と手順は提案の時点でしか残らないため、公開の直前に書き出している。

  • 対象範囲: containers/base/tmux-session, containers/base/tmux.conf, tests/containers/test_tmux_session.py, tests/containers/test_tmux_conf.py
  • 着手前のテスト: env -u DEVBASE_ROOT uv run pytest -q -p no:cacheprovider

ラウンド 1(実装 codex)

R1-001 — containers/base/tmux-session#do_go

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude / codex 採用 1

なぜ: do_go は実行元が既に対象のセッションにいるとき switch-client を飛ばし、他の端末を外すだけにする分岐を持つ。テストはすべて別のセッションから移る場合で、この分岐は固定されていない

手順: 1. 状態を保持するtmuxスタブで、移動先に実行元と別端末、無関係なセッションに第三の端末が接続した状態を用意する。
2. 公開CLIのtmux-session go -c <実行元> <移動先>を実行し、現状の終了値・標準出力・接続状態を採取する。
3. 終了0、標準出力が空、移動先には実行元だけが残り、第三の端末の接続は変わらないことを固定する。tmuxコマンドの呼び出し回数や内部処理順序は検証しない。

R1-002 — containers/base/tmux-session#do_kill

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude / kiro 採用 1

なぜ: do_kill の LAST ブロックには DRY=1 の分岐があり、-f と -n を同時に与えて自分のセッションを予定表示だけして残す経路がある。既存の test_kill_force_ends_own_session_last は -f のみ (実際に落とす)、test_kill_dry_run_keeps_sessions は自分でないセッションへの -n のみで、この組み合わせの分岐は固定されていない

手順: 1. devbase-3 と other と keep を作り、devbase-3 の pane の環境 (inside_env) で tmux-kill -n -f devbase-3 other を実行する
2. 終了コード 0、KILL で始まる行が other → devbase-3 の順で両方 "(dry-run)" 付き、セッションの集合が変わらないことを確かめる
3. 別のテストで端末を home へ attach し、tmux-kill -c <その端末> home keep を実行する
4. 終了コード 1、標準出力が空、home は残り keep は消えていることを確かめる

R1-003 — containers/base/tmux-session#do_peek

兆候・経路 手法・階層 重要度 提案元 状態 コミット
boundary unit — claude / codex 採用 1

なぜ: peek のテストは端末が繋がったセッションと、画面の行が -n より多い場合だけを見ている。繋がっている端末が 0 件のときの clients 節と、-n が画面の行数より多いとき (start が 1 に丸められる境界) は固定されていない

手順: 1. 端末を繋がないセッション devbase-2 を作り、send-keys で line-1 と line-2 だけを出して capture-pane に line-2 が出るまで待つ
2. tmux-peek -n 50 devbase-2 を実行する
3. 終了コード 0、session 行の attached が 0、clients 節の見出しと panes 節の見出しの間が 1 行だけでそこに端末の名前 (/dev/ で始まる語) が無いことを確かめる
4. screen 節に line-1 と line-2 の両方が含まれ、節の最後の行が空白だけの行ではないことを確かめる

R1-004 — containers/base/tmux-session#do_go

兆候・経路 手法・階層 重要度 提案元 状態 コミット
boundary unit — codex 採用 1

なぜ: 実行元端末の判定はプロンプトからの成功と11秒待った失敗のみで、最終操作からちょうど10秒の境界は固定されていない。閾値の比較演算を変えた退行を既存テストでは検出できない。

手順: 1. PATHに状態を保持するtmuxのスタブと固定時刻を返すdateのスタブを置き、TMUXを設定する。移動元・移動先・第三のセッションと各クライアントを用意する。
2. 現在時刻との差を10秒・11秒にしたclient_activityを返し、公開CLIのtmux-session goを-cなしでそれぞれ実行して現状の終了値と接続状態を採取する。
3. 10秒では終了0で実行元が移動先へ移り移動先の他端末が外れること、11秒では終了1で全接続が維持されることを固定する。第三のセッションの接続はいずれも維持されることを確認する。実時間のsleepや内部関数の直接呼び出しは使わない。

R1-005 — containers/base/tmux-session#do_kill

兆候・経路 手法・階層 重要度 提案元 状態 コミット
error unit — codex 採用 1

なぜ: 対象が見つからない場合の継続は固定されているが、対象を解決できた後にtmux kill-sessionが失敗する経路は固定されていない。通常対象の削除失敗と、-fで最後に処理する自己セッションの削除失敗で終了値を失わないことを守る。

手順: 1. セッション状態を保持するtmuxスタブを用意し、指定したIDの削除だけを非0で失敗させ、他のIDの削除は状態へ反映する。
2. 公開CLIのtmux-session killに失敗対象・成功対象をこの順で渡し、現状の終了値と残存セッションを採取する。終了1となり失敗対象は残り、後続の成功対象は削除されることを固定する。診断は対象名の包含だけを確認する。
3. 別ケースでTMUXとTMUX_PANEを設定し、自己セッションの削除を失敗させてkill -fへ自己・他対象を渡す。終了1となり自己は残るが他対象は削除されることを固定する。どちらも無関係なセッションが残ることを確認する。

ラウンド 2(実装 kiro)

R2-001 — containers/base/tmux-session#do_go

兆候・経路 手法・階層 重要度 提案元 状態 コミット
error unit — claude / codex / kiro 採用 1

なぜ: do_go の go 経路のうち、外への attach・-c 切替の成功・プロンプト推定・実行元不明の 4 本は固定済みだが、cur != id で switch-client が非 0 を返し fail する分岐は固定されていない。既存の do_kill 失敗系と同じ tmux スタブ方式で、公開入口の終了コードとして観測できる。

手順: 1. 既存の go 単体テストと同様に、端末と接続先を保持する tmux スタブを PATH に置く。実行元を source、他の端末 2 台を target、無関係な端末を unrelated に接続した初期状態を作る。内部関数は直接呼ばず、各ケースで状態を作り直して tmux-session go -c <実行元> target を実行する。
2. 一方の対象端末の切断だけを失敗させるケースを実行し、現状の終了コード・標準出力・標準エラーと最終接続状態を採取する。終了コード 0、実行元は target へ移動、切断失敗端末は target に残留、切断成功端末は接続なし、無関係端末は不変となることを固定する。警告は失敗端末の識別子を含むことだけを確認する。
3. 切断は成功し、実行元の切り替えだけを失敗させる別ケースを実行して同じ観測値を採取する。終了コード 1、実行元は source に残留、対象の他端末は切断済み、無関係端末は不変となることを固定する。標準エラーは対象名を含むことだけを確認する。
4. 両ケースで -c 指定時の標準出力が空であることを確認する。期待値は現行 CLI の実測で確定し、内部呼び出し回数・呼び出し順・表示全文は固定しない。

R2-002 — containers/base/tmux-session#do_go

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 採用 1

なぜ: do_go で detach-client が失敗した端末は warn だけ出して続ける分岐があるが固定されていない。失敗しても残りの端末を外し、切り替えまで進んで終了値 0 になる現状は、ループや失敗処理を書き換えると変わりやすい

手順: 1. clients.json 方式の tmux スタブで、指定した 1 端末の detach-client だけ非 0 で終わるようにする
2. 対象セッション $1 に /dev/pts/2 (外せない) と /dev/pts/3 (外せる) を置き、実行元 /dev/pts/1 を $2 に置く
3. tmux-session go -c /dev/pts/1 target を実行する
4. 終了値 0、標準エラーに外せなかった端末名 /dev/pts/2 が含まれること、保存後の状態で /dev/pts/3 が外れ /dev/pts/2 は残り /dev/pts/1 が $1 へ移っていることを比較する

R2-003 — containers/base/tmux-session#main

兆候・経路 手法・階層 重要度 提案元 状態 コミット
error unit — claude 採用 1

なぜ: 使い方の誤りのうち、オプションの値が欠けた場合 (-c / -n が末尾)、kill のセッション無し、peek への -c、menu への複数セッションは test_usage_errors_exit_two に無く、終了値 2 が固定されていない。引数解析の case を整理すると壊れやすい経路である

手順: 1. test_usage_errors_exit_two の parametrize に次を足す: (tmux-go, -c) / (tmux-peek, -n) / (tmux-kill,) / (tmux-peek, -c, /dev/pts/1, x) / (tmux-session, menu, -c, /dev/pts/1, a, b)
2. 既存と同じく終了値 2 と標準エラーが空でないことだけを確かめる (文言は比べない)
3. 追加前に実行し、現状が各入力で 2 を返すことを確認してから固定する

ラウンド 3(実装 claude)

R3-001 — tests/containers/test_tmux_session.py#_GO_FAIL_STUB

兆候・経路 手法・階層 重要度 提案元 状態 コミット
duplication consolidate_duplication major claude / kiro 取り消し 1

なぜ: go の経路を固定する tmux スタブ (clients.json を読み、list-sessions / list-clients / display-message / detach-client / switch-client を返す Python) が test_go_from_target_session_detaches_only_other_target_clients、test_go_infers_client_at_activity_boundary、_GO_FAIL_STUB の 3 箇所にほぼ同じ内容で書かれ、差は list-sessions の行・activity の返し方・fail の有無だけ。さらに別テストでは文字列置換 (.replace) で list-sessions を差し替えている

手順: 1. _GO_FAIL_STUB を、list-sessions の出力を sessions.txt から、activity を activity ファイル (無ければ該当書式を未対応扱い) から、fail を fail ファイル (無ければ空) から読む汎用スタブ _GO_STUB に改める
2. 準備関数を _go_env(tmp_path, clients, sessions='$1 source\n$2 target\n$3 unrelated', fail='', activity=None) に広げ、clients.json・sessions.txt・fail・activity を書いてスタブと環境を返す
3. test_go_from_target_session_detaches_only_other_target_clients と test_go_infers_client_at_activity_boundary のインラインのスタブを削り _go_env を使う (date スタブは activity のテストに残す)
4. test_go_detach_failure_continues_to_remaining_client_and_earlier_session の .replace による差し替えを sessions 引数に置き換える
5. 対象テストの結果が変わらないこと (各テストのアサーションは触らない) を確認する

R3-002 — containers/base/tmux-session#do_go

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major claude 取り消し 1

なぜ: do_go に tmux 外での attach、実行元の端末の推定 (date と client_activity の比較、SELF_FRESH の判定、case での分解)、他端末の detach、switch-client が同居している。推定部 (ME=... から fi まで 13 行) は tmux-first と同じ規則を写したもので、独立した名前があれば規則の対応 (コメントの『両方直す』) も追いやすい

手順: 1. ME の推定部 (ME=$CLIENT から if [ "$HAVE_CLIENT" = 0 ] ... fi まで) を関数 infer_client として抽出し、推定した端末名を標準出力へ出す (特定できなければ空)。SELF_FRESH とコメントも関数側へ移す
2. do_go では ME=$(infer_client) で受ける。set -e 下で失敗しないよう、関数内の tmux 呼び出しは現状どおり || true を保つ
3. 以降の [ -z "$ME" ] の判定・detach・switch は変えない
4. test_go_infers_client_at_activity_boundary (10 秒/11 秒) と test_go_from_prompt_switches_the_typing_client、test_go_inside_without_known_client_does_nothing を実行して境界と失敗経路が同じであることを確かめる

ラウンド 4(実装 codex)

R4-001 — tests/containers/test_tmux_conf.py#_effective_options / _client_capabilities / _prefix_keys

兆候・経路 手法・階層 重要度 提案元 状態 コミット
duplication consolidate_duplication major kiro 取り消し 1

なぜ: 3 つのヘルパーが同じテスト用 tmux サーバの生成・破棄の儀式を繰り返す: $TMPDIR 直下へ短い名前でソケットを作る、TMUX を除いた env に TERM を足す、base=["tmux","-S",str(socket)] を組む、new-session -d を assert 付きで起動する、finally で kill-server と socket.unlink()(FileNotFoundError 抑制) をする。ソケットのライフサイクルと OS のパス長上限という同じ理由で一緒に変わる箇所が 3 つに散っており、片方だけ直すと後始末が食い違う。

手順: 1. @contextlib.contextmanager の _tmux_server(*configs) を追加し、ソケット生成・env 構築・base の組み立て・new-session -d 起動の assert・finally の kill-server+unlink を 1 箇所へ寄せ、(base, env) を yield する
2. _effective_options を with _tmux_server(*configs) as (base, env): に置き換え、内部は show-options の 2 スコープ読みだけ残す
3. _client_capabilities を同じ with へ置き換える。ただし new-session が -s p sleep 30 と pty クライアントを持つため、config の付与とセッション起動の差分をどう表すか(yield する base に -f を含めるか、context 側で new-session まで行うか)を決め、クライアント接続と polling は関数側に残す
4. _prefix_keys を with へ置き換え、list-keys 読みだけ残す
5. 現状固定として env -u DEVBASE_ROOT uv run pytest -q -p no:cacheprovider tests/containers/test_tmux_conf.py を実行し 1 手ごとに緑を確認する

R4-002 — containers/base/tmux-session#do_peek

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major claude 取り消し 1

なぜ: do_peek (約 60 行) に、見出し行・端末一覧・pane のプロセス木 (ps と組んだ 25 行の awk)・画面の直近 N 行 (capture-pane と awk) という独立した 4 つの出力が同居している。各段は id だけを受け取り互いに値を渡さないため、段ごとに関数へ切り出せば do_peek は出力順を並べるだけになり、プロセス木の awk を読むときに画面の切り出しを追わずに済む

手順: 1. 252-284 行 (echo "panes" から awk の終わりまで、直前のコメントを含む) を peek_panes() として抽出し、先頭で id=$1 を受ける。本体は移すだけで変えない
2. 286-298 行 (画面のコメントと if [ "$LINES_N" -gt 0 ] のブロック) を peek_screen() として抽出し、id=$1 を受ける。LINES_N は従来どおり大域変数を読む
3. do_peek の該当箇所を peek_panes "$id" / peek_screen "$id" の呼び出しへ置き換える。見出し行と clients の段は do_peek に残す
4. 出力の順序・文言・終了値が変わらないことを test_peek_shows_clients_panes_processes_and_screen / test_peek_screen_lines / test_peek_without_clients_and_n_beyond_screen / test_peek_special_names / test_menu_peek_opens_popup で確かめる (テストは変えない)

見送った項目

ラウンド 対象 兆候・経路 理由
1 containers/base/tmux-session#do_peek branch 1 ラウンドの採用上限 5 件を超えた
1 containers/base/tmux-session#main branch 1 ラウンドの採用上限 5 件を超えた
1 containers/base/tmux-session#resolve branch 1 ラウンドの採用上限 5 件を超えた
3 tests/containers/test_tmux_session.py#_kill_fail_env duplication 重要度 minor がしきい値 major 未満
3 containers/base/tmux-session#warn duplication 重要度 minor がしきい値 major 未満
3 tests/containers/test_tmux_session.py#_GO_FAIL_STUB duplication テストの期待する振る舞いが変わっています(tests/containers/test_tmux_session.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください
3 containers/base/tmux-session#do_go long_method テストの期待する振る舞いが変わっています(tests/containers/test_tmux_session.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください
4 tests/containers/test_tmux_conf.py#_effective_options / _client_capabilities / _prefix_keys duplication テストの期待する振る舞いが変わっています(tests/containers/test_tmux_conf.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください
4 containers/base/tmux-session#do_peek long_method テストの期待する振る舞いが変わっています(tests/containers/test_tmux_conf.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください

takemi-ohama and others added 11 commits September 24, 2026 12:47
do_kill の LAST ブロックの DRY=1 分岐 (-f と -n を同時に与えて自分の
セッションを予定表示だけして残す経路) と、-c で自分の端末を渡したときに
自分のセッションを残しつつ他を落とす経路を現状固定する。対象コードは変更しない。

Item-Id: R1-002
Round: 1
Impl-Runtime: kiro
Impl-Model: default
繋がっている端末が 0 件のときの clients 節((なし) の 1 行だけ)と、
-n が画面の行数より多いときに先頭から出す境界 (start を 1 に丸める) を固定する。

Item-Id: R1-003
Round: 1
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fix the current 10-second acceptance and 11-second rejection behavior through the public CLI using deterministic tmux and date stubs.

Item-Id: R1-004
Round: 1
Impl-Runtime: codex
Impl-Model: default
do_kill の kill-session 失敗の 2 経路を現状固定する。通常対象の削除が
失敗しても終了値 1 を保ち後続の成功対象は落とす経路と、-f で最後に回す
自己セッションの削除が失敗しても終了値 1 を保ち他対象は落とす経路。
特定 ID の削除だけを非 0 にする状態付き tmux スタブで固定する。

Item-Id: R1-005
Round: 1
Impl-Runtime: kiro
Impl-Model: default
go -c で detach-client / switch-client が失敗する経路を tmux スタブで固定する。
対象の他端末を外せないときは警告だけで実行元は移り終了値 0、切り替えに失敗すると
他端末は外した後で実行元は残り終了値 1。どちらも標準出力は空。

Item-Id: R2-001
Round: 2
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add the target $1/source $2 case, preserving the failed client while detaching the remaining client and switching the caller successfully.

Item-Id: R2-002
Round: 2
Impl-Runtime: codex
Impl-Model: default
…sage_errors_exit_two

引数解析の使い方の誤りのうち終了値 2 が固定されていなかった経路を現状固定する。
tmux-go の -c 末尾・tmux-peek の -n 末尾・kill のセッション無し・peek への -c・
menu への複数セッションを parametrize に追加し、終了値 2 と標準エラーが空でない
ことだけを確かめる (文言は比べない)。対象のコードは変更しない。

Item-Id: R2-003
Round: 2
Impl-Runtime: kiro
Impl-Model: default
…n.py#_GO_STUB

go の経路を固定する 3 つの tmux スタブを、sessions.txt / fail / activity を読む
汎用スタブ _GO_STUB と準備関数 _go_env にまとめた。list-sessions の差し替えは
文字列置換ではなく sessions 引数で渡す。アサーションは変えていない。

Refactor: extract_method — containers/base/tmux-session#do_go

実行元の端末の推定部を infer_client として抽出し、do_go は ME=$(infer_client) で
受ける。推定の規則・境界・失敗時の扱いは変えていない。

Item-Id: R3-001
Round: 3
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Share tmux test server startup and cleanup while preserving session arguments and terminal environments. Extract pane and screen output from do_peek without changing output order.

Item-Id: R4-001
Round: 4
Impl-Runtime: codex
Impl-Model: default

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

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 | REQUEST_CHANGES

修正が必要な指摘は1件です。

Comment thread tests/containers/test_tmux_session.py Outdated

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 cross-review | round 1 | agy | APPROVE

- prefix S を送った後 2 秒で tree-mode に入らなければ送り直す (_open_tree)。
  繋いだ直後のクライアントが端末問い合わせの応答待ちの間に入力を捨て、
  CI (Python 3.10) で 10 秒待っても一覧が出ず 8 件失敗していた
- TmuxEnv.close() の kill-server を tmux の有無でガードし、needs_tmux の
  付かないテストが tmux の無い環境で teardown エラーにならないようにする

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | round 1 | commit b3b9b88

対応件数: critical=0 / major=0 / minor=1(合計 1 件)
決着: 1 件 / 見送り: 0 件 / 却下: 0 件
CI: FAILURE

Pytest (Python 3.10) の失敗は _open_menu の tree-mode 待ちのタイミング依存 (flaky)。prefix S の送り直しで対処

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 cross-review | round 2 | agy | APPROVE

PLAN69の受け入れ条件、POSIX shとしての移植性、多段引用および特殊文字処理、利用者のtmuxサーバからのテスト隔離を含め、修正が必要な指摘事項はありません。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 cross-review | round 2 | kiro | APPROVE

PLAN69 の受け入れ条件 (1〜21) を満たす実装で、POSIX sh・ShellCheck 既定 severity・dash で clean、テストは 81 件通り TMUX_TMPDIR / TMUX 除去でユーザーの tmux サーバに触れない。go / kill / peek の失敗系・境界・使い方誤り (2)・メニュー引用の入れ子は既存スナップショットの指摘で網羅済み。新規に修正を要する欠陥は見つからなかった。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | commit (なし)

対応件数: critical=0 / major=0 / minor=0(合計 0 件)
決着: 0 件 / 見送り: 0 件 / 却下: 0 件
CI: NONE

@takemi-ohama
takemi-ohama marked this pull request as ready for review September 24, 2026 05:18
takemi-ohama and others added 2 commits September 24, 2026 18:58
)

PLAN69 の要求と設計を issues/old/ へ移し、呼び出しの形・セッションの指し方・
-c と知らせの出し先・go/peek/kill/menu の振る舞い・prefix S の割り当て・終了コード・
常に成り立つ条件・伝播の規則・テスト観点を tmux-named-session.md として確定仕様にした。
利用者向けの小節と tmux.conf を扱う既存の仕様から新しい仕様へリンクする。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama
takemi-ohama merged commit 3d80c12 into main Sep 24, 2026
7 checks passed
@takemi-ohama
takemi-ohama deleted the feature/plan69-tmux-named-session branch September 24, 2026 10:26
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.

feat: tmux のセッションを名指しで attach・調査・終了できるようにする(名指しのコマンドと tmux 組み込みの TUI)

1 participant