release: v0.2.0 repository hygiene, CI, and docs sync

Stop tracking personal workflow artifacts at repo root, add CI and MIT
license, align README and agent skills with artifacts/ defaults, and
enable Ruff in dev/CI so releases are verifiable without local-only runs.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
windyboy
2026-06-01 15:32:03 +08:00
co-authored by Claude Sonnet 4.5 Cursor
parent e70bd35498
commit 6f0df5a774
101 changed files with 1451 additions and 653105 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ This module provides functionality to analyze video collections for:
- Quality comparison (comparing video quality metrics)
"""
from vlm.models import SeriesIdentity, SeasonCompleteness, DuplicateGroup, VideoFile, MovieIdentity
from vlm.models import DuplicateGroup, MovieIdentity, SeasonCompleteness, SeriesIdentity, VideoFile
def analyze_series_completeness(episodes: list[SeriesIdentity]) -> list[SeasonCompleteness]:
-1
View File
@@ -18,7 +18,6 @@ from vlm.cli_helpers import (
default_config_path,
initialize_cli_context,
resolve_legacy_default_input_path,
review_plan_tui_streams_ok as _review_plan_tui_streams_ok,
)
from vlm.context import CLIContext, pass_context
-2
View File
@@ -18,7 +18,6 @@ from vlm.models import (
AnalysisDuplicateIdentityRecord,
AnalysisDuplicateRecord,
MovieIdentity,
SeriesIdentity,
)
@@ -29,7 +28,6 @@ def analyze_cmd(
inventory: Optional[Path],
) -> None:
"""Run analysis: completeness and duplicate detection."""
config = ctx.config
logger = ctx.logger
click.echo(f"Analyzing identities from: {input}")
+1 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import click
from vlm.cli_helpers import command_error, default_config_path
from vlm.cli_helpers import command_error
from vlm.config import create_default_config, validate_config
from vlm.context import CLIContext
+1 -1
View File
@@ -9,8 +9,8 @@ import click
from vlm.context import CLIContext
from vlm.executor import ExecutionEngine
from vlm.planner import load_plan
from vlm.plan_render import preferred_plan_summary
from vlm.planner import load_plan
from vlm.state import StateManager
+7 -1
View File
@@ -9,7 +9,13 @@ import click
from vlm.context import CLIContext
from vlm.io import load_inventory_csv, save_identities_json
from vlm.models import IdentityRecord, MovieIdentityRecord, ParsedIdentitiesJSON, SeriesIdentityRecord, VideoFile
from vlm.models import (
IdentityRecord,
MovieIdentityRecord,
ParsedIdentitiesJSON,
SeriesIdentityRecord,
VideoFile,
)
from vlm.parser import parse_movie, parse_series
from vlm.utils import utc_now
+1 -1
View File
@@ -7,7 +7,7 @@ from typing import Optional
import click
from vlm.context import CLIContext
from vlm.io import identities_to_plan_input, load_identities_json, load_analysis_json
from vlm.io import identities_to_plan_input, load_analysis_json, load_identities_json
from vlm.planner import generate_plan, save_plan
+6 -1
View File
@@ -9,7 +9,12 @@ from typing import Optional
import click
from vlm.cli_helpers import command_error, default_artifact_path, resolve_legacy_default_input_path, review_plan_tui_streams_ok
from vlm.cli_helpers import (
command_error,
default_artifact_path,
resolve_legacy_default_input_path,
review_plan_tui_streams_ok,
)
from vlm.context import CLIContext
from vlm.io import load_analysis_json, load_identities_json
from vlm.plan_render import (
-1
View File
@@ -1,6 +1,5 @@
"""Scan command implementation."""
import sys
from pathlib import Path
from typing import Optional
+1
View File
@@ -3,6 +3,7 @@
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
import yaml
DEFAULT_VIDEO_EXTENSIONS = [
+1 -1
View File
@@ -1,7 +1,7 @@
"""Duplicate group resolution: choose which file to keep when consuming analysis."""
from datetime import datetime
import re
from datetime import datetime
from pathlib import Path
from typing import Optional, Union
+2 -2
View File
@@ -9,12 +9,12 @@ import hashlib
import json
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Callable, Optional
from urllib.request import urlopen, Request
from urllib.request import Request, urlopen
from vlm.cache import EnrichmentCache
from vlm.config import Config
from vlm.providers import ProviderResult, TMDBAuthError, TMDBProvider, TMDBProviderError
from vlm.parser import normalize_title
from vlm.providers import ProviderResult, TMDBAuthError, TMDBProvider, TMDBProviderError
from vlm.utils import sanitize_path_component
RefreshMode = str
+8 -8
View File
@@ -14,13 +14,13 @@ from pathlib import Path
from typing import Optional
from uuid import uuid4
from .config import Config
from .logging_config import get_logger, log_operation
from .models import ExecutionPlan, FileOperation, OperationResult, RollbackLog
from .quarantine import QuarantineManager
from .state import StateManager
from .transaction import TransactionLog
from .utils import ensure_utc, is_within_root, utc_now
from vlm.config import Config
from vlm.logging_config import get_logger, log_operation
from vlm.models import ExecutionPlan, FileOperation, OperationResult, RollbackLog
from vlm.quarantine import QuarantineManager
from vlm.state import StateManager
from vlm.transaction import TransactionLog
from vlm.utils import ensure_utc, is_within_root, utc_now
class ExecutionEngine:
@@ -681,7 +681,7 @@ class ExecutionEngine:
log_operation(
self.logger,
logging.DEBUG,
f"Skipping rollback of no-op operation",
"Skipping rollback of no-op operation",
operation_type="rollback",
file_path=operation.source_path
)
+2 -3
View File
@@ -7,9 +7,9 @@ from pathlib import Path
from typing import Union
from vlm.models import (
AnalysisJSON,
AnalysisCompletenessRecord,
AnalysisDuplicateRecord,
AnalysisJSON,
ExecutionPlan,
FileOperation,
MovieIdentity,
@@ -21,9 +21,8 @@ from vlm.models import (
SeriesIdentityRecord,
VideoFile,
)
from vlm.utils import ensure_utc, utc_now
from vlm.scanner import load_inventory_csv, save_inventory_csv
from vlm.utils import ensure_utc, utc_now
__all__ = [
"load_inventory_csv",
-1
View File
@@ -12,7 +12,6 @@ import logging.handlers
from pathlib import Path
from typing import Optional
DEFAULT_LOG_FILE = "vlm.log"
MAX_LOG_SIZE = 10 * 1024 * 1024 # 10MB in bytes
BACKUP_COUNT = 5 # Keep 5 backup log files
+1 -1
View File
@@ -10,7 +10,7 @@ from typing import Any
from vlm.models import ExecutionPlan, FileOperation, MovieIdentity, SeriesIdentity
from vlm.review_display import display_path
from vlm.utils import canonical_path_str, format_size, is_sample_path, utc_now
from vlm.utils import canonical_path_str, format_size, is_sample_path
REVIEW_APPLIED_AT_KEY = "review_applied_at"
REVIEW_CSV_PATH_KEY = "review_csv_path"
+8 -10
View File
@@ -4,16 +4,21 @@ This module generates structured execution plans that specify how video files
should be organized based on their parsed identities and configuration templates.
"""
import re
import uuid
from dataclasses import replace
from pathlib import Path
from typing import Optional, Union
from dataclasses import replace
from vlm.config import Config
from vlm.duplicate_resolve import DuplicateResolutionError, choose_keep_index
from vlm.io import load_execution_plan, save_execution_plan
from vlm.models import (
ExecutionPlan,
FileOperation,
MovieIdentity,
SeriesIdentity,
VideoFile,
)
from vlm.plan_review import (
REVIEW_APPLIED_AT_KEY,
REVIEW_CSV_PATH_KEY,
@@ -27,13 +32,6 @@ from vlm.utils import (
sanitize_path_component,
utc_now,
)
from vlm.models import (
ExecutionPlan,
FileOperation,
MovieIdentity,
SeriesIdentity,
VideoFile,
)
QUARANTINE_REASON_DUPLICATE = "重复项(已按外部评分保留一条)"
QUARANTINE_REASON_DUPLICATE_FALLBACK_QUALITY = "重复项(外部评分缺失/并列,按画质回退保留一条)"
+1 -1
View File
@@ -3,7 +3,7 @@
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Protocol, Optional
from typing import Optional, Protocol
@dataclass
+2 -2
View File
@@ -16,10 +16,10 @@ from pathlib import Path
from typing import Optional
from .config import Config
from .utils import utc_now
from .logging_config import get_logger, log_operation
from .models import QuarantineEntry, QuarantineManifest, OperationResult, FileOperation
from .models import FileOperation, OperationResult, QuarantineEntry, QuarantineManifest
from .scanner import categorize_file
from .utils import utc_now
class QuarantineManager:
+1 -1
View File
@@ -14,7 +14,7 @@ from datetime import datetime, timezone
from io import StringIO
from pathlib import Path
from vlm.models import SeasonCompleteness, DuplicateGroup, VideoFile, MovieIdentity, SeriesIdentity
from vlm.models import DuplicateGroup, MovieIdentity, SeasonCompleteness, VideoFile
logger = logging.getLogger(__name__)
-1
View File
@@ -5,7 +5,6 @@ from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from vlm.plan_review import save_review_csv
from vlm.review_display import (
build_csv_rows,
+1 -1
View File
@@ -6,11 +6,11 @@ directory structure.
"""
import csv
from concurrent.futures import ThreadPoolExecutor, as_completed
import json
import logging
import os
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timezone
from pathlib import Path
from typing import Callable, Iterator, Optional
-1
View File
@@ -14,7 +14,6 @@ from typing import Optional
from vlm.models import FileState, StateStore
from vlm.utils import canonical_path, canonical_path_str, ensure_utc, utc_now
# Valid status values
VALID_STATUSES = {"reviewed", "ignored", "planned", "executed", "quarantined"}
+2 -3
View File
@@ -5,12 +5,11 @@ before they are executed, allowing for crash recovery and audit trails.
"""
import json
from datetime import datetime
from pathlib import Path
from typing import Any, Optional, Dict, List
from typing import Any, Dict, Optional
from uuid import uuid4
from vlm.models import ExecutionPlan, FileOperation
from vlm.models import ExecutionPlan
from vlm.utils import utc_now
+1 -1
View File
@@ -1,8 +1,8 @@
"""Shared utilities for Video Library Manager."""
import re
from datetime import datetime, timezone
from pathlib import Path
import re
def utc_now() -> datetime: