Skip to content

スプリント m8b - #472

Merged
takemi-ohama merged 23 commits into
mainfrom
sprint/m8b
Oct 12, 2026
Merged

takemi-ohama merged 23 commits into
mainfrom
sprint/m8b

Conversation

@takemi-ohama

@takemi-ohama takemi-ohama commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

スプリント m8b の課題を main へ取り込む。

利用者向けの変化

移行の手順

  • 無し

課題と設計

コミット

変更の統計

 tests/cli/test_zsh_completion_run.py           |  28 +-
 tests/commands/test_container_bao.py           |  67 ++++
 tests/docs/__init__.py                         |   0
 tests/docs/test_openbao_templates.py           | 140 ++++++++
 tests/snapshot/fake_tar.py                     |  20 ++
 tests/snapshot/test_archive_layout.py          |   6 +-
 tests/snapshot/test_auto_snapshot_series.py    |   6 +-
 tests/snapshot/test_backup_real_tar.py         |  73 +++++
 tests/snapshot/test_exclude_generations.py     |   6 +-
 tests/snapshot/test_manager_series.py          |  10 +-
 tests/snapshot/test_manager_volumes.py         |   5 +-
 tests/snapshot/test_pre_restore_backup.py      |   5 +-
 tests/snapshot/test_rebuild_generation.py      | 359 ++++++++++++++++++++
 tests/volume/test_compose_host_gateway.py      | 110 +++++++
 36 files changed, 1818 insertions(+), 90 deletions(-)

テスト(supervise.py の run のステップ)

ステップ exit 最後の行
collect 0

集めた実装の PR

閉じる課題

Closes #295
Closes #453
Closes #458

手動確認

モード: standard / 通した工程: 実装 → Pull Request

🤖 Generated with Claude Code

takemi-ohama and others added 21 commits October 12, 2026 22:58
前の snapshot.snar を引き継がずに full.tar.zst.new・snapshot.snar.new へ控え、
成功したら状態ファイル → 差分(番号の大きい順)→ 印付きの meta.yml → full →
印無しの meta.yml → 状態ファイルの順に入れ替える。印のある世代は restore が消去の
前に止める。テストの docker の差し替えは、書くファイルの名前をコマンドから拾う。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#458 を実装する(スプリント m8b)
…nternal に置き換える (#295)

openbao.url が http の loopback で docker の接続先がローカル扱いのときだけ、dev の
インスタンスの BAO_ADDR のホストを host.docker.internal に置き換え、
host.docker.internal:host-gateway の行を足す。https・リモート扱い・network_mode: host の
dev サービスは今のまま。ホストの devbase が使う URL と検査は変えない。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/user/openbao-server.md に個人・チーム・既存のサーバの 3 つの形と、マウント・AppRole・
ポリシー・entity と alias・ロール・端末の secret_id の発行と失効の手順を書く。
docs/user/openbao/ に version 1 / 2 のポリシーの雛形と、開発モードの試用の構成
(compose.yml) を置く。env-backend.md は管理者から受け取る前提を既存のサーバの形だけにし、
利用者の識別子をサーバの entity 名と同じ値と説明する。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
非公開の運用のリポジトリへの参照と、利用者の識別子を組織の決まりで説明した記述を外す。
devbase がサーバに求める条件(マウント・パス・AppRole・本人とチームの権限・拒否・
version 2 のグループ単位)と雛形の置き場、loopback の接続先の置き換えを書く。目次に
サーバの用意の文書を足す。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
雛形がマウント devbase の data/ と metadata/ の下だけを書き、管理の経路を含まないこと、
個人の雛形が本人の entity に限ること、読み取りの雛形が読むだけであること、version 2 の
雛形が __GROUP__ の置き換えで 1 つのグループを指すこと、試用の構成の版が base の
BAO_VERSION と同じ 2.6 系でポートが loopback だけであることを確かめる。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… サービスを足す (#295)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#295 を実装する(スプリント m8b)
一致テストに、子の parser を持たない末端の道から --context の集合を引いた
NO_CONTEXT_LEAF_PATHS を足し、bash の補完の余分を比べる。zsh は補完の実行テスト
に X1 の行を足し、実際の候補で余分を比べる。親の道は子の分岐を含むため比べない。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#453 を実装する(スプリント m8b)
…SNAP_META_FILE

_load_snap_meta・_save_snap_meta・snapshot_volumes に残っていた 'meta.yml' の直書きを
SNAP_META_FILE に置き換える。META_FILE_TMP と同じ定数から名前を引くようにする。

Item-Id: I-001
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#CONTAINER_HOST_NAME

コンテナからホストを指す名前を volume/compose.py の HOST_GATEWAY_NAME に寄せる。
BAO_ADDR の書き換え先と extra_hosts に足す名前を同じ定数から取る。
container.py は既に devbase.volume.compose に依存しており、依存の向きは変わらない。

Item-Id: I-002
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…al.py#_run_docker_tar

StubManager._run_docker_tar の backup の分岐を fake_tar.write_backup_outputs に寄せ、
コマンドが書く名前のファイルを置く。前準備(backup のコマンドを通らない)の直書きは残す。

Item-Id: I-004
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st_gateway(現状固定テスト)

extra_hosts が解釈できない形(文字列)のときに触らないことを現状固定テストで押さえる。
list / dict / None の場合は既存のテストが押さえている。

Item-Id: I-006
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st_gateway

_extra_host_names の辞書形の判定を _add_host_gateway と同じ isinstance(existing, dict) に揃え、
名前の読み取りと追記で形の分類が食い違わないようにする。extra_hosts は yaml.safe_load の
出力なので、辞書形は常に dict であり振る舞いは変わらない。

Item-Id: I-006
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…napshotManager._replace_snap_meta

メタデータと meta.yml を YAML で書く open と yaml.dump の組をモジュールの _dump_yaml に寄せ、
_save_snap_meta・_replace_snap_meta・_save_metadata から呼ぶ。書式の知識を 1 か所にする。
_replace_snap_meta は仮の名前へ _dump_yaml したあと os.replace する形のまま。

Item-Id: I-007
Impl-Runtime: claude
Impl-Model: claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/devbase #472

/ndf:cross-refactoring が提案し、改修計画し、適用した改善項目の記録である。
理由と手順は提案の時点でしか残らないため、公開の直前に書き出している。

  • 件数: 採用 5・未確認 0・取り消し 1・見送り 1(最終ゲート: passed)
  • 公開: 72e0217 を push した
  • 書き直した時刻: 2026-10-13T00:09:14
  • 対象範囲: CHANGELOG.md, docs/README.md, docs/glossary.md, docs/glossary/glossary.json, docs/specifications/cli-argument-resolution.md, docs/specifications/secret-backend.md, docs/specifications/snapshot-exclude.md, docs/specifications/snapshot-series.md, docs/user/cli-reference/05-snapshot.md, docs/user/env-backend.md, docs/user/openbao-server.md, docs/user/openbao/compose.yml, docs/user/openbao/policies/devbase-user.hcl, docs/user/openbao/policies/v1/team-read.hcl, docs/user/openbao/policies/v1/team-write.hcl, docs/user/openbao/policies/v2/team-read.hcl, docs/user/openbao/policies/v2/team-write.hcl, docs/user/snapshot-guide.md, lib/devbase/commands/container.py, lib/devbase/snapshot/manager.py, lib/devbase/volume/compose.py, tests
  • テストの戦略: local-full(根拠 test.strategy)
  • 範囲テストの雛形: env -u DEVBASE_ROOT uv run --locked pytest -q -o junit_family=xunit1 --junitxml=build/ndf/junit.xml {paths}
  • 着手前のテスト: env -u DEVBASE_ROOT uv run --locked pytest tests/ -q -o junit_family=xunit1 --junitxml=build/ndf/junit.xml(whole)
  • 着手前のテストの結果: 通過(160.6 秒 / HEAD 0eb4af9)
  • 既存失敗の件数: 0
  • 想定最大時間: 30 分 / 改修計画の時点で使えた時間: 8.03 分
  • 実装担当: claude

改善項目

I-001 — lib/devbase/snapshot/manager.py#SNAP_META_FILE

兆候 手法 重要度 等級 提案元 状態 コミット
magic_value introduce_named_constant minor high claude 採用 1

なぜ: PR で SNAP_META_FILE = 'meta.yml' を定義したが、_load_snap_meta・_save_snap_meta・snapshot_volumes(1383 行)は 'meta.yml' の直書きのまま。META_FILE_TMP はこの定数から作るので、本来の名前と仮の名前の対応が直書きの側で崩れ得る

手順: 1. _load_snap_meta・_save_snap_meta・snapshot_volumes の snap_dir / 'meta.yml' を snap_dir / SNAP_META_FILE に置き換える
2. manager.py に他の 'meta.yml' の直書きが残っていないかを grep で確かめる(ログ・メッセージの文言は変えない)
3. tests/snapshot/ を通す

I-002 — lib/devbase/commands/container.py#CONTAINER_HOST_NAME

兆候 手法 重要度 等級 提案元 状態 コミット
duplication consolidate_duplication minor high claude 採用 1

なぜ: コンテナからホストを指す名前 'host.docker.internal' が container.py の CONTAINER_HOST_NAME と volume/compose.py の HOST_GATEWAY_NAME の 2 か所に別の名前で定義されている。BAO_ADDR の書き換え先と extra_hosts に足す名前は一致していないと届かないので、同じ知識を 1 か所に寄せるべき

手順: 1. container.py の CONTAINER_HOST_NAME の定義を消し、from devbase.volume.compose import HOST_GATEWAY_NAME を足す(container.py は既に devbase.volume.compose を使っているので依存の向きは変わらない。import 済みかを確かめ、無ければ足す)
2. container_bao_address の netloc = CONTAINER_HOST_NAME を HOST_GATEWAY_NAME に書き換え、docstring の :data: 参照を直す
3. tests/ で CONTAINER_HOST_NAME を参照している所が無いことを grep で確かめる
4. pytest tests/commands/test_container_bao.py tests/volume/test_compose_host_gateway.py を通す

I-003 — lib/devbase/commands/container.py#container_bao_address

兆候 手法 重要度 等級 提案元 状態 コミット
duplication consolidate_duplication minor high codex 見送り 0

なぜ: container.py の CONTAINER_HOST_NAME と volume/compose.py の HOST_GATEWAY_NAME が同じ host.docker.internal を別々に定義している。URL の置換先と extra_hosts の登録名は必ず一致すべき同じ知識である。

手順: 1. volume/compose.py の HOST_GATEWAY_NAME を正とし、既に同モジュールへ依存する container.py から import する。既存の CONTAINER_HOST_NAME は互換性が必要なら同定数への別名として残す。
2. URL の組み立てと Compose の登録値を変えず、tests/commands/test_container_bao.py と tests/volume/test_compose_host_gateway.py を実行する。期待値の文字列は実装の定数へ置き換えない。

取り消した理由: 実装の終わりまでにコミットが無く、残った時間に入らない

I-004 — tests/snapshot/test_restore_incremental.py#_run_docker_tar

兆候 手法 重要度 等級 提案元 状態 コミット
duplication extract_test_helper minor high claude 採用 1

なぜ: PR で控えのコマンドが書くファイルを置く処理を tests/snapshot/fake_tar.write_backup_outputs に寄せたが、test_restore_incremental.py の差し替え(135-137 行)は 'full.tar.zst' と 'snapshot.snar' を直書きで置いたまま残っている。作り直しで仮の名前へ書く経路をこの差し替えが通ると、コマンドと違うファイルを置いてしまう

手順: 1. test_restore_incremental.py の _run_docker_tar の backup 分岐を write_backup_outputs(snap_dir, command) に置き換え、from .fake_tar import write_backup_outputs を足す
2. 110 行の前準備の直書きは backup のコマンドを通らないためそのまま残す
3. pytest tests/snapshot/test_restore_incremental.py を通す

レビューで確かめるテストの差分: tests/snapshot/test_restore_incremental.py(機械で期待値が変わったか決まらなかった)

I-005 — tests/volume/test_compose_dev_environment.py#generated

兆候 手法 重要度 等級 提案元 状態 コミット
duplication extract_test_helper minor high codex 取り消し 0

なぜ: 生成した .docker-compose.scale.yml の読み込みが、この generated、test_compose_secret_env.py の generated、test_compose.py の _load_scaled に重複する。tests/volume/conftest.py に同じ責務の load_scaled が既にある。

手順: 1. 3 ファイルの生成物読み込みを既存の tests.volume.conftest.load_scaled へ統一する。
2. 重複定義を削除し、呼び出し名と不要になった import だけを整理する。YAML の入力と期待値は維持する。
3. 3 ファイルのテストを実行する。

取り消した理由: テストの期待する振る舞いが変わっています(tests/volume/test_compose.py, tests/volume/test_compose_dev_environment.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください

I-006 — lib/devbase/volume/compose.py#_add_host_gateway

兆候 手法 重要度 等級 提案元 状態 コミット
inconsistent_naming flatten_conditional minor medium claude 採用 2

なぜ: 対になる _extra_host_names は辞書形を Mapping で判定するのに、_add_host_gateway は dict で判定している。Mapping だが dict でない値は名前の読み取りでは辞書として扱われ、追記では『解釈できない形』へ落ちるという判定の食い違いがあり、同じ形の分類が 2 か所に散らばっている

手順: 1. 現状固定として、extra_hosts が list / dict / None / 文字列のときの結果を tests/volume/test_compose_host_gateway.py で押さえていることを確かめる(足りなければ dict 形と未知の形のケースを足す)
2. YAML から読んだ値は dict なので、_extra_host_names 側の判定を isinstance(existing, dict) に揃える(振る舞いは yaml.safe_load の出力に対して不変)
3. pytest tests/volume/ を通す

レビューで確かめるテストの差分: tests/volume/test_compose_host_gateway.py(機械で期待値が変わったか決まらなかった)

I-007 — lib/devbase/snapshot/manager.py#SnapshotManager._replace_snap_meta

兆候 手法 重要度 等級 提案元 状態 コミット
duplication consolidate_duplication minor medium claude 採用 1

なぜ: _replace_snap_meta と _save_snap_meta が同じ yaml.dump(meta, f, default_flow_style=False, allow_unicode=True) を持ち、違いは仮の名前を経由するかだけ。meta.yml の書式の知識が 2 か所(_save_metadata を入れると 3 か所)にある

手順: 1. モジュールに _dump_yaml(path: Path, data: dict) -> None を抽出し、open と yaml.dump の組をそこへ寄せる
2. _save_snap_meta・_replace_snap_meta・_save_metadata の本体をそれを呼ぶ形に書き換える(_replace_snap_meta は _dump_yaml(tmp) のあと os.replace)
3. tests/snapshot/ を通す

指標の測定

  • 状態: written / 言語とツールの対応: 既定(.ndf/code-metrics.json は無い) / 所要: 8.4 秒(使えた時間 90 秒 / 上限 90 秒)
  • 指標のファイル: /var/folders/qz/qxt0p_y15xv5jg4x77zmtxj80000gp/T/ndf-worktrees/devbasex--devbase/rf472/work/.cross_refactoring/code-metrics-rf472.md
言語 ツール 版 ランナー ファイル 秒 結果
python ruff-complexipy ruff 0.16.9 / complexipy 8.0.1 uvx 209 0.9 測った
重複: python symilar pylint 4.0.9 uvx 209 7.0 測った(3 箇所)

時間の上限

値 中身
提案の枠の終わり(監視の上限 = 残り + 余裕) 2026-10-13T00:00:10+09:00
改修計画の枠の終わり(同上) 2026-10-13T00:03:10+09:00
テストの追加の終わり = 実装の終わり − Σ(採っていて未検証の項目の実装の見積り) 2026-10-13T00:00:17+09:00
実装の終わり = 最終ゲートの修正の打ち切り − バッファ − Σ(採っていて未検証の項目の検証の見積り) 2026-10-13T00:04:24+09:00
直しの試行の打ち切り 2026-10-13T00:13:19+09:00
最終ゲートの修正の打ち切り(想定最大時間の終わり) 2026-10-13T00:21:30+09:00
打ち切りの後の取り消し(案 A)の締め切り = 最終ゲートの修正の打ち切り + 0.20·B(工程の 1 つとして起動したとき) 2026-10-13T00:27:30+09:00
最終ゲートの修正の 1 回目に必ず渡す長さ(秒。予備時間の final_fix) 330
指標の測定の上限(秒。提案の枠の中から割く) 90
着手前のテスト 1 回の上限(秒) 393
範囲テスト 1 回の上限(秒) 482
手元の全体テスト 1 回の上限(秒) 393
CI の待ちの上限(秒) 327
余裕(秒。手順の上限と CLI の上限に足す) 90

入力: 予算 30 分 / 全体テストの所要 w 130.8(ndf-record) / 着手前の実測 x 160.6 / CI の壁時計 c 109.0 / 範囲テストの所要 s None(—) / 戦略 local-full

無音の打ち切りは手順の監視の上限と同じ値である。項目ごとの期限は持たない(実装を止めるのは実装の終わりだけ)。

見送った提案

対象 兆候 理由 根拠(MVV) 補足
lib/devbase/volume/compose.py#_apply_dev_environment duplication budget Value 2 見積り 1.1 分が残りに入らない
lib/devbase/commands/container.py#container_bao_address hidden_dependency budget C1 / Vision 見積り 1.2 分が残りに入らない
lib/devbase/commands/container.py#cmd_scale duplication budget Vision / Value 2 見積り 1.5 分が残りに入らない
lib/devbase/snapshot/manager.py#SnapshotManager._apply_rotation_plan duplication budget Value 2 見積り 1.5 分が残りに入らない
lib/devbase/snapshot/manager.py#SnapshotManager._create_full long_method budget Value 2 見積り 1.5 分が残りに入らない
lib/devbase/snapshot/manager.py#SnapshotManager.auto_snapshot_target conditional_chain budget Value 2 見積り 1.4 分が残りに入らない
lib/devbase/volume/compose.py#_drop_missing_env_files inconsistent_naming budget Value 3 見積り 0.9 分が残りに入らない
lib/devbase/volume/compose.py#_build_scaled_services data_clump budget Value 3 見積り 1.3 分が残りに入らない
lib/devbase/commands/container.py#_ensure_env_files long_method budget Value 3 見積り 1.5 分が残りに入らない
lib/devbase/snapshot/manager.py#SnapshotManager._apply_rotation_plan divergent_change budget Value 2 見積り 1.5 分が残りに入らない
lib/devbase/snapshot/manager.py#ensure_snapshot_image long_method budget Value 2 見積り 1.5 分が残りに入らない
tests/cli/zsh_completion_harness.py#run_completions long_method budget Mission 見積り 1.5 分が残りに入らない
tests/containers/test_base_dockerfile_fonts.py#_run_blocks duplication budget Vision 見積り 1.9 分が残りに入らない
lib/devbase/commands/container.py#_should_skip_by_interval hidden_dependency budget Value 2 / Vision 見積り 2.0 分が残りに入らない
lib/devbase/commands/container.py#container_bao_address duplication not_done Value 3 / Vision 実装の終わりまでにコミットが無く、残った時間に入らない

@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 | codex | REQUEST_CHANGES

データ保全と端末のアクセス失効に関する major 3 件の修正を求めます。

差分の外を指す指摘

  • lib/devbase/snapshot/manager.py:1156 [major] [major / データ保全] 控えを入れ替える前に、tar と zstd の両方の成功を確認してください(控えの bash に pipefail を設定するなど)。現在は tar の読み取りエラーでも zstd が成功すればこの入れ替えへ進み、不完全な full で既存の full と差分を消してしまいます。
  • lib/devbase/snapshot/manager.py:599 [major] [major / データ保全] 復元前バックアップは、既存の世代と衝突したら別の一意な名前で作り、既存世代を作り直さないようにしてください。今回の _create_full の変更により同じ秒の控えが上書きされ、復元対象自体がその名前なら展開前に復元元まで現在のボリュームで置き換わります。
  • docs/user/openbao-server.md:366 [major] [major / 認証・認可] 端末を手放す際の失効手順に、その端末へ発行済みの token を accessor で失効させる操作を加えてください。secret_id の破棄だけでは新規ログインしか止まらず、コンテナの ~/.vault-token は期限まで最大 1 時間読み書きできるため、backend test の認証失敗だけでは端末のアクセス停止を確認できません。

@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

PR #472 (0eb4af9..72e0217) は振る舞いを保つ機械的なリファクタリングのみ。SNAP_META_FILE への集約(残存リテラルは定数定義 1 箇所のみ・grep で確認)、CONTAINER_HOST_NAME→HOST_GATEWAY_NAME の統合(値 'host.docker.internal' を保持・残存参照なし)、_dump_yaml 抽出(yaml.dump 引数不変)、_extra_host_names の Mapping→dict(入力は yaml.safe_load の dict なので等価)、テストヘルパ write_backup_outputs の抽出(テスト専用)。利用者経路の誤動作・秘密/認可/データ/不可逆操作への影響・設計文書の食い違いのいずれも確認できず、critical/major の基準に該当する指摘は無い。

- 作り直しの控えのコマンドに PIPESTATUS の検査を足す。tar が読み取りで
  止まっても zstd が成功すると入れ替えへ進み、前の full と差分を消していた
- 端末を手放す手順に、その端末へ発行済みの token を accessor で失効させる
  操作を足す。secret_id の破棄だけでは ~/.vault-token が最大 1 時間使える

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | round 1 | commit cac6b75

対応件数: critical=0 / major=2 / minor=0(合計 2 件)
決着: 2 件 / 見送り: 1 件 / 却下: 0 件
CI: SUCCESS

レビュー本文の指摘への返事:

  • 対応しました。(cac6b75)
  • 対応しました。(cac6b75)
  • 同じ秒の復元前バックアップが既存の世代を作り直す: 見送ります。要ユーザ判断。承認済みの設計 issues/issue-458-design.md の F3 が「同じ秒に重なった復元前バックアップを作り直しとして作る」と決め、テスト test_pre_restore_backup_rebuilds_an_existing_generation もそれを縛っている。一意な別名にするのは設計の変更になるため、修正担当では変えない。復元する世代自身が同じ秒の pre-restore であるときに復元元を失う場面は指摘のとおりで、別名にするか・その場合だけ避けるかを人が決める

@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 | claude | REQUEST_CHANGES

round 1 の修正(作り直しの tar の失敗の検査・発行済み token の失効)を確認した。残りは、失効の確認手順が名前の取り違えでも『確かめた』になる点と、確定仕様が作り直しの控えの失敗に tar の終了コードを含めることを書いていない点の 2 件。

Comment thread docs/user/openbao-server.md Outdated
Comment thread docs/specifications/snapshot-series.md

@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

round 2 の修正コミット cac6b75 を検査した。checked_backup_command は PIPESTATUS[0]=tar / PIPESTATUS[1]=zstd を正しく読み、tar の致命的失敗 (>=2) または zstd 失敗で非ゼロ終了させて _create_full の rebuild と pre-restore の rebuild 経路の両方で入れ替え前に止める形で、設計 issue-458-design.md の決定 1(控え失敗時に前の控えを 1 バイトも変えない)と整合する。fake_tar.py の正規表現を ([^\s;]+) にした変更は、仮の名前の後ろに付く ; を取り込まないために必要で妥当。openbao-server.md の token 失効手順は bao_admin が dev モードの root token で動く(capability 不足なし)、secret_id の metadata (terminal) と role_name は AppRole ログインで token の meta に載る(Vault/OpenBao の文書化済み挙動)ため手順は到達可能で、検証メモ(backend test は新規ログインの停止しか確かめられない)も正確。新しい critical/major の指摘は無い。既存の pre-restore の同一秒の衝突(round 1 の codex が manager.py:599 で指摘し、修正担当が設計 F3 を根拠に人の判断へ回したもの)は本修正で新しい論点を生んでおらず、重複指摘にあたるため挙げない。

- openbao-server: 失効の例を member02 の端末 desktop02 に揃え、失効した accessor を出して
  1 回目に 1 件も当たらない取り違えを見分けられるようにする
- snapshot-series: 作り直しの控えの失敗を tar の 2 以上または zstd の 0 以外で判定する
  (checked_backup_command) と明記し、テストの節に tar の失敗で世代が変わらないことを足す

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | round 2 | commit d313de5

対応件数: critical=0 / major=2 / minor=0(合計 2 件)
決着: 2 件 / 見送り: 0 件 / 却下: 0 件
CI: SUCCESS

@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 | claude | APPROVE

round 2 の修正(d313de5)を確認した。失効の例は u=member02 の端末 desktop02 に揃い、revoke の行の出力で取り違えを見分けられる。確定仕様は作り直しの控えの失敗を checked_backup_command(tar が 2 以上・zstd が 0 以外)で定義し、実装(manager.py:1032)と実の tar のテスト(test_backup_real_tar.py:282)に一致する。新しい critical/major の指摘は無い。

@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

既存指摘を除き、新たな critical / major の修正指摘はありません(判断基準: C1・C2・C3・C4、Value 2・3。機密・認可・データ保全の経路と設計を照合)。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | commit (なし)

対応件数: critical=0 / major=0 / minor=0(合計 0 件)
決着: 0 件 / 見送り: 0 件 / 却下: 0 件
CI: NONE

@takemi-ohama
takemi-ohama marked this pull request as ready for review October 12, 2026 15:35
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

手動確認(マージ前)の記録

2026-10-13、承認ゲート 2 で利用者が「担当の結果で印を付ける」と決めた。

  • OpenBao backend を、利用者が個人・チームで自分のサーバを立てて使う前提の文書と雛形に揃える #295 の受け入れ条件 4・14・15、8・13 は、#295 を実装する(スプリント m8b) #470 の担当が試用の構成(OpenBao 2.6.2、macOS の Docker Desktop)で打った。コマンドと結果の表は #295 を実装する(スプリント m8b) #470 の本文の「手で確かめたこと」にある
  • 受け入れ条件 8・13 の devbase up は、作業用のプロジェクト(グループ personal)で打った。このとき既存のボリューム devbase_home_personal・devbase_home_ubuntu・devbase_work_1 を付けてコンテナを起動しており、行の「実の利用者の環境ではない」を完全には満たしていない。conductor が確かめたところ、動いていた利用者のコンテナは止まっておらず、ホームのボリュームに試用の痕跡(member01・試用のサーバの宛先)は無かった。担当への指示の直し方は振り返りで扱う
  • レビューで持ち越した 1 件(manager.py:599、同じ秒の復元前バックアップが既存の世代を作り直す)は、利用者の判断で設計 F3 のとおり残し、別の課題で起票する

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

リリース後テスト(スプリント m8b、2026-10-13)

対象: main fb8e695(#472 と確定仕様化 #474 の後)。macOS(Docker Desktop)。タグは切っていない。

課題 観点 結果 根拠
#458 既にある世代へ差分を 1 本積み、同じ名前へ full をもう 1 回作ると、世代は full.tar.zst・meta.yml・snapshot.snar だけになる 合格 作り直しの前は incr-001.tar.zst・snapshot.snar.bak を持ち、後は 3 ファイルだけ。INFO「世代 rv を今のボリュームの全体で作り直しました(前の差分 1 本を除きました)」。snapshot.yml は 1 件のまま、created_at 不変、incremental_count: 0
#458 作り直した世代の復元で、作り直した時点に戻る 合格 復元前 B C D → 復元後 A B C。pre-restore-* が 1 つ作られた
#458 rebuilding: true の世代の復元は、復元前バックアップとボリュームの消去の前に止まる 合格 SnapshotError(作り直しを案内)。新しい世代なし、ボリュームの中身はそのまま
#458 Linux でコンテナが root で書いた仮のファイルを改名できる 保留 Linux の端末が無い
#295 既存のサーバの形(https・version 2・グループのレイアウト)が変わらない 合格 実のサーバへ devbase env backend status と devbase env backend test --group team-a が rc=0。チームと個人の置き場を読めた
#295 loopback の http だけをコンテナから見た接続先へ置き換える 合格 container_bao_address: http://127.0.0.1:8200・http://localhost:8200 → http://host.docker.internal:8200、https・非 loopback・リモート扱いは置き換えない
#295 Linux の Docker で host-gateway を通して手元のサーバへ届く 保留 Linux の端末が無い
#453 末端の道(env set)へ --context を足すと bash・zsh の一致テストが落ちる 合格 一時のコピーで 2 failed、戻すと 35 passed
共通 固有の語の検査 合格(CI) 手元は語の一覧が無く飛ばした。#474 の CI の Proper term check は passed

#458 は作業用のボリューム(数 MB)と一時のルートで、実の devbase-snapshot イメージを使って試した。対象ボリュームの名前をプロセスの中だけ作業用に差し替え、利用者のボリューム・backups/・snapshot.yml には触れていない。作業用のボリュームは消した。

#295 の実のサーバへの接続は、ホストの Netskope の TLS 傍受のため CA バンドルと Python 3.12 の環境を付けて打った(従来どおり。#295 の変更とは関係しない)。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

振り返り(2026-10-13)

対象: スプリント m8b — issue #458・#295・#453 / PR #472(確定仕様化 #474)

既にある世代へ full を作るときの「世代の作り直し」(#458)、OpenBao を利用者が自分で立てる前提の文書・ポリシーの雛形・loopback のサーバへコンテナから届く接続先の置き換え(#295)、補完の --context の余分を比べる一致テスト(#453)を入れた。mode は standard。設計 PR は #467(#458)・#468(#295)の 2 本。

何が起きたか

観点 事実
受け入れ条件 途中で変えた条件は無い。#453 は設計を持たず、#435 の決定 5 を元に受け入れ条件の節を本文へ足してから入れた
手戻り 構造改善の採用 5。レビュー 3 ラウンド、指摘 5・修正 4・持ち越し 1(manager.py:599 の同じ秒の復元前バックアップが既存の世代を作り直す。承認済みの設計 F3 と食い違うため利用者の判断で残し #473 を起票)
見落とし リリース後テストは 9 観点中 7 合格・2 保留(どちらも Linux の端末が要る: #458 の root が書いた仮のファイルの改名、#295 の host-gateway での到達)。マージ前に踏めなかった経路で失敗したものは無い
範囲 #458 の担当は、課題の本文の壊れ方(full.tar.zst が差分で上書きされる)と実際(zstd が上書きを拒み snapshot.snar だけ進む)の違いを報告。直す向きは変わらず範囲も変えていない
工程 飛ばした工程は無い。#470 の担当が受け入れ条件の手動確認として作業用のプロジェクトで devbase up を打ち、共通のホーム・グループのホーム・作業ボリュームの実物を付けたコンテナを立てた(P3 に近い。利用者のコンテナは止まらず、ホームに痕跡は無かった)。担当は非対話で P3 を聞けない
本文の取りこぼし 3 本の実装プランの pr ステップに下書きの append を足した(ai-plugins#1742 の利用側の回避)。3 本とも担当の下書きが PR 本文に載った。直前の m8a(#461)では回避なしで取りこぼした
確定仕様化 3 本とも実装の PR が仕様書を先に書いており、確定仕様化は設計の決定の理由・常に成り立つ条件・テスト観点の補いが中心だった

context window の大きさ

conductor 2 セッション(m8b の開始〜スプリント PR のマージ、仕上げ)。プランの worker(claude -p)は含まない。

層 フェーズ モデル 件数 固定費の中央値 実作業の中央値 実作業 < 固定費 最大充填の最大 目印
conductor - claude-opus-5-5 2 65505 96989 0 184162
supervisor その他 claude-opus-5-5 4 30765 64902 1 144508
層 件数 固定費の合計 実作業の合計 総消費
conductor 2 131010 193978 324988
supervisor 4 123132 268285 391417
合計 6 254142 462263 716405

目印の付いた行は無い。そのままにする。

用語集の変化

コンテキスト 足した語 廃止した語 意味を変えた語
snapshot 世代の作り直し — —
secret 利用の形・ポリシーの雛形・試用の構成・利用者の識別子・コンテナから見た接続先・管理する人 — —

承認ゲートの差し戻し

関門 1: 0 件、関門 2: 0 件。

MVV を見直すか

版 1。覆し 0(閾値 3)・判定できない 0(閾値 5)・流出不具合 0(閾値 3)。利用者の答え: 改訂しない。#470 の件は P3 の定義ではなく、担当に up を禁じる運用の取り決め(AGENTS.md)で受ける。

次に変えること

変えること 落とし先 状態
実装のプロンプトで担当に devbase up を禁じ、up の確認は conductor が P3 の承認を取って打つか、up を使わない確かめ方へ置き換える AGENTS.md の落とし穴 #475 で反映済み
実装プランの pr ステップに下書きの append を入れる回避を続ける。テンプレートの既定へ入れるよう上流へ実績を伝えた 次の変更で試すこと(上流) ai-plugins#1742 にコメント

途中で起票した課題

番号 何を見つけたか 見つけた場面
#466 差分の作成が失敗すると snapshot.snar が進んだまま残る 設計中(#458)
#473 復元前バックアップが同じ秒の既存の世代と重なると、その世代を作り直す レビュー中(持ち越し)

取りこぼしの検索(起点 #458 #295 #453・PR #469〜#472、上流を含む)で、番号の無い範囲外の項目は見つからなかった。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment