Repository navigation
スプリント m8d - #488
スプリント m8d#488
Conversation
devbase_vscode-server-bin を ~/.vscode-server/bin に付け、コンテナごとの devbase_vscode_<project>_<index> を作らない・付けないようにする。 旧形式の名前を読むだけの find_legacy_vscode_volumes を足す。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
~/.vscode-server と bin を開発ユーザーが書ける形にし、bin/ の版を product.json の 更新時刻の新しい順に 5 版だけ残す。同時の展開で残った入れ子の本体と、60 分より 古い展開の途中のディレクトリも消す。消せないものは WARNING だけで起動を止めない。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
建て直す前のイメージでは bin が root のまま残るため、docker exec -u 0 で ~/.vscode-server の所有者へ揃える。devbase up の最後に、旧形式の devbase_vscode_<project>_<index> の名前と消すコマンドを出す(消さない)。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#463 を実装する(スプリント m8d)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#454 を実装する(スプリント m8d)
数え方(1 秒休む巡の回数・上限 60)は変えない。StartupFailure に elapsed(既定 0)を足し、 単調な時計で測った経過を整数の秒で入れる。時計を差し替えたテストを足した。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#374 を実装する(スプリント m8d)
…_volumes Item-Id: I-001 Impl-Runtime: claude Impl-Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r.ensure_volumes 存在確認→ログ→作成→失敗時 DockerError の 4 回の繰り返しを _ensure_volume(name, label=None) へ抽出した。ログの文言と呼ぶ順は変えない。 Item-Id: I-001 Impl-Runtime: claude Impl-Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iners_ready 1 つの番号の状態の分類 (not_found / exited / ready / pending) を _classify_instance へ抽出し、巡のループは戻りを振り分けるだけにした。 Item-Id: I-002 Impl-Runtime: claude Impl-Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….py#bin_fix_script VS Code Server の置き場のパス VSCODE_SERVER_TARGET・VSCODE_BIN_TARGET を VSCODE_SERVER_VOLUME と同じ volume/manager.py へ移し、compose.py と bin_fix_script の既定はそこから読む。home_root を渡す試験の経路は残した。 生成する手順の文字列は変わらない。 Item-Id: I-004 Impl-Runtime: claude Impl-Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…_vscode_server_bin _apply_window_titles と _prepare_vscode_server_bin が写していた 「番号ごとに名前を引き、1 台ずつ試して失敗を debug に落とす」ループを _for_each_dev_container へ抽出した。debug の文言は変わらない。 Item-Id: I-005 Impl-Runtime: claude Impl-Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
改修計画 — devbasex/devbase #488
改善項目I-001 —
|
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| duplication | extract_method | major | high | claude / codex / kiro | 採用 | 2 |
なぜ: 共有ホーム・グループ・VS Code Server・各 work ボリュームで、存在確認→ログ→作成→失敗時 DockerError が4回繰り返される。同じ作成契約の変更を4か所へ反映する必要がある。tests/volume/test_manager_vscode.py は作成・既存・作成失敗、test_manager_group.py は不正グループで Docker に触れないことを保護するが、全種類の失敗とログの同値性は補う必要がある。
手順: 1. VolumeManager に _ensure_volume(name, label=None) を抽出する。label があれば既存の文言 " %s (, exists)" / " Creating %s ()..."、無ければ作業ボリュームの文言 " %s (exists)" / " Creating %s..." をそのまま出す(ログの文言を 1 文字も変えない)
2. 失敗時は従来どおり DockerError(f"Failed to create volume {name}") を送出する
3. ensure_volumes の 4 つの塊を _ensure_volume(HOME_UBUNTU_VOLUME, 'shared home')・_ensure_volume(group_volume, 'account group')・_ensure_volume(VSCODE_SERVER_VOLUME, 'VS Code Server')・ループ内の _ensure_volume(work_volume) に置き換える。呼ぶ順(グループ名の検証 → home → group → vscode → work)は変えない
4. tests/volume/test_manager_vscode.py と tests/volume/test_manager_group.py を走らせる
I-002 — lib/devbase/utils/docker.py#wait_for_containers_ready
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| long_method | extract_method | major | medium | codex / kiro / claude | 採用 | 1 |
なぜ: 1 関数にログ出力・巡ループ制御・1 インスタンスの状態分類 (not_found / exited / ready / pending) ・時間切れの集計が同居し、認知的複雑度 19・分岐 8・71 行。1 インスタンスの判定ロジックが while ループ本体に埋まり単体で読めない。
手順: 1. 1 インスタンス分の分類を _classify_instance(index, container_prefix, ready_file, compose_file) -> ('ready'|'exited'|'not_found'|'pending', Optional[StartupFailure]) として抽出
2. while ループ内の for を、_classify_instance の戻りで ready / failures / still_pending へ振り分けるだけにする
3. 時間切れの StartupFailure 生成はそのまま残す
4. tests/utils/test_wait_for_containers.py を実行し、各経路 (ready / exited / not_found / timeout) が不変であることを確認
I-003 — lib/devbase/volume/manager.py#VolumeManager.__init__
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| dead_code | remove_dead_code | minor | medium | claude | 取り消し | 0 |
なぜ: #463 で VS Code Server のボリュームが共通の 1 本になり、self.project_name と ensure_volumes(project_name) はどこからも読まれなくなった。docstring も「使わない」と書いて残しており、読む人に名前がボリュームに効くと誤解させる
手順: 1. VolumeManager.init の project_name 引数と self.project_name を消す
2. モジュール関数 ensure_volumes の project_name 引数を消し、VolumeManager() で作る
3. commands/container.py の ensure_volumes(scale, project_name)・ensure_volumes(new_scale, project_name) を ensure_volumes(scale) へ直す
4. tests/volume/test_manager_vscode.py の ensure_volumes(..., project_name=...) と、tests/commands/test_container_scale_order.py の「project_name が ensure_volumes に渡る」現状固定テストを、渡らなくなった形へ直す(test-changes.md に従い、変えた理由をテストに残す)
5. 全体の pytest を走らせる
取り消した理由: テストの期待する振る舞いが変わっています(tests/commands/test_container_scale_order.py, tests/volume/test_manager_ensure_volumes.py, tests/volume/test_manager_vscode.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください
I-004 — lib/devbase/editor/vscode_server.py#bin_fix_script
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| scattered_config | centralize_configuration | minor | medium | claude | 採用 | 1 |
なぜ: VS Code Server の置き場のパスが、vscode_server.py の HOME_ROOT + "/.vscode-server"・"/.vscode-server/bin" と、volume/compose.py の VSCODE_SERVER_TARGET・VSCODE_BIN_TARGET の 2 か所で別々に組まれている。マウント先と所有者を直す先が食い違うと attach が失敗する
手順: 1. VSCODE_SERVER_TARGET と VSCODE_BIN_TARGET を、VSCODE_SERVER_VOLUME と同じ volume/manager.py へ移す(compose.py は manager から import して従来の名前で参照できるようにする)
2. bin_fix_script の既定を manager の 2 つの定数から組む形にし、home_root を渡すテスト用の経路は残す
3. tests/editor/test_vscode_server.py と tests/volume/test_compose_vscode.py を走らせる
I-005 — lib/devbase/commands/container.py#_prepare_vscode_server_bin
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| duplication | extract_method | minor | medium | claude | 採用 | 1 |
なぜ: #463 で足した _prepare_vscode_server_bin は _apply_window_titles と同じ形(_target_indices を回し、opener.resolve_container_name で名前を引き、1 台ずつ try して失敗を debug に落とす)を写している。起動の後の処理にインスタンスごとの付随処理を足すたびに同じループが増える
手順: 1. _for_each_dev_container(project_name, scale, dev_service_name, compose_file, indices, action, what) を抽出する。各番号で名前を引いて action(container_name) を呼び、例外は logger.debug("%s をスキップしました (index=%d): %s", what, index, e) の形で従来の文言を保って落とす
2. _apply_window_titles のループ部をこの関数の呼び出しに置き換える(template の解決と早期 return は呼び出し側に残す)
3. _prepare_vscode_server_bin を同じ呼び出しに置き換える
4. 両関数の debug の文言が変わらないことを確かめ、tests/commands/test_container_post_start.py と window title のテストを走らせる
I-006 — containers/base/entrypoint.sh#devbase_prune_vscode_server_bin
| 兆候 | 手法 | 重要度 | 等級 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|---|
| long_method | extract_method | minor | low | claude / codex | 見送り | 0 |
なぜ: 完成版の収集・保持数による削除・保持版にある入れ子の掃除・古い展開途中ディレクトリの掃除という異なる選別規則が1関数に同居する。tests/containers/test_entrypoint_vscode_server.py に同時実行、同時刻の順序、入れ子、古い展開途中、削除不能の振る舞いのテストがある。
手順: 1. 版を数えて古い版を消し、残した版の名前を出す段を devbase_prune_vscode_server_versions として抽出する(kept は標準出力の行で返すか、呼び出し側の配列へ読む)
2. 入れ子の本体を消す段を devbase_prune_vscode_server_nested として抽出する
3. 展開の途中のディレクトリを消す段を devbase_prune_vscode_server_stale として抽出する
4. devbase_prune_vscode_server_bin は 3 つを順に呼ぶだけにし、終了コード 0 を保つ
5. tests/containers/test_entrypoint_vscode_server.py(同時実行の試験を含む)と ShellCheck を走らせる。イメージに入るファイルのため、実機の確認は base の建て直しが要る(AGENTS.md の落とし穴)
取り消した理由: 実装の終わりまでにコミットが無く、残った時間に入らない
指標の測定
- 状態: written / 言語とツールの対応: 既定(.ndf/code-metrics.json は無い) / 所要: 9.3 秒(使えた時間 90 秒 / 上限 90 秒)
- 指標のファイル: /var/folders/qz/qxt0p_y15xv5jg4x77zmtxj80000gp/T/ndf-worktrees/devbasex--devbase/rf488/work/.cross_refactoring/code-metrics-rf488.md
| 言語 | ツール | 版 | ランナー | ファイル | 秒 | 結果 |
|---|---|---|---|---|---|---|
| python | ruff-complexipy | ruff 0.16.9 / complexipy 8.0.1 | uvx | 214 | 1.1 | 測った |
| shell | — | — | — | 2 | — | unsupported_language |
| 重複: python | symilar | pylint 4.0.9 | uvx | 214 | 6.9 | 測った(3 箇所) |
| 重複: shell | jscpd | jscpd 4.3.0 | npx | 2 | 0.9 | 測った(0 箇所) |
時間の上限
| 値 | 中身 |
|---|---|
| 提案の枠の終わり(監視の上限 = 残り + 余裕) | 2026-10-14T10:26:56+09:00 |
| 改修計画の枠の終わり(同上) | 2026-10-14T10:29:56+09:00 |
| テストの追加の終わり = 実装の終わり − Σ(採っていて未検証の項目の実装の見積り) | 2026-10-14T10:27:21+09:00 |
| 実装の終わり = 最終ゲートの修正の打ち切り − バッファ − Σ(採っていて未検証の項目の検証の見積り) | 2026-10-14T10:32:13+09:00 |
| 直しの試行の打ち切り | 2026-10-14T10:41:01+09:00 |
| 想定最大時間の終わり H(子プロセスはすべてここまでに止まる) | 2026-10-14T10:48:44+09:00 |
| 確かめの開始の締め切り = H − 確かめの見込み(最終ゲート修正と打ち切りの後の取り消しもここまで) | 2026-10-14T10:46:31+09:00 |
| 確かめの見込み(秒。最終ゲートの確かめ 1 回。バッファの最終ゲートの全体テスト) | 133 |
| 最終ゲート修正 1 回の見込み(秒。バッファの final_fix。起動は今 + この値が確かめの開始の締め切り以前のときだけ) | 330 |
| 指標の測定の上限(秒。提案の枠の中から割く) | 90 |
| 着手前のテスト 1 回の上限(秒) | 420 |
| 範囲テスト 1 回の上限(秒) | 398 |
| 手元の全体テスト 1 回の上限(秒) | 420 |
| CI の待ちの上限(秒) | 324 |
| 余裕(秒。手順の上限と CLI の上限に足す) | 90 |
入力: 予算 30 分 / 全体テストの所要 w 139.8(ndf-record) / 着手前の実測 x 132.4 / CI の壁時計 c 108.0 / 範囲テストの所要 s None(—) / 戦略 local-full
無音の打ち切りは手順の監視の上限と同じ値である。項目ごとの期限は持たない(実装を止めるのは実装の終わりだけ)。
見送った提案
| 対象 | 兆候 | 理由 | 根拠(MVV) | 補足 |
|---|---|---|---|---|
lib/devbase/utils/docker.py#wait_for_containers_ready |
deep_nesting | duplicate | Vision | C-002 と同じ変更 |
tests/volume/test_compose_dev_environment.py#project |
duplication | budget | Vision / Value 3 | 見積り 1.1 分が残りに入らない |
lib/devbase/editor/vscode_server.py#prepare_bin_dir |
duplication | budget | Vision | 見積り 1.1 分が残りに入らない |
lib/devbase/volume/manager.py#_LEGACY_VSCODE_VOLUME_RE |
duplication | budget | Value 2 / Vision | 見積り 1.1 分が残りに入らない |
lib/devbase/volume/manager.py#get_volume_for_index |
duplication | budget | Value 2 | 見積り 1.1 分が残りに入らない |
lib/devbase/commands/container.py#_run_post_start |
data_clump | budget | Value 3 / Vision | 見積り 1.4 分が残りに入らない |
containers/base/entrypoint.sh#devbase_remove_vscode_server_path |
duplication | budget | Value 1 / Vision | 見積り 1.6 分が残りに入らない |
lib/devbase/commands/container.py#_load_project_env |
long_method | budget | Value 3 / Value 2 | 見積り 1.6 分が残りに入らない |
lib/devbase/commands/container.py#cmd_down |
swallowed_exception | budget | Value 2 | 見積り 1.6 分が残りに入らない |
lib/devbase/volume/compose.py#_rewrite_depends_on |
long_method | budget | Value 2 | 見積り 1.6 分が残りに入らない |
tests/containers/test_base_image_font_matching.py#_docker_unavailable |
duplication | budget | Vision | 見積り 1.8 分が残りに入らない |
tests/cli/zsh_completion_harness.py#run_completions |
long_method | budget | Vision | 見積り 2.4 分が残りに入らない |
containers/base/entrypoint.sh#devbase_prune_vscode_server_bin |
long_method | not_done | Vision / Value 1 / Value 2 | 実装の終わりまでにコミットが無く、残った時間に入らない |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | codex | REQUEST_CHANGES
利用者データの削除に関わる修正提案が2件あります。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | kiro | APPROVE
振る舞いを変えない構造改善の PR。4 件の抽出・集約はログ文言・例外の扱い・公開シグネチャをすべて保ったまま重複を除いている。vscode_server.py がモジュール先頭で volume.manager を import する点は循環 import の懸念があったが、manager は env.keys / errors / log しか import せず editor を参照しないため循環は無い(import 成功を確認)。VSCODE_SERVER_TARGET・VSCODE_BIN_TARGET の参照元(compose.py 内の 3 箇所)も解決し、削除した HOME_ROOT への残参照も無い。critical / major の基準に当たる指摘は無い。
- entrypoint の bin/ の片付けで、bin/ 自身・bin/<commit> がシンボリックリンクなら版に数えず 入れ子の掃除もしない。リンク先の bin の外のものを消さないため - 旧形式の devbase_vscode_* ボリュームは ~/.vscode-server 全体を持つため、削除でリモートの 設定・ローカル履歴・拡張機能の状態も失われることを文書と devbase up の案内に書き、退避の手順を足す Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔧 /ndf:fix サマリ | round 1 | commit f042cc4対応件数: critical=0 / major=2 / minor=0(合計 2 件) |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | claude | APPROVE
round 1 の 2 件(片付けがリンクを辿る・旧ボリューム削除で失うものの案内)は f042cc4 で直っている。entrypoint の片付け(set -e 下の分岐・空の一致・リンクの除外)、bin の所有者の直し、旧形式の案内の位置と名前の形、確定仕様(post-start.md・compose-profiles.md)の順序、refactor 4 件の振る舞いの同値性を確かめ、critical / major の基準に当たる指摘は無い。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | kiro | APPROVE
振る舞いを変えない構造改善 4 件(I-001 _ensure_volume / I-002 classify_instance / I-004 VSCODE*_TARGET の集約 / I-005 _for_each_dev_container)と、round 1 の major 2 件の修正を確認した。4 件の抽出・集約はログ文言(manager の作成/存在のメッセージ、container の debug スキップ文言)・例外(DockerError)・公開シグネチャ(ensure_volumes の project_name も含む。I-003 は取り消し)をすべて保ったまま重複・長さを除いている。VSCODE_SERVER_TARGET / VSCODE_BIN_TARGET を manager へ移したことで vscode_server.py がモジュール先頭で volume.manager を import するが、manager は env.keys / errors / log だけを import し editor を参照しないため循環 import は無い。round 1 の 2 件(entrypoint の bin 片付けがシンボリックリンクを辿って bin 外の product.json を削除し得る点、container-operations.md の削除案内が ~/.vscode-server 全体の消失を伝えていなかった点)は f042cc4 で修正され、entrypoint は bin 自身・bin/・入れ子のいずれかがリンクなら版に数えず入れ子掃除もしない形になり、CLI の _report_legacy_vscode_volumes の案内も文書の退避手順と一致する。新規テスト(test_manager_ensure_volumes.py の順序・文言・例外の固定、test_entrypoint_vscode_server.py の 2 つのリンク試験)は観測可能な振る舞いを検証している。critical / major の基準に当たる指摘は無い。
🔧 /ndf:fix サマリ | commit (なし)対応件数: critical=0 / major=0 / minor=0(合計 0 件) |
手動確認 M1(#463)の結果(2026-10-14)利用者が P3 を承認し、conductor がメインディレクトリを一時的に
|
リリース後テスト対象の版: main 実のイメージでの確かめは、使い捨てのボリューム
合否: 合格(受け入れ条件 27 件すべて合格。実の VS Code の更新を要る M4・M5 の実機の 1 行は保留) |
|
構造改善で取り消し・見送った 2 件(コメント 6158923037)は範囲外と判断し、#490 として残した。 |
振り返り(2026-10-15)対象: issue #463・#454・#374 / PR #488(設計 #484、実装 #485 #486 #487、確定仕様 #489) スプリント m8d(マイルストーン 04、mode standard)。#463 で VS Code Server の本体( 何が起きたか
context window の大きさ
用語集の変化
承認ゲートの差し戻し
MVV を見直すか
次に変えること
途中で起票した課題
|
スプリント m8d の課題を main へ取り込む。
利用者向けの変化
devbase upがそのことを案内します。(#463 を実装する(スプリント m8d) #485)devbase envのシェル補完(bash・zsh)で、サブコマンドの候補にtokenとbackendが出る(#454 を実装する(スプリント m8d) #486)移行の手順
課題と設計
bin/)だけを全コンテナで 1 本のボリュームに置いて版の数に上限を置き、拡張と状態はコンテナの書き込みレイヤーに残す(#463) #484コミット
変更の統計
テスト(supervise.py の run のステップ)
集めた実装の PR
閉じる課題
Closes #374
Closes #454
Closes #463
手動確認
devbase upが要るため、conductor が P3 の承認を取ってから打つか、利用者が行う。担当は打たない(2026-10-14 conductor が P3 の承認を取って novel・bi-tools で実施、利用者が attach。合格。記録は PR のコメント)モード: standard / 通した工程: 実装 → Pull Request
conductor の補記
docs/user/troubleshooting.mdの行は古い。後のステップで、旧形式の VS Code Server ボリュームの消し方の節に直っている(このスプリント PR の差分に入っている)🤖 Generated with Claude Code