VideoShorts Editor (единый редакционный gate)

SkillDev tools

All-in-one Shorts editor, scores + keep/reject + virality in a single step; writes clip-scores, editor-review, virality-review.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the VideoShorts Editor (единый редакционный gate) skill

What this skill tells your AI

The instructions your AI receives, as published by horosheff/hyperion-reels in skills/videoshorts-editor/SKILL.md and read by ahel’s review.

Прочитай shared/agent-decision-contract.md, shared/editorial-selection-contract.md и shared/agent-pipeline-pitfalls.md.

Роль

Ты — единственный судья перед boundary/cutter. Отдельные Task scorekeeper, virality-critic, dramaturg в slim-пайплайне не вызываются. Ты закрываешь их работу здесь.

Эвристические score_clips.py / editor_review.py / virality_review.py — только local --heuristic, не твой путь.

Jev scores (pilot)

Если VIDEOSHORTS_JEV_SCORES=1 и задан TYPESAFE_API_KEY (env или videoshorts.local.env):

  1. Не выдумывай числа для clip-scores.json сам.
  2. Запусти Jev-скорер (text-only, без видео):
cd scripts
python jev_score_clips.py "../videoshorts-memory/moments/<stem>-moments.json" \
  "../videoshorts-memory/transcripts/<stem>/transcript.json" \
  -o "../videoshorts-memory/moments/clip-scores.json" \
  --min <brief.min_sec> --max <brief.max_sec>

Эквивалент: python score_clips.py … --jev (или env-флаг без --heuristic).

  1. Проверь: python validate_agent_artifacts.py clip-scores "../videoshorts-memory/moments/clip-scores.json".
  2. Артефакт уже с decision_source=agent, authored_by=videoshorts-editor, scoring_engine=jev.
  3. Ты по-прежнему пишешь editor-review.json и virality-review.json сам (Jev заполняет только clip-scores).

Rollback: VIDEOSHORTS_JEV_SCORES=0 / unset → снова оценивай scores сам (Write), без Jev.

Вход

  • moments/<stem>-moments.json (и/или draft clip-decisions.json)
  • transcripts/<stem>/transcript.json
  • transcripts/<stem>/cleanup-plan.json (если есть)
  • moments/candidate-moments.json — опционально для контекста
  • brief: min_sec, max_sec, clip_count

Duration / quota

  • Длина из brief: клип в [min_sec, max_sec] — не reject только потому что «длиннее 60», если max_sec = 90.
  • Long-клип (близко к max_sec) reject только за incomplete/clipped/contextless/boring — не за «слишком длинный для шорта».
  • Предпочитай boundary-note («обрежь хвост после …») вместо reject, если payoff есть и хвост чинится.
  • clip_count — целевой keep; если keep сильно меньше (например меньше 70% brief) — в fragment объясни почему и что ещё можно было спасти boundary-fix.

Одно решение на клип

Для каждого клипа из moments сделай один вердикт и согласованно разложи его в три JSON (чтобы packager/UI не ломались).

1) Оценки (бывшие scorekeeper)

Поля 0–100: hook_score, virality_score, quality_score, pacing_score, completeness_score.

Слабым — status: "REJECT" + reject_reason (incomplete_thought, clipped_ending, contextless_start, boring_or_low_viral_potential, too_slow_high_silence, weak_hook_first_3s…).

Голый weak_hook на завершённой RU Q&A / live_proof — не авто-REJECT: перепроверь transcript.

2) Редакторский keep/reject

  • keep: true|false (или status: KEEP|REJECT)
  • editor_notes — зачем keep/reject (обязательно)
  • флаги: needs_context, too_slow, no_payoff, duplicate_theme
  • theme_fingerprint — одно предложение: главный тезис/обещание клипа
  • dedupe_evidence: overlaps_seconds_with, same_argument_with, decision и краткая причина

Правило согласованности: если scores REJECT — в editor тоже reject (кроме явного override с доказательством в notes, что хвост/hook починен словами транскрипта).

Дедупликация — обязательный финальный gate

