[
  {
    "id": "R01",
    "level": "macro",
    "group": "harness",
    "title": "Разделить источник истории, продукт и эталон вкуса",
    "observation": "Оригинал показывает SEORA; наш фильм — goPure; CustomTarasFinal — HANBIT. У последнего сохранена пигментация лица. Это не одинаковый продуктовый эксперимент.",
    "recommendation": "Хранить три отдельных паспорта. Для новой генерации исходный творческий source остаётся targ. CustomTarasFinal задаёт проверяемые предпочтения исполнения; чужой тюбик, механизм и каст не становятся вложениями goPure.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "Adaptation passport and generation attachment contract",
        "line": 67,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/single_reference.py",
        "anchor": "def validate_manifest",
        "line": 33,
        "sha256": "c7e61b968713d0a8a9dd89db7a6840041f50e11694bc419ee9a10e4c3598a4e0",
        "role": "harness"
      }
    ],
    "proposedFields": "comparisonRoles: {creativeSource, productTruth, preferenceBenchmark}; observedBrand; provenanceKnown",
    "validation": "SHA каждого файла совпадает; бренд прочитан с кадра; неизвестный генератор/провайдер CustomTarasFinal остаётся unknown.",
    "evidence": [
      "presenter",
      "endcard"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "source-preparation"
  },
  {
    "id": "R02",
    "level": "macro",
    "group": "song",
    "title": "Планировать длительность до песни по смысловым блокам",
    "observation": "Наш экспорт длится 239.73 с, оригинал 194.49 с, CustomTarasFinal 194.24 с. В нашем handoff увеличение распределилось почти по всей истории, включая вход в магазин и финал.",
    "recommendation": "На музыкальном этапе, до покупки, писать song-plan: полные смысловые разделы, намерение по длительности, слогам, фразировке и контрасту подачи. Проверить удобство пения. После генерации заменить намерение фактическими временами принятой песни; видео строится по ним. Длина будущих клипов не диктует музыкальные фразы. ±5 % не универсальный допуск.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "### Длина против смысла",
        "line": 253,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "scripts/gen2.py",
        "anchor": "def song_fields",
        "line": 55,
        "sha256": "b62f79ce3929e3ee3c1c19e7cfc360dc8f4d233140aea0bdedbde2501bcfa6be",
        "role": "harness"
      }
    ],
    "proposedFields": "song-plan-vNN.json: semanticSections[], protectedFunctions[], intendedSeconds, intendedPhrasing, rationale; after review -> performed-song-passport-vNN.json with actual times",
    "validation": "Проверить фактический LYRICS, семантическую полноту и комфортный спетый дубль. Нельзя исправлять потерю мысли только уменьшением длины.",
    "evidence": [
      "pity",
      "product",
      "endcard"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R03",
    "level": "micro",
    "group": "song",
    "title": "Развести мысль, спетую фразу и карточку титров",
    "observation": "В старом анализе 75/70/43 ASR-сегмента названы количеством спетых фраз. Это границы распознавания, не разметка дыхания. 65 исходных карточек не требуют 65 одинаково построенных новых фраз.",
    "recommendation": "Сначала связать каждую защищённую мысль с естественной музыкальной фразой и ударениями, без зависимости от будущих склеек/титров. После генерации отдельно разметить реально спетые фразы, слова и дыхание на окончательном мастере. CaptionIds и videoShotIds добавляются на этапе видео как потребители этой разметки; ASR-сегменты не назначают фразы автоматически.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "### Полная мысль и музыкальная фраза",
        "line": 230,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "tools/song_stress.py",
        "anchor": "def validate",
        "line": 55,
        "sha256": "a2aa326511cc7c10690e9c08544df80642f97dcdebc431e0b0a573ed6795d3bb",
        "role": "harness"
      }
    ],
    "proposedFields": "phraseId, meaningIds[], stressedNuclei[], breathIn/Out, captionIds[], submittedTextSha",
    "validation": "Фраза произносится и поётся целиком с понятным адресатом и сказуемым; ASR служит указателем, слух разрешает спор.",
    "evidence": [
      "pity",
      "payoff"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R04",
    "level": "micro",
    "group": "song",
    "title": "Создавать дыхание и музыкальные развороты до фиксации песни",
    "observation": "Предыдущая проверка vocal stem нашла пять пауз ≥1 с внутри CustomTarasFinal; у оригинала найденные длинные тишины относятся к окончанию. Воздух — отличие предпочтённого исполнения, не требование исходника.",
    "recommendation": "В песенном плане заложить слышимую смену подачи и осмысленное завершение фраз: осознание, ответ, облегчение. Проверить реальные паузы и окончания до принятия песни; не заказывать музыку ради уже нарезанных кадров. FILM использует существующие паузы/продолжения и помещает реакцию внутри принятого времени; не добавляет тишину и не растягивает мастер ради сцены.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "## Стадия 4 — отбор",
        "line": 299,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "tools/video_dna_audio.py",
        "anchor": "def measure",
        "line": 65,
        "sha256": "8b4c396250bec5a0dbfedeaf844d75e4833f5781e25a76e9a41f4d2b77b710b9",
        "role": "harness"
      }
    ],
    "proposedFields": "intendedPhraseRelease; heardRests[]: {start,end,dramaticFunction,method,uncertainty}; masterSha256; visualOwner assigned only after song lock",
    "validation": "Слушающий критик подтверждает реальный отдых, не отсутствие оценки высоты тона. Кадр несёт функцию и во время паузы.",
    "evidence": [
      "pity",
      "resolved"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R05",
    "level": "macro",
    "group": "song",
    "title": "Паспортировать вокальную драматургию, а не только BPM",
    "observation": "Сходный средний темп не описывает мелодическую фразу, переход от рассказа к уязвимости и облегчению, повтор мотива или характер CTA.",
    "recommendation": "В существующем song-clone-ua первым улучшить музыкальную карту по смысловым разделам: речевой акт, адресат, разговорно-спетая подача, локальный подъём, выпуск окончания, мотив и его возврат, развитие аранжировки. Намерение входит в песенную редактуру/STYLE в пределах возможностей провайдера. После генерации карта actual performance проверяется по целому аудио; слова жанра и BPM не заменяют прослушивание.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "## Стадия 0 — паспорт ДНК эталона",
        "line": 190,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "scripts/critic_music.py",
        "anchor": "def feat",
        "line": 31,
        "sha256": "2760b84b62b22b197dbecccf2eac9b08c40b4eee68e420a5ae3cc7687e62ef95",
        "role": "harness"
      }
    ],
    "proposedFields": "songPlan.performanceArc[]: {sourceAudioRange,semanticFunction,deliveryIntent,motifIntent,arrangementIntent}; performedSongPassports[]: {masterSha256,actualSectionRange,heardDelivery,motifReturn,actualEvidence,uncertainty}",
    "validation": "Полный трек и локальные A/B-фрагменты слушаются отдельно от технической оценки. Pitch spread и RMS не доказывают эмоцию.",
    "evidence": [
      "opening",
      "pity",
      "payoff"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R06",
    "level": "macro",
    "group": "song",
    "title": "Отделить похожесть музыки от художественной состоятельности",
    "observation": "В прежних замерах наш трек ближе к оригиналу по chroma-DTW; CustomTarasFinal имеет другую оценку гармонического профиля. Владелец предпочёл другой фильм, что не доказывает отдельного предпочтения его тональности.",
    "recommendation": "В критике иметь две независимые оси: сохранение собственного исходного музыкального ДНК и качество исполнения. Любое намеренное музыкальное отклонение описать явно; исходное аудио всё равно обязательно. Не менять Suno V6 или seed по догадке о рендере.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "Оценка модели — сохранённая критика",
        "line": 320,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "scripts/critic_music.py",
        "anchor": "A_AXES",
        "line": 22,
        "sha256": "2760b84b62b22b197dbecccf2eac9b08c40b4eee68e420a5ae3cc7687e62ef95",
        "role": "harness"
      }
    ],
    "proposedFields": "sourceSimilarity, performedMusicality, intentionalDepartures[], noCompositeAcceptance",
    "validation": "Гармонический алгоритм не определяет генератор и не отвергает песню автоматически. Новый музыкальный target — отдельное проверяемое решение.",
    "evidence": [
      "opening",
      "payoff"
    ],
    "priority": "P1",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R07",
    "level": "micro",
    "group": "song",
    "title": "Сохранять разговорную цель фразы и проверять ударения в пении",
    "observation": "В нашей продуктовой части 139–150 с героиня читает применение; в CustomTarasFinal 121–131 с короткие команды переходят в действие. Его разговорность не оправдывает потерю исходных фактов или неверную грамматику.",
    "recommendation": "Писать фразу как обращение конкретного человека: вопрос, совет, признание, ответ. Длинное объяснение разбить музыкально; сохранить обязательный полный STRESS_LEDGER и проверить услышанные ударения. Квоты на тире, кавычки или место первого ударения заменить проверкой звучания.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "### Полная мысль и музыкальная фраза",
        "line": 230,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "scripts/gen2.py",
        "anchor": "def stress_fields",
        "line": 101,
        "sha256": "b62f79ce3929e3ee3c1c19e7cfc360dc8f4d233140aea0bdedbde2501bcfa6be",
        "role": "harness"
      }
    ],
    "proposedFields": "speechAct, addressee, naturalParaphrase, stressLedgerBinding, heardStressFindings[]",
    "validation": "Понятный смысл сохраняется после песенной редактуры; стресс подтверждён в контексте полной фразы, а не только текстовым знаком.",
    "evidence": [
      "product",
      "application"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R08",
    "level": "macro",
    "group": "song",
    "title": "Сжимать формулировку без удаления причины и последствия",
    "observation": "CustomTarasFinal пропускает поддержку детей в раннем кризисе и конкретные пятнадцать минут в машине; сохраняет главные развороты. Эти потери нельзя автоматически узаконить ради длины.",
    "recommendation": "В adaptation-map оставить каждую исходную мысль и причинный beat. Для объединения строк документировать, где новая формулировка сохраняет функцию и конкретный смысл. Новый продукт может требовать явной замены механизма; это не произвольная ампутация истории.",
    "placements": [
      {
        "path": "references/owner-generation-rules.md",
        "anchor": "Permanent advertorial-to-song",
        "line": 37,
        "sha256": "d824d139d455f147ef0d41e34cce0c6939c25ed896f8a9cb22afcde892cdf4b2",
        "role": "contract"
      },
      {
        "path": "tools/build_adapt_report.py",
        "anchor": "def validate_mapping",
        "line": 54,
        "sha256": "d2ec0ce3bac7186a34d134b0833067df9e3006b06689f7fc6a5b6b28f6511893",
        "role": "harness"
      }
    ],
    "proposedFields": "meaningMap[]: {sourceThoughtId,sourceRange,performedPhraseIds,transformation,reason,retainedFunction}",
    "validation": "Ни один protected causal event не исчезает; визуальная компенсация не считается сохранённым спетым фактом без явного решения.",
    "evidence": [
      "diagnosis",
      "daughter"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R09",
    "level": "micro",
    "group": "song",
    "title": "Сохранить мгновенный полный вокальный хук",
    "observation": "В замере CustomTarasFinal начало вокала примерно 0.9 с; на нулевом кадре нет титра. Это не преимущество, которое надо копировать: действующий контракт требует первого спетого слова сразу.",
    "recommendation": "На окончательно доведённой песне, до lock, проверить первый слышимый звук и целое спетое слово. Если до приёмки удалено вступление, заново рассчитать все временные якоря по этому мастеру. FILM начинает своё причинное действие на уже принятом вокальном входе и не меняет его ради кадра.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F12",
        "line": 125,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/verify_song_openings.py",
        "anchor": "def verify",
        "line": 24,
        "sha256": "232b4b46c80efb6b851e56c4a4eacb4bdf99fb09c4b27c973a58aa27dd53694a",
        "role": "harness"
      }
    ],
    "proposedFields": "firstAudibleEvent, firstCompleteSungWord, retainedConsonant, openingActionRange",
    "validation": "Слух и waveform вместе подтверждают вход; длительность тишины не равна доказательству целого слова.",
    "evidence": [
      "opening"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "retain",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R10",
    "level": "macro",
    "group": "video",
    "title": "Делать отдельное покрытие для взгляда и ответной реакции",
    "observation": "На сцене оценки original 47–57 с и наш фильм 62–74 с используют общий план. CustomTarasFinal 54–69 с чередует пару и крупные лица: виден сам взгляд, затем ответ.",
    "recommendation": "Для причинного обмена заранее выбрать owner кадра: смотрящий → то, что он видит → тот, кто понял взгляд. Один исходный план может дать несколько адаптированных кадров при сохранении всего события и его порядка.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F02",
        "line": 29,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_prepare.py",
        "anchor": "def prepare",
        "line": 75,
        "sha256": "fe19d82a026bd5489d829f20195630d1092872484bfd42f04ff0d292db8ae2ea",
        "role": "harness"
      }
    ],
    "proposedFields": "coverageShots[]: {sourceEventIds,observer,target,reactionOwner,framing,targetRange}",
    "validation": "На мобильном размере понятно, кто увидел что и что изменилось. Не навязывать всегда три плана или лимит 4.5 секунды.",
    "evidence": [
      "pity"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R11",
    "level": "micro",
    "group": "video",
    "title": "Задать видимую траекторию взгляда на новую проблемную зону",
    "observation": "Текст нашей сцены говорит «від обличчя до шиї», но общий кадр оставляет саму кожу небольшой. У исходника и CustomTarasFinal оценивается лицо, оно совпадает с центром внимания.",
    "recommendation": "В паспорте события хранить точку начала и цель взгляда, смену выражения и ответ героини. Для шеи адаптировать оптическую ось и крупность; не сохранять автоматически исходный жест к щеке.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "Canonical time and event contract",
        "line": 48,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/video_dna_join.py",
        "anchor": "def join_source",
        "line": 112,
        "sha256": "351a3e98f61bbbe77e1fe36a496431e292555344de46dd607ab7254f39ba8bb6",
        "role": "harness"
      }
    ],
    "proposedFields": "gazeStartTarget, gazeEndTarget, visibleReaction, problemRoi, keyWordOccurrence",
    "validation": "В экспортном фрагменте взгляд имеет правильного адресата и последовательность; отдельный crop зоны доступен для проверки.",
    "evidence": [
      "pity",
      "diagnosis"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R12",
    "level": "macro",
    "group": "passport",
    "title": "Паспортировать читаемость проблемы в кадре телефона",
    "observation": "В нашем начале шею видно в небольшом размере; выразительные морщины показаны позднее крупными планами. Пигментация лица в эталонах может читаться вместе с эмоциональным лицом.",
    "recommendation": "Задать bounding box зоны, минимальный принятый масштаб для конкретного дефекта и чистую экспозицию before. Проверять реальный кадр целиком при ширине 360 px и отдельно увеличенную зону; 15 % высоты не универсальный порог.",
    "placements": [
      {
        "path": "references/problem-passport-contract.md",
        "anchor": "Versioned JSON contract",
        "line": 18,
        "sha256": "e68a6ff8da0e057813529d858e53e02089fb255e008753d3521875b4c1658f14",
        "role": "contract"
      },
      {
        "path": "tools/problem_quality.py",
        "anchor": "def validate_plan",
        "line": 14,
        "sha256": "3caa0a566aac5eda06c102936944666cabb1e821c1aa7ad485ae20d288fcb63a",
        "role": "harness"
      }
    ],
    "proposedFields": "legibilityTargets[]: {characterId,state,zoneRoi,phoneFrame,acceptedEvidence,occlusionLimits}",
    "validation": "Независимый просмотр узнаёт заданную проблему без подписи. Факт видимости шеи сам по себе не считается читаемостью заломов.",
    "evidence": [
      "opening",
      "diagnosis"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R13",
    "level": "micro",
    "group": "passport",
    "title": "Согласовать одежду и причёску с показом результата",
    "observation": "Наставница CustomTarasFinal в зелёной водолазке подходит для демонстрации лица, но скрыла бы шею goPure. У нашей Ирины крупный портрет должен показывать и лицо, и принятую зону результата.",
    "recommendation": "В continuityGroups одновременно задавать волосы/ворот/ракурс и открытость продуктовой зоны. Пакет still и motion должен содержать именно такой композиционный референс; не лечить скрытую шею одной надписью resolved.",
    "placements": [
      {
        "path": "references/problem-passport-contract.md",
        "anchor": "continuityGroups",
        "line": 147,
        "sha256": "e68a6ff8da0e057813529d858e53e02089fb255e008753d3521875b4c1658f14",
        "role": "contract"
      },
      {
        "path": "tools/problem_quality.py",
        "anchor": "def preflight",
        "line": 67,
        "sha256": "3caa0a566aac5eda06c102936944666cabb1e821c1aa7ad485ae20d288fcb63a",
        "role": "harness"
      }
    ],
    "proposedFields": "exposureInvariants: {neckline,hairSilhouette,pose,roi}; perCharacterVisibilityReason",
    "validation": "В каждом утверждении результата зона реально открыта; скрытое состояние имеет объяснение и отдельное видимое доказательство в нужном beat.",
    "evidence": [
      "mentor"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R14",
    "level": "macro",
    "group": "passport",
    "title": "Состояния должны сохраняться между всеми появлениями",
    "observation": "В CustomTarasFinal пятна заметно светлее/менее плотные на 39 с, чем на 46 с в том же магазине до применения. В других планах проблема снова ослабляется. Предпочтённое исполнение не делает эту непоследовательность допустимой.",
    "recommendation": "Привязывать before/intermediate/resolved к каждому appearance, включая флешбэк и отражение. У каждого рекомендателя своё идеальное состояние. Проверять сохранение определённого дефекта, а затем его полное исчезновение, не случайную смену текстуры.",
    "placements": [
      {
        "path": "references/problem-passport-contract.md",
        "anchor": "completionPolicy",
        "line": 132,
        "sha256": "e68a6ff8da0e057813529d858e53e02089fb255e008753d3521875b4c1658f14",
        "role": "contract"
      },
      {
        "path": "tools/problem_quality.py",
        "anchor": "def validate_export",
        "line": 130,
        "sha256": "3caa0a566aac5eda06c102936944666cabb1e821c1aa7ad485ae20d288fcb63a",
        "role": "harness"
      }
    ],
    "proposedFields": "appearances[]: {characterId,state,exportRange,forbiddenResidualChecks[],reflectionChecks}",
    "validation": "Нет преждевременного результата до действия продукта; окончание полностью решает утверждённую проблему в рамках допустимого косметического результата.",
    "evidence": [
      "continuity-early",
      "continuity-late",
      "partial",
      "resolved"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R15",
    "level": "macro",
    "group": "passport",
    "title": "Сохранить одну визуальную систему между лицом и крупным планом кожи",
    "observation": "В нашем фильме 94–101 с и 150–155 с кожа и пропорции лица выглядят реалистичнее, чем в широких сценах. CustomTarasFinal чаще сохраняет единый крупный мультяшный портрет.",
    "recommendation": "Паспорт содержит вид спереди/в профиль и целевой крупный план проблемной зоны в той же стилизации. Сохранять зрелый возраст без случайного усиления реализма или омоложения; сравнивать соседние масштабы.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F09",
        "line": 93,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/problem_quality.py",
        "anchor": "def validate_plan",
        "line": 14,
        "sha256": "3caa0a566aac5eda06c102936944666cabb1e821c1aa7ad485ae20d288fcb63a",
        "role": "harness"
      }
    ],
    "proposedFields": "renderStyleInvariants, faceAgeInvariants, closeupStyleReferences[], scaleLadder",
    "validation": "Before/result остаются тем же человеком и тем же визуальным миром. Красивое молодое лицо не считается успешной косметической трансформацией.",
    "evidence": [
      "diagnosis",
      "application",
      "resolved"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R16",
    "level": "micro",
    "group": "video",
    "title": "Назвать физический поворот эмоции внутри каждого значимого действия",
    "observation": "В нашей сцене 62–74 с финальная широко открытая челюсть может читаться как страх; CustomTarasFinal показывает более локальную смену взгляда и сдержанную мимику. В других его кадрах тоже есть преувеличенные эмоции.",
    "recommendation": "Задать до → trigger → ответ → состояние после через бровь, взгляд, рот, позу и предмет. На облегчении дать снятие напряжения и чистый показ результата. Не прописывать всем сценам «тихую улыбку» или обязательную эмоцию за одну секунду.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F11",
        "line": 115,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_prepare.py",
        "anchor": "directions =",
        "line": 136,
        "sha256": "fe19d82a026bd5489d829f20195630d1092872484bfd42f04ff0d292db8ae2ea",
        "role": "harness"
      }
    ],
    "proposedFields": "actingBeat: {before,trigger,onset,physicalAction,release,after}; failureExamples",
    "validation": "Без титров различим нужный речевой акт: жалость, обида, любопытство, признание. Камера и движение рта не заменяют реакцию.",
    "evidence": [
      "pity",
      "daughter",
      "payoff"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R17",
    "level": "micro",
    "group": "video",
    "title": "Заканчивать действие и оставлять осмысленное удержание",
    "observation": "CustomTarasFinal 17–22 с показывает уход мужчины и пустую дверь; кадр после выхода несёт утрату. В нашем 82–89 с существенное время занимает вход в машину.",
    "recommendation": "После принятия песни выделить setup/action/consequence/hold каждого кадра внутри доступной спетой фразы или её реального продолжения. Сокращать транспортную механику, добавлять покрытие либо менять выбранный дубль, сохраняя полный причинный смысл. Не удлинять песню, не вставлять паузу и не обрывать слово ради завершения жеста.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F11",
        "line": 115,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_build.py",
        "anchor": "def stage",
        "line": 57,
        "sha256": "750f14a102f67a9e3996bfe22893638db33e4c79283488ad708c7a23c970ad37",
        "role": "harness"
      }
    ],
    "proposedFields": "actionEnvelope: {setup,onset,completion,consequence,holdPurpose}; chosenTakeRange",
    "validation": "Нет обрезанного жеста или необъяснённого зависания; замедление не превращает действие в неподвижный постер.",
    "evidence": [
      "opening",
      "diagnosis"
    ],
    "priority": "P1",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R18",
    "level": "macro",
    "group": "video",
    "title": "Ритм оценивать по событиям, а не по одному среднему плану",
    "observation": "Старый детектор при одинаковом scene-score даёт медианы 4.48/5.97/4.17 с. Это кандидаты границ. Ручные ledger-медианы искажены пересечениями; длинный кадр может быть выразительным при развитии действия.",
    "recommendation": "Сравнивать профиль каждой фазы уже принятой песни: её фразы, энергию и реальные паузы, затем склейки и внутрикадровые перемены. Длительности видео и удержаний выводить из музыкального и смыслового развития. Средняя длина исходных кадров служит диагностикой, не сеткой для ретайминга песни.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "What the harness must preserve",
        "line": 9,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/video_dna.py",
        "anchor": "def validate_structure",
        "line": 234,
        "sha256": "b12f8e31c81ff40eb4de8ba0ecd66a8c01cb12aebf2a683668986dfe2c669801",
        "role": "harness"
      }
    ],
    "proposedFields": "phaseRhythm[]: {exclusiveShots,withinShotChanges,holdAfterAction,cameraPurpose,uncertainty}",
    "validation": "Только очищенные интервалы идут в статистику; необычный долгий кадр получает просмотр по содержанию, не автоматический fail.",
    "evidence": [
      "pity",
      "product",
      "payoff"
    ],
    "priority": "P1",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R19",
    "level": "micro",
    "group": "av",
    "title": "Передавать в FILM фактический паспорт принятой песни",
    "observation": "В CustomTarasFinal карточка часто переживает несколько склеек. Поэтому cut-to-ASR-start может выглядеть хуже даже при убедительной сцене; ближайший бит также не доказывает смысловую синхронность.",
    "recommendation": "После всей музыкальной доводки зафиксировать master SHA и reviewed performed-song-passport: реально спетые слова/фразы, паузы, акценты, границы разделов и неопределённость. FILM добавляет visual/caption времена относительно этого неизменного аудио. В song-clone-ua уточнить строку про retime.py: это не автоматическая подготовка песни к видео; музыкальный ретайм возможен только до нового lock с повторной приёмкой, а не внутри FILM.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "Join the timelines",
        "line": 42,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/video_dna_join.py",
        "anchor": "def join_source",
        "line": 112,
        "sha256": "351a3e98f61bbbe77e1fe36a496431e292555344de46dd607ab7254f39ba8bb6",
        "role": "harness"
      },
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "`retime.py` —",
        "line": 336,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      }
    ],
    "proposedFields": "performed-song-passport-vNN.json: {masterSha256,performedTextSha256,songAcceptance,actualSections[],performedPhrases[],wordOccurrences[],heardRests[],energyArc[],motifReturns[],uncertainty}; film.avEvents[]: {songPassportSha256,wordId,musicalCue,visualOnset,captionOnset,intendedRelation}",
    "validation": "Паспорт размечен по финальному принятому master, а не по черновику/таймкодам оригинала. Все ссылки и диапазоны входят в этот файл; предполагаемые паузы отделены от услышанных. При другой версии песни прежний handoff недействителен. После picture assembly проверяется неизменность принятого soundtrack и выбранные смысловые смещения.",
    "evidence": [
      "pity",
      "product",
      "payoff"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "song-to-film-handoff"
  },
  {
    "id": "R20",
    "level": "micro",
    "group": "video",
    "title": "Сохранить state-fades, но проверять наложенные лица",
    "observation": "В нашем экспорте на 108 и 173 с видны наложения двух разных композиций. У CustomTarasFinal тоже есть намеренное двойное изображение воспоминания 114–119 с.",
    "recommendation": "Различать memory-overlay и переход состояния. Для состояний подготовить сопоставимые планы и deliberate fade, проверить начало/середину/конец на двоение и остаточную проблему. Не отменять постоянное требование фейдов.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F05",
        "line": 58,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_build.py",
        "anchor": "def build",
        "line": 154,
        "sha256": "750f14a102f67a9e3996bfe22893638db33e4c79283488ad708c7a23c970ad37",
        "role": "harness"
      }
    ],
    "proposedFields": "transition: {purpose,statePair,fromRoi,toRoi,start,end,cleanHolds,midpointEvidence}",
    "validation": "Чистые before/result читаются отдельно; в середине нет непреднамеренного гибрида лиц. Длительность выбирается по фактическому материалу.",
    "evidence": [
      "partial",
      "resolved"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R21",
    "level": "macro",
    "group": "passport",
    "title": "Паспортировать изменение упаковки как изменение действия",
    "observation": "Оригинальный тюбик выдаёт дозу сжатием; goPure в банке требует открытия и набора крема. В CustomTarasFinal крупный тюбик 126–131 с одновременно поясняет предмет и сохраняет интригу до применения.",
    "recommendation": "В product-action passport задать крышку, руку, количество, место контакта и исходное/конечное положение. Сохранить функцию reveal, не обещать идентичную секунду появления и не требовать один брендовый токен во всех историях.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "Adaptation obligations",
        "line": 26,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_prepare.py",
        "anchor": "def prepare",
        "line": 75,
        "sha256": "fe19d82a026bd5489d829f20195630d1092872484bfd42f04ff0d292db8ae2ea",
        "role": "harness"
      }
    ],
    "proposedFields": "productAction: {packagingType,grip,openState,dose,contact,transfer,claimFactIds}",
    "validation": "Предмет не телепортируется, анатомия и направление движения правдоподобны. Бренд и факты относятся к текущему goPure SKU.",
    "evidence": [
      "product",
      "application"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R22",
    "level": "micro",
    "group": "video",
    "title": "Проверять читаемую этикетку и экранное доказательство продукта",
    "observation": "На крупном тюбике CustomTarasFinal слово HANBIT читается; на маленьком предмете мелкая генеративная печать ненадёжна. Наш финал уже использует реальный packshot.",
    "recommendation": "Сохранить реальную упаковку в основном reveal и финальной карточке. Если нужен композит на движущемся предмете, заранее решить tracking/perspective/occlusion; простой плоский overlay не универсальное исправление.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F17",
        "line": 177,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_build.py",
        "anchor": "def build",
        "line": 154,
        "sha256": "750f14a102f67a9e3996bfe22893638db33e4c79283488ad708c7a23c970ad37",
        "role": "harness"
      }
    ],
    "proposedFields": "labelLegibilityEvidence, packshotSha, trackedSurfacePlan, labelOcclusion",
    "validation": "Бренд читается на экспортном телефоном кадре и совпадает с утверждённой упаковкой; мелкие надписи не выдумываются.",
    "evidence": [
      "product",
      "presenter",
      "endcard"
    ],
    "priority": "P1",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R23",
    "level": "micro",
    "group": "av",
    "title": "Титр поддерживает фразу и не скрывает лицо, шею или руку",
    "observation": "Наши карточки часто содержат несколько полных предложений и позднее второй текстовый слой. CustomTarasFinal чаще держит короткую карточку поверх разных крупностей, но тоже содержит ошибки и перенос поверх начала end-card.",
    "recommendation": "Разбивать реальный performance-текст по прочитываемым смысловым кускам; проверять два уровня: точность слов и видимость кадра. Caption placement зависит от product ROI; фиксированная высота 70 % не подходит всем.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F16",
        "line": 170,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_build.py",
        "anchor": "def display_caption",
        "line": 142,
        "sha256": "750f14a102f67a9e3996bfe22893638db33e4c79283488ad708c7a23c970ad37",
        "role": "harness"
      }
    ],
    "proposedFields": "caption: {wordIds,readingSpan,roiExclusions,charsPerSecond,overlapChecks}; phonePreview",
    "validation": "Все слова читаются и соответствуют звуку; лицо/зона/действие остаются доступны; численный reading-rate только диагностический до проверки человеком/моделью.",
    "evidence": [
      "product",
      "application",
      "endcard"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R24",
    "level": "macro",
    "group": "song",
    "title": "CTA завершает историю в своём ритме",
    "observation": "У нашего финала отдельная инструкция имени/телефона; у двух других — краткий link CTA. В CustomTarasFinal сам CTA поётся на end-card, а продукт в руках появляется ещё на словах о собственной ценности.",
    "recommendation": "До lock песни сочинить CTA как музыкальное завершение: требуемое действие, естественная спетая формулировка, цельная каденция и обязательные сведения по офферу. Прослушать его вместе с катарсисом. После принятия видео размещает продукт/end-card/экранные подробности на фактическом CTA; не дописывает спетые инструкции и не меняет длину мастера под карточку.",
    "placements": [
      {
        "path": ".agents/skills/song-clone-ua/SKILL.md",
        "anchor": "## Стадия 4 — отбор",
        "line": 299,
        "sha256": "690400a3fcb6c49da9abbeb092826337ce3e41c50d9e43ce8cf9a9982752bb66",
        "role": "contract"
      },
      {
        "path": "tools/verify_adapt_handoff.py",
        "anchor": "def audit",
        "line": 30,
        "sha256": "af932bbc5f775c767c2e457634c72ce56a349a5b27586ae735d748cb0056bd40",
        "role": "harness"
      }
    ],
    "proposedFields": "songEndingIntent: {ctaSpeechAct,requiredSungMeaning,cadence}; acceptedEnding: {masterSha256,payoffEnd,ctaStart,lastWord,tailEnd}; filmEnding: {endCardRange,screenInfo,readabilityReview}",
    "validation": "Конец слушается как естественная кода; последняя фраза и карточка не обрываются. Проверить всю информацию и фактический срок чтения.",
    "evidence": [
      "payoff",
      "presenter",
      "endcard"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "strengthen",
    "workflowPhase": "music-before-lock"
  },
  {
    "id": "R25",
    "level": "macro",
    "group": "harness",
    "title": "Сохранять продуктовую правду и локализацию при переносе мастерства",
    "observation": "CustomTarasFinal сохраняет фразы об удалении пигментации и корейской женщине. Такие детали относятся к его истории и продукту, а не автоматически к goPure.",
    "recommendation": "Оставить current product truth, украинскую локализацию, зрелый возраст и полное решение. Решение о disclosure сначала фиксирует необходимый смысл, затем его естественное место в тексте/экране. Нельзя превращать отсутствие оговорок у эталона в запрет оговорок.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F03",
        "line": 40,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/problem_passport.py",
        "anchor": "def validate",
        "line": 13,
        "sha256": "587f5b29fe976e1e5d0231e80d929893efa4da3aba7b4d058c8d15bd7bdc48eb",
        "role": "harness"
      }
    ],
    "proposedFields": "productTruthBinding, localizedRoleIdentity, claimPlacement[]: {claimId,requiredMeaning,channel,reason}",
    "validation": "Никаких неподдерживаемых гарантий, чужой формулы, вывода гражданства по внешности или удаления защищённых требований. Текущую формулу проверяют до новой генерации.",
    "evidence": [
      "mentor",
      "product",
      "endcard"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "retain",
    "workflowPhase": "source-preparation"
  },
  {
    "id": "R26",
    "level": "macro",
    "group": "harness",
    "title": "Не превращать один исходный план в обязательный один заказ",
    "observation": "targ_film_prepare.prepare() проходит по 43 единицам handoff: 42 получают по одному motion generation spec, одна — end-card. Handoff хранит 217 событий, но sourceComposition и одна постановка задаются на уровне исходной единицы.",
    "recommendation": "Только после принятия песни строить coverageShots по её actual phrase/word/energy anchors и полным причинным событиям своего оригинала. Несколько кадров могут обслуживать одну спетую фразу. Production job — транспорт, editorial shot — монтаж, causal event — смысл; ни одна из этих сущностей не заставляет менять locked master. На каждом кадре остаются собственные source/state/continuity attachments.",
    "placements": [
      {
        "path": "generation_contracts.md",
        "anchor": "8.",
        "line": 46,
        "sha256": "e77d4756ddd3f75c1a2a24d04ac69bc083460ace6db415aad21009938273264e",
        "role": "contract"
      },
      {
        "path": "tools/targ_film_prepare.py",
        "anchor": "for u in h['units']",
        "line": 80,
        "sha256": "fe19d82a026bd5489d829f20195630d1092872484bfd42f04ff0d292db8ae2ea",
        "role": "harness"
      }
    ],
    "proposedFields": "acceptedMaster + performedSongPassport -> sourceCausalEvents mapped to actualSongTime -> coverageShots[] -> generationJobs[] -> editClips[]",
    "validation": "Все исходные события сохранены независимо от числа заказов. Никаких 43/217 как универсальных констант для следующего оригинала.",
    "evidence": [
      "pity",
      "product"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "film-after-lock"
  },
  {
    "id": "R27",
    "level": "macro",
    "group": "harness",
    "title": "Сначала проверять измерительный инструмент",
    "observation": "В прежних ledger 47/46/49 строк, а суммы интервалов 210.367/259.6/205.05 с. Дубликаты и пересечения искажают некоторые доли. ASR-пауза, voiced-frame и musical phrase не одно и то же.",
    "recommendation": "Перед метрикой проверять SHA, единицы, эксклюзивные интервалы, определения признаков и неопределённость. Для threshold хранить основание: owner requirement, source observation, экспериментальная гипотеза. Не называть ±5 % source-derived только потому, что оно умножено на источник.",
    "placements": [
      {
        "path": "references/video-dna-contract.md",
        "anchor": "Evidence honesty",
        "line": 91,
        "sha256": "d8afc79bc6a30cadbcc0aa69104ad96499ae12a915467dff4c14376e2a6351e7",
        "role": "contract"
      },
      {
        "path": "tools/video_dna.py",
        "anchor": "def validate_structure",
        "line": 234,
        "sha256": "b12f8e31c81ff40eb4de8ba0ecd66a8c01cb12aebf2a683668986dfe2c669801",
        "role": "harness"
      }
    ],
    "proposedFields": "metric: {definition,inputHashes,intervalIntegrity,method,uncertainty,thresholdBasis}; unknownOnInvalidInput",
    "validation": "Некорректные данные дают unknown, а не pass/fail. Research-утилита dna_measurement_integrity.py уже воспроизводит найденную ошибку; production gate пока предложен.",
    "evidence": [
      "measurement-integrity"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "all-phases"
  },
  {
    "id": "R28",
    "level": "macro",
    "group": "harness",
    "title": "Проверять улучшения в порядке «песня → lock → видео»",
    "observation": "Три фильма меняют сразу продукт, язык, длину, голос, кадрирование и стиль. Из одного предпочтения нельзя вычислить причинный эффект каждого приёма или настройки генератора.",
    "recommendation": "Первый production-приоритет — песенная редактура, вокальная драматургия и приёмка целой песни. Затем фиксировать фактический музыкальный паспорт и строить видео. Визуальные A/B проводят на одном принятом мастере. Монтажный A/B старого song-v02 допустим как отдельная диагностика причины предпочтения, но не переставляет видео перед созданием музыки. Все новые покупки — только в разрешённой фазе; неизвестные POST не повторяются.",
    "placements": [
      {
        "path": "references/film-quality-meta-rules.md",
        "anchor": "**F13",
        "line": 136,
        "sha256": "20f86873c0a3303e71635cd6da2f979c55952578f81effdc36072c6385fa3ddc",
        "role": "contract"
      },
      {
        "path": "tools/film_provider.py",
        "anchor": "def review",
        "line": 381,
        "sha256": "2f86ecefa30368cb301e78cd5d0fdbbc1a592d4120e32fa2621d83bb43a17ea9",
        "role": "harness"
      }
    ],
    "proposedFields": "experiment: {workflowPhase,dependsOnAcceptedSong,changedFactor,lockedInputs,observableCriterion,rawCritique,adjudication}; productionOrder: music -> acceptAndFreeze -> film -> fullExport; diagnosticOnly",
    "validation": "Результат не объявляется 10/10 по среднему баллу. Ошибка/неизвестный POST сохраняются, одинаковая покупка не повторяется.",
    "evidence": [
      "pity",
      "resolved",
      "payoff"
    ],
    "priority": "P0",
    "status": "proposed-not-production-policy",
    "changeKind": "new",
    "workflowPhase": "ordered-validation"
  }
]
