chore: trim dead code, modularize CLI, and archive stale docs
Extract review-plan, report, quarantine, state, and config handlers into commands/ with shared cli_helpers; remove unused exceptions and duplicate plan summary wrappers. Archive superseded review markdown, sync docs to 517-test baseline, and fix empty series titles when only a quality tag remains. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
Cursor
parent
5f0b531269
commit
79797644e1
@@ -99,7 +99,7 @@ def test_review_plan_generates_csv_summary_and_preview(tmp_path):
|
||||
assert "Plan overview:" in result.output
|
||||
assert "这是测试计划摘要" in result.output
|
||||
assert "Plan review summary:" in result.output
|
||||
assert "High-risk operations: 2" in result.output
|
||||
assert "High-risk operations: 1" in result.output
|
||||
assert "High-risk operations preview:" in result.output
|
||||
assert "source:" in result.output
|
||||
assert "destination:" in result.output
|
||||
@@ -294,7 +294,7 @@ def test_review_plan_tui_stubbed_success(tmp_path, monkeypatch):
|
||||
summary={"total": 1, "move": 1, "rename": 0, "quarantine": 0, "no-op": 0},
|
||||
)
|
||||
|
||||
monkeypatch.setattr("vlm.cli._review_plan_tui_streams_ok", lambda: True)
|
||||
monkeypatch.setattr("vlm.commands.review_plan.review_plan_tui_streams_ok", lambda: True)
|
||||
monkeypatch.setattr("vlm.review_tui.run_plan_review_tui", lambda ctx: 0)
|
||||
|
||||
output_csv = tmp_path / "review.csv"
|
||||
@@ -332,7 +332,7 @@ def test_review_plan_tui_stubbed_abort(tmp_path, monkeypatch):
|
||||
summary={"total": 1, "move": 1, "rename": 0, "quarantine": 0, "no-op": 0},
|
||||
)
|
||||
|
||||
monkeypatch.setattr("vlm.cli._review_plan_tui_streams_ok", lambda: True)
|
||||
monkeypatch.setattr("vlm.commands.review_plan.review_plan_tui_streams_ok", lambda: True)
|
||||
monkeypatch.setattr("vlm.review_tui.run_plan_review_tui", lambda ctx: 1)
|
||||
|
||||
output_csv = tmp_path / "review.csv"
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
"""Tests for plan review helpers."""
|
||||
|
||||
import json
|
||||
import csv
|
||||
from pathlib import Path
|
||||
|
||||
from vlm.models import ExecutionPlan, FileOperation
|
||||
from vlm.plan_review import (
|
||||
REVIEW_APPLIED_AT_KEY,
|
||||
build_duplicate_path_maps,
|
||||
build_identity_lookup,
|
||||
check_review_requirements,
|
||||
enrich_review_rows,
|
||||
normalized_path_key,
|
||||
prepare_review_rows,
|
||||
review_plan,
|
||||
save_review_csv,
|
||||
)
|
||||
from vlm.plan_render import render_review_verdict
|
||||
from vlm.plan_structure_preview import build_structure_preview_lines
|
||||
from vlm.planner import load_plan, save_plan
|
||||
from vlm.planner import apply_review_to_plan, load_plan, save_plan
|
||||
from vlm.utils import utc_now
|
||||
|
||||
|
||||
@@ -78,7 +82,7 @@ def test_build_identity_lookup_and_enrich(tmp_path):
|
||||
def test_check_review_requirements_missing_csv(tmp_path):
|
||||
plan_path = tmp_path / "plan.json"
|
||||
op = FileOperation(
|
||||
operation_type="no-op",
|
||||
operation_type="quarantine",
|
||||
source_path=tmp_path / "Series.S20E01.mkv",
|
||||
destination_path=None,
|
||||
reason="Series needs manual review (season exceeds configured threshold)",
|
||||
@@ -92,6 +96,95 @@ def test_check_review_requirements_missing_csv(tmp_path):
|
||||
assert "not found" in errors[0]
|
||||
|
||||
|
||||
def test_check_review_requirements_requires_apply_review(tmp_path):
|
||||
plan_path = tmp_path / "plan.json"
|
||||
csv_path = tmp_path / "plan_manual_review.csv"
|
||||
op = FileOperation(
|
||||
operation_type="move",
|
||||
source_path=tmp_path / "a.mkv",
|
||||
destination_path=tmp_path / "lib/a.mkv",
|
||||
reason="Series needs manual review (season exceeds configured threshold)",
|
||||
has_conflict=True,
|
||||
)
|
||||
plan = _minimal_plan([op])
|
||||
save_plan(plan, plan_path)
|
||||
rows, _ = review_plan(plan)
|
||||
save_review_csv(rows, csv_path)
|
||||
|
||||
errors = check_review_requirements(load_plan(plan_path), plan_path, csv_path)
|
||||
assert len(errors) == 1
|
||||
assert "apply-review" in errors[0]
|
||||
|
||||
|
||||
def test_check_review_requirements_passes_after_apply_review(tmp_path):
|
||||
plan_path = tmp_path / "plan.json"
|
||||
csv_path = tmp_path / "plan_manual_review.csv"
|
||||
op = FileOperation(
|
||||
operation_type="move",
|
||||
source_path=tmp_path / "a.mkv",
|
||||
destination_path=tmp_path / "lib/a.mkv",
|
||||
reason="Series needs manual review (season exceeds configured threshold)",
|
||||
has_conflict=True,
|
||||
)
|
||||
plan = _minimal_plan([op])
|
||||
save_plan(plan, plan_path)
|
||||
rows, _ = review_plan(plan)
|
||||
for row in rows:
|
||||
row["operation_type"] = "no-op"
|
||||
save_review_csv(rows, csv_path)
|
||||
|
||||
updated = apply_review_to_plan(load_plan(plan_path), csv_path)
|
||||
save_plan(updated, plan_path)
|
||||
|
||||
errors = check_review_requirements(load_plan(plan_path), plan_path, csv_path)
|
||||
assert errors == []
|
||||
|
||||
|
||||
def test_planner_noop_manual_review_does_not_block_execute_gate(tmp_path):
|
||||
plan_path = tmp_path / "plan.json"
|
||||
op = FileOperation(
|
||||
operation_type="no-op",
|
||||
source_path=tmp_path / "Series.S20E01.mkv",
|
||||
destination_path=None,
|
||||
reason="Series needs manual review (season exceeds configured threshold)",
|
||||
has_conflict=False,
|
||||
)
|
||||
plan = _minimal_plan([op])
|
||||
save_plan(plan, plan_path)
|
||||
errors = check_review_requirements(load_plan(plan_path), plan_path, tmp_path / "missing.csv")
|
||||
assert errors == []
|
||||
|
||||
|
||||
def test_review_plan_skips_applied_noop_reason(tmp_path):
|
||||
op = FileOperation(
|
||||
operation_type="no-op",
|
||||
source_path=tmp_path / "a.mkv",
|
||||
destination_path=None,
|
||||
reason="Modified via manual review: Series needs manual review (season exceeds configured threshold)",
|
||||
has_conflict=False,
|
||||
)
|
||||
rows, counters = review_plan(_minimal_plan([op]))
|
||||
assert rows == []
|
||||
assert counters["high_risk_operations"] == 0
|
||||
|
||||
|
||||
def test_build_duplicate_path_maps_uses_canonical_keys(tmp_path):
|
||||
raw = str(tmp_path / "movie.mkv")
|
||||
analysis = {
|
||||
"duplicates": [
|
||||
{
|
||||
"identity": {"type": "movie", "title": "X", "year": 2020},
|
||||
"files": [raw],
|
||||
"quality_comparison": [{"path": raw, "resolution": "1080p"}],
|
||||
}
|
||||
]
|
||||
}
|
||||
path_to_group, path_to_quality = build_duplicate_path_maps(analysis)
|
||||
key = normalized_path_key(raw)
|
||||
assert path_to_group[key] == "movie:X:2020"
|
||||
assert path_to_quality[key]["resolution"] == "1080p"
|
||||
|
||||
|
||||
def test_structure_preview_lines(tmp_path):
|
||||
lib = tmp_path / "library"
|
||||
op = FileOperation(
|
||||
|
||||
Reference in New Issue
Block a user