Skip to content

設計(PLAN65): devbase scale の Compose 呼び出しを共通経路へ寄せ、cmd_scale の段階を分ける (#192) - #225

Merged
takemi-ohama merged 3 commits into
release/v3.7.0from
design/v3.7.0-scale-compose-path
Sep 22, 2026
Merged

takemi-ohama merged 3 commits into
release/v3.7.0from
design/v3.7.0-scale-compose-path

Conversation

@takemi-ohama

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

Copy link
Copy Markdown
Contributor

Summary

devbase scale の Compose 呼び出しを共通経路へ寄せるか、確定仕様へ例外を書くかを決め、
cmd_scale の段階の抽出と docker compose config --format json の統合の設計を置く。
実装は含まない。

  • 要求と受け入れ条件: issues/PLAN65_scale-compose-path.md
  • 設計: issues/PLAN65_scale-compose-path-design.md

参照: #192 / release Pull Request #212 / 範囲外として起票した #224

決めたこと

issues/PLAN65_scale-compose-path-design.md

  • 決定 1: devbase scale の Compose 呼び出しを共通経路へ寄せる(issue container.py: cmd_scale の長いメソッドと compose config 読み取りの重複を整理する #192 の案 A)
  • 決定 2: cmd_login の穴も同じ Pull Request で塞ぐ
  • 決定 3: docker_compose_up() は拡張せず、docker_compose() を直接呼ぶ
  • 決定 4: 起動の対象は default_services(<生成物>) で明示する
  • 決定 5: 失敗の扱いとログの文言は変えない
  • 決定 6: _previous_scale_compose() は使わない
  • 決定 7: 段階の番号の文字列は変えない
  • 決定 8: 抽出は 2 つの関数に分け、cmd_up と対称にする
  • 決定 9: config の読み取りは「下位の 1 関数 + 既存の名前を残した包み」に統合する
  • 決定 10: 実装は 2 本の Pull Request に分ける

この設計で変わること

devbase scale の子プロセスの COMPOSE_PROFILES が常に __devbase_none__ になり、起動の
対象が既定のサービスに限られる。端末または .env に COMPOSE_PROFILES を置いている人は、
devbase scale がプロファイルのサービスを起動しなくなる。
既に動いているプロファイルの
サービスは止まらない(scale は停止の段を持たない)。プロファイルを持たないプロジェクトの
振る舞いは変わらない。

実測(この作業ツリー / release/v3.7.0 の先頭 688efde)

$ grep -rn "'docker', 'compose'\|\"docker\", \"compose\"" lib/ | wc -l
6
$ grep -rn "no-recreate" tests/ | wc -l
0
$ grep -rn "'config', '--format', 'json'" lib/ | wc -l
2

grep の 6 件だけでは数え足りない。 _compose_base_args() が返した配列を使う呼び出し元は
その行に ['docker', 'compose'] を持たない。呼び出し元まで辿ると Compose を起動する箇所は
8 か所で、compose_env() を渡していないのは 2 か所(cmd_scale:1648 と
cmd_login:1413)である。issue #192 の本文は cmd_scale だけを挙げている。

実装の分け方

# 名前 依存
1 振る舞いと仕様(確定仕様の書き換え・共通経路へ寄せる・cmd_login の 1 行・現状固定テスト) 無し
2 構造(段階の抽出・config 読み取りの統合) Pull Request 1 の :マージ が要る

他の束との重なり

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 を起動する 8 か所を 1 つずつ辿り、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)
  • 既存の 4 か所の cmd_scale のテストが、この設計で書き換え不要であることを確認した
    (default_services はいずれの harness でも差し替えられている)
  • ドキュメント再構成の前後の値を測った(下記)

ドキュメント再構成の前後

指標 要求仕様 前 要求仕様 後 設計 前 設計 後
結論が定義される位置 12 行目 12 行目 8 行目 8 行目
平均文長 53.6 字 49.8 字 48.9 字 42.8 字
最長文 161 字 98 字 174 字 99 字
章の数 12 16 8 14
行数 287 282 465 498
40 行を超える章 2 0 4 2

「後」の値は round 1 のレビュー指摘への対応(847865f)を含む。

目安を超えた項目:

  • 設計の「決定の記録」181 行(目安 40 行)。理由: 10 の決定がそれぞれ結論・理由・
    採らなかった案を持つ。採らなかった直し方: 決定を章へ分ける(設計文書の雛形が
    「決定の記録」を 1 節と定めており、pr-body-decisions.sh もこの見出しの下を読む)
  • 設計の「受け入れ条件とどちらの Pull Request が対応するか」43 行(目安 40 行)。理由:
    21 の受け入れ条件を 8 行へまとめた表と、grep の件数が段階で変わる説明が占める

平均文長と最長文は、どちらの文書も目安(40 字 / 100 字)に収まった。

測れなかった指標: なし

再構成の中で別の作業として足したもの: 設計文書の「図に現れない要素」の表(4 行)と、
処理の流れの図の後の 1 文。どちらも突き合わせの対のために要った説明である。

takemi-ohama and others added 2 commits September 22, 2026 11:38
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 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 | 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 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 | REQUEST_CHANGES

総評

PR #225 の要求仕様と設計は、devbase scale の共通経路化や段階分割について詳細に整理されていますが、PR 1 と PR 2 の分割境界と、要求仕様の受け入れ条件・確定仕様の更新タイミングとの間に以下の不整合があります。2 本の Pull Request に分けて安全に移行するという目的に沿い、各段階の検証可能性と仕様・実装の一致を保つための修正を提案します。

  1. 受け入れ条件 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)側に整理してください。
  2. 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 境界を調整してください。
  3. 受け入れ条件 A-5(棚卸しコメントとテスト一覧の一致)の検証時期

    • PR 1 の段階では config 読み取り関数がまだ直接呼び出しのまま残るため、棚卸しコメントやテスト一覧を変更後の 4 経路に一致させることはできません(設計書 426 行目でも棚卸しコメントの更新は PR 2 とされています)。
    • 修正提案: A-5 を PR 2(構造グループ D)へ移動するか、PR 1 では cmd_login のテスト追加のみを検証する形に改めてください。

Comment thread issues/PLAN65_scale-compose-path.md
Comment thread issues/PLAN65_scale-compose-path-design.md
Comment thread issues/PLAN65_scale-compose-path.md
確定仕様の経路の表は _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 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 | codex | APPROVE

修正を求める指摘はありません。

@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

設計・要求文書の実測(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 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 3 | codex | APPROVE

修正を要する指摘はありません。

@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 3 | agy | APPROVE

概要

PR #225 における要求仕様書 (issues/PLAN65_scale-compose-path.md) および設計文書 (issues/PLAN65_scale-compose-path-design.md) の内容を、release/v3.7.0 の現行コード・仕様書・既存テストと突き合わせて確認しました。

確認事項

  1. 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) と整合しています。
  2. config 読み取りの統合 (決定 9):
    • _resolve_dev_service と _read_compose_services を _compose_config_services() へ統合し、_resolve_dev_service を薄いラッパーとして維持することで tests/cli/test_base_image_staleness.py の既存テストを壊さない配慮が妥当です。
  3. 段階抽出と PR 分割 (決定 7・8・10):
    • _check_scale_request および _run_scale_pipeline への抽出、ならびに「振る舞い・仕様・テスト (PR 1)」と「構造抽出 (PR 2)」の分割計画が明確で、PR 1 で固定したテストを PR 2 で変更せずに維持できる設計になっています。
  4. 受け入れ条件とテスト設計 (A-1〜E-3):
    • tests/commands/test_container_scale_order.py の新設設計および tests/utils/test_docker_profiles.py の棚卸し更新設計が具体的で、正常系の実行順序 (calls) や失敗時の契約が網羅されています。

ブロックすべき問題や不整合はなく、要求仕様・設計文書として承認基準を満たしています。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

cross-review の収束(3 ラウンド)

round レビュー fix
1 agy=REQUEST_CHANGES (major 2 / minor 1) / kiro=APPROVE 847865f
2 codex=APPROVE / kiro=APPROVE —
3 codex=APPROVE / agy=APPROVE —

3 ラウンド回したのは、round 1 で指摘した agy が修正後の差分を見ていなかったためです。
round 2 で承認した 2 者(codex / kiro)は 847865f を含む状態を見ていますが、agy は round 3 で
初めて見ています。未解決の指摘は 0 件(GitHub 側で確認済み)。

設計を変えた指摘

3 件はすべて同じ原因を指していました。確定仕様の経路の表を 1 本目で畳むのに、畳む対象の
実装(config 読み取りの統合)を 2 本目に置いていたため、1 本目のマージの時点で仕様と実装が
食い違った版が残る
というものです。kiro の反証も 3 件すべてを support としました。

受け入れ条件を 2 本目へ移すのではなく、config 読み取りの統合を 1 本目へ移しました
(847865f)。分け目は「Compose の呼び出しを共通経路へ寄せる」と「cmd_scale の段階を
分ける」になり、#192 が指定した順序にもより素直になりました。あわせて、どの受け入れ条件が
どちらの Pull Request で満たされるかの表を設計文書へ足しました。

手元の検証(CI は動かないため)

release/v3.7.0 を base にした Pull Request では検査ジョブが 1 件も動きません(#216)。
gh pr checks 225 は no checks reported、mergeStateStatus は CLEAN です。緑に見えるのは
検査が無いためで、通ったためではありません。
この Pull Request は設計文書だけなので、
確かめたのは文書の側です。

$ 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

lib/ と docs/specifications/ の変更はこの Pull Request に含まれません(実装の
Pull Request 1 で入ります)。

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.

1 participant