{"record":{"id":"572a66efec1c9c33","repo":"affaan-m/ECC","slug":"protected-interval-has-no-original-video-stack","errorCode":null,"errorMessage":"protected interval has no original video stack","messagePattern":"protected interval has no original video stack","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/integration.py","lineNumber":274,"sourceCode":"        raise ValueError(\"source capacity does not match native offsets\")\n    source = _range(item[\"source_range\"], [clip[\"left_offset\"], clip[\"left_offset\"] + duration])\n    target = _range(item[\"timeline_range\"], [clip[\"start\"], clip[\"end\"]])\n    mapped = [clip[\"start\"] + f - clip[\"left_offset\"] for f in source]\n    if mapped != target or (audio and target != [clip[\"start\"], clip[\"end\"]]):\n        raise ValueError(\"source/audio placement must preserve native timing\")\n    return track, index\n\n\ndef _preserved_stack(protected: Any, tracks: dict, bounds: list[int]) -> list[dict]:\n    if not isinstance(protected, list) or not protected:\n        raise ValueError(\"protected intervals must be explicit and nonempty\")\n    for item in protected:\n        _object(item, {\"range\", \"reason\"})\n        _range(item[\"range\"], bounds)\n        _text(item[\"reason\"])\n        if not any(_overlap(item[\"range\"], [c[\"start\"], c[\"end\"]])\n                   for key, clips in tracks.items() if key.startswith(\"video\") for c in clips):\n            raise ValueError(\"protected interval has no original video stack\")\n    return [{\"track\": track, \"clip_index\": index, \"clip\": copy.deepcopy(clip),\n             \"clip_sha256\": _digest(clip)}\n            for track, clips in sorted(tracks.items()) for index, clip in enumerate(clips)\n            if any(_overlap(p[\"range\"], [clip[\"start\"], clip[\"end\"]]) for p in protected)]\n\n\ndef _candidates(items: list, source_hash: str, input_hash: str, source_url: str) -> dict:\n    result = {}\n    for item in items:\n        _object(item, {\"id\", \"media\", \"media_frames\", \"fps\", \"origin\", \"relationship\",\n                       \"source_sha256\", \"compiled_input_sha256\", \"review_status\", \"generation_receipt\"})\n        name = _text(item[\"id\"])\n        if name in result:\n            raise ValueError(\"candidate ids must be unique\")\n        _artifact(item[\"media\"])\n        _integer(item[\"media_frames\"], 1)\n        _rate(item[\"fps\"])\n        if item[\"origin\"] != \"provider_generated\" or item[\"relationship\"] != \"generated_variation\":","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/integration.py#L256-L292","documentation":"TasteForge's build_application_bundle validates that every user-marked 'protected' interval in the compiled edit actually overlaps at least one clip on a video track in the original timeline (checked in _preserved_stack). If a protected range exists but no original video clip covers any part of it, the bundle cannot guarantee the original footage is preserved there, so it refuses to build. This is a consistency check between the protected-interval list and the actual video stack.","triggerScenarios":"Calling build_application_bundle with a config whose protected_intervals contain a range (item['range'] within bounds, with a 'reason') that does not overlap any clip on any track whose key starts with 'video'. This happens when the protected interval refers to a deleted clip, a typo'd frame range, or clips on non-video tracks only (e.g. audio).","commonSituations":"Editing a compiled project where the user marked a region as protected but the corresponding video clip was removed or trimmed earlier in the pipeline; copy-pasting protected ranges between projects with different clip layouts; timebase drift after re-compilation so ranges no longer align.","solutions":["Inspect each protected interval's [start, end] against the video-track clip ranges in the compiled project and fix ranges that no longer cover any clip","Remove the stale protected interval, or re-derive protected ranges from the current video stack before calling build_application_bundle","Verify the tracks dict passed in still contains the video tracks (keys starting with 'video') that used to cover the interval — the check ignores audio/overlay tracks"],"exampleFix":"// before\nprotected_intervals: [{range: [5000, 6000], reason: \"hero shot\"}]  // video clips end at 4800\n// after\nprotected_intervals: [{range: [4000, 4800], reason: \"hero shot\"}]  // overlaps existing clip","handlingStrategy":"validation","validationCode":"function ensureProtectedRangesCoverVideo(protected, tracks) {\n  const videoClips = Object.entries(tracks)\n    .filter(([k]) => k.startsWith(\"video\"))\n    .flatMap(([, clips]) => clips);\n  for (const p of protected) {\n    const covered = videoClips.some(c => p.range[0] < c.end && c.start < p.range[1]);\n    if (!covered) throw new Error(`protected range ${JSON.stringify(p.range)} covers no video clip`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const bundle = buildApplicationBundle(config);\n} catch (e) {\n  if (e.message.includes(\"protected interval has no original video stack\")) {\n    config.protected_intervals = recomputeProtectedFromVideoStack(config);\n    // retry build\n  } else throw e;\n}","preventionTips":["Derive protected intervals from actual video clip ranges, never hand-type frame numbers","Re-derive protected ranges after any clip add/remove/trim operation","Keep a unit test asserting every protected range overlaps the video stack before bundle build"],"tags":["validation","video-editing","integrity"],"backgroundTag":"conflicting-config-options","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}