diff --git a/gnommo/cli.py b/gnommo/cli.py index d6f04af..5f0776a 100644 --- a/gnommo/cli.py +++ b/gnommo/cli.py @@ -4637,14 +4637,19 @@ def _files_modified_since(root: Path, since: float, pattern: str) -> bool: def _trim_outputs_current(project_path: Path) -> bool: """Return True if the trim stage can be safely skipped for every segment. - A segment is considered resolved when narration.json already records an - explicit skip/take for it, or a cached Whisper transcript exists at - narration/transcripts/{seg_id}.json (from which trim would just recompute - the same skip/take). Used by the 'all' pipeline to avoid re-running the - expensive transcription stage when nothing upstream changed. + A segment is resolved only when its trim *output* is actually present on + BOTH sides — begin (a user 'begin'/'start' pin or a written 'skip') AND end + (a user 'end' pin or a written 'take'). This mirrors the per-side resolution + logic in cmd_trim itself. + + A cached transcript is deliberately NOT treated as "resolved": the transcript + existing does not mean skip/take were ever written (an interrupted run, a + manual edit, or a begin-only pin can leave the end un-trimmed). Trim will + still reuse the cached transcript when it runs, so skipping re-transcription + stays cheap — we just no longer skip trim while real work remains. Returns False (i.e. "run trim") if narration can't be read or any segment - is still unresolved. + is still unresolved on either side. """ from .parser import parse_project_config, parse_narration @@ -4657,7 +4662,6 @@ def _trim_outputs_current(project_path: Path) -> bool: if not narration: return False - transcripts_dir = narration_dir / "transcripts" try: raw_data = _read_json(narration_dir / "narration.json") except (OSError, json.JSONDecodeError): @@ -4665,11 +4669,10 @@ def _trim_outputs_current(project_path: Path) -> bool: for seg_id in narration: entry = raw_data.get(seg_id, {}) - if "skip" in entry or "take" in entry: - continue # already trimmed - if (transcripts_dir / f"{seg_id}.json").exists(): - continue # transcript cached — trim would just reuse it - return False # unresolved segment: trim still has work to do + begin_resolved = bool(entry.get("begin") or entry.get("start")) or "skip" in entry + end_resolved = bool(entry.get("end")) or "take" in entry + if not (begin_resolved and end_resolved): + return False # a side still needs trimming return True