Skip to content

t27f: beat_clock.t27 -- the three beats cut on the voice (R4a of #10560) #10596

Closed as not planned

Description

@gHashTag

Sub-issue of epic #10560 (content factory), R4a: the first part of R4. R7 (#10584) gave every lesson reel three beats: open, main and close. Nothing yet says when each beat is on screen. A cut at fixed thirds of the 15 s reel would land in the middle of a spoken phrase. Editing tools cut on speech: Descript cuts a scene per sentence, CapCut's auto-cut uses pauses, and Remotion's TransitionSeries needs explicit frame counts per sequence.

Boundary

  • In: a new module specs/t27f/beat_clock.t27, its seal and its ledger row.
  • It decides, for any millisecond or frame of a lesson reel, which beat is on screen and the crossfade weight of each beat. It uses lesson_reel.t27's own voice timing (phrase_start, cta_from) and reel.t27's transition and minimum-scene constants.
  • Out: drawing the beats (R3, t27f factory R3: a renderer per scene archetype and the still anomaly gate (SSIM) #10571), and wiring the clock into lesson_reel's ffmpeg graph (R4b). No change to existing specs.

User Scenarios

  • A viewer sees the picture change when the goal starts being spoken and when the address appears, not mid-word.
  • A lesson with a very short title still shows its open beat long enough to read.
  • The frame renderer asks the clock for frame f and gets the beat and the blend, so a reel needs no hand-made edit list.

Requirements

  • R1. Cut 0 (open to main) is at the goal phrase's start. It moves later only when the open beat would otherwise be on screen alone for less than the minimum scene length.
  • R2. Cut 1 (main to close) is where the address takes over, cta_from.
  • R3. Each cut is a crossfade of TRANSITION_FRAMES at BASE_FPS, centred on the cut. At every millisecond the three beats' weights sum to 1000 permille.
  • R4. Each beat is on screen alone for at least MIN_SCENE_FRAMES. This holds for every lesson in both languages, across a grid of phrase lengths that the voice rule accepts.
  • R5. A negative control shows that a fixed-thirds cut lands inside a spoken phrase for the measured lesson-1 lengths.

Success Criteria

  • t27c test-report specs/t27f/beat_clock.t27 passes on the Railway lab with 0 vacuous tests.
  • Seal saved and verified; one ledger row; max_not_pass unchanged.
  • The PR is based on master and does not depend on the open loop PRs.

Requirements

  • FR-001: The clock MUST place Cut 0 (open to main) at the goal phrase's start, and MUST move it later only when the open beat would otherwise be on screen alone for less than the minimum scene length.
  • FR-002: The clock MUST place Cut 1 (main to close) at cta_from where the address takes over.
  • FR-003: Each cut MUST be a crossfade of TRANSITION_FRAMES at BASE_FPS, centred on the cut, and at every millisecond the three beats' weights MUST sum to 1000 permille.
  • FR-004: Each beat MUST be on screen alone for at least MIN_SCENE_FRAMES, and this MUST hold for every lesson in both languages across a grid of phrase lengths that the voice rule accepts.
  • FR-005: A negative control MUST demonstrate that a fixed-thirds cut lands inside a spoken phrase for the measured lesson-1 lengths.

Activity

  1. gHashTag commented on Oct 18, 2026

    @gHashTag
    OwnerAuthor

    Amendment to the Boundary, measured on the Railway lab (PR #10598).

    The issue asks for a new module specs/t27f/beat_clock.t27. I wrote that module and measured it. It cannot work today. use t27f::lesson_reel::phrase_start, and likewise cta_from and voice_fits, comes back as:

    // UNRESOLVED phrase_start: declared in t27f/lesson_reel.t27 and t27f/token_floor_mux.t27 -- ambiguous, not spliced
    

    The explicit module path does not disambiguate. This is the #10556 family.

    The clock therefore lives inside lesson_reel.t27, where local declarations win, and every new name carries a beat_ prefix. The success criteria apply to lesson_reel.t27: 13/13 tests pass, 0 vacuous, the seal is saved and verified, and the existing ledger row (t27b blocked, type [N]T) is unchanged.

    One rule changed under measurement: R1 now gives way when the voice is very short.

    • If the voice reaches the address before 2750 ms, the open beat gives up its floor, so the main beat keeps its scene.
    • This happens at one grid point, 200/1500/13100 ms, where the task phrase is dropped.
    • The test counts that case exactly, and asserts that the open beat is under a scene's length there.
  2. added
    shape-refusedClosed by the issue-shape gate (specs/policy/issue_shape.t27); a passing edit reopens it
    on Oct 18, 2026
  3. github-actions commented on Oct 18, 2026

    @github-actions
    Contributor

    Closed by the issue-shape gate (specs/policy/issue_shape.t27, #7498): an issue must have the template's sections. Edit the body; an edit that passes reopens it.

    • missing: ## Requirements -- numbered obligations, FR-001: ... MUST ...
  4. added 4 commits that reference this issue on Oct 18, 2026
    aa8871b
    d61e981
    8c1ca72
    8c7a2c2
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

    queen-shapedshape-refusedClosed by the issue-shape gate (specs/policy/issue_shape.t27); a passing edit reopens it

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions