/**
 * @module _shared/sub-comp-duration-sync
 *
 * Propagate narration-synced beat durations INTO sub-composition HTML.
 *
 * The root sync (root-sync.ts) stretches each beat's clip window in
 * index.html to `max(storyboard duration, narration + 0.5s)` — but scenes
 * composed before the narration existed still carry the storyboard duration
 * in their own markup: the composition root's `data-duration`, end-aligned
 * inner `.clip` windows, and GSAP timeline anchor constants like
 * `const DUR = 7;`. The runtime then ends the scene early and the stretched
 * tail renders BLACK.
 *
 * The compose stage now pins prompts to the final duration
 * (ComposeBeatContext.finalDurationSec), so fresh scenes are born correct.
 * This module is the REPAIR path for already-composed scenes. It is
 * deliberately surgical:
 *
 *   1. Composition root `data-duration`   — always rewritten (attribute).
 *   2. End-aligned `.clip` `data-duration` — rewritten when start+duration
 *      lands on the OLD beat end (±0.01s); other clips are untouched.
 *   3. GSAP anchor const                  — rewritten only when exactly one
 *      `const NAME = <oldDur>;` exists and NAME is referenced in a timeline
 *      call. Anything ambiguous emits a SCENE_TIMELINE_DURATION_OUT_OF_SYNC
 *      warning for the host agent instead of risking a bad code edit.
 */
import type { ReviewIssue } from "./review-report.js";
import { type RootSyncBeatInput } from "./root-sync.js";
export declare const SUB_COMP_SYNC_FIX_CODES: {
    readonly rootDuration: "scene_duration_synced";
    readonly clipDurations: "scene_clip_durations_synced";
    readonly timelineConst: "scene_timeline_const_synced";
};
export interface SubCompDurationSyncOutcome {
    oldDurationSec?: number;
    newDurationSec: number;
    changed: boolean;
    nextHtml?: string;
    fixCodes: string[];
    issues: ReviewIssue[];
}
export interface SubCompDurationSyncFileResult extends SubCompDurationSyncOutcome {
    /** Project-relative path, e.g. "compositions/scene-hook.html". */
    file: string;
    beatId: string;
}
/**
 * Pure core: rewrite one sub-composition's internal durations to
 * `newDurationSec`. Returns `changed: false` when the scene already matches
 * (±0.01s) or its root duration can't be located.
 */
export declare function syncSubCompositionDurationHtml(html: string, beatId: string, newDurationSec: number, fileRel?: string): SubCompDurationSyncOutcome;
/** I/O wrapper: plan duration sync for every beat's composition file. */
export declare function createSubCompDurationSyncPlans(opts: {
    projectDir: string;
    beats: RootSyncBeatInput[];
}): Promise<SubCompDurationSyncFileResult[]>;
