feat(cli): import に --dry-run / --yes / --report を追加する(B6) - #39
Merged
Conversation
設計は docs/dev/designs/import-dry-run-and-ai-guide.md。AI 変換ガイドは別 PR。 - **--dry-run**: トランザクション内で実際に取り込んでからロールバックする。 サービス層は flush しかせず CLI が commit を持っているので、commit を飛ばす だけで成立する。事前推定は採らない(削除範囲はヘッダの列構成と有効行数で 決まるため、推定は取り込み処理の二重実装になる) - **確認ガード**: commit ゲートで判定する。破壊的変更は削除件数ではなく正味の 損失で数える。(a) 削除され再作成されない関連(`(type, origin, destination)` で比較。並び替えや親の変更は同じ組が再作成されるので発火しない)、(b) 他 ドキュメントからのリソース移動。ドキュメント単位の再構築は毎回全削除して 再作成するため、削除件数で数えると毎回発火して形骸化する - **非対話環境**では、--yes が無ければロールバックして exit 1。ハングも、 黙って先に進むことも防ぐ - **--report**: 実行結果を JSON で書き出す。issue に code を付け、required 欠落(C3 の運用側)を機械可読にする。分類されなかった警告も含めるので、 ファイルが実行結果の欠落した写しにならない 設計からの逸脱が1点ある。設計は `warnings` を property 化して全 85 箇所を `warn()` に置換するとしていたが、`issues` を併存させる形にした。property が 返すリストへの append は黙って捨てられるため、`warnings: list[str]` を引数で 引き回すパーサ群と併せて事故になりやすい。外部契約(code 付きの構造化 JSON) は同じで、分類は必要な箇所から段階的に増やせる。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
レビュー指摘の反映。must-fix 3件はいずれも実測で再現していた。 **M1: xlsx の往復インポートが毎回ガードに掛かっていた。** 生成する custom CSV のヘッダは関連列を全て含むため Step 7.5 が該当タイプを全削除するが、CSV 段では 1件も再作成しない。再作成は xlsx の第2パスが行うので、import_csv の末尾で数える と全件が lost になる。削除・作成のタプル集合をレポートに持たせ、第2パスの作成 分を足してから確定する形にした。設計が避けたかった「毎回発火して形骸化する」 状態そのものだった。 **M2: 確認プロンプトが Rich のスピナーに消されていた。** `console.status` の 内側で `click.prompt` を呼ぶと、書かれた質問が次のリフレッシュで消える。利用者 には「警告だけ出て固まったスピナー」しか見えない。ガードの中心が対話確認である 以上、機能していないに等しかった。commit ゲートをスピナーの外に出した。実端末 (pty)でプロンプトとサンプル一覧が見えることを確認した。 **M3: ドキュメント4箇所が事実と逆だった。** 「親の変更はガードに掛からない」と 書いていたが、旧親との関連は実際に消えるので掛かる(設計どおりの、安全側に 倒した過剰検知)。掛からないのは並び替えのみ。 should も反映した。 - レポートに `reportVersion` / `applied` / `cancelled` を追加。ガード拒否時も レポートは書かれるので、これが無いと成功した run と区別できない - `destructive` を設計どおりの形に戻し、`itemsMoved` と `associationsMoved` を 分けた(項目を奪われるのと関連が付け替わるのは判断材料として別物) - `ValidationIssue` に `severity` を追加 - C3 の `required_field_missing` が新規作成時にしか付いていなかった。既存 ドキュメントへの再インポートは CASE import の主経路なので更新側にも付けた - `--report` の書き込み可能性を事前に確認する。`click.Path(writable=True)` は 存在しないパスを検査しないため、大きなフレームワークを丸ごと走らせてから トレースバックで落ちていた テストの穴も埋めた。CliRunner は tty を持たないため対話分岐が1行も通って おらず、xlsx / 親変更のテストも無かった(M1 と M3 はここで漏れた)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
インポートに
--dry-run/--yes/--reportを追加した(バックログ B6 のコード部分。AI 変換ガイドは別 PR)。4つの import コマンド(csv / xlsx / case / rubric)すべてが対象。--dry-run--yes--report <path>破壊的変更は「正味の損失」で数える
ドキュメント単位の再構築は更新のたびに該当タイプの関連を全削除して再作成する。削除件数で判定すると毎回発火し、運用者はプロンプトを読まなくなる。
数えるのは2つ。
(associationType, origin, destination)で比較)。並び替えは同じ組を再作成するので発火しない。親の変更は発火する(旧親との関連は実際に消える。安全側に倒した意図的な過剰検知)判定は commit ゲート(サービス実行後・同一トランザクション内)で行う。事前推定は採らない。削除範囲はヘッダの列構成と有効行数で決まるので、推定は取り込み処理の二重実装になる。
非対話環境(
stdinが tty でない)で--yesが無い場合、ロールバックして exit 1 する。 CI やスクリプトが黙って先に進むことと、プロンプト待ちでハングすることの両方を防ぐためである。compeito-aws には予告済み。Admin API とスクリプトに
--yesを通す作業が要る。C3 との関係
--reportのissuesには code が付く。required_field_missing(公式スキーマが required とするフィールドが元データで空)は、strict 出力で残るギャップ(conformance backlog C3)を運用で閉じるための入口である。compeito は出力側で値を捏造しないので、生成側が何を直すべきかを知る経路がこれしかない。設計から意図的に外した点
設計は
warningsを property 化し、85 箇所のwarnings.appendをwarn()に置換するとしていた。採らなかった。 property が返すリストへのappendは黙って捨てられ、warnings: list[str]を引数で引き回すパーサが多数ある。issuesを併存させる形にし、外部契約(code 付き JSON)は設計どおりにした。レビュー
Claude Opus 5 で2ラウンド。must-fix 3件はいずれも実測で再現されたもの。
テストの穴も埋めた。CliRunner は tty を持たないため対話分岐が1行も通っておらず、xlsx と親変更のテストも無かった(上記2件はここで漏れた)。
Test plan
uv run pytest(905 passed / ローカル)uv run ruff check ./uv run ruff format --check .cancelled)🤖 Generated with Claude Code