refactor: consolidate skill docs, add anti-drift tests, and apply audit fixes
DLO-13: Restructure vlm-library-workflow skill as safety contract layer. - Rewrite SKILL.md (69 lines): safety contract, execution threshold semantics, six-step high-risk loop, decision rules, phase skeleton - Delete redundant references (cli-reference, workflow, command-recipes, dev-guide) - Add triage.md (failure mapping + preflight) and dev-map.md (module→test mapping) - Add tests/test_docs_consistency.py: 78 parametrized tests verifying documented vlm commands exist in CLI registry - Add CSV path mismatch test to test_plan_review.py (4th safety gate path) - Delete vlm-expert.skill (Gemini package, 7 months stale) and README Gemini section DLO-2 audit fixes: rate limiter injection, symmetric quarantine categories, review-plan safety gates, parser improvements, planner validation. CLI modularization: commands/ directory with one module per command group.
This commit is contained in:
@@ -290,6 +290,56 @@ def _is_video_file(file_path: Path, video_extensions: list[str]) -> bool:
|
||||
return file_extension in [ext.lower() for ext in video_extensions]
|
||||
|
||||
|
||||
DEFAULT_SIDECAR_EXTENSIONS = (".srt", ".ass", ".sub", ".idx", ".sup", ".nfo")
|
||||
|
||||
|
||||
def find_sidecar_companions(
|
||||
video_path: Path,
|
||||
sidecar_extensions: tuple = DEFAULT_SIDECAR_EXTENSIONS,
|
||||
) -> list[Path]:
|
||||
"""Find sidecar files in the same directory that belong to a video file.
|
||||
|
||||
Conservative matching: a companion must share the video's exact stem,
|
||||
optionally followed by dot-separated alphabetic suffix tokens (e.g.
|
||||
language or track tags such as ``zh`` or ``en.forced``). Numeric or
|
||||
otherwise non-alphabetic tokens are rejected so unrelated files are
|
||||
never associated.
|
||||
|
||||
Args:
|
||||
video_path: Path to the video file
|
||||
sidecar_extensions: Sidecar extensions to consider (case-insensitive)
|
||||
|
||||
Returns:
|
||||
Sorted list of companion paths (empty when none are found).
|
||||
"""
|
||||
parent = video_path.parent
|
||||
try:
|
||||
with os.scandir(parent) as it:
|
||||
entries = [e for e in it if e.is_file(follow_symlinks=False)]
|
||||
except OSError:
|
||||
return []
|
||||
|
||||
stem = video_path.stem
|
||||
exts = {ext.lower() for ext in sidecar_extensions}
|
||||
companions: list[Path] = []
|
||||
for entry in entries:
|
||||
name = entry.name
|
||||
suffix = Path(name).suffix.lower()
|
||||
if suffix not in exts:
|
||||
continue
|
||||
base = name[: -len(suffix)]
|
||||
if base == stem:
|
||||
companions.append(Path(entry.path))
|
||||
continue
|
||||
if not base.startswith(stem + "."):
|
||||
continue
|
||||
tokens = base[len(stem) + 1:].split(".")
|
||||
if tokens and all(token and token.isalpha() for token in tokens):
|
||||
companions.append(Path(entry.path))
|
||||
|
||||
return sorted(companions, key=lambda p: p.name)
|
||||
|
||||
|
||||
def _create_video_file(
|
||||
file_path: Path,
|
||||
library_root: Path,
|
||||
|
||||
Reference in New Issue
Block a user