release: v3.7.0 base イメージの描画と、名前・見出し・文書の食い違いの解消 - #212
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(PLAN63): base イメージの日本語の描画と、文書を扱う軽量の道具の要求仕様と設計 (#161, #160) base コンテナで sans-serif が中国語フェイス(WenQuanYi Zen Hei)へ解決される問題と、 Office 文書・PDF を扱う軽量の道具が無い問題を、1 本の設計にまとめた。 どちらも containers/base/Dockerfile の同じ apt / COPY の区画を触るため 1 本にした。 実装は別のブランチで行う。この Pull Request は設計文書だけを載せる。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 受け入れ条件 6 の表を 8 通りへ揃え、wqy-zenhei の扱いを実態へ直す レビュー指摘 2 件への対応。 - 受け入れ条件 6 の表に総称ファミリ 4 つ × 言語 2 つの 8 行が揃っていなかった。 `sans:lang=zh-cn` / `sans:lang=ko` / `monospace:lang=ko` を足し、欧文を名指しした 行にも `Arial:lang=ko` を足して 12 行にした(major) - 設計文書の「解決先の表」にも同じ 4 行を足し、`serif:lang=ko` の変更前が `(未測定)` のままだったのを実測値 `WenQuanYi Zen Hei` へ直した - テスト設計の受け入れ条件 6 の行を「8 つ」から「12 行(総称ファミリ 4 つ × 言語 2 つの 8 行と、欧文を名指しした 3 行、中国語の書体を名指しした 1 行)」へ改めた - 「変えないもの」の `fonts-wqy-zenhei` の行が Dockerfile の実態と合っていなかった。 導入の行は無く `npx playwright install --with-deps chromium` が依存として入れる、 と書き直した。決定 6 の検査の観点も `apt-get remove` / `apt-get purge` / `dpkg -r` が無いことの確認へ具体化した(minor) いずれも手元の devbase-base:latest(arm64)での実測にもとづく。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 切り戻し手順に派生イメージとコンテナの建て直しを足し、`<match>` の数を 9 に直す cross-review round 2 (codex) の 2 件へ対応した。 - 切り戻し手順を 4 段(revert / base の再ビルド / 派生イメージの建て直し / 稼働中コンテナの作り直し)へ書き直した。base のタグを戻しても、派生イメージは `FROM devbase-base:latest` を自分のビルドの時点で焼き込むため建て直すまで古い層を持つ。 「影響」の表の「利用者の操作」の行にも同じことを書いた - `fonts-local.conf` の `<match>` は、未導入の書体の受け皿 1 つと総称ファミリ 4 つ × 言語 2 つの 8 つで合計 9 つである。テスト設計の検査条件と本文の説明の両方を 9 つへ直した Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 解決先の表の漏れ・参照先・キャッシュの説明を直す round 3 のレビュー指摘 3 件へ対応する。 - 解決先の表へ `Times New Roman:lang=zh-cn` の行を足す(実測済みの値。 `Arial:lang=ko` は既にあった) - 決定 2 の中の参照先を「決定 4」から「決定 8」へ直す。`sans-serif` の prefer を日本語へ向けるのは決定 8 である - 決定 4 のキャッシュの説明を Docker の仕様へ合わせる。`RUN` のキャッシュが 効いている間はその中身が実行されないため、取得先の内容が変わっても キャッシュは無効にならない Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 受け入れ条件 13 の合否のラインを測り方の違いに耐える形へ直す 受け入れ条件 13 は合否のラインを「約 24 MB」とし、検証を `docker images` の差と定めていた。しかし 24 MB は稼働中のコンテナでの `du` の差(apt の リストとキャッシュを含む)で、`docker images` が出す層単位の値とは測り方が 違う。そのままでは正しい実装でも不合格になりうる。 合否のラインを「7.09GB に対して +0.5% 未満(40 MB 以下)」へ改め、 24 MB をラインに使わない理由を条件の中に書いた。設計文書の 「未確認のまま残ること」にも、このラインが測り方の違いを吸収するための ものである旨を追記した。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): コンテナの作り直しの案内を devbase down → up へ統一する devbase rebuild は devbase build --expires=7 のシノニム (lib/devbase/commands/container.py の cmd_rebuild) で、イメージのビルドしか 行わず稼働中のコンテナを作り直さない。期限内ならビルドそのものを飛ばすため、 切り戻しにも適用にも使えない。 「影響」の表の「利用者の操作」と「切り戻し手順」の 4 番目の両方で、稼働中の コンテナの作り直しを devbase down → devbase up に統一し、devbase rebuild が ここでは使えない理由を書き添えた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 受け入れ条件へ IPAPGothic と fc-match sans を足し、テスト設計に fc-match -s を書く (#221) round 6 のレビュー指摘 3 件への対応。 - 受け入れ条件 6 の表へ `IPAPGothic`(名指し)の行を足した。イメージに実在する 日本語の書体がそのまま残ることを固定する。受け入れ条件 4 は「イメージに無い 書体名が JP へ落ちる」条件なので、`WenQuanYi Zen Hei`(名指し)と同じ性質の この行は 6 の表へ置いた - 受け入れ条件 1 へ `fc-match sans`(`lang` なし)を足した。`fonts-local.conf` は `sans` の `<alias>` を持つのに、`lang` を付けない照合が固定されていなかった - テスト設計の受け入れ条件 1〜4 の行へ、`fc-match -s sans-serif:lang=ja` の 1 件目も 確かめることを明記した。あわせて受け入れ条件 6 の行数を 12 から 13 へ直した Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 受け入れ条件 5 から Calibri / Cambria を外し 11 へ移す 受け入れ条件 5 の見出しは「欧文が壊れない」だが、`Calibri` と `Cambria` は 変更前に `WenQuanYi Zen Hei`(中国語のフェイス)へ落ちており、`Arial` などの 「変更の前後で変わらない」ものとは性質が違う。同じ枠に並べると基準を誤読させる。 - 受け入れ条件 5 は変わらない 3 つ(`Arial` / `Times New Roman` / `Courier New`)に絞る - 受け入れ条件 11 を「欧文の metric 互換が直る」とし、現状がどちらも `WenQuanYi Zen Hei` であることと、直す手段(`fonts-crosextra-carlito` / `fonts-crosextra-caladea`)を書く - 設計文書のテスト設計の表の `5・11` の行を、上の切り分けに合わせる 受け入れ条件の番号は 1〜16 のまま変えていない。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN63): 決定 2 の表がどの状態を測っているかを列の見出しと前置きで示す 「解決先の表」の ko の「変更前」と、決定 2 の表の ko の「規則なし」は 食い違って見えるが、測っている状態が違う。前者は /etc/fonts/local.conf が無い今の base イメージそのまま(WenQuanYi Zen Hei)、後者は local.conf は置いたうえで zh-cn / ko の <match> だけを書かなかった状態 (Noto Sans CJK JP / Noto Serif CJK JP)である。どちらも 2026-09-22 に arm64 で実測した値なので、値は変えない。 読み分けられるように、決定 2 の表の列の見出しを「zh-cn / ko の規則なし」 へ改め、表の直前に 3 つの列がどれも local.conf を置いた状態であることと、 local.conf を置く前の値は「解決先の表」の「変更前」にあることを書いた。 決定 2 の末尾の段落の言い回しも同じ語に揃えた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(PLAN64): 機密の参照の見出しにグループの読み替えの前後を出す設計 (#188) 要求と受け入れ条件 (issues/PLAN64_secret-label-group.md) と設計 (issues/PLAN64_secret-label-group-design.md) の 2 文書を足す。lib/ は変えない。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN64): レビューの指摘 3 件を反映 (#188) - 受け入れ条件 7 の例示を、実際に SecretRef.label() の既定を使う文言 (OpenBaoBackend._check_group / runtime の DEVBASE_ACCOUNT_GROUP 警告) へ差し替えた。 --group の不一致の文言 (_project_group_mismatch) は display_group を直接呼んでおり、 今も読み替えの前後を出す。対象範囲の「含まない」と決定 2 に明記した - 設計のテスト設計 7 の参照先を OpenBaoSettings.path_of から OpenBaoBackend._check_group へ直した - 影響の「公開インタフェース」に env backend migrate を足した Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN64): round 2 の指摘 2 件を反映 (#188) - 前提 2 を直した。config.openbao が None かどうかで backend の種類を判定しては ならない (backend: age でも openbao: 節が残れば None にならない)。表示の分岐は SecretStore.storage_group に任せる旨へ揃え、決定 3 の根拠にも足した - 受け入れ条件 5・6 の検証を、既存テストの通過から新規の出力テストへ変えた。 既存の assert は '=== グローバル' の前方一致で、見出しにグループが付いても通る ため「変わらないこと」を確かめられない Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN64): round 3 の指摘 2 件を反映 (#188) - 設計文書の末尾に残っていた不要なタグ </content> を消した - 受け入れ条件 3 とテスト設計を、env backend migrate の 2 つの一覧の両方を 確かめる形へ直した。計画の一覧 (_MigrationPlan._heading) と --to age の 完了表示は別の関数が出すため、--dry-run の計画一覧だけでは決定 4 を 確かめられない Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN64): 決定 6 の仕様の書き換え指示を決定 2 の例外へ揃えた (#188) 「エラー文言とログを除く」と書くと、display_group を直接呼ぶ _project_group_mismatch の -p の拒否の文言 (default → nyle を出す既存の仕様と テスト) と矛盾する。除くものを「引数なしの SecretRef.label() で参照を表示する エラー文言・ログ」に限る形へ直し、機能一覧 F2 と曖昧語の具体化にも同じ分かれ目を 書いた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN64): テスト設計 7 の検証対象を要求文書へ揃えた (#188) 受け入れ条件 7 は 2 つの文言 (OpenBaoBackend._check_group の例外と、 runtime.py の DEVBASE_ACCOUNT_GROUP の警告) を挙げているが、設計のテスト設計は 例外だけを書いていた。警告文でも → が出ないことを見る旨を足した。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
) (#225) * docs(PLAN65): devbase scale の Compose 呼び出しを共通経路へ寄せる要求仕様と設計 (#192) 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> * docs(PLAN65): 決定 10 を決定の記録の一覧へ載せる (#192) Pull Request 本文の「決めたこと」の節は設計文書の `## 決定の記録` の `###` 見出しから 作られるため、章へ切り出した決定 10 が一覧から漏れていた。章を指す見出しを置く。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN65): config 読み取りの統合を 1 本目の Pull Request へ移す (#192) 確定仕様の経路の表は _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> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(PLAN66): 名前の形に合わないプロジェクトを作られた時点で知らせる要求仕様と設計 (#203) - プラグインの同期と env import で名前の形を検査し、弾かずに警告に留める - スナップショットの名前の形を utils/names の述語へ寄せる - 実装は含まない(設計だけの Pull Request) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): round 1 のレビュー指摘を反映する (#203) - 検査の位置を候補の集約から symlink を張る直前へ移す(同じ名前で 2 行出る・載らない名前にも出る) - 知らせの文を完了形にせず、dry-run や書き込み失敗と矛盾しない形にする - 決定 7 の共通化の範囲(ヒント文だけ)を明記する - 既存のテストファイルへの追加であることを検証欄に書く Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): round 2 のレビュー指摘を反映する (#203) - env import の知らせを保存先ごとの文にする(age・サーバ backend は projects/ に作らない) - 受け入れ条件へ age の保存先の条件を足す(番号を 1 つ繰り下げ) - 受け入れ条件 11 の拒否リストへ末尾の改行を足し、設計の 8 件と揃える Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): round 3 のレビュー指摘を反映する (#203) - age の保存先の受け入れ条件を backend を明示する流儀へ(平文へ落ちると条件を確かめられない) - 同期の知らせの案内を出所ごとに分ける(別名と実ディレクトリでは改名先が違う) - F2 と用語の定義を保存先の違いに合わせる - real_projects を sorted で走査する旨を明記する - 前提の番号の順序を昇順へ直す Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): F1 の文から、同期が作らない実ディレクトリを分けて書く (#203) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): round 5 のレビュー指摘を反映する (#203) - 別名の案内を、名前の側と owner の側で分ける(_foo.valid-owner は改名で直る) - 分かれ目を is_single_segment_name(<名前>) と明記し、_warn_unusable_name へ base を渡す - 受け入れ条件 3 を 2 つの分岐で確かめる形にする(3 と 3-2) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): 知らせを出す時点の記述を、計画を立てた直後へ揃える (#203) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…の手順を足す (#208, #195) (#213) * chore: 文書の列挙を揃える作業の Draft Pull Request を開く Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: [name] / --context を取るサブコマンドの列挙を揃え、profiles に requires.devbase の手順を足す #208: argparse の集合を正本として、文書 8 か所の列挙に rebuild / open を足す。 - [name]: 02-project.md / cli-reference/README.md(mermaid・ショートカットの表)/ container-operations.md / specifications/compose-profiles.md - --context: 02-project.md / remote-docker-context.md の 2 か所(env token も)/ environment-variables.md - profile も [name] を取るが解決の経路が違うことを 1 行添える - cli-argument-resolution.md と DEVBASE_DOCKER_CONTEXT の行は正しいので触らない #195: profiles: を使う Plugin が plugin.yml の requires.devbase を ">=3.5.0" へ 上げる手順を plugin-dev/compose-profiles.md へ足し、上げる契機を 1 つに限定していた plugin-yml-reference.md 側を広げて相互リンクする。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore: #209 の作業ツリーを開く pytest のセッション全体で DEVBASE_ROOT を隔離する作業の口を開ける。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: pytest のセッション全体で DEVBASE_ROOT を隔離する (#209) pytest は実行したシェルの環境を継承するため、tmp の root を作るだけで setenv しない fixture を使うテストが、自前の `monkeypatch.setenv('DEVBASE_ROOT', ...)` を忘れると 実環境の devbase の `projects/` と `secrets/backend.yml` を読む。 fixture 1 つに setenv を足しても同じ穴は他にも残るため、`tests/conftest.py` に autouse fixture `_isolate_devbase_root` を置き、テストごとの空の tmp の root へ固定する (#209 の案 B)。autouse は同じ scope の明示の fixture より先に立つので、既存の 32 か所の setenv は書き換えずに後勝ちで働き、未設定の分岐を試す道 (delenv) も残る。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
#231) * chore: #192 の実装 1 本目(Compose の呼び出しを共通経路へ寄せる)を始める Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN65): 実装 1 本目の計画を置く (#192) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN65): devbase scale と login を Compose の共通経路の対象に含める (#192) 確定仕様の「COMPOSE_PROFILES は devbase 経由の操作には効かない」を例外なしの約束にする (設計の決定 1)。経路の表から cmd_scale の除外を削り、経路を 5 つに畳む。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(PLAN65): devbase scale の起動と config の読み取りを Compose の共通経路へ寄せる (#192) - cmd_scale の [4/5] を docker_compose(['up', '-d', '--no-recreate', *services], check=False) にし、 起動の対象を default_services(<生成物>) で明示する(設計の決定 1・3・4) - config --format json を読む関数を _compose_config_services の 1 つにし、docker_compose を通す。 _read_compose_services を削除し、_resolve_dev_service は名前と契約を保って載せ替える(決定 9) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(PLAN65): devbase login の exec にも compose_env() を渡す (#192) 経路の表が devbase の Compose の起動を網羅するよう、cmd_login の 1 行を塞ぐ(設計の決定 2)。 棚卸しのコメントを変更後の 4 経路(_compose_run / _compose_lines / cmd_login / _query_container_name)へ書き直し、_compose_lines と cmd_login のテストを並べる。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(PLAN65): devbase scale の正常系の手順と範囲を固定する (#192) cmd_scale の段階を分ける前の安全網。順序(グループの検査 → write_scale → ボリューム → network → 生成 → default_services → 起動 → ready 待ち → bao → ./deploy)、bao と ./deploy の 範囲(current + 1 から new まで)、停止を呼ばないこと、受け付けない scale の扱いを固定する。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Test: characterize scale deploy failure and default login Add current-behavior tests for continuing deployment after an instance failure and logging into instance 1 when arguments are omitted. Production code is unchanged. Item-Id: R1-001 Round: 1 Impl-Runtime: codex Impl-Model: default * Test: characterization test for cmd_scale branch — lib/devbase/commands/container.py#cmd_scale cmd_scale に明示的な project_name が渡された場合の分岐を固定する現状固定テストを追加。 Item-Id: R1-003 Round: 1 Impl-Runtime: agy Impl-Model: default --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore: #192 の実装 2 本目(cmd_scale の段階を分ける)を始める Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN65): 実装 2 本目の計画を置く (#192) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(PLAN65): cmd_scale の前提の検査を _check_scale_request へ出す (#192) new_scale の 1 未満・現在以下の判定とログを関数へ移す(設計の決定 8)。 文言と出し分けは変えない。契約のテストを足し、既存の現状固定テストは書き換えない。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(PLAN65): cmd_scale の [1/5]〜[5/5] を _run_scale_pipeline へ出す (#192) cmd_up の _run_deploy_pipeline と対称の段にする(設計の決定 8)。起動が 0 以外なら Failed to start new containers を出して None を返し、ほかの失敗は伝播する。後処理 (bao の token・./deploy・完了のログ)は cmd_scale の本体に残す。段階の番号とログの 文言は変えない(決定 7)。cmd_scale の本体は 92 行から 40 行になる(D-3)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN65): 実装 2 本目の計画の受け入れ条件に結果を記す (#192) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style(PLAN65): cmd_scale の空行と折り返しを元へ戻し、D-3 の行数の判断を記す (#192) 40 行に届かせるために削った空行・1 行へ詰めた文・短くしたコメントを、抽出前の書式へ戻した。 振る舞いは変えない。D-3 の意図(段階の命名と cmd_up との形の一致)は満たし、行数は 要求の数え方で 51 行になる。数字のために読みやすさを犠牲にしない判断を要求の文書と計画に記した。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Test: characterize cmd_scale error paths Preserve configuration and subprocess side effects on target resolution and readiness failures. Item-Id: R1-001 Round: 1 Impl-Runtime: codex Impl-Model: default * Test: characterize cmd_scale default scale handling Fix current behavior when config.scale is omitted in project.yml. DEFAULT_SCALE is treated as current scale, rejecting scale 2 and deploying only instance 3 on scale 3. Item-Id: R1-002 Round: 1 Impl-Runtime: agy Impl-Model: default --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(PLAN66): 名前の形の知らせ(実装 1 本目)の作業を始める Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): 実装 1 本目(知らせ)の計画を置く Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(PLAN66): プラグインの同期が名前の形に合わない名前を projects/ に載せる直前に知らせる symlink は今と同じく張り、戻り値も変えない(決定 1)。検査は winner の symlink の直前・ 別名の symlink の直前・実ディレクトリの採取の直後の 3 か所に置き、discover_projects と _collect_project_candidates には置かない(決定 2)。別名の案内は元の名前と <owner> の どちらが原因かで分ける。名前の形の説明文は utils/names.NAME_FORM_HINT に置く(決定 7)。 Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(PLAN66): env import が名前の形に合わないプロジェクト名を取り込むとき保存先に応じて知らせる import は今と同じく通し、書庫の名前の規則(_PROJECT_ENV_RE)も変えない(決定 4)。 知らせは _build_plans の直後、--dry-run の判定より前に出す。平文の projects/<name>/.env では作ることと改名の案内を、age・サーバ backend では保存先を名指しして projects/ に 何も作らないことを書く。env/secret_store.py は触らない。 Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): 確定仕様の「運用」と CHANGELOG に名前の形の知らせを書く Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Test: characterize project name extraction, server import, and sync aliases Add characterization coverage for R1-001, R1-002, and R1-003 without changing production code. Item-Id: R1-001 Round: 1 Impl-Runtime: codex Impl-Model: default * fix(PLAN66): projects/ 直下の . 始まりの実ディレクトリに名前の形の警告を出さない sync_projects の実ディレクトリの知らせが .vscode などにも出ていた。 決定 8 のとおり . 始まりはプロジェクトとして扱わず、知らせも出さない。 回帰テスト test_dot_real_directories_are_not_warned を追加。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(PLAN66): スナップショットの名前の寄せ(実装 2 本目)の作業を始める Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): 実装 2 本目の計画を置いた Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(PLAN66): スナップショットの名前の検証を utils/names の述語へ寄せる _VALID_NAME_RE を消し、_validate_name が is_single_segment_name を呼ぶ(決定 5)。 例外の型・文言・_safe_snap_dir の封じ込めは変えない。狭まるのは末尾の改行を持つ名前だけ。 tests/snapshot/test_manager_name.py で受理 4 件・拒否 8 件を固定する(決定 6)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(PLAN66): 確定仕様の「運用」の 2 つ目と CHANGELOG の Changed を書いた Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Test: characterize invalid snapshot name rejection in create Fix current public-entry behavior before directory creation or Docker execution. Item-Id: R1-001 Round: 1 Impl-Runtime: codex Impl-Model: default * Test: characterize invalid snapshot name rejection in delete Fix current public-entry behavior before directory deletion or rmtree execution. Item-Id: R1-002 Round: 1 Impl-Runtime: agy Impl-Model: default --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(PLAN64): 実装の作業場所を用意する (#188) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(PLAN64): 機密の参照の見出しにグループの読み替えの前後を出す (#188) SecretRef.label() にキーワード引数 group_display を足し、見出し用の表示を作る口を SecretStore.display_label(ref) の 1 つに置いた。読み替えの要否は storage_group が 決める (backend の種類・設定の有無・layout・グループの有無をまとめて見る唯一の判定)。 label() の既定の返り値は変えていない。読み替えの解決は BackendConfigError を送出 しうるため、43 か所のエラー文言・警告・ログを巻き込まない。 見出しの呼び出し 5 か所 (env list の節の見出しと件数の行・env backend test の参照 ごとの行・env backend migrate の計画の一覧と --to age の完了後の一覧) を display_label へ寄せた。読み替えの対応が無いグループ・version: 1・ファイル backend の出力と、 env backend status の表示は変わらない。 確定仕様の相反する 2 つの記述を、文言の種類で分ける形に書き分けた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: characterize backend probe and flat layout labels Add characterization tests for current-group probe headings, skipped project aliases, and grouped references on a flat layout. Item-Id: R1-001 Round: 1 Impl-Runtime: codex Impl-Model: default * test: characterize project references in the migration plan and display_label Add characterization tests for the project heading in the migration plan listing and for project / personal-project references passed to SecretStore.display_label. Item-Id: R1-002 Item-Id: R1-005 Round: 1 Impl-Runtime: agy Impl-Model: default Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * test: characterize the migration plan listing towards openbao Fix the headings of the reverse direction (age -> openbao) of `env backend migrate --dry-run`, where the aliased group name and the destination path have to name the same group on one line. Item-Id: R1-003 Round: 1 Impl-Runtime: claude Impl-Model: claude-opus-5 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * Refactor: consolidate_duplication — lib/devbase/env/secret_store.py#SecretStore.mode SecretStore.mode が backend_for と同じ backend の選択・存在判定・衝突検出を 重複して持っていたため、backend_for の結果の exists で判定する形にまとめた。 あわせて extract_method — lib/devbase/commands/env_backend.py#_MigrationPlan.apply: 書き込み後の読み戻し検証ループを _verify_read_back へ抽出した (R2-002)。 Item-Id: R2-001 Round: 2 Impl-Runtime: claude Impl-Model: default Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Revert "Refactor: consolidate_duplication — lib/devbase/env/secret_store.py#SecretStore.mode" This reverts commit cd75e0e. 構造改善の提案 R2-001 / R2-002 は、この Pull Request の差分の外 (`SecretStore.mode` と `_MigrationPlan.apply` の読み戻し検証) を指していた。 R2-001 は `mode` の分岐を `backend_for` へ寄せており、見出しの表示だけを変える この変更の範囲を越えて振る舞いに触れうる。範囲外として取り消す。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(PLAN63): base イメージの描画と文書の道具の実装の作業場所を用意する (#161, #160) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * feat(PLAN63): base イメージの日本語の描画を直し、文書を扱う軽量の道具を足す (#161, #160) `/etc/fonts/local.conf` を 1 つ置き、総称ファミリ (sans-serif / sans / serif / monospace) と、イメージに無い書体名を Noto CJK の JP フェイスへ向ける。中国語・ 韓国語の規則は総称ファミリを名指ししたときだけ効かせる (`<test name="family">`)。 この test を省くと `Arial:lang=zh-cn` から Liberation Sans を奪い、様式も崩れる。 conf.d/99-*.conf へ置くと `<alias><prefer>` が効かない。local.conf は conf.d/51-local.conf 経由で読まれ、sans-serif を中国語フェイスへ向けている 64 / 65 より「先」になるためで、理由と実測は fonts-local.conf の先頭に残した。 あわせて 6 パッケージを 1 つ目の RUN の 1 回目の apt-get install へ足す。 poppler-utils / python3-pil / python3-defusedxml / python3-lxml と、欧文の metric 互換の fonts-crosextra-carlito / fonts-crosextra-caladea である。 LibreOffice と pip は入れず、fonts-wqy-zenhei も消さない。 回帰テストは 2 段。Dockerfile と fonts-local.conf の形は Docker なしで、 fc-match の解決先は建てたイメージの中で固定する。後者はイメージが無い・古い ときは skip する。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * fix(PLAN63): probe の実行中の異常を skip でなく失敗として知らせる (#161) docker run を包む except (SubprocessError, OSError) が TimeoutExpired まで pytest.skip にしていたため、Docker もイメージもある状態で probe が 300 秒で タイムアウトすると 39 件すべてが skip になり pytest が成功終了していた。 skip してよいのは Docker が使えない・イメージが無い (_docker_unavailable) と イメージが古い (STALE_IMAGE_EXIT) の 3 つだけなので、docker run の try/except を 外して例外のまま失敗させる。意図はコメントで残す。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * test(PLAN63): 新しい RUN の検査を RUN ブロック単位へ直す (#161) `RUN ` で始まる行だけを集めていたため、各要素は `RUN set -eux; \` のような 1 行目だけになり、パッケージ名が入る継続行を見ていなかった。 `poppler-utils` / `fonts-crosextra` が無いという 2 つの assert は常に真で、 「6 パッケージのために RUN を足していない」という意図を固定できていなかった。 `_run_blocks()` を足して Dockerfile を RUN ブロック (行継続を含む 1 命令分) へ 分け、`_first_run_block()` はその 1 つ目を返す形に寄せた。検査は 1 つ目以外の 各ブロックの全文に対して行う。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…192, #203) (#240) * docs(PLAN63): base イメージの文字の描画と文書の道具を確定仕様へ移す 新規の確定仕様 docs/specifications/base-image-rendering.md を置く。設定の置き場所を /etc/fonts/local.conf から動かせない理由 (スロット 51 と <prefer> の prepend)、zh-cn / ko の <match> が <test name="family"> を必ず持つ理由、未導入の書体の受け皿、fc-cache -f の位置の 制約、解決先の 26 行、入れないもの (LibreOffice / pip / ENV LANG / fonts-wqy-zenhei の削除)、 同梱する 6 パッケージ、派生イメージと稼働中コンテナへの伝播、テストの 2 段構成と skip の 4 段を書く。containers/lfm が対象外であること、確かめたのは fc-match の水準までで amd64 は 未確認であることは運用に残す。 docs/user/container-operations.md には devbase rebuild ではイメージが建て直らないこと (build --expires=7 のシノニムで期限内はビルドを飛ばす) を足し、新規仕様へ相互リンクする。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 * docs(PLAN64, PLAN65, PLAN66): 残る決定と検証の観点を確定仕様へ移す cli-argument-resolution.md (PLAN66): 構成要素の表へ plugin/syncer.py・env/io_import.py・ env/_import_merge.py・snapshot/manager.py の行を足し、utils/names.py へ NAME_FORM_HINT を 書き足す。仕様に「名前の形に合わない名前の知らせ」を置き、1 件 1 回の保証と検査の位置、 discover_projects に置かない理由、出所で 4 通りに分かれる案内、--dry-run でも出すこと、 保存先で文が分かれる理由を書く。運用の側は結果の要約にとどめて小節へリンクし、知らせが 同期のたびに毎回出ることを足す。テスト観点へ同期・import・age の保存先・スナップショットの 名前のテストを足す。 secret-backend.md (PLAN64): テスト観点へ test_secret_store_label.py と test_env_group_label.py が固定している 5 点を足す。 compose-profiles.md (PLAN65): devbase scale の段落へ _previous_scale_compose を入れない 理由を 1 文足す。 CHANGELOG.md: Unreleased の Changed へ、devbase scale が端末や .env の COMPOSE_PROFILES を 見なくなる旨を足す。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
- CHANGELOG の [Unreleased] を [3.7.0] - 2026-09-23 として確定し、比較リンクを足す - pyproject.toml / lib/devbase/__init__.py / lib/devbase/cli.py / uv.lock / architecture.md の版数を 3.7.0 にする Claude-Session: https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
本文の「配布の記録」は承認待ちの時点で書いたもので、 配布の記録段階: 本番(検証のチャネルが無いため |
リリース後テスト対象の版: 3.7.0(2026-09-23 07:52 JST に #161 / #160 の変更は、
合否: 合格(表の 34 行中 32 行を実施、2 行は保留) 保留の 2 行は、いずれも base イメージの再ビルドを要するもの(#161 の 15、#160 の 13)である。 起票したもの:
|
振り返り(2026-09-23)対象: マイルストーン v3.7.0 の 8 課題 — #161 / #160 / #188 / #192 / #195 / #203 / #208 / #209 base イメージの日本語の描画を直して文書を扱う軽量の道具を足し(#161 / #160)、機密の見出しに 何が起きたか課題本文の「実測」が 4 束すべてで誤っていた設計の束 4 つすべてで、issue 本文に実測として書かれた値が誤っていた。 誤りの種類は
共通するのは、起票の時点の調査が「症状を再現するところまで」で止まり、修正の範囲までは 輪番の収束が 1 ラウンドでは足りなかったラウンド 1 の収束をそのまま信じていたら見逃していた指摘が複数あった。 3 者輪番では、
どちらも「テストがある」という証跡そのものを無効にする穴で、ラウンド 1 の 2 者は指摘して 個別の Pull Request には CI が 1 件も当たっていなかった
ただし、束の中身がまったく検査されていなかったわけではない。 release PR #212 は束の 構造改善が Pull Request の外を指し続けた
既存の課題(devbasex/ai-plugins#622)が同じ形を指している。 受け入れ条件の数字が、意図に反する満たし方を誘発した#192 の D-3( 配布した 並行度を測れず、32 GiB の端末で 1 本に抑えた
中断と 3 層の運用
配布の記録が承認待ちの値のまま残っていたPR #212 の本文の「配布の記録」が 「別途起票する」と書いた宿題が 6 件、番号を持たないまま残っていた振り返りの段 1(起票の取りこぼしを拾う)で、範囲外と判断しながら番号が付いていない項目が
3 件は同じ形で落ちていた。 計画・設計に「別途起票する」「別の課題である」と書きながら 拾えたのは計画ファイルが 同じ束から出た context window の大きさ
束ねの表から外した記録: 1 件(応答が 3 に満たない)
印ごとの判断
次に変えること
途中で起票した課題工程の中で起票したもの(16 件)
振り返りで拾って起票したもの(9 件)
起票しないと明記されたものは対象外である。 PR #231 の「範囲外と判断したもの(起票しない。 起票済みの 25 件はいずれもマイルストーンが未設定で、v3.7.0 由来であることは本文の |
実行計画: v3.7.0(マイルストーン 4 / 8 件)状態: 閉じた 行
release ブランチ: 重なり
測った値
見直し
閉じたときの測定
「最大同時 6」は担当の本数ではない。 起動してよい本数は最後まで 1 で、動いていた担当(supervisor)は常に 1 つだった。この値は Pull Request が同時に open だった数で、検査を終えてレビュー待ちのまま取り込みを待っていた本数を含む。実行計画の「本数に数えるのは 並行度 61.7% も同じ理由で、担当の並行ではない。 1 本ずつ順に通しても、先の束の Pull Request が open のまま残るため重なりは生じる。 閉じたときの記録(進め方)
|
このリリースの狙い
devbase の base コンテナでは、日本語が中国語のフォントで描かれていました。
sans-serifがWenQuanYi Zen Heiへ解決されるため、Chromium / Playwright のスクリーンショット、PDF の生成、画像の生成のすべてが中国語の字形と字幅で写ります。見た目だけの問題ではなく、生成物をそのまま
成果物として出せません。あわせて base には PDF や Office 文書を扱う道具が無く、確認のたびに
利用者がコンテナへ何かを入れる状態でした。
もう 1 つは、文書と確定仕様が約束していることと、実装が食い違ったまま残っていたことです。
devbase scaleだけがdocker composeを共通経路を通さずに呼ぶため、確定仕様が「
COMPOSE_PROFILESは devbase 経由の操作に効かない」と書いている約束がscaleで破れていたDEVBASE_ROOTを継承するため、テストが実環境の設定を読むことがあった[name]と--contextを取るサブコマンドの列挙が、文書の各所で実装より古かったこの版は、この 2 つ ── base イメージの描画と道具立て、約束と実装の食い違い ── を
まとめて解きます。
利用者に操作をお願いする変更(2 点)
1. base イメージは
devbase build base --no-cacheで建て直してくださいフォントの解決とパッケージの追加はイメージの中の変更です。
devbase upだけでは手元は変わりません。
containers/generalなど base から派生したイメージを使っているプロジェクトは、その派生イメージも建て直し、コンテナを作り直してください(
devbase down→devbase up)。devbase rebuildでは建て直りません ──devbase build --expires=7のシノニムのため、期限内はビルドそのものを飛ばします。建て直すまで、手元の描画と道具立ては前の版のままです。
建て直した後は次のようになります。
sans-serif/sans/serif/monospaceと、イメージに無い和文書体名(Meiryo/Yu Gothic/MS PGothic/Noto Sans JPなど)が Noto CJK の JP フェイスへ解決されるCalibri/Cambriaが metric 互換の Carlito / Caladea へ解決される(従来はどちらも中国語フォント)pdftoppm/pdfinfo/pdffonts/pdftocairoと、python3 のPIL/defusedxml/lxmlが使えるArial/Times New Roman/Courier New)は Liberation の metric 互換のまま変わらないlang=zh-cn/lang=koを明示した指定は、その言語の、同じ様式のフェイスのまま~/.config/fontconfig/fonts.conf)で上書きできますイメージは +10.0 MB です。LibreOffice と
pipは入れていません。Python パッケージが要るときは既にある
uv/uvxを使ってください。2.
COMPOSE_PROFILESを端末や.envに置いている方へdevbase scaleが、プロファイルのサービスを起動しなくなります。これは是正です。確定仕様は以前から「
COMPOSE_PROFILESを端末や.envに置いても devbase経由の操作には効かない」と定めており、
scaleだけがその経路を外れて環境変数を素通しにしていました。
up/down/psなど他のサブコマンドは以前からこの約束どおりに動いています。プロファイルのサービスを起動するときは、明示のコマンドを使ってください。
プロファイルを持たないプロジェクトでは、起動の対象の集合は変わりません。
そのほかの変更
devbase plugin install/update/syncとdevbase env importが、projects/に載る名前(衝突時に合成する<名前>.<owner>を含む)を見て、名前を指定した操作ができない形なら警告を 1 行出します。弾きません。 作られる symlink・ディレクトリと終了コードは変わりません
group_aliasesのある置き場で、
devbase env listの見出しと件数、devbase env backend testの参照ごとの行、devbase env backend migrateの計画と完了の一覧がグローバル(グループ default)からグローバル(グループ default → nyle)になります。読み替えの無いグループ・version: 1・ファイル backend の表示と、置き場のパス・サーバへの要求・キャッシュは変わりません
abc\n)を受け付けなくなりました。位置引数のプロジェクト名と同じ規則へ寄せた結果です。それ以外に受け付ける名前とエラーの
文言は変わりません
devbase scaleの内部構造を、devbase upと同じ形(前提の検査 → 段階の実行 → 後処理)へ揃えました。 本番の振る舞いは変えていません
[name]と--contextを取るサブコマンドの列挙を argparse の実際の集合へ揃え(
rebuild/openの漏れ)、プラグインがprofiles:を使うときにrequires.devbaseを">=3.5.0"へ上げる手順を足しました。あわせて、この版で実装が終わった設計の文書を確定仕様(
docs/specifications/)へ取り込み、base イメージの描画の確定仕様を新設しましたDEVBASE_ROOTをテストごとの一時ディレクトリへ隔離します。実環境の
projects/とsecrets/backend.ymlを読む穴を塞ぎました取り消しの手段と、その限界
mainの内容mainへ入れるcontainers/baseでdevbase build base --no-cachemainを戻しても置き換わりません。派生イメージとコンテナの作り直しも各自で要りますdevbase scaleの振る舞いdevbase project profile upは以前からあるコマンドのため、手順を移した人はそのまま使えますTest plan(結合の観点)
個別の振る舞いの確認は繰り返しません。ここで見るのは、束をまたいで同じ系を指すかだけです。
release/v3.7.0の先端でenv -u DEVBASE_ROOT uv run pytest -qが 3022 passed / exit=0(
DEVBASE_ROOTの隔離が入った後も全体が緑であること)uv lock --checkが exit=0、python -m devbase.cli --versionがdevbase 3.7.0--no-cacheで建て直し、変更前後を同じ日に建てて比較。fc-matchの解決先 28 通り、
pdftoppmと python3 のPIL/defusedxml/lxml、soffice/pipが入っていないこと、層の合計で +10.0 MB。派生イメージ(
containers/general)でも同じ解決先devbase up/scale/env backend test/env listが同じ系を指すこと — マージ後のリリース後テストで確かめます
CI はこの Pull Request(base が
main)で初めて全ジョブが動きます。release/v3.7.0を base にした個別の Pull Request では
on.pull_request.branchesがmainだけのため 1 件も動きませんでした(#216)。
関連 Issue
Fixes #161
Fixes #160
Fixes #188
Fixes #192
Fixes #195
Fixes #203
Fixes #208
Fixes #209
開発用の進捗(レビュー対象外)
scaleの Compose の共通経路この版で起票した範囲外の課題: #214 #215 #216 #218 #219 #220 #224 #226 #227 #228 #229 #234 #239
🤖 Generated with Claude Code
https://claude.ai/code/session_011Vu8hNTZKeDeXVLg8hYuK8
配布の記録
段階: 検証(検証のチャネルが無いため、
mainへのマージが本番への配布にあたる。承認待ちのため未実施)版: 3.6.0 → 3.7.0(MINOR: 後方互換のある追加と、確定仕様に合わせた
scaleの是正)まとまり: PR #213 / #217 / #221 / #223 / #225 / #230 / #231 / #232 / #233 / #235 / #237 / #238 / #240 / #241