Update analysis and plan files to enhance duplicate handling and reporting

- Updated `analysis.json` with a new generation timestamp.
- Modified `plan.json` to include a new plan ID and created timestamp, and changed operation types from "no-op" to "quarantine" for specific files needing manual review.
- Enhanced the README.md to document the new `--analysis` option for generating execution plans, which now includes a human-readable summary and duplicate handling strategies.
- Introduced a new `duplicate_resolve.py` module to manage duplicate file resolution strategies.
- Improved the execution engine to support quarantine operations and added rollback functionality for quarantined files.

These changes improve the functionality of the Video Library Manager by providing better duplicate management and clearer reporting capabilities.
This commit is contained in:
windyboy
2026-02-10 18:07:38 +08:00
parent dcd87754cf
commit 79f5ddf1f5
14 changed files with 882 additions and 456 deletions
+14
View File
@@ -47,6 +47,9 @@ class Config:
reputation_policy: str = "flag_for_review"
naming_title_format: str = "{title_zh} {title_en}"
# Plan settings (e.g. duplicate handling when consuming analysis)
duplicate_keep: str = "by_reputation"
def load_config(path: Path) -> Config:
"""Load configuration from YAML file."""
@@ -86,6 +89,9 @@ def load_config(path: Path) -> Config:
"anime": ["anime"]
})
plan = data.get("plan", {})
duplicate_keep = plan.get("duplicate_keep", "by_reputation")
enrichment = data.get("enrichment")
if enrichment is None:
enrichment = data.get("enrich", {})
@@ -126,6 +132,7 @@ def load_config(path: Path) -> Config:
reputation_low_score_threshold=reputation.get("low_score_threshold", 6.0),
reputation_policy=reputation.get("policy", "flag_for_review"),
naming_title_format=naming.get("title_format", "{title_zh} {title_en}"),
duplicate_keep=duplicate_keep,
)
@@ -168,9 +175,12 @@ def create_default_config(path: Path) -> Config:
},
}
plan_content = {"duplicate_keep": default_config.duplicate_keep}
yaml_content = {
"library_root": str(default_config.library_root),
"video_extensions": default_config.video_extensions,
"plan": plan_content,
"templates": {
"movie_dir": default_config.movie_template,
"series_dir": default_config.series_template,
@@ -314,5 +324,9 @@ def validate_config(config: Config) -> list[str]:
errors.append("tmdb_region must be a string when set")
if not isinstance(config.tmdb_include_adult, bool):
errors.append("tmdb_include_adult must be a boolean")
if config.duplicate_keep not in ("by_reputation", "first_seen", "manual"):
errors.append(
f"duplicate_keep must be one of 'by_reputation', 'first_seen', 'manual', got: {config.duplicate_keep!r}"
)
return errors