feat(PLAN66): 名前の形に合わないプロジェクトを、作られた時点で知らせる (#203) - #233
Conversation
Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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>
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>
Refs #203 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…liases 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
改修計画 — devbasex/devbase #233
ラウンド 1(実装 codex / レビュー agy / kiro)R1-001 —
|
| 兆候・経路 | 手法・階層 | 重要度 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|
| branch | unit | — | agy | 検証中 | 1 |
なぜ: PR #233 で追加された公開関数 project_name_of はバンドル内メンバー名からプロジェクト名を抽出するが、プロジェクト名に合致するメンバーと、それ以外のメンバー(グローバル設定、メタデータ、不正なパス)で None を返す分岐の単体テストが存在しない。
手順: 1. 'env/projects/web/.env' や 'env/projects/_foo/.env' を渡し、プロジェクト名文字列 ('web', '_foo') が正しく抽出されることを確認する
2. 'env/global.env' や 'env/sources.yml' などの全体設定メンバー名を渡し、None が返されることを確認する
3. パス階層の異なる形式外パスを渡し、例外を送出せず None が返されることを確認する
R1-002 — lib/devbase/env/io_import.py#import_bundle
| 兆候・経路 | 手法・階層 | 重要度 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|
| branch | integration | — | agy | 検証中 | 1 |
なぜ: _warn_unusable_project_names の保存先別案内において、ファイル backend 平文(projects/ 作成)と age backend(secrets/projects/ 作成)は固定されているが、サーバ backend(OpenBao)への import で形に合わないプロジェクト名を取り込む経路(plan.ref is not None)の警告文(サーバの...)および取り込み完了の振る舞いが未固定である。
手順: 1. OpenBao の fixture (openbao_root, openbao, bundle_keys) を用いて、形に合わないプロジェクト名 ('env/projects/_foo/.env') を含む暗号化バンドルを作成する
2. import_bundle を実行し、戻り値が 0 であることを確認する
3. projects/_foo ディレクトリが作成されず、サーバ (OpenBao) 側に機密が正常に保存されていることを確認する
4. caplog に形に合わないプロジェクト名に対する警告が 1 行記録され、保存先としてサーバのラベルが含まれ、'projects/ には何も作られません' が案内されていることを確認する
R1-003 — lib/devbase/plugin/syncer.py#sync_projects
| 兆候・経路 | 手法・階層 | 重要度 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|
| normal | unit | — | agy | 検証中 | 1 |
なぜ: TestSyncProjectsNameForm では別名の owner または base が不正で警告が出るケースは固定されているが、プラグイン競合による別名 symlink 生成において、base と owner の双方が名前の形に合致する場合に警告が出ずに正常にリンクが作成される正常系経路が固定されていない。
手順: 1. 優先度の異なる 2 つのプラグインで同一プロジェクト名を定義し、双方のプロジェクト名および loser 側の owner 名が名前の形に合致するよう設定する
2. sync_projects(registry, verbose=False) を実行し、戻り値が 2 であることを確認する
3. winner の symlink と loser の別名 symlink が正常に作成されていることを確認する
4. caplog に名前の形に関する警告が 1 行も出力されていないことを確認する
見送った項目
(なし)
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | kiro | REQUEST_CHANGES
syncer.py:202 の real_projects 経路が . 始まりの実ディレクトリを除外しないため、projects/.vscode などの隠しディレクトリで毎回の同期に不要な警告が出ます。仕様の決定8(. 始まりは同期対象外・知らせも出さない)と CHANGELOG/spec の記述に反するので、実ディレクトリ列挙にも dot 除外を入れてください。詳細はインラインを参照。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | agy | APPROVE
PLAN66 実装1本目の要件(同期・import時の名前警告、弾かずに通知、出所に応じた案内)および確定仕様・CHANGELOGとの整合性が確認され、修正アクションを要する問題はありません。
sync_projects の実ディレクトリの知らせが .vscode などにも出ていた。 決定 8 のとおり . 始まりはプロジェクトとして扱わず、知らせも出さない。 回帰テスト test_dot_real_directories_are_not_warned を追加。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/ndf:fix サマリ (round 1)対応件数: critical=0 / major=1 / minor=0 (合計 1 件) 詳細
|
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | codex | APPROVE
新たな修正指摘はありません(関連テスト 107 件成功)。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | kiro | APPROVE
PLAN66 の「知らせだけ出し弾かない」方針に沿った追加変更で、sync_projects(実ディレクトリ / winner / 別名)と import_bundle(平文・age・サーバ backend)の各経路が保存先ごとに正しく文面を分岐している。終了コード・生成される symlink / ディレクトリは不変で、. 始まりの除外も維持されている。別名の owner 抽出 (name[len(base)+1:]) と保存先判定 (plan.ref is None かつ plan.target == projects/<name>/.env) の分岐も、age が plan.ref is None かつ plan.target が .age パスになる点と整合しており正しい。ラウンド1で提案された 3 件(project_name_of の単体、OpenBao 取り込み、正常系別名リンク)はいずれも本 PR のテストで固定済み。tests/plugin tests/env tests/cli 全 1681 件がグリーン。修正を要する点は見当たらない。
Pull Request
概要
名前の形(
bin/devbaseが受け付ける形)に合わない名前がprojects/に載る時点で、警告を 1 行出して知らせる。弾かずに警告に留める(設計の決定 1)。
plugin install/update/syncとenv importの終了コードと、作られる symlink・ディレクトリは変えない。設計文書
issues/PLAN66_project-name-validation-design.mdの「実装の分け方」の 1 本目(知らせ。F1・F2)である。2 本目(スナップショットの名前の検証を
utils/namesの述語へ寄せる。F3・決定 5・6)はこの Pull Request のマージ後に別に出す。計画は
issues/PLAN66_project-name-validation-impl1.md。release/v3.7.0)関連 Issue
変更点
docs(PLAN66): 実装 1 本目の計画を置いたfeat(PLAN66)(同期・F1):utils/names.NAME_FORM_HINT(名前の形の説明文。ログは出さない。決定 7)とsyncer._warn_unusable_name(name, source, base=None)を足した。呼ぶのは 3 か所だけ(決定 2)sync_projects:real_projectsを採取した直後にsorted(real_projects)の名前ごと / winner の symlink を張る直前(実ディレクトリのスキップより後)_link_loser_projects: 別名の symlink を張る直前(元のプロジェクト名をbaseに渡す)<owner>の側が原因 / 実ディレクトリ)。verboseに依存させないdiscover_projects(.始まりの除外を含む。決定 8)・_collect_project_candidates・戻り値は変えていないfeat(PLAN66)(import・F2):_import_merge.project_name_of(arcname)を足し、import_bundleが_build_plansの直後・--dry-runの判定より前にplansを回して知らせる。平文のprojects/<name>/.env(plan.ref is Noneかつplan.targetがそのパス)なら「この import がprojects/<name>/を作る」と改名の案内、それ以外(age・サーバ backend)は保存先を名指しして
projects/には何も作られないことを書き、改名の案内は出さない(決定 4)。_PROJECT_ENV_RE・env/bundle.py・env/secret_store.pyは触っていないdocs(PLAN66): 確定仕様docs/specifications/cli-argument-resolution.mdの「運用」の 1 つ目の箇条書きだけを書き換え(2 つ目は 2 本目)、CHANGELOG.mdの[Unreleased]に Added を足した(Changed は 2 本目)Test(構造改善のテスト追加ラウンド): cross-refactoring が現状固定のテストを 3 ファイルへ足した(570a2fe。プロジェクト名の取り出し・サーバ backend の import・同期の別名。追加のみ)。コミットメッセージが英語なのはボットの既定のためで、履歴は書き換えていないfix(PLAN66)(実装レビュー round 1 の指摘):sync_projectsの実ディレクトリの知らせがprojects/.vscodeなど.始まりのディレクトリにも出ていた。決定 8 のとおり.始まりは知らせの対象から外した(real_projectsの集合と「実ディレクトリならスキップ」の判定は変えていない)。回帰テストtest_dot_real_directories_are_not_warnedを追加(7687bfb)下流の検証(
bin/devbase・cli.py・commands/container.py)は変えていない(決定 3)。受け付ける名前を狭める変更は含まない。補足: 設計の「実装の分け方」はテストのファイルを 3 つ(
tests/plugin/test_repos_core.py・tests/env/test_io_import.py・tests/cli/test_env_bundle_backend.py)挙げており、そのとおりに 3 つへ足した。既存のテストは 1 行も変えていない(差分は 3 ファイルとも追加のみ。構造改善と実装レビューで足した分も追加のみ)。テスト駆動の証跡: 新しいテストを先に書き、変更前の実装で期待どおりの理由で落ちることを確かめてから実装した
(同期:
TestSyncProjectsNameForm6 件のうち警告を期待する 4 件がassert 0 == 1/assert 0 == 2(警告が 0 件)。条件 2・5 の 2 件は「警告が出ない」ことの固定のため変更前から緑。import: 条件 6・7・9 の 3 件が
assert 0 == 1、条件 8 は変更前から緑)。構造改善(打ち切り)
構造改善(
/ndf:cross-refactoring)は 利用者の判断で途中で打ち切った(2026-09-23)。テスト追加のラウンド(570a2fe)までで終え、提案ラウンド 2 の途中で止めた。構造の変更は入れていない。570a2feの時点の全体テストは2921 passed、exit=0 で確かめた。実装レビュー
/ndf:cross-review 233で 2 ラウンド、approvedで収束した。.始まりの実ディレクトリにも知らせが出る)7687bfb(1 件修正)最終スイープ: 未解決の指摘 0 件(GitHub 側で確認)。deferred / rejected 0 件。
Test plan
release/v3.7.0を base にした Pull Request では CI が動かない(#216)。以下はすべて手元(作業ツリー、macOS)で実行した。実環境のプラグイン・
projects/に対してplugin install/update/syncとenv importは実行していない。uv run --locked pytest tests/ -q(ff48e8e+ 空コミット)→2900 passed、exit=0uv run --locked pytest tests/plugin/test_repos_core.py -q→60 passed(新設TestSyncProjectsNameForm6 件。既存のTestSyncProjects7 件は無変更で通過=条件 15)uv run --locked pytest tests/env/ tests/cli/test_env_bundle_backend.py -q→661 passed(新設 4 件。既存のtest_io_import.py・test_import_merge.py・test_store_roundtrip.py・test_env_bundle_backend.pyは無変更で通過=条件 16)uv run --locked pytest tests/ -q(788d727)→2910 passed、exit=0(新設 10 件。失敗 0)— 条件 17DEVBASE_ROOTとHOME)でpython -m devbase.cli env import <_foo を含む書庫> --no-global→ 標準エラーにWarning: プロジェクト名として使えない形の名前を取り込みます: '_foo'(出所: 書庫)。この import が projects/_foo/ を作ります。…が 1 行、projects/_foo/.envが作られ exit=0uv run --locked pytest tests/ -q(570a2fe)→2921 passed、exit=07687bfb、2026-09-23 00:43):uv run --locked pytest tests/plugin/test_repos_core.py tests/env/ tests/cli/test_env_bundle_backend.py -q→733 passed、exit=07687bfb、2026-09-23 00:43〜00:46):uv run --locked pytest tests/ -q→2922 passed、exit=0uv run --locked python -m compileall -q lib→ exit=0 /uvx ruff check --select=E9,F63,F7,F82 lib→All checks passed!、exit=07687bfb)でenv import <_foo と ok-name を含む書庫> --no-global→_fooだけに警告 1 行、projects/_foo/.env・projects/ok-name/.envが作られ exit=07687bfb)でprojects/.vscodeとprojects/_barを置いてplugin sync→_bar(と前項の_foo)の実ディレクトリの警告だけが出て.vscodeには出ない、exit=0🤖 Generated with Claude Code