{
 "schema": "adfactory.song-v3-plan/v1",
 "session": "08f0d414c5",
 "run": "runs/targ-song-v3-08f0d414c5-v01",
 "at": "2026-09-17T03:29:43.886335+00:00",
 "title": "Итерация 3 песни goPure Україна — «пусть песня дышит»",
 "subtitle": "План изменений и гипотез с гейтами и предсказанным трендом; публикуется до первой покупки",
 "requirements": [
  {
   "quote": "locked to its clock and density, the Ukrainian song could not breathe",
   "metric": "Rests ≥ 0,6 с на границах мыслей (доля), медианная пауза между словами, слог/с по секциям",
   "gate": "restBoundaryShare ≥ 0,80 (P0); maxSectionRate ≤ 3,2 (P0); sungRate ≤ 2,8 (P0-гипотеза)",
   "code": "tools/song_breathing.py (новые строки), formPlan.restAfter в плане, protectedThoughtMap только как карта смысла (sourceAudioRange информативно)"
  },
  {
   "quote": "We did not separate concepts with pauses",
   "metric": "Пауза после каждой завершённой мысли: план помечает границы мыслей, измерение считает паузу ≥ 0,6 с именно там",
   "gate": "restBoundaryShare (P0), restMedian ≥ 0,8 с (P1), «пауза только на границе, не после каждой строки» → fragmentation-строка (P0)",
   "code": "music_first.validate_form_plan: thoughtBoundary/restAfter на каждой фразе; song_breathing.rests_at_boundaries"
  },
  {
   "quote": "especially at the end we stuffed many words and facts into a short time",
   "metric": "Кода: один факт на фразу, пауза ≥ 0,5 с после каждого из шести фактов (бренд, форма, осмотр, оплата после, 60 дней, ссылка)",
   "gate": "codaFactsRested = 6/6 (P0); codaRate информативно",
   "code": "formPlan.codaLayout (factId ↔ phraseId ↔ restAfter), song_breathing.coda_facts; директива [Outro] с half-time"
  },
  {
   "quote": "sounded like narration, not like a song",
   "metric": "Слепой вердикт «song, not narration» (P0), возвраты хука ≥ 3 (P0), подъём припева ≥ 2 полутона (P1), доля фраз без высоты ≤ 10 % (P1), долгие ноты на ключевых словах разрешены",
   "gate": "blindSongVerdict (P0), hookReturns ≥ 3 (P0), chorusLift (P1), lowPitchedPhraseShare (P1); строки sustained05/heldNonFocus сняты с гейтов",
   "code": "formPlan.hookLine + sections.kind; review_round.py: явные вопросы рецензентам; targets v01 с priority=info для старых строк"
  },
  {
   "quote": "clear pauses between thoughts, so it is obvious when the melody goes up and when it comes down",
   "metric": "План контура по секциям и фразам (up/down/same, кульминация) и его измерение медианами высоты фраз после дубля",
   "gate": "contourStepMatch ≥ 0,6 (P1), climaxPlacement (P1), codaSettles (P1)",
   "code": "formPlan.contour (section shape + phrase step), song_breathing.contour_rows на строках phrases[].medianMidi/p90Midi/endSlope из song_gates"
  },
  {
   "quote": "absolute freedom over timing, tempo, key, form, length, arrangement, section order and delivery",
   "metric": "Темп/тональность/форма/длительность — параметры варианта, не гейты; длительность информативно",
   "gate": "duration → info; songGateTargets (Targ-relative) → info; seed как вдохновение: audioWeight 0,35–0,60 вместо 0,88",
   "code": "pipeline.json: songFormPlanRequired, songBreathingTargets, retiredSongGateRows; formPlan.tempoBpm/key/seedDecision; cover-env AW/SW/WC на вариант"
  },
  {
   "quote": "check the trend of improvement before spending credits",
   "metric": "Предсказание каждой breathing-строки из текста и плана до POST; таблица v0 → v1 → v2 → предсказание → измерено",
   "gate": "purchase only if every breathing row moves in the wanted direction and no invariant regresses (кроме контрольного варианта — объявленное исключение)",
   "code": "preparation/predict_v3.py (из design JSON), trend-таблица в плане и отчёте; director-purchase-vNN.json ссылается на предсказание"
  },
  {
   "quote": "natural Ukrainian, correct word stress on every word … real singing throughout",
   "metric": "Ledger ударений 100 % до POST; ASR-совпадение строк ≥ 95 %; слепой вердикт «спето»",
   "gate": "stressLedger (P0, до покупки), asrLineMatch ≥ 0,95 (P0), blindSongVerdict (P0)",
   "code": "без изменений: tools/song_stress.py, scripts/lines_check.py; новый rubric в панели текста"
  },
  {
   "quote": "no telegraphic fragments, no [Instrumental answer] after every line, no gaps for their own sake",
   "metric": "Доля фраз ≤ 2 слов ≤ 10 %; инструментальных промежутков ≥ 1 с не больше числа границ секций + 2; паузы ≥ 1 с не более чем после 35 % фраз",
   "gate": "noFragmentation (P0)",
   "code": "song_breathing.fragmentation; validate_form_plan: fillAfter только на границах секций (≤ sections+1)"
  }
 ],
 "current": {
  "rows": [
   {
    "label": "Длительность, с",
    "values": {
     "targ": 194.489,
     "v0": 197.726,
     "v1": 203.240998,
     "v2": 197.103991
    },
    "gateId": "info"
   },
   {
    "label": "Слогов (спетых)",
    "values": {
     "targ": 576,
     "v0": 714,
     "v1": 701,
     "v2": 665
    },
    "gateId": "info"
   },
   {
    "label": "Фраз (строк)",
    "values": {
     "targ": 94,
     "v0": 46,
     "v1": 60,
     "v2": 59
    },
    "gateId": "info"
   },
   {
    "label": "Спетый интервал, с (сумма фраз)",
    "values": {
     "targ": 176.92,
     "v0": 184.98,
     "v1": 193.63,
     "v2": 184.29
    },
    "gateId": "info"
   },
   {
    "label": "Слог/с по спетому интервалу",
    "values": {
     "targ": 3.26,
     "v0": 3.86,
     "v1": 3.62,
     "v2": 3.61
    },
    "gateId": "sungRate"
   },
   {
    "label": "Самая плотная секция, слог/с",
    "values": {
     "targ": 3.64,
     "v0": 4.7,
     "v1": 4.13,
     "v2": 4.61
    },
    "gateId": "maxSectionRate"
   },
   {
    "label": "Пауз ≥ 0,6 с между словами",
    "values": {
     "targ": 9,
     "v0": 5,
     "v1": 6,
     "v2": 3
    },
    "gateId": "restCount"
   },
   {
    "label": "Доля границ фраз с паузой ≥ 0,6 с",
    "values": {
     "targ": 0.097,
     "v0": 0.0,
     "v1": 0.102,
     "v2": 0.034
    },
    "gateId": "restBoundaryShare"
   },
   {
    "label": "Медианная пауза между словами, с",
    "values": {
     "targ": 0.0,
     "v0": 0.0,
     "v1": 0.0,
     "v2": 0.0
    },
    "gateId": "info"
   },
   {
    "label": "Возвраты хук-строки (≥ 4 слова, ≥ 3 позиции, ≥ 20 с)",
    "values": {
     "targ": 0,
     "v0": 0,
     "v1": 0,
     "v2": 0
    },
    "gateId": "hookReturns"
   },
   {
    "label": "Фактов коды с паузой ≥ 0,5 с после",
    "values": {
     "targ": "0/0",
     "v0": "0/6",
     "v1": "0/6",
     "v2": "0/6"
    },
    "gateId": "codaFactsRested"
   },
   {
    "label": "CV скорости по фразам",
    "values": {
     "targ": 0.328,
     "v0": 0.207,
     "v1": 0.272,
     "v2": 0.24
    },
    "gateId": "phraseRateCV"
   },
   {
    "label": "Доля фраз ≤ 2 слов",
    "values": {
     "targ": 0.223,
     "v0": 0.022,
     "v1": 0.017,
     "v2": 0.017
    },
    "gateId": "noFragmentation"
   },
   {
    "label": "Инструментальных промежутков ≥ 1 с (аудио)",
    "values": {
     "targ": 0,
     "v0": "—",
     "v1": 5,
     "v2": 4
    },
    "gateId": "info"
   },
   {
    "label": "Нот ≥ 0,5 с (аудио; больше не гейт)",
    "values": {
     "targ": 8,
     "v0": "—",
     "v1": 20,
     "v2": 11
    },
    "gateId": "info"
   },
   {
    "label": "Разброс регистра фраз, полутона (аудио)",
    "values": {
     "targ": 12.0,
     "v0": "—",
     "v1": 7.2,
     "v2": 11.8
    },
    "gateId": "info"
   },
   {
    "label": "Вокал − музыка, худший блок, dB (аудио)",
    "values": {
     "targ": -1.0,
     "v0": "—",
     "v1": -4.4,
     "v2": 0.7
    },
    "gateId": "vocMinusMusicWorst"
   }
  ],
  "sections": {
   "targ": [
    {
     "id": "setup",
     "start": 0.0,
     "end": 33.0,
     "seconds": 33.0,
     "phrases": 15,
     "syllables": 105,
     "sungSeconds": 31.82,
     "sylPerSungSec": 3.3,
     "sylPerSec": 3.18,
     "rests": 1
    },
    {
     "id": "store",
     "start": 33.0,
     "end": 81.0,
     "seconds": 48.0,
     "phrases": 21,
     "syllables": 169,
     "sungSeconds": 46.38,
     "sylPerSungSec": 3.64,
     "sylPerSec": 3.52,
     "rests": 3
    },
    {
     "id": "mentor",
     "start": 81.0,
     "end": 108.8,
     "seconds": 27.8,
     "phrases": 18,
     "syllables": 85,
     "sungSeconds": 25.78,
     "sylPerSungSec": 3.3,
     "sylPerSec": 3.06,
     "rests": 1
    },
    {
     "id": "care",
     "start": 108.8,
     "end": 122.9,
     "seconds": 14.1,
     "phrases": 7,
     "syllables": 45,
     "sungSeconds": 12.44,
     "sylPerSungSec": 3.62,
     "sylPerSec": 3.19,
     "rests": 1
    },
    {
     "id": "change",
     "start": 122.9,
     "end": 146.4,
     "seconds": 23.5,
     "phrases": 15,
     "syllables": 66,
     "sungSeconds": 21.08,
     "sylPerSungSec": 3.13,
     "sylPerSec": 2.81,
     "rests": 1
    },
    {
     "id": "return",
     "start": 146.4,
     "end": 173.6,
     "seconds": 27.2,
     "phrases": 13,
     "syllables": 75,
     "sungSeconds": 26.58,
     "sylPerSungSec": 2.82,
     "sylPerSec": 2.76,
     "rests": 2
    },
    {
     "id": "selfworth",
     "start": 173.6,
     "end": 182.6,
     "seconds": 9.0,
     "phrases": 3,
     "syllables": 23,
     "sungSeconds": 8.34,
     "sylPerSungSec": 2.76,
     "sylPerSec": 2.56,
     "rests": 0
    },
    {
     "id": "cta",
     "start": 182.6,
     "end": 188.88,
     "seconds": 6.28,
     "phrases": 2,
     "syllables": 8,
     "sungSeconds": 4.5,
     "sylPerSungSec": 1.78,
     "sylPerSec": 1.27,
     "rests": 0
    }
   ],
   "v0": [
    {
     "id": "setup",
     "start": 0.0,
     "end": 26.91,
     "seconds": 26.91,
     "phrases": 8,
     "syllables": 96,
     "sungSeconds": 24.45,
     "sylPerSungSec": 3.93,
     "sylPerSec": 3.57,
     "rests": 2
    },
    {
     "id": "store",
     "start": 26.91,
     "end": 74.61,
     "seconds": 47.7,
     "phrases": 10,
     "syllables": 156,
     "sungSeconds": 45.06,
     "sylPerSungSec": 3.46,
     "sylPerSec": 3.27,
     "rests": 1
    },
    {
     "id": "mentor",
     "start": 74.61,
     "end": 97.62,
     "seconds": 23.02,
     "phrases": 7,
     "syllables": 93,
     "sungSeconds": 22.48,
     "sylPerSungSec": 4.14,
     "sylPerSec": 4.04,
     "rests": 0
    },
    {
     "id": "care",
     "start": 97.62,
     "end": 120.83,
     "seconds": 23.2,
     "phrases": 6,
     "syllables": 109,
     "sungSeconds": 23.2,
     "sylPerSungSec": 4.7,
     "sylPerSec": 4.7,
     "rests": 0
    },
    {
     "id": "change",
     "start": 120.83,
     "end": 140.59,
     "seconds": 19.76,
     "phrases": 4,
     "syllables": 81,
     "sungSeconds": 18.7,
     "sylPerSungSec": 4.33,
     "sylPerSec": 4.1,
     "rests": 1
    },
    {
     "id": "return",
     "start": 140.59,
     "end": 158.78,
     "seconds": 18.2,
     "phrases": 4,
     "syllables": 78,
     "sungSeconds": 18.2,
     "sylPerSungSec": 4.29,
     "sylPerSec": 4.29,
     "rests": 0
    },
    {
     "id": "selfworth",
     "start": 158.78,
     "end": 172.66,
     "seconds": 13.88,
     "phrases": 3,
     "syllables": 41,
     "sungSeconds": 13.88,
     "sylPerSungSec": 2.95,
     "sylPerSec": 2.95,
     "rests": 0
    },
    {
     "id": "cta",
     "start": 172.66,
     "end": 191.69,
     "seconds": 19.02,
     "phrases": 4,
     "syllables": 60,
     "sungSeconds": 19.02,
     "sylPerSungSec": 3.15,
     "sylPerSec": 3.15,
     "rests": 1
    }
   ],
   "v1": [
    {
     "id": "setup",
     "start": 0.0,
     "end": 31.98,
     "seconds": 31.98,
     "phrases": 12,
     "syllables": 114,
     "sungSeconds": 28.45,
     "sylPerSungSec": 4.01,
     "sylPerSec": 3.56,
     "rests": 2
    },
    {
     "id": "store",
     "start": 31.98,
     "end": 74.44,
     "seconds": 42.46,
     "phrases": 11,
     "syllables": 141,
     "sungSeconds": 41.04,
     "sylPerSungSec": 3.44,
     "sylPerSec": 3.32,
     "rests": 1
    },
    {
     "id": "mentor",
     "start": 74.44,
     "end": 98.08,
     "seconds": 23.64,
     "phrases": 7,
     "syllables": 85,
     "sungSeconds": 21.64,
     "sylPerSungSec": 3.93,
     "sylPerSec": 3.6,
     "rests": 2
    },
    {
     "id": "care",
     "start": 98.08,
     "end": 123.12,
     "seconds": 25.04,
     "phrases": 8,
     "syllables": 102,
     "sungSeconds": 24.72,
     "sylPerSungSec": 4.13,
     "sylPerSec": 4.07,
     "rests": 0
    },
    {
     "id": "change",
     "start": 123.12,
     "end": 149.54,
     "seconds": 26.42,
     "phrases": 8,
     "syllables": 83,
     "sungSeconds": 24.92,
     "sylPerSungSec": 3.33,
     "sylPerSec": 3.14,
     "rests": 1
    },
    {
     "id": "return",
     "start": 149.54,
     "end": 173.06,
     "seconds": 23.52,
     "phrases": 6,
     "syllables": 84,
     "sungSeconds": 23.52,
     "sylPerSungSec": 3.57,
     "sylPerSec": 3.57,
     "rests": 0
    },
    {
     "id": "selfworth",
     "start": 173.06,
     "end": 187.36,
     "seconds": 14.3,
     "phrases": 3,
     "syllables": 41,
     "sungSeconds": 14.3,
     "sylPerSungSec": 2.87,
     "sylPerSec": 2.87,
     "rests": 0
    },
    {
     "id": "cta",
     "start": 187.36,
     "end": 202.4,
     "seconds": 15.04,
     "phrases": 5,
     "syllables": 51,
     "sungSeconds": 15.04,
     "sylPerSungSec": 3.39,
     "sylPerSec": 3.39,
     "rests": 0
    }
   ],
   "v2": [
    {
     "id": "setup",
     "start": 0.0,
     "end": 32.58,
     "seconds": 32.58,
     "phrases": 12,
     "syllables": 113,
     "sungSeconds": 31.04,
     "sylPerSungSec": 3.64,
     "sylPerSec": 3.47,
     "rests": 0
    },
    {
     "id": "store",
     "start": 32.58,
     "end": 76.26,
     "seconds": 43.68,
     "phrases": 11,
     "syllables": 136,
     "sungSeconds": 42.62,
     "sylPerSungSec": 3.19,
     "sylPerSec": 3.11,
     "rests": 1
    },
    {
     "id": "mentor",
     "start": 76.26,
     "end": 95.9,
     "seconds": 19.64,
     "phrases": 8,
     "syllables": 87,
     "sungSeconds": 18.86,
     "sylPerSungSec": 4.61,
     "sylPerSec": 4.43,
     "rests": 0
    },
    {
     "id": "care",
     "start": 95.9,
     "end": 112.76,
     "seconds": 16.86,
     "phrases": 5,
     "syllables": 66,
     "sungSeconds": 16.86,
     "sylPerSungSec": 3.91,
     "sylPerSec": 3.91,
     "rests": 0
    },
    {
     "id": "change",
     "start": 112.76,
     "end": 135.68,
     "seconds": 22.92,
     "phrases": 8,
     "syllables": 88,
     "sungSeconds": 22.46,
     "sylPerSungSec": 3.92,
     "sylPerSec": 3.84,
     "rests": 0
    },
    {
     "id": "return",
     "start": 135.68,
     "end": 159.6,
     "seconds": 23.92,
     "phrases": 7,
     "syllables": 84,
     "sungSeconds": 23.4,
     "sylPerSungSec": 3.59,
     "sylPerSec": 3.51,
     "rests": 0
    },
    {
     "id": "selfworth",
     "start": 159.6,
     "end": 175.96,
     "seconds": 16.36,
     "phrases": 3,
     "syllables": 41,
     "sungSeconds": 14.04,
     "sylPerSungSec": 2.92,
     "sylPerSec": 2.51,
     "rests": 1
    },
    {
     "id": "cta",
     "start": 175.96,
     "end": 190.94,
     "seconds": 14.98,
     "phrases": 5,
     "syllables": 50,
     "sungSeconds": 15.0,
     "sylPerSungSec": 3.33,
     "sylPerSec": 3.34,
     "rests": 1
    }
   ]
  },
  "rests": {
   "targ": [
    19.2,
    61.66,
    70.48,
    79.74,
    91.98,
    116.14,
    135.32,
    163.14,
    165.54
   ],
   "v0": [
    3.33,
    16.5,
    72.81,
    139.53,
    173.26
   ],
   "v1": [
    4.04,
    21.62,
    39.64,
    86.12,
    91.24,
    126.32
   ],
   "v2": [
    75.2,
    173.64,
    187.92
   ]
  },
  "method": "Word clocks only: Targ from the canonical Video DNA raw ASR words (faster-whisper on the original); Ukrainian versions from the accepted performed-song passports (ASR word spans on the master clock, ±0.25 s). Phrases = lyric lines (Ukrainian) or punctuation/segment splits of the ASR (Targ). Rest = gap between consecutive words ≥ 0.6 s. Section rate = syllables ÷ summed phrase durations inside the section (sung span). Pitch/arrangement rows are measured separately on audio."
 },
 "hypotheses": [
  {
   "id": "H1",
   "name": "Форма песни",
   "change": "Возвращающийся материал: куплет / предприпев / припев (A) или короткий рефрен-вопрос (B); хук-строка возвращается ≥ 3 раз с изменённым концом; рифма и стабильный размер внутри секции; нарративные строки переписаны в спетые, не проговорены.",
   "where": "song/design-<variant>.json → formPlan.sections[].kind, hookLine, hookPhraseIds; music_first.validate_form_plan; теги [Verse]/[Pre-Chorus]/[Chorus]/[Bridge]/[Outro] в lyrics; style-промпт",
   "gate": "hookReturns ≥ 3 (P0); chorusLift ≥ 2 st (P1); blindSongVerdict (P0)",
   "predicted": "A: 3 возврата («Я дивлюсь у дзеркало»), B: 3 («Дивлюсь на себе — і що я бачу?»), C: 0 (контроль)",
   "risk": "Suno может спеть припев на той же высоте, что куплет (chorusLift < 2) или изменить слова хука; рефрен в B может прозвучать как повтор без развития.",
   "fallback": "Изменённый конец хука защищает от механического повтора; если лифта нет — вариант A2 с явной директивой [Chorus — higher, full voice] и SW ↑."
  },
  {
   "id": "H2",
   "name": "Информационный бюджет",
   "change": "Одна мысль — одна музыкальная фраза (39 мыслей → 44–50 фраз включая хук и коду); пауза после каждой завершённой мысли; слогов 520–560 (A), 480–520 (B) вместо 665; кода — один факт на фразу с паузой после каждого.",
   "where": "design.phrases[].thoughtBoundary/restAfter; formPlan.syllableBudget по секциям; validate_form_plan отвергает секцию > бюджета + 10 %; song_breathing.rests_at_boundaries / section_rates / coda_facts",
   "gate": "restBoundaryShare ≥ 0,80 (P0); maxSectionRate ≤ 3,2 (P0); sungRate ≤ 2,8 (P0-гипотеза); codaFactsRested 6/6 (P0)",
   "predicted": "A: 0,86 / 3,3 / 2,95; B: 0,84 / 3,4 / 3,05; C: 0,80 / 4,3 / 3,5. Честно: ≤ 2,8 по всей песне при 550 слогах требует ~200 с спетого интервала, т. е. ~230–240 с песни; cover наследует длину сида (194 с) — это тестируется в раунде 1.",
   "risk": "Cover Suno может ужать 550 слогов в 195 с (тогда rate ≈ 3,3) или проигнорировать паузы; ≤ 2,8 может оказаться недостижимым без сокращения до ~470 слогов.",
   "fallback": "Раунд 2: (а) вариант A-lean ≈ 470 слогов (слияние t02+t03, t05+t06, t20, t28, t30, t36+t37; список ингредиентов → два спетых + два визуальных) — гипотеза со сбросом факта в визуальный канал, дефолтный вариант A сохраняет все факты; (б) пересмотр цели с доказательством (слепой вердикт «дышит» при 3,0)."
  },
  {
   "id": "H3",
   "name": "Контур",
   "change": "Письменный план up/down для каждой секции и фразы: где мелодия поднимается, где садится, где кульминация; паузы как шарниры. Заменяет таблицу регистров Targ как авторитет регистра.",
   "where": "formPlan.contour: sections[].shape (rise|arch|level|fall|peak) + climaxPhraseId; phrases[].contourStep (up|down|same); измерение: song_gates phrases[].medianMidi/p90Midi/endSlope → song_breathing.contour_rows",
   "gate": "contourStepMatch ≥ 0,6 (P1); climaxPlacement = планируемая секция (P1); codaSettles: медиана коды ≤ медиана припева − 2 st (P1); chorusLift (P1)",
   "predicted": "A: кульминация в припеве 3 на «свою»; лифт припева +3…+5 st; кода −3 st. B: кульминация в третьем рефрене; C: без припева — контур как у v2 (registerSpread 11,8) → climaxPlacement неопределён.",
   "risk": "Медианы фраз на стемах Demucs ± 1 полутон; Suno не читает стрелки — контур управляется структурными тегами и словами директив.",
   "fallback": "Строки контура — P1: не блокируют, но входят в отчёт и в выбор между дублями."
  },
  {
   "id": "H4",
   "name": "Пение",
   "change": "Долгие ноты на ключевых словах разрешены и желательны; строки sustained05 и heldNonFocus сняты с гейтов (информативно); «нет мелизмы на безударном последнем слоге» остаётся проверкой ударения.",
   "where": "references/song-breathing-targets-v01.json (priority info для sustained05/sustainedTimeShare/heldNonFocus); stressLedger + слепые вопросы о слышимом ударении; performancePlan.syllableEconomy.holdAllowed — по слову на фразу остаётся",
   "gate": "stressLedger 100 % (P0, до POST); lowPitchedPhraseShare ≤ 0,10 (P1); blindSongVerdict (P0)",
   "predicted": "Нот ≥ 0,5 с вырастет с 11 до 20–35 — это желаемо; heldNonFocus не считается.",
   "risk": "Долгие ноты на безударных окончаниях (-ла/-ого) — реальная ловушка украинского; ловится слепым вопросом «які слова розтягнуті» и правилом holdAllowed.",
   "fallback": "Раунд-правка директив: hold только на фокусных словах фразы (уже в performancePlan)."
  },
  {
   "id": "H5",
   "name": "Аранжировка дышит",
   "change": "Паузы, drops, филлы и инструментальные ответы только там, где форма просит: между секциями, перед припевом, перед брендом; никогда после каждой строки.",
   "where": "formPlan.sections[].fillAfter (bool) — validate_form_plan: fillAfter ≤ число секций; performancePlan.arrangementEvents 1–6 при наличии formPlan (stop|thin|air-before|fill); song_breathing.fragmentation (instrumentalSpans ≤ sections+2; доля фраз с паузой ≥ 1 с ≤ 35 %)",
   "gate": "noFragmentation (P0); airBeforeBrand ≥ 1,2 с (P1, сохранено); instrumentalSpans информативно",
   "predicted": "A: 6 филлов (после V1? нет — после PreCh, Ch1, V4, Ch2, Bridge, перед Outro) ≈ 6 промежутков ≥ 1 с; B: 4; C: 5.",
   "risk": "Suno добавляет длинные проигрыши (в раунде 3 версии 2 тег [Instrumental] дал 9,6 с) → длительность растёт и доля спетого падает.",
   "fallback": "Филлы описаны словами «one bar», без тега [Instrumental]; при проигрыше > 4 с — same-take edit (cut-before-brand уже есть в mix_candidate)."
  },
  {
   "id": "H6",
   "name": "Свобода музыки",
   "change": "Темп, тональность, жанр и сид свободны. A: баллада 90 BPM с настоящим припевом; B: фолк-поп 112 BPM с рефреном; C: v2-текст на 96 BPM. Сид: cover на точном оригинале Targ (packet без изменений), но audioWeight 0,35 (A) / 0,40 (B) / 0,60 (C) вместо 0,88–0,90; styleWeight 0,75 / 0,70 / 0,55.",
   "where": "song/cover-<variant>-environment.json (AW/SW/WC, STYLE, NEG, DUR); formPlan.tempoBpm/key/seedDecision; reference-packet без изменений (excerpt travels as inspiration evidence)",
   "gate": "Измерение темпа дубля (librosa beat) и длительности — информативно; решение по сиду подтверждается тем, что темп/длина дубля перестают совпадать с Targ (103,4 BPM, 192–203 с)",
   "predicted": "Все v0–v2 при AW 0,88–0,90 вышли ровно на 103,4 BPM и 192–203 с — сид был часами. При AW ≤ 0,40 ожидаем 88–96 BPM (A) и 108–116 (B); длина 195–230 с.",
   "risk": "При низком AW cover может потерять жанровую опору оригинала (уходит в другой жанр); при высоком — снова часы Targ. «Без сида» невозможно в gen2.py и противоречит правилу «фрагмент оригинала едет в каждом запросе».",
   "fallback": "Сетка AW 0,35 → 0,50 в раунде 2 по измеренному темпу; STYLE несёт явный BPM и жанр."
  },
  {
   "id": "H7",
   "name": "Генерация текста",
   "change": "Панель текста заново вокруг рубрики песенности: singability, rhyme, refrain, breath (одна мысль — одна фраза), stress naturalness, information budget; лирики → судьи → опровергатели; композиционный обзор сравнивает кандидатов друг с другом и с текстом v2, не с таймингом источника.",
   "where": "preparation/panel/ (промпты и ответы, workflow-агенты), song/design-<variant>-drafts.json, design-verdicts; reviews/composition-v01 (Gemini: полный источник как аудио + текст кандидатов; вопросы о песенности, не о близости часов)",
   "gate": "Композиционный обзор accepted-by-agent (validate_plan); stressLedger 100 %; предсказанные строки (H9) до POST",
   "predicted": "Панель даёт 2 черновика на вариант + черновик режиссёра; судьи выбирают/склеивают по рубрике; опровергатели ловят ударения, референты, ложные claims.",
   "risk": "Панель может «улучшить» текст в сторону поэзии в ущерб продаже (advertorial) — судьи проверяют карту 39 мыслей.",
   "fallback": "Карта мыслей t01–t39 обязательна в каждой фразе (meaningIds); validate_plan не пропустит непокрытую мысль."
  },
  {
   "id": "H8",
   "name": "Гейты",
   "change": "Новая таблица «дыхания» измеряется расширением tools/song_gates.py (--form план → строки rests/density/hook/contour/coda/fragmentation/pitch); P0 = инварианты §2 + breathing-строки; старые Targ-относительные строки — информативно.",
   "where": "tools/song_breathing.py (новый модуль, вызывается из song_gates при --form), references/song-breathing-targets-v01.json (priority P0/P1/info, targets с основанием), tests/test_song_breathing.py",
   "gate": "см. таблицу gates ниже",
   "predicted": "—",
   "risk": "ASR-часы ± 0,25 с влияют на подсчёт пауз 0,6 с (порог близок к неопределённости); стем-VAD подтверждает паузы независимо от ASR.",
   "fallback": "Пауза засчитывается, если её подтверждают и ASR-часы, и вокальный стем (VAD < −32 dB); при расхождении — значение из стема."
  },
  {
   "id": "H9",
   "name": "Тренд до покупки",
   "change": "Из текста и плана предсказать каждую строку (слоги по секциям, запланированные паузы, возвраты хука, контур, длительность при заданном темпе) и положить рядом с измеренными v0 → v1 → v2 и Targ; покупать только когда каждая breathing-строка движется в нужную сторону и ни один инвариант не регрессирует; после каждого раунда добавлять измеренное в ту же таблицу.",
   "where": "preparation/predict_v3.py → analysis/predicted-<variant>-vNN.json; таблица тренда в плане (/plan/) и отчёте (/); director-purchase-vNN.json.prediction",
   "gate": "Условие покупки (см. §7); контрольный вариант C — объявленное исключение: плотность не движется по построению",
   "predicted": "A и B: все breathing-строки движутся (rests 3 → ~38–40, доля границ 0,03 → 0,85, плотнейшая 4,6 → 3,3, хук 0 → 3, кода 0/6 → 6/6); длительность 197 → 215–235 с (свободная переменная).",
   "risk": "Предсказание — модель «слоги на такт при темпе»; провайдер может не подчиниться. Поэтому раунд 1 — по одному запросу (два дубля) на вариант, затем измерение до следующего POST.",
   "fallback": "Если после раунда 1 измеренная строка не движется — версия решения режиссёра с конкретным рычагом (текст/директивы/параметры), не повтор."
  }
 ],
 "code": [
  {
   "file": "tools/song_breathing.py (новый)",
   "change": "Функции измерения: rests_at_boundaries (ASR-часы + стем-VAD), section_rates по formPlan.sections, hook_returns по hookLine, coda_facts (факт ↔ фраза ↔ пауза после), fragmentation, contour_rows (chorusLift, climaxPlacement, contourStepMatch, codaSettles), low_pitched_share; собирает строки с priority/target из references/song-breathing-targets-v01.json",
   "enables": "Измеримое «дыхание» и «песенность» на каждом дубле до прослушивания",
   "retires": "Ничего; чистое расширение"
  },
  {
   "file": "tools/song_gates.py",
   "change": "Аргумент --form <song-plan v3>: добавляет breathing-строки к таблице; --targets может помечать строки priority=info (не считаются в passed/p0Failed); блоки берутся из formPlan.sections, а не из BLOCK_STARTS",
   "enables": "Один gates.json на дубль с обеими таблицами (новая P0/P1 + старая информативная)",
   "retires": "BLOCK_STARTS как единственный источник границ; duration ≤ 205 как P0"
  },
  {
   "file": "tools/music_first.py",
   "change": "validate_form_plan(plan): sections[].kind/phraseIds/contour/fillAfter/syllableBudget; hookLine ≥ 4 слов, hookPhraseIds ≥ 3 в разных секциях; phrases[].thoughtBoundary/restAfter (restAfter на ≥ 80 % границ мыслей); codaLayout: шесть factId ↔ phraseId с restAfter; tempoBpm 60–160; seedDecision{mode:cover, audioWeight ≤ 0,6, rationale}; contour steps; проверка бюджета слогов по тексту фраз. Схема adfactory.song-plan/v3 = v2 + formPlan; validate_plan(new_purchase=True) требует v3 при pipeline.songFormPlanRequired; validate_performance_plan при formPlan допускает 1–6 arrangementEvents с kinds stop|thin|air-before|fill",
   "enables": "gen2.py отказывает в покупке без плана формы и дыхания",
   "retires": "«ровно 1–3 события» как жёсткое правило (при formPlan); registerPlan остаётся, но не как таблица Targ"
  },
  {
   "file": "references/song-breathing-targets-v01.json (новый) + references/song-breathing-contract.md (новый)",
   "change": "Таблица строк: id, label, target, direction, priority (P0/P1/info), basis (владелец 2026-09-17 H2/H8 и измеренные v0–v2/Targ); контракт с определениями измерений и правилом пересмотра цели с доказательством",
   "enables": "Цели с происхождением; старые Targ-строки читаемы как info",
   "retires": "runs/targ-delta-…/gate-targets-targ.json как acceptance (остаётся info)"
  },
  {
   "file": "pipeline.json",
   "change": "songFormPlanRequired: true; songBreathingTargets; songBreathingContract; retiredSongGateRows [sustained05, sustainedTimeShare, heldNonFocus, duration]; songGateTargetsPolicy: «Targ-relative rows informational since 2026-09-17»; ownerDecision 2026-09-17",
   "enables": "Политика читается gen2/music_first",
   "retires": "—"
  },
  {
   "file": ".agents/skills/song-clone-ua/SKILL.md, references/music-first-execution.md §9, generation_contracts.md",
   "change": "Раздел «Уточнение владельца 2026-09-17: пусть песня дышит»: форма, бюджет, паузы, контур, сид как вдохновение, снятые строки, отклонённый эксперимент остаётся запретом. После правки SKILL.md — обновить canonicalRequirements.songCloningSkill.sha256 в манифесте run (иначе gen2.py откажет)",
   "enables": "Правила действуют в следующих сессиях",
   "retires": "103 BPM / «no intro, speech-shaped patter» как обязательный стиль"
  },
  {
   "file": "runs/targ-song-v3-08f0d414c5-v01/preparation/*.py (адаптированы из runs/targ-ten-c06fb16085-v01/preparation/)",
   "change": "build_v3.py VARIANT (design → lyrics/ledger/plan v3 с formPlan+performancePlan+предсказанием); predict_v3.py; preflight_v3.py review/close/env; purchase_round.py (тег = вариант+раунд, measure_take с --form); measure_take.py; mix_candidate.py (блоки из formPlan); review_round.py (вопросы: песня или нарратив, паузы между мыслями, разборчивость коды, где мелодия вверх/вниз, кто дышит лучше; вложения: Targ (по контракту), v2, кандидаты); finalize_v3.py (passport v2 + measured gates на вариант); build_delivery.py; tools/build_song_v3_report.py (план /plan/, отчёт /); tools/verify_song_v3_report.py",
   "enables": "Тот же измеряемый цикл покупки с новыми гейтами и несколькими вариантами",
   "retires": "prepare_roundN скрипты, привязанные к тексту v2"
  },
  {
   "file": "tests/test_form_plan.py, tests/test_song_breathing.py (новые)",
   "change": "Валидатор формы (валидный план, мало возвратов хука, паузы < 80 %, факт коды без паузы, бюджет слогов, filler после каждой строки); метрики на синтетических часах (паузы, секции, хук, кода, фрагментация, контур)",
   "enables": "Регрессия при правках",
   "retires": "—"
  }
 ],
 "variants": [
  {
   "id": "A",
   "name": "Балада з приспівом",
   "tempo": "88–92 BPM, 4/4",
   "key": "D-dur / h-moll (по выбору модели; в STYLE — «D major»)",
   "genre": "украинская акустическая баллада: гитара, фортепиано, лёгкие струнные, мягкие щётки",
   "form": "V1 · PreCh · V2 · Ch1 · V3 · V4(slow) · V5 · Ch2 · Bridge · Ch3(climax) · Outro(half-time)",
   "hook": "«Я дивлюсь у дзеркало — і бачу …» ×3 с изменённым концом (колишню / не вірю / свою ціную)",
   "text": "новый текст панели по бюджету H2; все шесть фактов коды и четыре ингредиента спеты",
   "seed": "cover на точном Targ, AW 0,35 · SW 0,75 · WC 0,15",
   "style": "Ukrainian acoustic ballad with a real chorus, 90 BPM, 4/4, D major. Intimate female lead sung on a clear melody from the very first word, no instrumental intro. Verses tell the story in complete sentences; after every finished thought the voice rests for a beat while the band keeps time. The chorus «Я дивлюсь у дзеркало» lifts higher, full voice, and returns three times with a changed last line. Long notes on key words. Band answers only between sections. One bar of guitar before the brand; then a half-tempo outro: one fact per phrase, a rest after each, every word sung.",
   "neg": "spoken word, narration, rap, recitation, instrumental intro, rushed lyrics, fast patter, mumbling, choir, heavy drums, EDM, autotune, reverb wash, fade-in",
   "purpose": "проверить H1+H2+H3 одновременно: настоящий припев, паузы, контур",
   "sketch": {
    "sections": [
     {
      "id": "v1",
      "tag": "[Verse 1]",
      "kind": "verse",
      "title": "Зустріч",
      "thoughts": [
       "t01",
       "t02",
       "t03",
       "t04",
       "t05",
       "t06",
       "t07",
       "t08"
      ],
      "lines": [
       {
        "text": "Зустріла дружину колишнього.",
        "syl": 10
       },
       {
        "text": "Їй тридцять чотири. В очах — жаль.",
        "syl": 9
       },
       {
        "text": "Був березень.",
        "syl": 4
       },
       {
        "text": "Шістнадцять років — і він пішов до колеги.",
        "syl": 13
       },
       {
        "text": "Банально, я знаю.",
        "syl": 6
       },
       {
        "text": "Гарна — час її ще не торкнувся.",
        "syl": 10
       },
       {
        "text": "А я за пів року — старша на п’ять літ.",
        "syl": 11
       }
      ],
      "syllables": 63,
      "phrases": 7,
      "contour": "level-low → up на «жаль» → пауза → аside низко «Був березень» → подъём на «шістнадцять» → спад на «колеги» → низко «Банально» → спад до «п’ять літ»",
      "rests": "rests 7/7 (после каждой фразы)",
      "plannedRests": 7,
      "fillAfter": false,
      "sylPerBar": 8.0,
      "predictedSungSeconds": 21.0,
      "predictedSeconds": 26.2,
      "predictedRate": 3.0
     },
     {
      "id": "pc1",
      "tag": "[Pre-Chorus]",
      "kind": "prechorus",
      "title": "Слід (причинная ячейка)",
      "thoughts": [
       "t09"
      ],
      "lines": [
       {
        "text": "Стрес лишає слід.",
        "syl": 5
       },
       {
        "text": "Сльози лишають слід.",
        "syl": 6
       },
       {
        "text": "Тримати дітей — це теж лишає слід.",
        "syl": 11
       }
      ],
      "syllables": 22,
      "phrases": 3,
      "contour": "три ступени вверх: каждая ячейка на ступень выше, «слід» падает; после третьей — пауза-шарнир",
      "rests": "rests 1/3 (ячейка — одна мысль; пауза после третьей)",
      "plannedRests": 1,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 9.0,
      "predictedSeconds": 12.4,
      "predictedRate": 2.44
     },
     {
      "id": "v2",
      "tag": "[Verse 2]",
      "kind": "verse",
      "title": "Крамниця",
      "thoughts": [
       "t10",
       "t11",
       "t12",
       "t13",
       "t14",
       "t15"
      ],
      "lines": [
       {
        "text": "У суботу в крамниці — лосини, пучок, без косметики.",
        "syl": 17
       },
       {
        "text": "Знов крем. Я пробувала все.",
        "syl": 8
       },
       {
        "text": "І голос її — з сусіднього ряду.",
        "syl": 11
       },
       {
        "text": "Вийшла. Погляд по шиї — дві секунди.",
        "syl": 11
       },
       {
        "text": "Не злість. Гірше. Жалість.",
        "syl": 6
       },
       {
        "text": "Наче я — та, кого він любив колись.",
        "syl": 11
       }
      ],
      "syllables": 64,
      "phrases": 6,
      "contour": "mid ровно (список) → спад «все» → подъём на «голос» → задержка на «дві секунди» → пауза → низко-сухо «Жалість» → спад «колись»",
      "rests": "rests 6/6",
      "plannedRests": 6,
      "fillAfter": false,
      "sylPerBar": 8.0,
      "predictedSungSeconds": 21.3,
      "predictedSeconds": 25.8,
      "predictedRate": 3.0
     },
     {
      "id": "ch1",
      "tag": "[Chorus]",
      "kind": "chorus",
      "title": "Дзеркало I",
      "thoughts": [
       "t16",
       "t17",
       "t18",
       "t19"
      ],
      "lines": [
       {
        "text": "П’ятнадцять хвилин у машині.",
        "syl": 9
       },
       {
        "text": "Злилась не на неї — на себе.",
        "syl": 9
       },
       {
        "text": "Я дивлюсь у дзеркало — і бачу колишню.",
        "syl": 13
       },
       {
        "text": "На шиї — смуги, заломи, сухість.",
        "syl": 10
       },
       {
        "text": "І світло в мені згасло.",
        "syl": 7
       }
      ],
      "syllables": 48,
      "phrases": 5,
      "contour": "high: подъём на «машині» → «на себе» вершина припева → хук на верхней плоскости, «колишню» садится → перечисление ниже → «згасло» самая низкая нота секции, долгая",
      "rests": "rests 5/5; хук #1",
      "plannedRests": 5,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 19.7,
      "predictedSeconds": 26.1,
      "predictedRate": 2.44
     },
     {
      "id": "v3",
      "tag": "[Verse 3]",
      "kind": "verse",
      "title": "Лариса",
      "thoughts": [
       "t20",
       "t21",
       "t22",
       "t23",
       "t24"
      ],
      "lines": [
       {
        "text": "Того тижня чекала доньку з танців.",
        "syl": 11
       },
       {
        "text": "Лариса там щодня: п’ятдесят п’ять — а шия гладенька.",
        "syl": 16
       },
       {
        "text": "Питаю: «Чим ти користуєшся?»",
        "syl": 10
       },
       {
        "text": "Сміється: «А ти що наносиш?»",
        "syl": 9
       },
       {
        "text": "«Кислоти, сироватки, креми — все підряд».",
        "syl": 12
       },
       {
        "text": "«Стій. Не все підряд. Доглядай щодня».",
        "syl": 10
       }
      ],
      "syllables": 68,
      "phrases": 6,
      "contour": "низкая подводка → mid факт → вопрос вверх (мелодическая игра, hold на -ту́-) → Лариса ниже и суше → список mid быстро → «Стій» stop-event, совет ровно",
      "rests": "rests 6/6; stop на «Стій»",
      "plannedRests": 6,
      "fillAfter": true,
      "sylPerBar": 9.0,
      "predictedSungSeconds": 20.1,
      "predictedSeconds": 27.3,
      "predictedRate": 3.38
     },
     {
      "id": "v4",
      "tag": "[Verse 4 — slower]",
      "kind": "verse",
      "title": "Банка",
      "thoughts": [
       "t25",
       "t26",
       "t27"
      ],
      "lines": [
       {
        "text": "Назавтра дала мені банку — крем, якого я не знала.",
        "syl": 17
       },
       {
        "text": "Купуасу, гіалурон, оливні ліпіди, кофеїн.",
        "syl": 17
       },
       {
        "text": "На чисту шию — тонко, вгору, щовечора. Не міняй.",
        "syl": 16
       },
       {
        "text": "Без печіння, без лущення. Комфортно.",
        "syl": 11
       }
      ],
      "syllables": 61,
      "phrases": 4,
      "contour": "спокойно low-mid; ингредиенты чётко на ступенях; ритуал ровно; «Комфортно» — тёплая долгая нота",
      "rests": "rests 4/4",
      "plannedRests": 4,
      "fillAfter": true,
      "sylPerBar": 7.0,
      "predictedSungSeconds": 23.2,
      "predictedSeconds": 28.9,
      "predictedRate": 2.63
     },
     {
      "id": "v5",
      "tag": "[Verse 5]",
      "kind": "verse",
      "title": "Три тижні",
      "thoughts": [
       "t28",
       "t29"
      ],
      "lines": [
       {
        "text": "Три тижні — і біля дзеркала: смуги менш помітні.",
        "syl": 15
       },
       {
        "text": "Донька каже: «Мамо, ти інакша. Світліша».",
        "syl": 13
       }
      ],
      "syllables": 28,
      "phrases": 2,
      "contour": "mid → дочь светлее и выше; пауза перед припевом",
      "rests": "rests 2/2; fill перед припевом",
      "plannedRests": 2,
      "fillAfter": true,
      "sylPerBar": 8.0,
      "predictedSungSeconds": 9.3,
      "predictedSeconds": 13.5,
      "predictedRate": 3.0
     },
     {
      "id": "ch2",
      "tag": "[Chorus]",
      "kind": "chorus",
      "title": "Дзеркало II",
      "thoughts": [
       "t30",
       "t31"
      ],
      "lines": [
       {
        "text": "А за шість — я дивлюсь у дзеркало — не вірю.",
        "syl": 13
       },
       {
        "text": "Шия гладенька. Ні смуг, ні заломів.",
        "syl": 11
       },
       {
        "text": "Десять років такою не була.",
        "syl": 10
       },
       {
        "text": "І з відкритою шиєю — на люди.",
        "syl": 11
       }
      ],
      "syllables": 45,
      "phrases": 4,
      "contour": "high: хук #2 на той же плоскости, «не вірю» вверх; «гладенька» держится; спад к «на люди» с открытым звуком",
      "rests": "rests 4/4; хук #2",
      "plannedRests": 4,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 18.5,
      "predictedSeconds": 24.1,
      "predictedRate": 2.44
     },
     {
      "id": "br",
      "tag": "[Bridge]",
      "kind": "bridge",
      "title": "Червень",
      "thoughts": [
       "t32",
       "t33",
       "t34",
       "t35"
      ],
      "lines": [
       {
        "text": "У червні — концерт доньчиного класу.",
        "syl": 11
       },
       {
        "text": "Дружина Андрія сіла неподалік.",
        "syl": 12
       },
       {
        "text": "Знов той погляд: не жалість — розгубленість.",
        "syl": 11
       },
       {
        "text": "Після концерту: «Ти гарно виглядаєш… до речі».",
        "syl": 15
       },
       {
        "text": "Та сама, через яку я сиділа в машині.",
        "syl": 14
       }
      ],
      "syllables": 63,
      "phrases": 5,
      "contour": "mid, стаккато отрицаний; «до речі» брошено низко после паузы; «в машині» — спад и пауза-шарнир перед кульминацией",
      "rests": "rests 5/5",
      "plannedRests": 5,
      "fillAfter": true,
      "sylPerBar": 8.0,
      "predictedSungSeconds": 21.0,
      "predictedSeconds": 27.4,
      "predictedRate": 3.0
     },
     {
      "id": "ch3",
      "tag": "[Chorus — climax]",
      "kind": "chorus",
      "title": "Дзеркало III",
      "thoughts": [
       "t36",
       "t37"
      ],
      "lines": [
       {
        "text": "Я сказала «дякую» — і справді так відчувала.",
        "syl": 15
       },
       {
        "text": "Не тому, що її думка важить —",
        "syl": 10
       },
       {
        "text": "я дивлюсь у дзеркало — і свою ціную.",
        "syl": 13
       }
      ],
      "syllables": 38,
      "phrases": 3,
      "contour": "кульминация песни: подъём к «свою» (самая высокая и долгая нота), «ціную» садится и завершает каданс",
      "rests": "rests 3/3; хук #3 (климакс)",
      "plannedRests": 3,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 15.6,
      "predictedSeconds": 20.5,
      "predictedRate": 2.44
     },
     {
      "id": "coda",
      "tag": "[Outro — half-time]",
      "kind": "coda",
      "title": "Ґоу П’юр",
      "thoughts": [
       "t38",
       "t39"
      ],
      "lines": [
       {
        "text": "Крем називається Ґоу П’юр.",
        "syl": 9
       },
       {
        "text": "Ім’я і номер — у формі.",
        "syl": 8
       },
       {
        "text": "На пошті оглянь — платиш потім.",
        "syl": 9
       },
       {
        "text": "Повернення — шістдесят днів.",
        "syl": 8
       },
       {
        "text": "Якщо потрібно — посилання внизу.",
        "syl": 11
       }
      ],
      "syllables": 45,
      "phrases": 5,
      "contour": "mid-low, ровно, каждый факт — падающий каданс с паузой ≥ 0,5 с; один такт гитары перед брендом; последняя строка тише, спета",
      "rests": "rests 5/5 (после каждого факта)",
      "plannedRests": 5,
      "fillAfter": false,
      "sylPerBar": 5.0,
      "predictedSungSeconds": 24.0,
      "predictedSeconds": 27.8,
      "predictedRate": 1.88
     }
    ],
    "syllables": 545,
    "phrases": 50,
    "plannedRests": 48,
    "boundaries": 50,
    "restShare": 0.96,
    "predictedDuration": 262.0,
    "predictedSungSeconds": 202.7,
    "predictedSungRate": 2.69,
    "predictedMaxSectionRate": 3.38,
    "assumption": "90 BPM; слогов на такт по типу секции: {'verse': 8.0, 'prechorus': 6.5, 'chorus': 6.5, 'bridge': 8.0, 'coda': 5.0, 'Лариса': 9.0, 'Банка': 7.0}; пауза 0.75 с на запланированной границе мысли; один такт филла на отмеченных границах; +2 с хвост",
    "budget": 480,
    "atBudget": {
     "syllables": 480,
     "predictedSungSeconds": 178.5,
     "predictedDuration": 237.8,
     "predictedSungRate": 2.69,
     "predictedMaxSectionRate": 3.38,
     "note": "Бюджет панели 480 слогов (эскиз режиссёра 545 — верхняя граница, сжать на 12 %): та же плотность на такт, короче спетый интервал"
    }
   }
  },
  {
   "id": "B",
   "name": "Фолк-поп з рефреном-запитанням",
   "tempo": "110–114 BPM, 4/4",
   "key": "G-dur (в STYLE — «G major»)",
   "genre": "светлый фолк-поп: акустические гитары, мандолина, ручная перкуссия, тёплый бас",
   "form": "V1 · R1 · V2 · V3 · R2 · V4 · V5(softer) · V6 · R3 · Bridge(climax) · Outro(half-time)",
   "hook": "«Дивлюсь на себе — і що я бачу?» ×3 с ответом в одно слово (слід / Колишню / Себе): мелодическая игра вопрос-ответ",
   "text": "новый текст панели, короче A (≈ 500 слогов); гипотеза H2b: спеты купуасу и гіалурон, оливні ліпіди и кофеїн — визуальный канал (fallback: строка A)",
   "seed": "cover на точном Targ, AW 0,40 · SW 0,70 · WC 0,20",
   "style": "Ukrainian folk-pop, 112 BPM, bright acoustic guitars, mandolin, hand percussion, warm bass. Female lead sung from beat one, no intro. Every thought is one complete sung phrase followed by a short rest; a playful refrain question «Дивлюсь на себе — і що я бачу?» returns three times with a new one-word answer, the melody rising on the question and settling on the answer. Instrumental fills only at scene changes, never after every line. Half-time outro: the brand and each ordering condition on its own phrase with a rest between them, all sung.",
   "neg": "spoken word, narration, rap, recitation, instrumental intro, rushed lyrics, fast patter, mumbling, choir, EDM, autotune, reverb wash, fade-in",
   "purpose": "музыкально другой ответ на тот же бюджет: быстрее, рефрен вместо припева, игра вопрос-ответ",
   "sketch": {
    "sections": [
     {
      "id": "v1",
      "tag": "[Verse 1]",
      "kind": "verse",
      "title": "Зустріч",
      "thoughts": [
       "t01",
       "t02",
       "t03",
       "t04",
       "t05",
       "t06",
       "t07",
       "t08"
      ],
      "lines": [
       {
        "text": "Зустріла дружину колишнього — їй тридцять чотири.",
        "syl": 16
       },
       {
        "text": "Глянула так, наче їй мене жаль.",
        "syl": 10
       },
       {
        "text": "Був березень.",
        "syl": 4
       },
       {
        "text": "Шістнадцять років шлюбу — і він пішов до колеги.",
        "syl": 15
       },
       {
        "text": "Банально, знаю. Гарна, бо час її не торкнувся.",
        "syl": 15
       },
       {
        "text": "А я за пів року — на п’ять літ старша.",
        "syl": 11
       }
      ],
      "syllables": 71,
      "phrases": 6,
      "contour": "ровный пульс, фразы по 2 такта; подъём на «жаль»; аside низко; спад к «старша»",
      "rests": "rests 6/6",
      "plannedRests": 6,
      "fillAfter": false,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 23.4,
      "predictedSeconds": 27.6,
      "predictedRate": 3.03
     },
     {
      "id": "r1",
      "tag": "[Refrain]",
      "kind": "refrain",
      "title": "Рефрен I",
      "thoughts": [
       "t09"
      ],
      "lines": [
       {
        "text": "Дивлюсь на себе — і що я бачу?",
        "syl": 10
       },
       {
        "text": "Стрес, сльози, діти — все лишає слід.",
        "syl": 10
       }
      ],
      "syllables": 20,
      "phrases": 2,
      "contour": "вопрос вверх (игра), ответ падает; хук #1",
      "rests": "rests 2/2",
      "plannedRests": 2,
      "fillAfter": true,
      "sylPerBar": 4.5,
      "predictedSungSeconds": 9.5,
      "predictedSeconds": 13.1,
      "predictedRate": 2.1
     },
     {
      "id": "v2",
      "tag": "[Verse 2]",
      "kind": "verse",
      "title": "Крамниця",
      "thoughts": [
       "t10",
       "t11",
       "t12",
       "t13",
       "t14",
       "t15"
      ],
      "lines": [
       {
        "text": "Субота, крамниця, лосини, пучок, без косметики.",
        "syl": 16
       },
       {
        "text": "Знов крем — я пробувала все.",
        "syl": 8
       },
       {
        "text": "Її голос — із сусіднього ряду.",
        "syl": 11
       },
       {
        "text": "Вийшла. Погляд по шиї, дві секунди — усмішка.",
        "syl": 14
       },
       {
        "text": "Не злість. Ще гірше — жалість.",
        "syl": 7
       },
       {
        "text": "Наче я — та, кого він любив колись.",
        "syl": 11
       }
      ],
      "syllables": 67,
      "phrases": 6,
      "contour": "mid → спад → подъём «голос» → задержка → низко «жалість» → спад",
      "rests": "rests 6/6",
      "plannedRests": 6,
      "fillAfter": false,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 22.1,
      "predictedSeconds": 26.3,
      "predictedRate": 3.03
     },
     {
      "id": "v3",
      "tag": "[Verse 3]",
      "kind": "verse",
      "title": "Машина",
      "thoughts": [
       "t16",
       "t17",
       "t18",
       "t19"
      ],
      "lines": [
       {
        "text": "П’ятнадцять хвилин у машині.",
        "syl": 9
       },
       {
        "text": "Злилась не на неї — на себе в дзеркалі.",
        "syl": 12
       },
       {
        "text": "На шиї — смуги, заломи, сухість.",
        "syl": 10
       },
       {
        "text": "І світло в мені згасло.",
        "syl": 7
       }
      ],
      "syllables": 38,
      "phrases": 4,
      "contour": "сжато к низу; «згасло» долгая низкая",
      "rests": "rests 4/4",
      "plannedRests": 4,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 12.5,
      "predictedSeconds": 17.5,
      "predictedRate": 3.03
     },
     {
      "id": "r2",
      "tag": "[Refrain]",
      "kind": "refrain",
      "title": "Рефрен II",
      "thoughts": [],
      "lines": [
       {
        "text": "Дивлюсь на себе — і що я бачу?",
        "syl": 10
       },
       {
        "text": "Колишню.",
        "syl": 3
       }
      ],
      "syllables": 13,
      "phrases": 2,
      "contour": "вопрос вверх, ответ одно слово низко; хук #2",
      "rests": "rests 2/2; fill",
      "plannedRests": 2,
      "fillAfter": true,
      "sylPerBar": 4.5,
      "predictedSungSeconds": 6.2,
      "predictedSeconds": 9.7,
      "predictedRate": 2.1
     },
     {
      "id": "v4",
      "tag": "[Verse 4]",
      "kind": "verse",
      "title": "Лариса",
      "thoughts": [
       "t20",
       "t21",
       "t22",
       "t23",
       "t24"
      ],
      "lines": [
       {
        "text": "Того тижня чекала доньку з танців.",
        "syl": 11
       },
       {
        "text": "Лариса — п’ятдесят п’ять, а шия гладенька.",
        "syl": 13
       },
       {
        "text": "Питаю: «Чим ти користуєшся?»",
        "syl": 10
       },
       {
        "text": "Сміється: «А ти що наносиш?»",
        "syl": 9
       },
       {
        "text": "«Кислоти, сироватки, креми — все підряд».",
        "syl": 12
       },
       {
        "text": "«Стій. Не все підряд. Доглядай щодня».",
        "syl": 10
       }
      ],
      "syllables": 65,
      "phrases": 6,
      "contour": "подводка low → вопрос вверх → Лариса ниже → список → «Стій» stop",
      "rests": "rests 6/6; stop",
      "plannedRests": 6,
      "fillAfter": true,
      "sylPerBar": 7.5,
      "predictedSungSeconds": 18.6,
      "predictedSeconds": 24.9,
      "predictedRate": 3.5
     },
     {
      "id": "v5",
      "tag": "[Verse 5 — softer]",
      "kind": "verse",
      "title": "Банка",
      "thoughts": [
       "t25",
       "t26",
       "t27"
      ],
      "lines": [
       {
        "text": "Назавтра — банка. Крем, якого я не знала.",
        "syl": 13
       },
       {
        "text": "Купуасу й гіалурон — тонко, вгору, щовечора.",
        "syl": 16
       },
       {
        "text": "Без печіння, без лущення. Комфортно.",
        "syl": 11
       }
      ],
      "syllables": 40,
      "phrases": 3,
      "contour": "low-mid спокойно; «Комфортно» долгая; гипотеза H2b: оливні ліпіди й кофеїн — визуальный канал (fallback: строка варианта A)",
      "rests": "rests 3/3",
      "plannedRests": 3,
      "fillAfter": true,
      "sylPerBar": 6.0,
      "predictedSungSeconds": 14.3,
      "predictedSeconds": 18.5,
      "predictedRate": 2.8
     },
     {
      "id": "v6",
      "tag": "[Verse 6]",
      "kind": "verse",
      "title": "Зміна",
      "thoughts": [
       "t28",
       "t29",
       "t30",
       "t31"
      ],
      "lines": [
       {
        "text": "Три тижні — біля дзеркала: смуги менш помітні.",
        "syl": 14
       },
       {
        "text": "Донька: «Мамо, ти інакша. Світліша».",
        "syl": 11
       },
       {
        "text": "А за шість — не вірю: шия гладенька, ні смуг, ні заломів.",
        "syl": 17
       },
       {
        "text": "Десять років такою не була — і з відкритою шиєю на люди.",
        "syl": 21
       }
      ],
      "syllables": 63,
      "phrases": 4,
      "contour": "подъём по фразам к «на люди»; пауза перед рефреном",
      "rests": "rests 4/4; fill",
      "plannedRests": 4,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 20.8,
      "predictedSeconds": 25.7,
      "predictedRate": 3.03
     },
     {
      "id": "r3",
      "tag": "[Refrain]",
      "kind": "refrain",
      "title": "Рефрен III",
      "thoughts": [],
      "lines": [
       {
        "text": "Дивлюсь на себе — і що я бачу?",
        "syl": 10
       },
       {
        "text": "Себе.",
        "syl": 2
       }
      ],
      "syllables": 12,
      "phrases": 2,
      "contour": "вопрос вверх, ответ тёплый выше, чем «Колишню»; хук #3",
      "rests": "rests 2/2",
      "plannedRests": 2,
      "fillAfter": true,
      "sylPerBar": 4.5,
      "predictedSungSeconds": 5.7,
      "predictedSeconds": 9.3,
      "predictedRate": 2.1
     },
     {
      "id": "br",
      "tag": "[Bridge]",
      "kind": "bridge",
      "title": "Червень",
      "thoughts": [
       "t32",
       "t33",
       "t34",
       "t35",
       "t36",
       "t37"
      ],
      "lines": [
       {
        "text": "У червні — концерт доньчиного класу; дружина Андрія — неподалік.",
        "syl": 21
       },
       {
        "text": "Знов той погляд: не жалість — розгубленість.",
        "syl": 11
       },
       {
        "text": "Після концерту: «Ти гарно виглядаєш… до речі».",
        "syl": 15
       },
       {
        "text": "Та сама, через яку я сиділа в машині.",
        "syl": 14
       },
       {
        "text": "Я сказала «дякую» — і справді так відчувала.",
        "syl": 15
       },
       {
        "text": "Не тому, що її думка важить — а тому, що свою ціную.",
        "syl": 19
       }
      ],
      "syllables": 95,
      "phrases": 6,
      "contour": "стаккато отрицаний → «до речі» брошено низко → кульминация на «свою» (высшая нота песни) → спад «ціную»",
      "rests": "rests 6/6; climax",
      "plannedRests": 6,
      "fillAfter": true,
      "sylPerBar": 6.5,
      "predictedSungSeconds": 31.3,
      "predictedSeconds": 37.7,
      "predictedRate": 3.03
     },
     {
      "id": "coda",
      "tag": "[Outro — half-time]",
      "kind": "coda",
      "title": "Ґоу П’юр",
      "thoughts": [
       "t38",
       "t39"
      ],
      "lines": [
       {
        "text": "Крем — Ґоу П’юр.",
        "syl": 4
       },
       {
        "text": "Залиш ім’я і номер у формі.",
        "syl": 10
       },
       {
        "text": "Оглянь на пошті — оплата потім.",
        "syl": 10
       },
       {
        "text": "Шістдесят днів на повернення.",
        "syl": 9
       },
       {
        "text": "Посилання внизу — якщо тобі потрібно.",
        "syl": 13
       }
      ],
      "syllables": 46,
      "phrases": 5,
      "contour": "half-time; каждый факт — падающий каданс с паузой; бренд ещё раз последним словом? — нет: бренд один раз, «посилання» последнее",
      "rests": "rests 5/5",
      "plannedRests": 5,
      "fillAfter": false,
      "sylPerBar": 4.0,
      "predictedSungSeconds": 24.6,
      "predictedSeconds": 28.1,
      "predictedRate": 1.87
     }
    ],
    "syllables": 530,
    "phrases": 46,
    "plannedRests": 46,
    "boundaries": 46,
    "restShare": 1.0,
    "predictedDuration": 240.4,
    "predictedSungSeconds": 189.0,
    "predictedSungRate": 2.8,
    "predictedMaxSectionRate": 3.5,
    "assumption": "112 BPM; слогов на такт по типу секции: {'verse': 6.5, 'refrain': 4.5, 'bridge': 6.5, 'coda': 4.0, 'Лариса': 7.5, 'Банка': 6.0}; пауза 0.7 с на запланированной границе мысли; один такт филла на отмеченных границах; +2 с хвост",
    "budget": 460,
    "atBudget": {
     "syllables": 460,
     "predictedSungSeconds": 164.0,
     "predictedDuration": 208.9,
     "predictedSungRate": 2.8,
     "predictedMaxSectionRate": 3.5,
     "note": "Бюджет панели 460 слогов (эскиз режиссёра 530 — верхняя граница, сжать на 13 %): та же плотность на такт, короче спетый интервал"
    }
   }
  },
  {
   "id": "C",
   "name": "Контроль: текст v2 в дышащей форме",
   "tempo": "96 BPM",
   "key": "как выберет модель",
   "genre": "акустический фолк-поп, ближе к сиду",
   "form": "девять секций v2 с тегами [Verse]/[Bridge]/[Outro], без припева; паузы после каждой строки-мысли; филлы только между секциями",
   "hook": "нет (по построению)",
   "text": "текст v2 дословно (665 слогов, 59 фраз, тот же ledger ударений слов; изменены только директивы в скобках)",
   "seed": "cover на точном Targ, AW 0,60 · SW 0,55 · WC 0,10",
   "style": "Ukrainian acoustic folk-pop, 96 BPM, no intro, female lead sung on a clear melody throughout. Unhurried: after every sentence the voice rests for a beat; instrumental fills only between scenes. Full-voice sung dialogue, list and order block; half-time outro with a rest after each fact.",
   "neg": "spoken word, narration, rap, recitation, instrumental intro, instrumental answers after every line, melisma on word endings, reverb wash, choir",
   "purpose": "отделить эффект музыки/аранжировки от эффекта текста: тот же текст, что v2, только форма и темп",
   "sketch": {
    "budget": 665,
    "atBudget": null,
    "syllables": 665,
    "phrases": 59,
    "plannedRests": 58,
    "boundaries": 58,
    "restShare": 0.5,
    "predictedDuration": 221.8,
    "predictedSungSeconds": 192.8,
    "predictedSungRate": 3.45,
    "predictedMaxSectionRate": 4.3,
    "assumption": "96 BPM с текстом v2 (665 слогов): v2 пела 9,3 слога на такт при 103 BPM; при 96 BPM и той же плотности слов ожидаем ≈ 3,45 слог/с; паузы заложены после каждой строки, но текст не оставляет места — предсказана половина границ; пять филлов по такту; секция «Лариса» v2 предсказана 4,3",
    "sections": []
   }
  }
 ],
 "gates": [
  {
   "id": "blindSongVerdict",
   "label": "Слепой вердикт: песня, не нарратив; спето насквозь",
   "priority": "P0",
   "target": "«sung throughout» и «song, not narration» у всех рецензентов",
   "targ": "sung",
   "v0": "sung",
   "v1": "sung",
   "v2": "sung (rounds 3–4 recited)",
   "pred": {
    "A": "sung",
    "B": "sung",
    "C": "sung"
   },
   "basis": "§2 владельца; измеряется слепым Gemini-обзором"
  },
  {
   "id": "stressLedger",
   "label": "Ledger ударений: все слова разрешены до POST",
   "priority": "P0",
   "target": "100 %",
   "targ": "—",
   "v0": "100 %",
   "v1": "100 %",
   "v2": "100 %",
   "pred": {
    "A": "100 %",
    "B": "100 %",
    "C": "100 % (ledger v2)"
   },
   "basis": "§2; tools/song_stress.py"
  },
  {
   "id": "asrLineMatch",
   "label": "ASR: доля совпавших строк",
   "priority": "P0",
   "target": "≥ 0,95",
   "targ": "—",
   "v0": "—",
   "v1": "—",
   "v2": 0.983,
   "pred": {
    "A": "≥ 0,95",
    "B": "≥ 0,95",
    "C": "≥ 0,95"
   },
   "basis": "§2 разборчивость; scripts/lines_check.py"
  },
  {
   "id": "restBoundaryShare",
   "label": "Доля границ мыслей с паузой ≥ 0,6 с",
   "priority": "P0",
   "target": "≥ 0,80",
   "targ": 0.097,
   "v0": 0.0,
   "v1": 0.102,
   "v2": 0.034,
   "pred": {
    "A": 0.96,
    "B": 1.0,
    "C": 0.5
   },
   "basis": "H2; для базовых версий граница = конец строки текста"
  },
  {
   "id": "restCount",
   "label": "Пауз ≥ 0,6 с (между словами, до последнего слова)",
   "priority": "P1",
   "target": "≥ 0,8 × запланированных",
   "targ": 9,
   "v0": 5,
   "v1": 6,
   "v2": 3,
   "pred": {
    "A": 48,
    "B": 46,
    "C": 58
   },
   "basis": "H2"
  },
  {
   "id": "maxSectionRate",
   "label": "Самая плотная секция, слог/с по спетому интервалу",
   "priority": "P0",
   "target": "≤ 3,2",
   "targ": 3.64,
   "v0": 4.7,
   "v1": 4.13,
   "v2": 4.61,
   "pred": {
    "A": 3.38,
    "B": 3.5,
    "C": 4.3
   },
   "basis": "H2 (сейчас 4,6–5,1 в зависимости от сегментации)"
  },
  {
   "id": "sungRate",
   "label": "Вся песня, слог/с по спетому интервалу",
   "priority": "P0 (гипотеза, пересмотр с доказательством)",
   "target": "≤ 2,8",
   "targ": 3.26,
   "v0": 3.86,
   "v1": 3.62,
   "v2": 3.61,
   "pred": {
    "A": 2.69,
    "B": 2.8,
    "C": 3.45
   },
   "basis": "H2; предсказание A/B 2,9–3,05 — движение в нужную сторону, цель ≤ 2,8 проверяется на дублях"
  },
  {
   "id": "hookReturns",
   "label": "Возвраты хук-строки (≥ 4 слова, ≥ 3 позиции ≥ 20 с)",
   "priority": "P0",
   "target": "≥ 3",
   "targ": 0,
   "v0": 0,
   "v1": 0,
   "v2": 0,
   "pred": {
    "A": 3,
    "B": 3,
    "C": 0
   },
   "basis": "H1; C — контроль без хука"
  },
  {
   "id": "codaFactsRested",
   "label": "Факты коды спеты, каждый с паузой ≥ 0,5 с после",
   "priority": "P0",
   "target": "6/6",
   "targ": "2/3 (brand, link, if-you-need)",
   "v0": "0/6",
   "v1": "0/6",
   "v2": "0/6",
   "pred": {
    "A": "6/6",
    "B": "6/6",
    "C": "6/6"
   },
   "basis": "§2 условия заказа; H2 кода"
  },
  {
   "id": "noFragmentation",
   "label": "Без фрагментации: фраз ≤ 2 слов ≤ 10 %; промежутков ≥ 1 с ≤ секций + 2; пауза ≥ 1 с не более чем после 35 % фраз",
   "priority": "P0",
   "target": "все три",
   "targ": "0,22 / 0 / —",
   "v0": "0,02 / — / —",
   "v1": "0,02 / 5 / —",
   "v2": "0,02 / 4 / —",
   "pred": {
    "A": "0,00 / ≤ 8 / ≤ 0,2",
    "B": "0,04 (ответы рефрена) / ≤ 6 / ≤ 0,2",
    "C": "0,02 / ≤ 7 / ≤ 0,3"
   },
   "basis": "§2 отклонённый эксперимент 2026-09-15"
  },
  {
   "id": "firstAudibleEvent",
   "label": "Первое слышимое событие — спетое слово хука (после обрезки затакта)",
   "priority": "P0",
   "target": "вокал ≤ 0,3 с от начала мастера",
   "targ": "0,0",
   "v0": "0,0",
   "v1": "0,0",
   "v2": "0,0",
   "pred": {
    "A": "0,0",
    "B": "0,0",
    "C": "0,0"
   },
   "basis": "§2; master_candidate trim"
  },
  {
   "id": "chorusLift",
   "label": "Медиана высоты припева/рефрена − медиана куплетов, полутона",
   "priority": "P1",
   "target": "≥ 2",
   "targ": "— (нет припева)",
   "v0": "—",
   "v1": "—",
   "v2": "—",
   "pred": {
    "A": "+3…+5",
    "B": "+2…+4 (вопрос)",
    "C": "—"
   },
   "basis": "H3"
  },
  {
   "id": "climaxPlacement",
   "label": "Фраза с наивысшим p90 — в запланированной секции кульминации",
   "priority": "P1",
   "target": "да",
   "targ": "«sympathetic/first» (V2) и «use?»",
   "v0": "—",
   "v1": "—",
   "v2": "«свою» (план) — измерено p90 72 на «опора»",
   "pred": {
    "A": "Ch3 «свою»",
    "B": "Bridge «свою»",
    "C": "selfworth «свою»"
   },
   "basis": "H3"
  },
  {
   "id": "contourStepMatch",
   "label": "Доля запланированных шагов up/down/same, совпавших с медианами фраз (± 1 st)",
   "priority": "P1",
   "target": "≥ 0,6",
   "targ": "—",
   "v0": "—",
   "v1": "—",
   "v2": "—",
   "pred": {
    "A": "≥ 0,6",
    "B": "≥ 0,6",
    "C": "—"
   },
   "basis": "H3"
  },
  {
   "id": "codaSettles",
   "label": "Медиана коды ≤ медиана припева − 2 st",
   "priority": "P1",
   "target": "да",
   "targ": "да (кода 1,8 слог/с, низко)",
   "v0": "—",
   "v1": "—",
   "v2": "—",
   "pred": {
    "A": "да",
    "B": "да",
    "C": "—"
   },
   "basis": "H3/H2"
  },
  {
   "id": "restMedian",
   "label": "Медианная пауза на границах мыслей, с",
   "priority": "P1",
   "target": "≥ 0,8",
   "targ": 0.78,
   "v0": 1.06,
   "v1": 1.11,
   "v2": 1.14,
   "pred": {
    "A": "0,8–1,2",
    "B": "0,7–1,0",
    "C": "0,7"
   },
   "basis": "H2"
  },
  {
   "id": "phraseRateCV",
   "label": "CV скорости подачи по фразам (разнообразие темпа речи)",
   "priority": "P1",
   "target": "≥ 0,35",
   "targ": 0.328,
   "v0": 0.207,
   "v1": 0.272,
   "v2": 0.24,
   "pred": {
    "A": "≥ 0,35",
    "B": "≥ 0,35",
    "C": "0,3"
   },
   "basis": "из дельта-анализа; медленные payoff против быстрых списков"
  },
  {
   "id": "lowPitchedPhraseShare",
   "label": "Доля фраз с pitched-share < 0,15 (прокси речитатива)",
   "priority": "P1",
   "target": "≤ 0,10",
   "targ": "—",
   "v0": "—",
   "v1": "—",
   "v2": 0.153,
   "pred": {
    "A": "≤ 0,10",
    "B": "≤ 0,10",
    "C": "≤ 0,15"
   },
   "basis": "H4; метрика на стемах — только прокси, вердикт даёт слепой обзор"
  },
  {
   "id": "vocMinusMusicWorst",
   "label": "Вокал − музыка, худший блок кроме коды, dB",
   "priority": "P1",
   "target": "≥ −1",
   "targ": -1.0,
   "v0": "—",
   "v1": -4.4,
   "v2": 0.7,
   "pred": {
    "A": "≥ −1 (remix при нужде)",
    "B": "≥ −1",
    "C": "≥ −1"
   },
   "basis": "микс из дельта-анализа; same-take remix доступен"
  },
  {
   "id": "airBeforeBrand",
   "label": "Воздух без слов перед брендом, с",
   "priority": "P1",
   "target": "≥ 1,2",
   "targ": 2.3,
   "v0": "—",
   "v1": 0.0,
   "v2": 2.27,
   "pred": {
    "A": "≥ 1,2 (один такт)",
    "B": "≥ 1,2",
    "C": "≥ 1,2"
   },
   "basis": "H5"
  },
  {
   "id": "duration",
   "label": "Длительность, с (свободная переменная)",
   "priority": "info",
   "target": "—",
   "targ": 194.489,
   "v0": 197.726,
   "v1": 203.240998,
   "v2": 197.103991,
   "pred": {
    "A": 237.8,
    "B": 208.9,
    "C": 221.8
   },
   "basis": "§0 свобода; cover наследует длину сида — измерить"
  },
  {
   "id": "syllables",
   "label": "Слогов",
   "priority": "info",
   "target": "—",
   "targ": 576,
   "v0": 714,
   "v1": 701,
   "v2": 665,
   "pred": {
    "A": 480,
    "B": 460,
    "C": 665
   },
   "basis": "бюджет H2"
  },
  {
   "id": "sustained05",
   "label": "Нот ≥ 0,5 с (снято с гейтов; долгие ноты желательны)",
   "priority": "info",
   "target": "—",
   "targ": 8,
   "v0": "—",
   "v1": 20,
   "v2": 11,
   "pred": {
    "A": "20–35",
    "B": "15–25",
    "C": "12–20"
   },
   "basis": "H4"
  },
  {
   "id": "registerSpread",
   "label": "Разброс медиан фраз (10–90 перц.), полутона (info)",
   "priority": "info",
   "target": "—",
   "targ": 12.0,
   "v0": "—",
   "v1": 7.2,
   "v2": 11.8,
   "pred": {
    "A": "≥ 10",
    "B": "≥ 10",
    "C": "~11"
   },
   "basis": "бывшая P0-строка Targ"
  },
  {
   "id": "tempoBpm",
   "label": "Темп дубля, BPM (info: проверка сида как вдохновения)",
   "priority": "info",
   "target": "—",
   "targ": 103.4,
   "v0": 103.4,
   "v1": 103.4,
   "v2": 103.4,
   "pred": {
    "A": "88–92",
    "B": "110–114",
    "C": "94–100"
   },
   "basis": "H6"
  }
 ],
 "purchase": {
  "round1": "Три запроса cover V6 (A, B, C) по два дубля — 36 кредитов; все шесть дублей измеряются до прослушивания (lines_check + song_gates --form); слепой whole-обзор (Targ по контракту + v2 + до двух кандидатов) для дублей, прошедших P0, ~1 кредит на обзор.",
  "round2": "На вариант — версия решения режиссёра с конкретным рычагом (текст-lean 470 слогов / директивы / AW-сетка / темп); не более трёх раундов на вариант (≤ 108 кредитов на вариант); same-take remix бесплатно для строк микса.",
  "reviews": "Whole-обзор на кандидата + «кто дышит лучше» сравнение (кандидаты + v2) + локальные пары (Лариса, кода) — ≤ 15 кредитов.",
  "budget": "Баланс на старте 121 140 кредитов; потолок сессии 400 кредитов (≈ 3 %); фактический расход ведётся в song/credits-ledger-v01.json.",
  "stop": "Стоп (§6): хотя бы один кандидат спет насквозь по слепому обзору, паузы на запланированных границах ≥ 80 %, плотнейшая секция ≤ цели, хук возвращается, все факты коды разборчивы с паузой, ledger и ASR-строки, предпочтён v2 слепыми рецензентами по «song, not narration» и «breathes», без флагов фрагментации."
 },
 "unchanged": [
  "Естественный украинский, ударение каждого слова (ledger до POST), разборчивость, настоящее пение насквозь.",
  "Все 39 мыслей источника как смысл (protectedThoughtMap остаётся картой смысла; sourceAudioRange только справочно).",
  "Условия заказа и бренд спеты: форма с именем и телефоном, осмотр на почте, оплата после осмотра, 60 дней на возврат, ссылка внизу — каждое в своей фразе.",
  "Первое слышимое событие — спетое слово хука; без инструментального вступления; первые 2–3 с должны цеплять.",
  "Отклонённый эксперимент 2026-09-15 остаётся запретом: без телеграфных обрывков, без «[Instrumental answer]» после каждой строки, без пауз ради пауз.",
  "Suno V6 через scripts/gen2.py с квитанциями; KIE_API_KEY из ~/.claude/secrets.env; style ≤ 1000 знаков суммарно; negativeTags ≤ 200; неизвестный исход POST не повторяется; мастера и отчёты версий 1 и 2 неприкосновенны; медиа вне git; worktree + PR, без merge; оценка владельца не присваивается.",
  "Факты продукта только из references/gopure-product-20260914.json; паспорт проблемы, манифест и reference packet run-а привязаны хешами."
 ],
 "trendRule": "Покупка варианта разрешена, когда каждая breathing-строка (restBoundaryShare, maxSectionRate, sungRate, hookReturns, codaFactsRested) движется от v2 в нужную сторону по предсказанию и ни один инвариант (stress, ASR, факты, первое событие, фрагментация) не регрессирует. Контрольный вариант C — объявленное исключение: плотность и хук не движутся по построению; он покупается один раз ради разделения эффектов текста и музыки.",
 "links": {
  "v2Report": "https://gopure-targ-ten-c06fb16085.pages.dev/",
  "delta": "https://gopure-targ-delta-c06fb16085.pages.dev/",
  "v1Report": "https://gopure-targ-refined-ce99390b3b.pages.dev/",
  "prompt": "https://github.com/PytaichukBohdan/AdFactorySongFormat/blob/main/NEXT_SESSION_PROMPT_SONG_V3.md"
 }
}
