設計(PLAN65): devbase scale の Compose 呼び出しを共通経路へ寄せ、cmd_scale の段階を分ける (#192) - #225
Conversation
cmd_scale が docker compose を共通経路 (utils/docker.py の docker_compose) を 通さずに呼ぶため、compose_env() が適用されない。確定仕様 docs/specifications/compose-profiles.md は「COMPOSE_PROFILES を端末や .env に 置いても devbase 経由の操作には効かない」と約束する一方で、同じ文書の中で cmd_scale をその対象から外している。 この食い違いを、約束の側を正として解く設計を置く。実測で cmd_login にも同じ穴が あることが分かったため、そちらも同じ Pull Request で塞ぐ決定にした。 実装は 2 本の Pull Request に分ける (振る舞いと仕様 / 構造)。順序は 仕様 → 共通経路へ寄せる → 現状固定テストを足す → 関数を分ける。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pull Request 本文の「決めたこと」の節は設計文書の `## 決定の記録` の `###` 見出しから 作られるため、章へ切り出した決定 10 が一覧から漏れていた。章を指す見出しを置く。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | kiro | APPROVE
設計・要求の 2 文書について、記載された実測値(grep 件数 6/2/0)、行番号参照(cmd_scale:1648・cmd_login の exec・_resolve_dev_service・_read_compose_services・_ensure_images:2019・test_docker_profiles.py:102 の「棚卸しの 4 か所」・test_base_image_staleness.py:158/173/188)、関数契約(_resolve_dev_service は非 0/不正 JSON で None、_read_compose_services は JSONDecodeError 伝播)、決定 3 の根拠(docker_compose_up() に --no-recreate 無し・check=True 固定・cmd_scale に except subprocess.CalledProcessError 無し)、確定仕様の食い違い(compose-profiles.md の 83-84 除外 vs 388-389 約束)を作業ツリーで突き合わせ、いずれも実装と一致することを確認した。修正を要する不整合・未検証の断定は見当たらず、実装を含まない設計 PR として整合している。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | agy | REQUEST_CHANGES
総評
PR #225 の要求仕様と設計は、devbase scale の共通経路化や段階分割について詳細に整理されていますが、PR 1 と PR 2 の分割境界と、要求仕様の受け入れ条件・確定仕様の更新タイミングとの間に以下の不整合があります。2 本の Pull Request に分けて安全に移行するという目的に沿い、各段階の検証可能性と仕様・実装の一致を保つための修正を提案します。
-
受け入れ条件 A-1 の grep 件数(6 → 3)と PR 1 / PR 2 の境界のズレ
- PR 1 では
cmd_scaleとcmd_loginのみを修正し、_resolve_dev_serviceと_read_compose_servicesの統合(決定 9)は PR 2 で行われます。 - そのため、PR 1 完了時点での
grep -rn "'docker', 'compose'|\"docker\", \"compose\"" lib/は 5 件(6 - 1)であり、3 件には減りません。 - 修正提案: A-1 の記述を「PR 1 時点では 6 → 5 件に減り、PR 2 の D-1 完了時に 5 → 3 件になる」と段階を明記するか、3 件の検証を PR 2(D-1)側に整理してください。
- PR 1 では
-
PR 1 での確定仕様更新と PR 2 での config 統合実装のズレ
- 設計書 180 行目では、PR 1 で
docs/specifications/compose-profiles.mdの経路表から_resolve_dev_serviceと_read_compose_servicesを畳み込んで「経路は 5 つだけ」と書き換える計画になっています。 - しかし実装側の統合は PR 2 で行われるため、PR 1 マージ時点で「確定仕様とコードが食い違う版」が中間に生じてしまいます。
- 修正提案: 当該 2 行の畳み込みは PR 2 で確定仕様を更新するよう分担するか、PR 1 に config 読み取りの統合(決定 9)まで含めるよう PR 境界を調整してください。
- 設計書 180 行目では、PR 1 で
-
受け入れ条件 A-5(棚卸しコメントとテスト一覧の一致)の検証時期
- PR 1 の段階では config 読み取り関数がまだ直接呼び出しのまま残るため、棚卸しコメントやテスト一覧を変更後の 4 経路に一致させることはできません(設計書 426 行目でも棚卸しコメントの更新は PR 2 とされています)。
- 修正提案: A-5 を PR 2(構造グループ D)へ移動するか、PR 1 では
cmd_loginのテスト追加のみを検証する形に改めてください。
確定仕様の経路の表は _resolve_dev_service / _read_compose_services の 2 行を docker_compose の用途へ畳む。畳んだ表を 1 本目で入れて統合を 2 本目に置くと、 1 本目のマージの時点で「共通経路を通る」と書いた仕様と、直接 subprocess.run を 呼ぶ実装が食い違った版が残る。受け入れ条件 A-1(grep が 6 → 3)・A-5(棚卸しの 一致)・D-1 も 1 本目では満たせない。 分け目を「Compose の呼び出しを共通経路へ寄せる」と「cmd_scale の段階を分ける」に 改め、受け入れ条件とどちらの Pull Request が対応するかの表を足した。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | codex | APPROVE
修正を求める指摘はありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | kiro | APPROVE
設計・要求文書の実測(grep 件数 6/2/0、compose_env() 未付与の 2 か所 = cmd_scale:1648 / cmd_login、config --format json 2 か所、_read_compose_services の唯一の呼び出し元 _ensure_images、default_services が生成物の dev-1..N を返すこと)を worktree 847865f のコードと突き合わせ、いずれも一致することを確認した。B-3 の期待コマンド列 ['...','dev-1','dev-2'] も _build_scaled_services の命名({dev}-{i})と整合する。修正を要する指摘は無い。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | codex | APPROVE
修正を要する指摘はありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | agy | APPROVE
概要
PR #225 における要求仕様書 (issues/PLAN65_scale-compose-path.md) および設計文書 (issues/PLAN65_scale-compose-path-design.md) の内容を、release/v3.7.0 の現行コード・仕様書・既存テストと突き合わせて確認しました。
確認事項
- Compose 呼び出し経路の一元化と COMPOSE_PROFILES 隔離 (決定 1・2・3・4):
devbase scaleの Compose 起動 (up -d --no-recreate) をdocker_compose()経由へ寄せ、default_services(override_file)でプロファイルを持たない既定サービスを明示して起動する設計が、確定仕様 (docs/specifications/compose-profiles.md) の方針と合致します。- 同時に棚卸しされた
cmd_login(subprocess.runへのenv=compose_env()渡し) の対処も含まれており、直接 Compose を呼ぶ箇所がlib/内で 0 件になることが実測検証 (grep件数 6 → 3) と整合しています。
- config 読み取りの統合 (決定 9):
_resolve_dev_serviceと_read_compose_servicesを_compose_config_services()へ統合し、_resolve_dev_serviceを薄いラッパーとして維持することでtests/cli/test_base_image_staleness.pyの既存テストを壊さない配慮が妥当です。
- 段階抽出と PR 分割 (決定 7・8・10):
_check_scale_requestおよび_run_scale_pipelineへの抽出、ならびに「振る舞い・仕様・テスト (PR 1)」と「構造抽出 (PR 2)」の分割計画が明確で、PR 1 で固定したテストを PR 2 で変更せずに維持できる設計になっています。
- 受け入れ条件とテスト設計 (A-1〜E-3):
tests/commands/test_container_scale_order.pyの新設設計およびtests/utils/test_docker_profiles.pyの棚卸し更新設計が具体的で、正常系の実行順序 (calls) や失敗時の契約が網羅されています。
ブロックすべき問題や不整合はなく、要求仕様・設計文書として承認基準を満たしています。
cross-review の収束(3 ラウンド)
3 ラウンド回したのは、round 1 で指摘した agy が修正後の差分を見ていなかったためです。 設計を変えた指摘3 件はすべて同じ原因を指していました。確定仕様の経路の表を 1 本目で畳むのに、畳む対象の 受け入れ条件を 2 本目へ移すのではなく、config 読み取りの統合を 1 本目へ移しました 手元の検証(CI は動かないため)
$ gh pr diff 225 --name-only
issues/PLAN65_scale-compose-path-design.md
issues/PLAN65_scale-compose-path.md
$ wc -l issues/PLAN65_scale-compose-path-design.md issues/PLAN65_scale-compose-path.md
498 issues/PLAN65_scale-compose-path-design.md
282 issues/PLAN65_scale-compose-path.md
$ bash "$SCRIPTS/pr-body-decisions.sh" check 225; echo "exit=$?"
一致: 設計文書 1 本 / 決定 10 件
exit=0
|
Summary
devbase scaleの Compose 呼び出しを共通経路へ寄せるか、確定仕様へ例外を書くかを決め、cmd_scaleの段階の抽出とdocker compose config --format jsonの統合の設計を置く。実装は含まない。
issues/PLAN65_scale-compose-path.mdissues/PLAN65_scale-compose-path-design.md参照: #192 / release Pull Request #212 / 範囲外として起票した #224
決めたこと
issues/PLAN65_scale-compose-path-design.mddevbase scaleの Compose 呼び出しを共通経路へ寄せる(issue container.py: cmd_scale の長いメソッドと compose config 読み取りの重複を整理する #192 の案 A)cmd_loginの穴も同じ Pull Request で塞ぐdocker_compose_up()は拡張せず、docker_compose()を直接呼ぶdefault_services(<生成物>)で明示する_previous_scale_compose()は使わないcmd_upと対称にするこの設計で変わること
devbase scaleの子プロセスのCOMPOSE_PROFILESが常に__devbase_none__になり、起動の対象が既定のサービスに限られる。端末または
.envにCOMPOSE_PROFILESを置いている人は、devbase scaleがプロファイルのサービスを起動しなくなる。 既に動いているプロファイルのサービスは止まらない(
scaleは停止の段を持たない)。プロファイルを持たないプロジェクトの振る舞いは変わらない。
実測(この作業ツリー /
release/v3.7.0の先頭 688efde)grepの 6 件だけでは数え足りない。_compose_base_args()が返した配列を使う呼び出し元はその行に
['docker', 'compose']を持たない。呼び出し元まで辿ると Compose を起動する箇所は8 か所で、
compose_env()を渡していないのは 2 か所(cmd_scale:1648とcmd_login:1413)である。issue #192 の本文はcmd_scaleだけを挙げている。実装の分け方
cmd_loginの 1 行・現状固定テスト):マージが要る他の束との重なり
docs/specifications/compose-profiles.mdは PR docs: [name] / --context を取るサブコマンドの列挙を揃え、profiles に requires.devbase の手順を足す (#208, #195) #213(未マージ)も触る。 docs: [name] / --context を取るサブコマンドの列挙を揃え、profiles に requires.devbase の手順を足す (#208, #195) #213 の hunk は193 行目付近の 1 行で、この束が触る節(74-84 / 107-120 / 386-390 / 445 付近)と重ならない。
後からマージする側が競合を解く
DEVBASE_ROOTの隔離は PR test: pytest のセッション全体で DEVBASE_ROOT を隔離する (#209) #217(未マージ)が入れる。 この束のテストの設計は既存の流儀(各テストが自分で
monkeypatch.setenv)に合わせてあるTest plan
設計の段階で確かめたことを載せる。実装はこの Pull Request に含まれないため、
pytestは実装の Pull Request で回す。
release/v3.7.0を base にした Pull Request では CI が 1 件も動かない(ci: リリースブランチ宛の Pull Request で検査ジョブが 1 件も動かない(on.pull_request.branches が main だけ) #216)。.github/workflows/ci.ymlのon.pull_request.branchesがmainだけであるcompose_env()の有無を数え直した(上の実測)_resolve_dev_serviceと_read_compose_servicesの契約の差(終了コードの扱い・不正 JSON の扱い・返す値)を実装本文から表にした
docker_compose_up()がcheck=True固定で、cmd_scaleがexcept subprocess.CalledProcessErrorを持たないことを確認した(設計の決定 3)(
tests/commands/test_container_up_order.py:46-92とtests/utils/test_docker_profiles.py:19-30)cmd_scaleのテストが、この設計で書き換え不要であることを確認した(
default_servicesはいずれの harness でも差し替えられている)ドキュメント再構成の前後
「後」の値は round 1 のレビュー指摘への対応(847865f)を含む。
目安を超えた項目:
採らなかった案を持つ。採らなかった直し方: 決定を章へ分ける(設計文書の雛形が
「決定の記録」を 1 節と定めており、
pr-body-decisions.shもこの見出しの下を読む)21 の受け入れ条件を 8 行へまとめた表と、
grepの件数が段階で変わる説明が占める平均文長と最長文は、どちらの文書も目安(40 字 / 100 字)に収まった。
測れなかった指標: なし
再構成の中で別の作業として足したもの: 設計文書の「図に現れない要素」の表(4 行)と、
処理の流れの図の後の 1 文。どちらも突き合わせの対のために要った説明である。