feat(list): devbase list を全操作対応の階層メニュー TUI へ統合 (PLAN31_2)#55
Conversation
…非回帰移送) (#56) * chore: PLAN31_2-tui-framework Draft PR 作成 * feat(tui): PLAN31_2 TUI 土台を tui/ へ分離・トップ階層メニュー化 (PR1 #56) devbase list の対話 TUI を commands/project.py から lib/devbase/tui/ パッケージへ 分離し、全カテゴリを束ねるトップ階層メニューの入口を新設する (PLAN31_2 PR1)。 - tui/menu.py: questionary ラッパ・MENU_BACK 番兵・Esc/← バインド・引数収集 ヘルパ (text/confirm/integer/path, input フォールバック) - tui/dispatch.py: dispatch_lifecycle / dispatch_group (旧 _start_project_action を一般化、PR3〜5 の group 委譲も先行整備) - tui/actions_project.py: 既存 project up/down/rebuild の非回帰移送 (一覧選択→ running はサブメニュー→他は直接 up、番号入力フォールバック) - tui/app.py: トップ階層メニュー (project/env/plugin/snapshot/status)。 「プロジェクト操作」を先頭・既定ハイライトで従来フローへ Enter 連打到達 (3.2)。 env 以降は後続 PR 用プレースホルダ (_route に1行追加で配線) - commands/project.py: listing/整形の純粋ロジックへ縮約、cmd_project_list は tui.run への薄い委譲に置換 後方互換: --plain/非TTY→table、questionary 不在→従来の番号入力フォールバックへ縮退。 テスト: TUI エンジン系を tests/cli/tui/ へ移設・拡充。全 pytest 510 passed/1 skipped。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tui): 実行 rc をトップメニューまで伝搬 + text/path 再帰除去 + Esc バインド (PR56 round1) cross-review round1 の 3 件を修正: 1. [major] actions_project.run() が dispatch_lifecycle の戻り値を捨てており project up/down/rebuild 失敗時も devbase list の終了コードが常に 0 になる問題を 修正。run() は操作実行時に rc(int) を返すプロトコルへ拡張し、app._top_menu_loop が last_rc を記憶して終了コードへ伝搬する (判定は is 同一性で rc=0 を誤マッチさせない)。 2. [minor] menu.text() / menu.path() の allow_empty=False 空入力時の自己再帰呼び出しを while ループへ変更し RecursionError リスクを除去。 3. [minor] questionary 経路の text/confirm/path に Esc→中止 (None) バインドが無く docstring/select のナビ規約と不整合だったため _ask_with_escape ヘルパで with_escape_cancel を適用。 テスト追従: rc 伝搬・非0 rc 伝搬・Esc バインド登録・while 再入力ループの検証を追加 (510 passed → 520 passed / 1 skipped)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR1 を cross-review approved → release へ merge (50ab9c2) 済みに更新し、 後続 PR (project/env/plugin/snapshot/status) が tui 土台へ配線する手順 (_route 1 行追加・menu 引数収集・dispatch_group・confirm/chdir) を申し送りとして追記。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#57) * chore: PLAN31_2-project-ops Draft PR 作成 * feat(tui): PLAN31_2 project 操作を login/ps/logs/scale/build へ拡張 (PR2 #57) running 行の操作サブメニューを up/down/login/ps/logs/scale/build/rebuild の全操作へ 拡張し、各操作の引数を tui.menu の収集ヘルパで CLI と同じ属性 (plan 2.3 契約) として 集める。stopped/unknown は従来どおり直接 up (PR1 非回帰)。 - login: index (既定 "1") を text で収集 - ps: --all を confirm で収集 - logs: --follow を confirm、--tail を optional int (空=全件) で収集 - scale: new_scale を integer (min=1) で収集 - build: containers/<image>/Dockerfile を列挙して選択 (compose.yml 全体= image None) - down: 破壊的操作のため confirm で確認 (plan 3.4) - 引数収集を Esc/Ctrl-C で中止したら操作サブメニューへ戻る (_ARG_CANCEL) login/ps/logs/scale は running コンテナ対象のため running 行限定とした。 全 pytest 542 passed / 1 skipped (PR2 で +22)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tui): project login の空 index バグ修正 + logs --tail 負数バリデーション (PR2 #57 round1) - login: menu.text(空入力で "" → --index= 失敗) を menu.integer(default=1, min_value=1) に変更し、str(index) で文字列契約を満たして dispatch。 - _optional_int: min_value=0 検証を追加し、logs --tail への負数入力を弾いて 再入力を促す (docker compose エラー防止)。 - テスト: login を menu.integer モックに追従、負数再入力テストを追加。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: PLAN31_2-env-ops Draft PR 作成 * feat: PLAN31_2-env-ops env 全操作の TUI 追加 - tui/actions_env.py 新設: env init/list/set/get/delete/edit/sync/project/ export/import を選択メニュー + 引数収集で cmd_env へ委譲 (plan 2.3 契約) - project スコープ (set --project / project) は事前にプロジェクト選択 → chdir + PWD 切替で実行し、try/finally で必ず元の CWD/PWD へ復帰 (plan 3.3) - 破壊的な env delete は実行前に menu.confirm で確認 (plan 3.4) - export/import は主要引数 (dest/source) のみ収集し、残りは CLI parser 既定値と 同一の属性を明示付与 (parser との同期テスト付き) - tui/app.py の _route に env を配線、未実装カテゴリ前提のテストを plugin へ更新 - tests/cli/tui/test_actions_env.py 新設 (契約・chdir 復帰・confirm・ナビ遷移) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: env list の「プロジェクトのみ」で対象プロジェクト選択 + chdir/PWD 切替を行う cmd_env_list は PWD が projects/ 配下のときだけプロジェクト .env を表示する ため、TUI (通常 DEVBASE_ROOT で稼働) から project スコープを選んでも何も 表示されなかった (codex round1 major 指摘)。set/project と同様に _select_project で対象を選ばせ、_run_in_project 経由で実行するよう修正。 回帰テスト (chdir + 復帰 / 選択中止) を追加。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: env get に取得元選択を追加しプロジェクト .env のキーを取得可能にする cmd_env_get はグローバル .env に無いキーを CWD (PWD) のプロジェクト .env へ フォールバックして探すが、TUI は常に DEVBASE_ROOT で実行されるため プロジェクト固有キーを取得できなかった (codex round2 指摘)。 list/set と同様に取得元 (グローバル / プロジェクト) を選ばせ、プロジェクト 選択時は _run_in_project 経由で chdir + PWD 切替後に dispatch する。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* chore: PLAN31_2-plugin-ops Draft PR 作成 * feat: PLAN31_2-plugin-ops plugin 全操作 + repo の TUI 追加 - tui/actions_plugin.py 新設: plugin list/install/uninstall/update/info/ sync/migrate と repo add/remove/list/refresh のサブ階層メニューを実装。 引数は menu.* で収集し dispatch_group 経由で cmd_plugin へ委譲 (plan 2.3 の属性契約は cli.py parser と突き合わせて検証済み・乖離なし) - uninstall/update/info と repo remove/refresh の name は registry (plugins.yml) の一覧から選択。破壊的な uninstall / repo remove は menu.confirm で実行前確認 (plan 3.4) - tui/app.py の _route に plugin を配線 (未実装プレースホルダ案内を解消) - tests/cli/tui/test_actions_plugin.py 新設 + test_app.py の routing 検証更新 (597 passed / 1 skipped・退行なし) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* chore: PLAN31_2-snapshot-status Draft PR 作成 * feat: PLAN31_2-snapshot-status snapshot 全操作 + status 閲覧の TUI 追加 - tui/actions_snapshot.py 新設: create/list/restore/copy/delete/rotate の 操作メニューと引数収集 (属性契約は cli.py parser と突き合わせ済み)。 restore/copy/delete の対象は SnapshotManager.list() の既存一覧から選択 (取得失敗時は自由入力へ縮退)。破壊的な restore/delete は menu.confirm で 確認し、拒否時は実行しない (plan 3.4) - tui/actions_status.py 新設: cmd_status(devbase_root) への薄い委譲 (引数なし・閲覧のみ。表示後トップへ rc を返す) - tui/app.py: _route に snapshot/status を配線 (残りは PR3 env / PR4 plugin) - テスト 39 件追加 (582 passed / 1 skipped、ベースライン 544 から退行ゼロ) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | codex | REQUEST_CHANGES
project 操作実行後に CWD/PWD が直前プロジェクトへ残るため、トップメニューへ戻ってから別カテゴリを実行する前に TUI 側で必ず元の状態へ復元してください。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | gemini | REQUEST_CHANGES
PR間結合での重大な状態リーク
tui/app.py のメインループ内で複数カテゴリをまたいで操作する際、project カテゴリの操作が CWD と os.environ を破壊したまま復帰し、後続の env 等の操作に誤った状態(意図せぬ .env の読み込み等)を引き継ぐ問題があります。TUI が永続プロセスとなったことで顕在化した問題のため、委譲層 (dispatch.py) での確実な状態復帰が必要です。
TUI から project 操作を実行すると _resolve_project_name の os.chdir / env 反映 / COMPOSE_PROJECT_NAME 上書きが同一プロセスに 残留し、トップメニュー復帰後の env get 等が直前プロジェクトの CWD・環境変数 (PWD 含む) を参照していた。 委譲チョークポイントの tui.dispatch に _preserve_cwd_env コンテキスト マネージャを追加し、dispatch_lifecycle / dispatch_group の前後で CWD と os.environ を保存・復元する (例外時も finally で保証)。 回帰テスト 3 件を追加。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 1)対応結果
修正内容
テスト
コミット
|
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | gemini | APPROVE
PR #55 の統合内容および各カテゴリの実装・テストを確認し、問題がないためマージ可能です。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | codex | REQUEST_CHANGES
Ctrl-C と Esc/戻るの意味が一部の選択ヘルパで同じ扱いになっているため、TUI 全体の中止規約に合わせて修正してください。
menu.select(back=True) ベースの選択ヘルパが Ctrl-C (None) と Esc/← (MENU_BACK) を両方 _ARG_CANCEL に畳んでいたため、選択中の Ctrl-C が ナビ規約の「全体中止」にならずサブメニュー再表示になっていた。 - actions_env: _select_project / list・set・get の scope 選択で None (Ctrl-C) を呼び出し元まで伝搬し、Esc のみ _ARG_CANCEL とする - actions_plugin: _select_name で同様に区別。all_label の「全対象」は "" のまま返し、呼び出し側 (update / repo refresh) で None へ変換 - actions_snapshot: _select_snapshot_name で同様に区別 (text 縮退時は Esc/Ctrl-C を区別できないため従来どおり _ARG_CANCEL) - actions_project: _select_build_image で同様に区別。「compose.yml 全体」は "" 番兵に統一し、呼び出し側で image=None へ変換 - 各 _run_operation は選択ヘルパの None を return し、run ループ経由で トップループの全体中止 (None) に到達させる テスト: 既存のキャンセル系を Esc=_ARG_CANCEL / Ctrl-C=None の新契約に 更新し、Ctrl-C 伝搬の回帰テスト 8 件を追加 (693→701 passed)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 2)対応結果
対応内容[minor / 正確性] 選択メニューで Ctrl-C が全体中止にならない(codex,
「全対象」「compose.yml 全体」の番兵は 🤖 Generated with Claude Code |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | gemini | APPROVE
統合および E2E 観点でのレビューを完了しました。各カテゴリの routing や状態復元 (_preserve_cwd_env 等) も適切で、問題となる箇所はありません。テストカバレッジ・非対話フォールバックも要件を満たしています。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | codex | REQUEST_CHANGES
env list の TUI 経路で表示範囲の選択肢と実際の表示対象がずれているため、修正してください。
…und3 major) TUI は DEVBASE_ROOT で動くため、both スコープを CWD 判定のまま dispatch すると cmd_env_list の projects/ 配下チェックに掛からずグローバルしか表示されなかった。 project スコープと同様に対象プロジェクトを選ばせ、_run_in_project で chdir + PWD 切替後に global_only=False / project_only=False で実行する。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 3)
対応内容
テスト
🤖 Generated with Claude Code |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 4 | gemini | APPROVE
これまでのラウンドで指摘された env list のスコープ処理、キャンセルの伝播、環境変数の復元などの問題が全て修正され、テストも追加されていることを確認しました。実装・設計ともに問題ありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 4 | codex | REQUEST_CHANGES
入力プロンプト中の Ctrl-C が全体中止として扱われない経路が残っています。
menu.text/confirm/path が Esc と Ctrl-C を同じ None で返し、各 actions_* が それを _ARG_CANCEL に畳んでいたため、引数入力中の Ctrl-C がナビ規約の 「全体中止」にならずサブメニュー再表示になっていた (round2 で対応した 選択メニューと同じ問題が入力プロンプトに残存)。 - menu: _ask_with_escape を with_escape_back(bind_left=False) ベースへ変更し、 text/confirm/path/integer が Esc=MENU_BACK / Ctrl-C=None を区別して返す 新契約に統一 (← は入力カーソル移動用に空ける) - actions_env/plugin/project/snapshot: 入力ヘルパの None (Ctrl-C) を 呼び出し元まで return し、MENU_BACK (Esc) のみ _ARG_CANCEL とする。 confirm の「not ok」判定は MENU_BACK が truthy のため is 判定を先行 - _optional_int / _optional_point: 「空入力 = None (既定動作)」と Ctrl-C の None が衝突するため専用番兵 _ABORT を導入し、呼び出し側で None へ変換 テスト: 入力系キャンセルを Esc=_ARG_CANCEL / Ctrl-C=None の新契約へ パラメトライズ更新し、Ctrl-C 全体中止と MENU_BACK 伝搬の回帰テストを追加 (701→732 passed)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 4)対応結果
修正内容
検証
🤖 Generated with Claude Code |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 5 | gemini | APPROVE
入力プロンプトでの Esc/Ctrl-C 識別と全体中止の伝搬、および番兵を用いた衝突回避が正しく実装されていることを確認しました。指摘事項はありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 5 | codex | APPROVE
指摘なし。
何のために
従来の
devbase listTUI はプロジェクト選択 → up/down/rebuild のサブメニューまでで、env / plugin / snapshot などの操作は CLI サブコマンドと引数を覚えて打つ必要があった。
本 PR は
devbaseのほぼ全操作(initを除く)をdevbase listの階層メニューから実行可能にし、コマンド体系を覚えていなくても対話的に devbase を操作できるようにする。
issues/PLAN31_2_list-tui-unified.md何を
TUI 基盤 (
lib/devbase/tui/新設)menu.py— questionary ラッパ(select/text/confirm/integer/path + 入力検証ループ、Esc/← バインド、
MENU_BACK番兵)dispatch.py—SimpleNamespaceを組んで既存 CLI ハンドラへ委譲する薄い共通関数(
dispatch_lifecycle/dispatch_group)。CLI parser の引数契約と同期テストで整合を保証し、ロジックの二重実装をしない
app.py— トップ階層メニュー(project / env / plugin / snapshot / status)と routing。操作 rc はループを通じて
devbase listの終了コードへ伝搬commands/project.pyは一覧表示・整形へ縮約カテゴリ別操作 (
actions_*.py)プロジェクトスコープの操作(list・get・set の対象選択や
env project)はプロジェクト選択 → chdir +
PWD切替 → 実行 → 復帰で CLI 実行時と同じ挙動を再現repo add / remove / list / refresh(サブ階層)。対象 name はレジストリ
(plugins.yml) の実一覧から選択
対象は既存 snapshot の実一覧(作成日時付き)から選択
ナビゲーション規約と安全装置
snapshot delete)は実行前に confirm を挟み、拒否時は実行しない
後方互換
従来の project 選択フローへ到達できる
--no-interactive/--plainと非 TTY は従来どおり一覧テーブルのみTest plan
SimpleNamespaceでハンドラを呼ぶこと、Esc/←/Ctrl-C の遷移、confirm 拒否で未実行、chdir +
PWDの復帰、非 TTY /questionary 不在のフォールバック
snapshot create→list