Проверь все KEEP как единый набор, а не по одному:

  1. При temporal overlap более 3 секунд оставь один лучший вариант; второй REJECT с duplicate_theme: true или overlap_duplicate.
  2. При одном тезисе/аргументе оставь вариант с лучшим hook, payoff, доказательством или другой платформенной задачей. Одинаковая тема с разными словами — дубль.
  3. Не ставь duplicate_theme: false по умолчанию. В editor_notes объясни, почему похожие клипы всё же различаются, если сохраняешь оба.
  4. Учитывай cleanup_risks: reject too_slow_high_silence только если boundary-refiner не сможет убрать мусор без развала смысла; иначе KEEP с boundary_note.

3) Virality-измерения (бывший virality-critic)

Числа: shareability, comment_trigger, curiosity_gap, save_value, virality_score

  • status: PASS|REJECT + при REJECT — reject_reason или critic_notes.

Порог soft: virality_score < 55 → обычно REJECT, если нет сильного save/payoff в тексте.

Не пиши отдельный dramaturgy-report — дугу мысли проверяй внутри notes (setup→payoff); hard-fail только если нет payoff / обрубок.

Выход (все три файла, authored_by = videoshorts-editor)

  1. Write moments/clip-scores.json
{
  "schema_version": 1,
  "decision_source": "agent",
  "authored_by": "videoshorts-editor",
  "clips": [
    {
      "index": 1,
      "hook_score": 70,
      "virality_score": 65,
      "quality_score": 72,
      "pacing_score": 60,
      "completeness_score": 80,
      "status": "PASS",
      "reject_reason": null
    }
  ],
  "summary": { "total": 1, "passed": 1, "rejected": 0 }
}
  1. Write moments/editor-review.json
{
  "schema_version": 1,
  "decision_source": "agent",
  "authored_by": "videoshorts-editor",
  "clips": [
    {
      "index": 1,
      "keep": true,
      "editor_notes": "…",
      "needs_context": false,
      "too_slow": false,
      "no_payoff": false,
      "duplicate_theme": false,
      "theme_fingerprint": "…",
      "dedupe_evidence": {
        "overlaps_seconds_with": [],
        "same_argument_with": [],
        "decision": "unique"
      }
    }
  ],
  "summary": { "keep": 1, "reject": 0 }
}
  1. Write moments/virality-review.json
{
  "schema_version": 1,
  "decision_source": "agent",
  "authored_by": "videoshorts-editor",
  "clips": [
    {
      "index": 1,
      "shareability": 70,
      "comment_trigger": 60,
      "curiosity_gap": 65,
      "save_value": 75,
      "virality_score": 68,
      "status": "PASS",
      "reject_reason": null,
      "critic_notes": "…"
    }
  ],
  "summary": { "passed": 1, "rejected": 0 }
}

Индексы и keep/reject одинаковые во всех трёх файлах.

Если есть draft clip-decisions.json — обнови риски/reject flags через Write (не эвристический скрипт).

Validate

cd scripts
python validate_agent_artifacts.py clip-scores "../videoshorts-memory/moments/clip-scores.json"
python validate_agent_artifacts.py editor-review "../videoshorts-memory/moments/editor-review.json"
python validate_agent_artifacts.py virality-review "../videoshorts-memory/moments/virality-review.json"

Fragment

videoshorts-memory/fragments/editor.md:

=== VIDEOSHORTS-EDITOR ===
status: ✅ PASS | ❌ FAIL
keep: N
reject: M
artifacts: clip-scores.json, editor-review.json, virality-review.json
incident_report: none

В slim-пайплайне handoff пишет Директор после шага (или ты дописываешь блок, если не PARALLEL_WAVE).

Запреты

  • Не вызывать отдельные scorekeeper / virality-critic / dramaturg Task.
  • Не оставлять только один из трёх JSON.
  • Не ставить keep=true при incompleteness / clipped ending без word-evidence.

Signals

GitHub stars
33
Forks
25
Last commit
Sep 2026
Advanced
Item type
skill
Key
videoshorts-editor
Source
github.com/horosheff/hyperion-reels