Issue 1 — `narration` is a contract field with no route-level policy, so `general-video` runs can ship silent · Issue #5686 · heygen-com/hyperframes · GitHub
Skip to content

Issue 1 — narration is a contract field with no route-level policy, so general-video runs can ship silent #5686

Open

Description

@Justin911009

Issue 1 — narration is a contract field with no route-level policy, so general-video runs can ship silent

Component: skills — hyperframes/references/brief-contract.md + hyperframes/references/routes/
Version: hyperframes 0.8.155
Severity: contract gap (silent-failure class — no error, no warning, no check)

Prior art note: #2775 reports the runtime half of silent narration (audio
produced but never wired / never verified). This issue is the contract half
one level up: the skills layer never asks whether narration is required in
the first place. Fixing #2775's gate would turn the failure described here
from "silent success" into "loud failure" — but the run would still be
dispatched without narration because no route contract requests it.

Summary

brief-contract.md § 2 declares narration as a shared brief field:

Field Meaning Policy
narration yes, minimal, or no, plus route-specific modes Follow the selected route.

The policy delegates entirely to the route. But the route contract files
(hyperframes/references/routes/*.md) do not define it:

routes/product-launch-video.md   0 hits
routes/faceless-explainer.md     0 hits
routes/general-video.md          0 hits
routes/pr-to-video.md            0 hits
routes/motion-graphics.md        1 hit
routes/music-to-video.md         1 hit

So for most routes the chain terminates in silence: narration → "follow the
route" → route says nothing → nothing is required → nothing is checked.

Why this matters (concrete repro)

A general-video run produced a 42s composition with zero <audio>
elements
and rendered it. Every available gate reported success:

$ npx hyperframes check
  0 error(s), 0 warning(s) · 318/318 text checks pass WCAG AA
◇  Check passed

check's --json top-level keys are ok, strict, browserSkipped, lint, runtime, layout, motion, contrast, hdr, snapshots — there is no audio/voice/track/media
dimension, so a fully silent deliverable passes cleanly.

The user, not the toolchain, caught it ("没声音?"). The narration field was
never set, because no route asked for it.

The asymmetry

Some workflow SKILL.md files discuss narration extensively:

product-launch-video/SKILL.md   11 hits
faceless-explainer/SKILL.md      7 hits
pr-to-video/SKILL.md             7 hits
general-video/SKILL.md           1 hit   ← only the /media-use routing table row

That single general-video hit is a routing entry ("Any media asset or
operation, including narration, BGM, …"), not a policy for when narration is
required. general-video is the documented fallback for any unmatched video
request, so it is the route most likely to be used by someone who has not
thought about narration at all — and it is the one that says least about it.

(To be precise: the gap is in the route contract file
hyperframes/references/routes/general-video.md, which is 1374 bytes and
contains 0 mentions of narration. The workflow's own SKILL.md mentions it
once, only in the media-operation routing table. Neither states a policy.)

Suggested direction (not prescriptive)

One or more of:

  1. Give general-video's route contract a narration rule — e.g. an
    interview question ("should this be narrated?") and a documented default,
    mirroring how the specialized routes handle it.
  2. Make the policy explicit in brief-contract.md for routes that do not
    define their own — otherwise "follow the selected route" is a no-op for
    anything but the specialized workflows.
  3. Consider a check dimension for declared capabilities. If the confirmed
    brief says narration: yes and the assembled composition contains no
    <audio> (or every <audio> lacks an id, which the core skill notes means
    it is never picked up by the mixer), that is a machine-detectable
    contradiction between the brief and the artifact. Today nothing compares the
    two.

Environment

  • Windows 11, hyperframes 0.8.155, Node v22.14.0
  • ffmpeg/ffprobe not on PATH (used a full build from another app); check
    itself ran fine, so this is unlikely to be related
  • TTS route used to fix it: msedge-tts + zh-CN-XiaoxiaoNeural (no HeyGen /
    ElevenLabs / Gemini credentials present; local Kokoro unavailable — missing
    kokoro-onnx, and espeak-ng absent which Mandarin phonemization needs)

Note

This is filed as a contract/coverage observation, not a crash. The failure mode
is that everything reports success.

Activity

  1. aditigaur27 commented on Oct 18, 2026

    @aditigaur27

    Claiming this for my CS146S OSS assignment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions