chore: import upstream snapshot with attribution
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Docs / Validate docs (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Sync skills to ClawHub / Publish changed skills (push) Waiting to run
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:35 +08:00
commit 85453da49f
4031 changed files with 710987 additions and 0 deletions
@@ -0,0 +1,94 @@
import { createHash } from "node:crypto";
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { buildSync } from "esbuild";
import {
HYPERFRAME_RUNTIME_ARTIFACTS,
HYPERFRAME_RUNTIME_CONTRACT,
loadHyperframeRuntimeSource,
} from "../src/inline-scripts/hyperframe";
const thisDir = dirname(fileURLToPath(import.meta.url));
const distDir = resolve(thisDir, "../dist");
const iifePath = resolve(distDir, HYPERFRAME_RUNTIME_ARTIFACTS.iife);
const esmPath = resolve(distDir, HYPERFRAME_RUNTIME_ARTIFACTS.esm);
const manifestPath = resolve(distDir, HYPERFRAME_RUNTIME_ARTIFACTS.manifest);
const runtimeSourceRaw = loadHyperframeRuntimeSource();
if (runtimeSourceRaw === null) {
throw new Error("Cannot build runtime artifact: entry.ts not found at expected path");
}
const runtimeSource = `${runtimeSourceRaw}\n`;
const runtimeSha256 = createHash("sha256").update(runtimeSource, "utf8").digest("hex");
const buildId = process.env.HYPERFRAME_RUNTIME_BUILD_ID?.trim() || "dev";
const runtimeEntryPath = resolve(thisDir, "../src/runtime/entry.ts");
const esmBuild = buildSync({
entryPoints: [runtimeEntryPath],
bundle: true,
write: false,
platform: "browser",
format: "esm",
target: ["es2020"],
minify: true,
legalComments: "none",
});
const esmSource = `${esmBuild.outputFiles[0]?.text ?? ""}\n`;
const manifest = {
version: process.env.HYPERFRAME_RUNTIME_VERSION?.trim() || "0.1.0",
buildId,
sha256: runtimeSha256,
artifacts: {
iife: HYPERFRAME_RUNTIME_ARTIFACTS.iife,
esm: HYPERFRAME_RUNTIME_ARTIFACTS.esm,
},
contract: HYPERFRAME_RUNTIME_CONTRACT,
};
mkdirSync(distDir, { recursive: true });
writeFileSync(iifePath, runtimeSource, "utf8");
writeFileSync(esmPath, esmSource, "utf8");
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
// ── Generate src/generated/runtime-inline.ts ──────────────────────────────
// This file is compiled by tsc into dist/ and provides the production-safe
// getHyperframeRuntimeScript() that returns the IIFE as a string constant —
// no esbuild, no file I/O, no import.meta.url arithmetic.
const generatedDir = resolve(thisDir, "../src/generated");
mkdirSync(generatedDir, { recursive: true });
const inlineModulePath = resolve(generatedDir, "runtime-inline.ts");
const escapedSource = JSON.stringify(runtimeSourceRaw);
writeFileSync(
inlineModulePath,
[
"// AUTO-GENERATED by scripts/build-hyperframes-runtime-artifact.ts — do not edit",
`const RUNTIME_IIFE: string = ${escapedSource};`,
"",
"/**",
" * Returns the pre-built hyperframe runtime IIFE as a string constant.",
" * This is the production-safe path: no esbuild, no file I/O,",
" * no import.meta.url arithmetic.",
" */",
"export function getHyperframeRuntimeScript(): string {",
" return RUNTIME_IIFE;",
"}",
"",
].join("\n"),
"utf8",
);
console.log(
JSON.stringify({
event: "hyperframe_runtime_artifacts_generated",
buildId,
distDir,
iifePath,
esmPath,
manifestPath,
inlineModulePath,
sourceBytes: Buffer.byteLength(runtimeSource, "utf8"),
esmBytes: Buffer.byteLength(esmSource, "utf8"),
sha256: runtimeSha256,
}),
);
@@ -0,0 +1,52 @@
/** Build the injectable position-edits render artifact from the canonical runtime. */
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { buildSync } from "esbuild";
import { execFileSync } from "node:child_process";
const thisDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(thisDir, "..");
const entry = resolve(repoRoot, "stubs/position-edits-render-entry.ts");
const generatedDir = resolve(repoRoot, "src/generated");
const outPath = resolve(generatedDir, "position-edits-render-inline.ts");
const result = buildSync({
entryPoints: [entry],
bundle: true,
write: false,
platform: "browser",
format: "iife",
target: ["es2020"],
minify: true,
legalComments: "none",
});
const iife = result.outputFiles[0]?.text ?? "";
if (!iife) throw new Error("esbuild produced no output for position-edits-render-entry.ts");
mkdirSync(generatedDir, { recursive: true });
writeFileSync(
outPath,
[
"// AUTO-GENERATED by scripts/build-position-edits-render.ts - do not edit",
`const POSITION_EDITS_RENDER_IIFE: string = ${JSON.stringify(iife)};`,
"",
"/** Returns the pre-built position-edits render IIFE as a string constant. */",
"export function getPositionEditsRenderScript(): string {",
" return POSITION_EDITS_RENDER_IIFE;",
"}",
"",
].join("\n"),
"utf8",
);
try {
execFileSync("bun", ["x", "oxfmt", outPath], { stdio: "ignore" });
} catch {
// Formatting is best effort when the generator runs in a minimal environment.
}
console.log(
JSON.stringify({ event: "position_edits_render_generated", outPath, bytes: iife.length }),
);
@@ -0,0 +1,73 @@
import fs from "node:fs";
import path from "node:path";
import { lintHyperframeHtml, type HyperframeLintResult } from "@hyperframes/lint";
function formatCounts(result: HyperframeLintResult): string {
const parts = [`${result.warningCount} warning${result.warningCount === 1 ? "" : "s"}`];
if (result.infoCount > 0) {
parts.push(`${result.infoCount} info${result.infoCount === 1 ? "" : "s"}`);
}
return parts.join(", ");
}
function formatHumanOutput(result: HyperframeLintResult, resolvedPath: string): string {
const counts = result.ok
? formatCounts(result)
: `${result.errorCount} error${result.errorCount === 1 ? "" : "s"}, ${formatCounts(result)}`;
const lines = [
result.ok ? `PASS ${resolvedPath} (${counts})` : `FAIL ${resolvedPath} (${counts})`,
];
for (const finding of result.findings) {
lines.push(`- [${finding.severity.toUpperCase()}] ${finding.code}: ${finding.message}`);
if (finding.selector) {
lines.push(` selector: ${finding.selector}`);
}
if (finding.elementId) {
lines.push(` elementId: ${finding.elementId}`);
}
if (finding.fixHint) {
lines.push(` fix: ${finding.fixHint}`);
}
}
return lines.join("\n");
}
async function main() {
const args = process.argv.slice(2);
const normalizedArgs = args[0] === "--" ? args.slice(1) : args;
const jsonOutput = normalizedArgs.includes("--json");
const positionalArgs = normalizedArgs.filter((arg) => arg !== "--json");
const inputPath = positionalArgs[0];
if (!inputPath) {
console.error(
"Usage: bun run check:hyperframe-html [--json] <path-to-html>\nExample: bun run check:hyperframe-html core/src/tests/broken-video.html",
);
process.exit(2);
}
const resolvedPath = path.resolve(process.cwd(), inputPath);
if (!fs.existsSync(resolvedPath)) {
console.error(`File not found: ${resolvedPath}`);
process.exit(2);
}
const html = fs.readFileSync(resolvedPath, "utf-8");
const result = await lintHyperframeHtml(html, { filePath: resolvedPath });
if (jsonOutput) {
console.log(JSON.stringify(result, null, 2));
process.exit(result.ok ? 0 : 1);
}
if (result.ok) {
console.log(formatHumanOutput(result, resolvedPath));
process.exit(0);
}
console.error(formatHumanOutput(result, resolvedPath));
process.exit(1);
}
main();
+318
View File
@@ -0,0 +1,318 @@
import fs from "node:fs";
import path from "node:path";
type AttrMap = Record<string, string>;
type ParsedTag = {
tagName: string;
attrs: AttrMap;
raw: string;
};
type TimelineClip = {
id: string | null;
label: string;
start: number;
duration: number;
track: number;
kind: "video" | "audio" | "image" | "element";
tagName: string | null;
compositionId: string | null;
compositionSrc: string | null;
assetUrl: string | null;
durationSource: "deterministic" | "fallback";
};
type TimelinePayload = {
source: "hf-preview";
type: "timeline";
durationInFrames: number;
clips: TimelineClip[];
scenes: [];
compositionWidth: number;
compositionHeight: number;
};
function parseNum(value: string | null | undefined): number | null {
if (value == null) return null;
const parsed = Number.parseFloat(String(value));
return Number.isFinite(parsed) ? parsed : null;
}
function parseArgs() {
const args = process.argv.slice(2);
const normalizedArgs = args[0] === "--" ? args.slice(1) : args;
const inputPath = normalizedArgs[0];
let forcedFps: number | null = null;
let forcedMaxDuration: number | null = null;
for (let i = 1; i < normalizedArgs.length; i += 1) {
const arg = normalizedArgs[i];
if (arg === "--fps" && normalizedArgs[i + 1]) {
forcedFps = parseNum(normalizedArgs[i + 1]);
i += 1;
continue;
}
if (arg === "--max-duration" && normalizedArgs[i + 1]) {
forcedMaxDuration = parseNum(normalizedArgs[i + 1]);
i += 1;
}
}
return { inputPath, forcedFps, forcedMaxDuration };
}
function parseAttributes(rawAttrs: string): AttrMap {
const attrs: AttrMap = {};
const attrRegex = /([^\s=/>]+)\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/g;
let match: RegExpExecArray | null = null;
while (true) {
match = attrRegex.exec(rawAttrs);
if (!match) break;
const key = match[1];
const value = match[3] ?? match[4] ?? match[5] ?? "";
attrs[key] = value;
}
return attrs;
}
function parseTags(html: string): ParsedTag[] {
const tags: ParsedTag[] = [];
const tagRegex = /<([a-zA-Z][\w:-]*)([^>]*)>/g;
let match: RegExpExecArray | null = null;
while (true) {
match = tagRegex.exec(html);
if (!match) break;
const raw = match[0];
if (raw.startsWith("</") || raw.startsWith("<!")) continue;
const tagName = String(match[1] || "").toLowerCase();
if (!tagName) continue;
tags.push({
tagName,
raw,
attrs: parseAttributes(match[2] || ""),
});
}
return tags;
}
function extractWindowNumber(html: string, key: string): number | null {
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const regex = new RegExp(`${escapedKey}\\s*=\\s*([0-9]+(?:\\.[0-9]+)?)`, "i");
const match = html.match(regex);
if (!match) return null;
return parseNum(match[1]);
}
function normalizeDurationSeconds(
rawDuration: number | null,
fallbackDuration: number | null,
maxDuration: number,
): number {
const safeFallback = fallbackDuration != null && fallbackDuration > 0 ? fallbackDuration : 0;
const safeRaw =
rawDuration != null && Number.isFinite(rawDuration) && rawDuration > 0 ? rawDuration : 0;
if (safeRaw > 0) return Math.min(safeRaw, maxDuration);
if (safeFallback > 0) return Math.min(safeFallback, maxDuration);
return 0;
}
function shouldIncludeTimelineNode(tag: ParsedTag, rootCompositionId: string | null): boolean {
const attrs = tag.attrs;
if (
attrs["data-composition-id"] &&
rootCompositionId &&
attrs["data-composition-id"] === rootCompositionId
) {
return false;
}
if (
tag.tagName === "script" ||
tag.tagName === "style" ||
tag.tagName === "link" ||
tag.tagName === "meta"
) {
return false;
}
if ((attrs.class || "").split(/\s+/).includes("__preview_render_frame__")) return false;
if (attrs["data-start"] != null) return true;
if (attrs["data-track-index"] != null) return true;
if (attrs["data-composition-src"] != null) return true;
if (attrs["data-composition-id"] != null) return true;
return tag.tagName === "video" || tag.tagName === "audio" || tag.tagName === "img";
}
function inferClipDuration(tag: ParsedTag, start: number, maxDuration: number): number | null {
const attrs = tag.attrs;
const durationAttr = parseNum(attrs["data-duration"]);
if (durationAttr != null && durationAttr > 0)
return normalizeDurationSeconds(durationAttr, null, maxDuration);
const endAttr = parseNum(attrs["data-end"]);
if (endAttr != null && endAttr > start) {
return normalizeDurationSeconds(endAttr - start, null, maxDuration);
}
if (tag.tagName === "video" || tag.tagName === "audio") {
const sourceDuration = parseNum(attrs["data-source-duration"]);
const playbackStart =
parseNum(attrs["data-playback-start"]) ?? parseNum(attrs["data-playbackStart"]) ?? 0;
if (sourceDuration != null && sourceDuration > 0) {
return normalizeDurationSeconds(
Math.max(0, sourceDuration - playbackStart),
null,
maxDuration,
);
}
}
if (attrs["data-composition-id"]) {
const sourceDuration = parseNum(attrs["data-source-duration"]);
if (sourceDuration != null && sourceDuration > 0) {
return normalizeDurationSeconds(sourceDuration, null, maxDuration);
}
}
return null;
}
function resolveNodeAssetUrl(tag: ParsedTag): string | null {
const attrs = tag.attrs;
return (
attrs.src ??
attrs["data-src"] ??
attrs["data-asset-src"] ??
attrs["data-video-src"] ??
attrs["data-image-src"] ??
null
);
}
function resolveRootTag(tags: ParsedTag[]): ParsedTag | null {
const explicitRoot = tags.find((tag) => tag.attrs["data-composition-id"] === "master");
if (explicitRoot) return explicitRoot;
return tags.find((tag) => tag.attrs["data-composition-id"] != null) ?? null;
}
function main() {
const { inputPath, forcedFps, forcedMaxDuration } = parseArgs();
if (!inputPath) {
console.error("Usage: bun run debug:timeline <path-to-html> [--fps 30] [--max-duration 1800]");
process.exit(2);
}
const resolvedPath = path.resolve(process.cwd(), inputPath);
if (!fs.existsSync(resolvedPath)) {
console.error(`File not found: ${resolvedPath}`);
process.exit(2);
}
const html = fs.readFileSync(resolvedPath, "utf-8");
const tags = parseTags(html);
const root = resolveRootTag(tags);
const rootCompositionId = root?.attrs["data-composition-id"] ?? null;
const maxDuration =
(forcedMaxDuration != null && forcedMaxDuration > 0
? forcedMaxDuration
: extractWindowNumber(html, "window.__HF_MAX_DURATION_SEC")) ?? 1800;
const canonicalFps =
(forcedFps != null && forcedFps > 0
? forcedFps
: (parseNum(root?.attrs["data-fps"]) ?? extractWindowNumber(html, "window.__HF_FPS"))) ?? 30;
const rootDurationRaw =
parseNum(root?.attrs["data-composition-duration"]) ??
parseNum(root?.attrs["data-duration"]) ??
parseNum(
tags.find((tag) => tag.tagName === "html")?.attrs["data-composition-duration"] ?? null,
);
const rootDuration = normalizeDurationSeconds(rootDurationRaw, null, maxDuration);
const nodes = tags.filter((tag) => shouldIncludeTimelineNode(tag, rootCompositionId));
const clips: TimelineClip[] = [];
let maxEnd = 0;
let unresolvedClipCount = 0;
for (let i = 0; i < nodes.length; i += 1) {
const node = nodes[i];
const attrs = node.attrs;
const start = Math.max(0, parseNum(attrs["data-start"]) ?? 0);
const inferredDuration = inferClipDuration(node, start, maxDuration);
const hasDeterministicDuration = inferredDuration != null && inferredDuration > 0;
let duration = hasDeterministicDuration
? normalizeDurationSeconds(inferredDuration, 0, maxDuration)
: 0;
let durationSource: "deterministic" | "fallback" = "deterministic";
if (duration <= 0 && rootDuration > start) {
duration = normalizeDurationSeconds(rootDuration - start, 0, maxDuration);
durationSource = "fallback";
}
if (duration <= 0) {
unresolvedClipCount += 1;
continue;
}
if (hasDeterministicDuration) {
const end = start + duration;
if (end > maxEnd) maxEnd = end;
}
const kind =
node.tagName === "video"
? "video"
: node.tagName === "audio"
? "audio"
: node.tagName === "img"
? "image"
: "element";
const trackRaw = parseNum(attrs["data-track-index"]);
const track = trackRaw != null && Number.isFinite(trackRaw) ? Math.floor(trackRaw) : i;
clips.push({
id: attrs.id ?? null,
label: attrs["data-label"] ?? attrs["aria-label"] ?? attrs.id ?? kind,
start,
duration,
track,
kind,
tagName: node.tagName || null,
compositionId: attrs["data-composition-id"] ?? null,
compositionSrc: attrs["data-composition-src"] ?? null,
assetUrl: resolveNodeAssetUrl(node),
durationSource,
});
}
let effectiveDuration = 0;
if (maxEnd > 0) effectiveDuration = normalizeDurationSeconds(maxEnd, 0, maxDuration);
if (effectiveDuration <= 0)
effectiveDuration = normalizeDurationSeconds(rootDuration, 1, maxDuration);
if (effectiveDuration <= 0) effectiveDuration = 1;
const compositionWidth = parseNum(root?.attrs["data-width"]) ?? 1920;
const compositionHeight = parseNum(root?.attrs["data-height"]) ?? 1080;
const payload: TimelinePayload = {
source: "hf-preview",
type: "timeline",
durationInFrames: Math.max(1, Math.round(effectiveDuration * canonicalFps)),
clips,
scenes: [],
compositionWidth,
compositionHeight,
};
const output = {
file: resolvedPath,
debug: {
canonicalFps,
maxDurationSeconds: maxDuration,
rootCompositionId,
rootDurationSeconds: rootDuration,
deterministicMaxEndSeconds: maxEnd,
effectiveDurationSeconds: effectiveDuration,
unresolvedClipCount,
clipCount: clips.length,
},
payload,
};
console.log(JSON.stringify(output, null, 2));
}
main();
@@ -0,0 +1,104 @@
import fs from "node:fs";
import path from "node:path";
type GuardSpec = {
id: string;
description: string;
filePath: string;
pattern: RegExp;
};
type GuardCheckResult = {
passed: GuardSpec[];
failed: GuardSpec[];
};
// Keep only temporary source-shape guards that do not yet have behavioral
// coverage. Timeline replacement and early-play rebinding are exercised by
// init.test.ts and timelineRebindPolicy.test.ts instead of regexes.
const GUARD_SPECS: GuardSpec[] = [
{
id: "external_compositions_gate",
description: "Do not bind timelines before external compositions are loaded",
filePath: "src/runtime/init.ts",
pattern: /if\s*\(\s*!externalCompositionsReady\s*\)\s*return\s+false;/,
},
{
id: "child_timeline_activation",
description: "Force root child timelines active before composition binding",
filePath: "src/runtime/init.ts",
pattern: /timelineWithPaused\.paused\(false\)/,
},
{
id: "root_unusable_fallback",
description: "Fallback to composite timeline when root duration is unusable",
filePath: "src/runtime/init.ts",
pattern:
/if\s*\(\s*!isUsableTimelineDuration\(rootDurationSeconds\)\s*&&\s*rootChildCandidates\.length\s*>\s*0\s*\)/,
},
{
id: "external_script_ordering",
description: "Inject external composition scripts with deterministic ordering",
filePath: "src/runtime/compositionLoader.ts",
pattern: /injectedScript\.async\s*=\s*false;/,
},
{
id: "external_script_load_wait",
description: "Await external composition script load before continuing",
filePath: "src/runtime/compositionLoader.ts",
pattern: /await\s+waitForExternalScriptLoad\(injectedScript\);/,
},
];
function resolveFilePath(relativePath: string): string {
return path.resolve(process.cwd(), relativePath);
}
function checkGuards(guards: GuardSpec[]): GuardCheckResult {
const passed: GuardSpec[] = [];
const failed: GuardSpec[] = [];
for (const guard of guards) {
const absolutePath = resolveFilePath(guard.filePath);
if (!fs.existsSync(absolutePath)) {
failed.push(guard);
continue;
}
const content = fs.readFileSync(absolutePath, "utf8");
if (guard.pattern.test(content)) {
passed.push(guard);
} else {
failed.push(guard);
}
}
return { passed, failed };
}
function main(): void {
const result = checkGuards(GUARD_SPECS);
if (result.failed.length === 0) {
console.log(
JSON.stringify({
event: "runtime_preview_guards_lint_passed",
checkedGuards: GUARD_SPECS.length,
}),
);
return;
}
console.error(
JSON.stringify({
event: "runtime_preview_guards_lint_failed",
checkedGuards: GUARD_SPECS.length,
missingGuards: result.failed.map((guard) => ({
id: guard.id,
filePath: guard.filePath,
description: guard.description,
})),
}),
);
process.exit(1);
}
main();
@@ -0,0 +1,77 @@
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { dirname, extname, join, normalize, resolve } from "node:path";
const distDir = resolve(import.meta.dirname, "../dist");
const runtimeExtensions = new Set([".js", ".mjs", ".cjs", ".json", ".wasm", ".node"]);
function listJavaScriptFiles(dir: string): string[] {
const files: string[] = [];
for (const entry of readdirSync(dir)) {
const fullPath = join(dir, entry);
const stat = statSync(fullPath);
if (stat.isDirectory()) {
files.push(...listJavaScriptFiles(fullPath));
} else if (entry.endsWith(".js")) {
files.push(fullPath);
}
}
return files;
}
function hasRuntimeExtension(specifier: string): boolean {
return runtimeExtensions.has(extname(specifier));
}
function isRelativeSpecifier(specifier: string): boolean {
return specifier.startsWith("./") || specifier.startsWith("../");
}
function resolveExistingJsSpecifier(fromFile: string, specifier: string): string | undefined {
const absolute = resolve(dirname(fromFile), specifier);
const jsFile = `${absolute}.js`;
const indexFile = join(absolute, "index.js");
if (existsSync(jsFile)) return `${specifier}.js`;
if (existsSync(indexFile)) return `${specifier}/index.js`;
}
function resolveRuntimeSpecifier(fromFile: string, specifier: string): string {
if (!isRelativeSpecifier(specifier)) return specifier;
if (hasRuntimeExtension(specifier)) return specifier;
return resolveExistingJsSpecifier(fromFile, specifier) ?? specifier;
}
function rewriteSpecifiers(filePath: string, source: string): string {
const patterns = [
/(from\s+["'])(\.\.?\/[^"']+)(["'])/g,
/(import\s+["'])(\.\.?\/[^"']+)(["'])/g,
/(import\(\s*["'])(\.\.?\/[^"']+)(["']\s*\))/g,
];
return patterns.reduce(
(nextSource, pattern) =>
nextSource.replace(pattern, (_match, prefix: string, specifier: string, suffix: string) => {
return `${prefix}${resolveRuntimeSpecifier(filePath, specifier)}${suffix}`;
}),
source,
);
}
let changed = 0;
for (const filePath of listJavaScriptFiles(distDir)) {
const source = readFileSync(filePath, "utf8");
const rewritten = rewriteSpecifiers(filePath, source);
if (rewritten !== source) {
writeFileSync(filePath, rewritten);
changed += 1;
}
}
console.log(
JSON.stringify({
event: "core_esm_extensions_rewritten",
distDir: normalize(distDir),
changedFiles: changed,
}),
);
@@ -0,0 +1,111 @@
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { lintHyperframeHtml } from "@hyperframes/lint";
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const VALID_COMPOSITION = `
<html>
<body>
<div id="root" data-composition-id="comp-1" data-width="1920" data-height="1080" data-start="0">
<div id="stage"></div>
</div>
<script src="https://cdn.gsap.com/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
tl.to("#stage", { opacity: 1, duration: 1 }, 0);
window.__timelines["comp-1"] = tl;
</script>
</body>
</html>`;
async function testCleanFixturePasses() {
const result = await lintHyperframeHtml(VALID_COMPOSITION, { filePath: "valid.html" });
assert.equal(result.ok, true, "valid composition should pass without lint errors");
assert.equal(result.errorCount, 0, "valid composition should have zero lint errors");
}
async function testDetectsMissingCompositionHostId() {
const html = `
<html>
<body>
<div id="root" data-width="1080" data-height="1920">
<div data-composition-src="compositions/overlays.html"></div>
</div>
<script>
window.__timelines = {};
const tl = gsap.timeline({ paused: true });
window.__timelines["root"] = tl;
</script>
</body>
</html>
`;
const result = await lintHyperframeHtml(html);
const codes = result.findings.map((finding) => finding.code);
assert.equal(result.ok, false, "missing composition ids should fail lint");
assert.ok(codes.includes("root_missing_composition_id"));
assert.ok(codes.includes("host_missing_composition_id"));
}
async function testDetectsOverlappingGsapTweens() {
const html = `
<html>
<body>
<div id="main" data-composition-id="main" data-width="1080" data-height="1920">
<div id="frame"></div>
</div>
<script>
window.__timelines = {};
const tl = gsap.timeline({ paused: true });
tl.to("#frame", { y: 15, duration: 2.5, repeat: 1, yoyo: true }, 1.5);
tl.to("#frame", { y: 400, duration: 1.2 }, 4.5);
window.__timelines["main"] = tl;
</script>
</body>
</html>
`;
const result = await lintHyperframeHtml(html);
const overlapFinding = result.findings.find(
(finding) => finding.code === "overlapping_gsap_tweens",
);
assert.ok(overlapFinding, "expected an overlapping GSAP tween warning");
assert.equal(overlapFinding?.severity, "warning");
}
function testCliJsonOutput() {
const tempDir = mkdtempSync(path.join(tmpdir(), "hf-core-lint-script-"));
try {
const fixturePath = path.join(tempDir, "index.html");
writeFileSync(fixturePath, VALID_COMPOSITION, "utf8");
const stdout = execFileSync("bun", ["run", "check:hyperframe-html", "--json", fixturePath], {
cwd: ROOT,
encoding: "utf8",
});
const payload = JSON.parse(stdout);
assert.equal(payload.ok, true);
assert.equal(typeof payload.errorCount, "number");
assert.ok(Array.isArray(payload.findings));
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
}
async function main() {
await testCleanFixturePasses();
await testDetectsMissingCompositionHostId();
await testDetectsOverlappingGsapTweens();
testCliJsonOutput();
console.log("hyperframe linter tests passed");
}
await main();
@@ -0,0 +1,36 @@
import { buildHyperframesRuntimeScript } from "../src/inline-scripts/hyperframesRuntime.engine";
function assert(condition: unknown, message: string): void {
if (!condition) {
throw new Error(message);
}
}
const baseline = buildHyperframesRuntimeScript();
assert(baseline !== null, "buildHyperframesRuntimeScript() returned null — entry.ts not found");
const parityEnabled = buildHyperframesRuntimeScript({ defaultParityMode: true });
assert(parityEnabled !== null, "Parity-enabled build returned null");
const parityDisabled = buildHyperframesRuntimeScript({ defaultParityMode: false });
assert(parityDisabled !== null, "Parity-disabled build returned null");
const withSourceUrl = buildHyperframesRuntimeScript({
sourceUrl: "hyperframe.runtime.iife.js",
});
assert(withSourceUrl !== null, "Build with sourceUrl returned null");
assert(baseline.includes("window.__player"), "Baseline runtime should include player contract");
assert(parityEnabled.length > 0, "Parity-enabled build should produce non-empty runtime source");
assert(parityDisabled.length > 0, "Parity-disabled build should produce non-empty runtime source");
assert(
withSourceUrl.includes("//# sourceURL=hyperframe.runtime.iife.js"),
"Build with sourceUrl should append sourceURL comment",
);
console.log(
JSON.stringify({
event: "hyperframe_runtime_behavior_verified",
baselineBytes: baseline.length,
parityEnabledBytes: parityEnabled.length,
parityDisabledBytes: parityDisabled.length,
sourceUrlBytes: withSourceUrl.length,
}),
);
@@ -0,0 +1,46 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { loadHyperframeRuntimeSource } from "../src/inline-scripts/hyperframe";
function assert(condition: unknown, message: string): void {
if (!condition) {
throw new Error(message);
}
}
const runtimeSource = loadHyperframeRuntimeSource();
assert(runtimeSource !== null, "loadHyperframeRuntimeSource() returned null — entry.ts not found");
const requiredSnippets = [
"window.__player",
"window.__playerReady",
"window.__renderReady",
"hf-preview",
"hf-parent",
"renderSeek",
"__hyperframes",
"fitTextFontSize",
];
for (const snippet of requiredSnippets) {
assert(runtimeSource.includes(snippet), `Runtime contract snippet missing: ${snippet}`);
}
const scriptDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
const manifestPath = resolve(scriptDir, "../dist/hyperframe.manifest.json");
try {
const manifestRaw = readFileSync(manifestPath, "utf8");
const manifest = JSON.parse(manifestRaw) as { artifacts?: { iife?: string; esm?: string } };
assert(Boolean(manifest.artifacts?.iife), "Manifest is missing iife artifact");
assert(Boolean(manifest.artifacts?.esm), "Manifest is missing esm artifact");
} catch {
// Build may not have run yet; contract-only checks above still provide signal.
}
console.log(
JSON.stringify({
event: "hyperframe_runtime_contract_verified",
requiredSnippetsChecked: requiredSnippets.length,
}),
);
@@ -0,0 +1,48 @@
import { readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
function assert(condition: unknown, message: string): void {
if (!condition) {
throw new Error(message);
}
}
const scriptDir = dirname(fileURLToPath(import.meta.url));
const initPath = resolve(scriptDir, "../src/runtime/init.ts");
const timelinePath = resolve(scriptDir, "../src/runtime/timeline.ts");
const initSource = readFileSync(initPath, "utf8");
const timelineSource = readFileSync(timelinePath, "utf8");
// Guard against regressions where preview duration gets capped by earliest video.
assert(
!initSource.includes("resolveMainVideoDurationSeconds"),
"init.ts should not use first-video duration helper",
);
assert(
!initSource.includes("Math.max(0, Math.min(safeDuration, mediaFloor))"),
"init.ts should not hard-clamp safe duration to media floor",
);
assert(
initSource.includes("resolveMediaWindowDurationSeconds"),
"init.ts should compute media window duration across timed media",
);
// Timeline payload windowing should also avoid first-video truncation.
assert(
!timelineSource.includes("resolveMainVideoWindowEndSeconds"),
"timeline.ts should not use first-video window end helper",
);
assert(
timelineSource.includes("resolveMediaWindowEndSeconds"),
"timeline.ts should compute media window end across timed media",
);
console.log(
JSON.stringify({
event: "hyperframe_runtime_duration_guards_verified",
initPath,
timelinePath,
}),
);
@@ -0,0 +1,44 @@
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { HYPERFRAME_RUNTIME_ARTIFACTS } from "../src/inline-scripts/hyperframe";
function assert(condition: unknown, message: string): void {
if (!condition) throw new Error(message);
}
const scriptsDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
const distDir = resolve(scriptsDir, "../dist");
const iifePath = resolve(distDir, HYPERFRAME_RUNTIME_ARTIFACTS.iife);
const manifestPath = resolve(distDir, HYPERFRAME_RUNTIME_ARTIFACTS.manifest);
const iifeSource = readFileSync(iifePath, "utf8");
const manifestRaw = readFileSync(manifestPath, "utf8");
const manifest = JSON.parse(manifestRaw) as {
sha256?: string;
artifacts?: { iife?: string; esm?: string };
};
assert(iifeSource.length > 0, "IIFE runtime artifact is empty");
assert(
manifest.artifacts?.iife === HYPERFRAME_RUNTIME_ARTIFACTS.iife,
"Manifest iife artifact name is not strict expected value",
);
assert(
manifest.artifacts?.esm === HYPERFRAME_RUNTIME_ARTIFACTS.esm,
"Manifest esm artifact name is not strict expected value",
);
assert(Boolean(manifest.artifacts?.iife), "Manifest missing iife artifact entry");
assert(Boolean(manifest.artifacts?.esm), "Manifest missing esm artifact entry");
const runtimeSha = createHash("sha256").update(iifeSource, "utf8").digest("hex");
assert(runtimeSha === manifest.sha256, "Manifest sha256 does not match runtime artifact");
console.log(
JSON.stringify({
event: "hyperframe_runtime_parity_verified",
bytes: iifeSource.length,
sha256: runtimeSha,
}),
);
@@ -0,0 +1,102 @@
function assert(condition: unknown, message: string): void {
if (!condition) {
throw new Error(message);
}
}
const ALLOWED_HOSTS = new Set(["runtime.example.com"]);
const ALLOWED_PATH_PREFIX = "/static/hyperframes-runtime/";
function isAllowedRuntimeUrl(candidate: string): boolean {
try {
const parsed = new URL(candidate);
return (
parsed.protocol === "https:" &&
ALLOWED_HOSTS.has(parsed.hostname.toLowerCase()) &&
parsed.pathname.startsWith(ALLOWED_PATH_PREFIX) &&
parsed.pathname.endsWith(".js")
);
} catch {
return false;
}
}
function isGuardedPreviewMessage(data: unknown): boolean {
if (!data || typeof data !== "object") {
return false;
}
const record = data as { source?: unknown; type?: unknown };
const source = typeof record.source === "string" ? record.source : null;
const type = typeof record.type === "string" ? record.type : null;
const guardedTypes = new Set([
"state",
"timeline",
"element-picked",
"element-picked-many",
"element-pick-candidates",
"pick-mode-cancelled",
]);
if (!type || !guardedTypes.has(type)) {
return false;
}
return source === "hf-preview";
}
const allowedRuntimeFixtures = [
"https://runtime.example.com/static/hyperframes-runtime/hyperframe.runtime.iife.js",
"https://runtime.example.com/static/hyperframes-runtime/v2026.02.20/hyperframe.runtime.iife.js",
];
const blockedRuntimeFixtures = [
"http://runtime.example.com/static/hyperframes-runtime/hyperframe.runtime.iife.js",
"javascript:alert(1)",
"data:text/javascript,alert(1)",
"https://evil.example/static/hyperframes-runtime/hyperframe.runtime.iife.js",
"https://runtime.example.com/static/other/hyperframe.runtime.iife.js",
"https://runtime.example.com/static/hyperframes-runtime/hyperframe.runtime.iife.css",
];
for (const fixture of allowedRuntimeFixtures) {
assert(isAllowedRuntimeUrl(fixture), `Expected runtime URL to be allowed: ${fixture}`);
}
for (const fixture of blockedRuntimeFixtures) {
assert(!isAllowedRuntimeUrl(fixture), `Expected runtime URL to be blocked: ${fixture}`);
}
const allowedMessages = [
{ type: "state", source: "hf-preview" },
{ type: "timeline", source: "hf-preview" },
{ type: "element-picked", source: "hf-preview" },
];
const blockedMessages = [
{ type: "state", source: "hf-parent" },
{ type: "timeline", source: "evil-origin" },
{ type: "element-picked", source: "hf-parent" },
{ type: "pick-mode-cancelled", source: null },
{ type: "unknown-type", source: "hf-preview" },
];
for (const fixture of allowedMessages) {
assert(
isGuardedPreviewMessage(fixture),
`Expected message fixture to pass guard: ${JSON.stringify(fixture)}`,
);
}
for (const fixture of blockedMessages) {
assert(
!isGuardedPreviewMessage(fixture),
`Expected message fixture to fail guard: ${JSON.stringify(fixture)}`,
);
}
console.log(
JSON.stringify({
event: "hyperframe_runtime_security_fixtures_verified",
allowedRuntimeFixtures: allowedRuntimeFixtures.length,
blockedRuntimeFixtures: blockedRuntimeFixtures.length,
allowedMessages: allowedMessages.length,
blockedMessages: blockedMessages.length,
}),
);
@@ -0,0 +1,133 @@
import assert from "node:assert/strict";
import { createGsapAdapter } from "../src/runtime/adapters/gsap";
import { createRuntimePlayer } from "../src/runtime/player";
import type { RuntimeTimelineLike } from "../src/runtime/types";
type Call = {
method: "pause" | "seek" | "totalTime";
time?: number;
suppressEvents?: boolean;
};
function createTimeline(withTotalTime: boolean): { calls: Call[]; timeline: RuntimeTimelineLike } {
const calls: Call[] = [];
const timeline: RuntimeTimelineLike = {
play: () => undefined,
pause: () => {
calls.push({ method: "pause" });
},
seek: (timeSeconds: number, suppressEvents?: boolean) => {
calls.push({ method: "seek", time: timeSeconds, suppressEvents });
},
time: () => 0,
duration: () => 12,
add: () => undefined,
paused: () => undefined,
set: () => undefined,
};
if (withTotalTime) {
timeline.totalTime = (timeSeconds: number, suppressEvents?: boolean) => {
calls.push({ method: "totalTime", time: timeSeconds, suppressEvents });
};
}
return { calls, timeline };
}
function createPlayer(timeline: RuntimeTimelineLike) {
const deterministicSeekCalls: number[] = [];
const syncMediaCalls: number[] = [];
const renderFrameSeekCalls: number[] = [];
const player = createRuntimePlayer({
getTimeline: () => timeline,
setTimeline: () => undefined,
getIsPlaying: () => false,
setIsPlaying: () => undefined,
getPlaybackRate: () => 1,
setPlaybackRate: () => undefined,
getCanonicalFps: () => 30,
onSyncMedia: (timeSeconds) => {
syncMediaCalls.push(timeSeconds);
},
onStatePost: () => undefined,
onDeterministicSeek: (timeSeconds) => {
deterministicSeekCalls.push(timeSeconds);
},
onDeterministicPause: () => undefined,
onDeterministicPlay: () => undefined,
onRenderFrameSeek: (timeSeconds) => {
renderFrameSeekCalls.push(timeSeconds);
},
onShowNativeVideos: () => undefined,
getSafeDuration: () => 12,
});
return { player, deterministicSeekCalls, syncMediaCalls, renderFrameSeekCalls };
}
function testSeekUsesDeterministicGsapPath(): void {
const { calls, timeline } = createTimeline(true);
const { player, deterministicSeekCalls, syncMediaCalls, renderFrameSeekCalls } =
createPlayer(timeline);
const quantizedTime = 2;
player.seek(2.017);
assert.deepEqual(
calls,
[{ method: "pause" }, { method: "totalTime", time: quantizedTime, suppressEvents: false }],
"player.seek() should use quantized totalTime() when available",
);
assert.deepEqual(
deterministicSeekCalls,
[quantizedTime],
"player.seek() should notify adapters with the quantized time",
);
assert.deepEqual(syncMediaCalls, [quantizedTime], "media sync should use quantized time");
assert.deepEqual(
renderFrameSeekCalls,
[quantizedTime],
"render frame seek should use quantized time",
);
}
function testGsapAdapterPreservesTotalTime(): void {
const { calls, timeline } = createTimeline(true);
const adapter = createGsapAdapter({ getTimeline: () => timeline });
const seekTime = 2.033333333333333;
adapter.seek({ time: seekTime });
assert.deepEqual(
calls,
[
{ method: "pause" },
// Nudge to force GSAP 3.x dirty state before the real seek
{ method: "totalTime", time: seekTime + 0.001, suppressEvents: true },
{ method: "totalTime", time: seekTime, suppressEvents: false },
],
"GSAP adapter should nudge then seek via totalTime() (not downgrade to seek())",
);
}
function testGsapAdapterFallsBackToSeek(): void {
const { calls, timeline } = createTimeline(false);
const adapter = createGsapAdapter({ getTimeline: () => timeline });
adapter.seek({ time: 1.5 });
assert.deepEqual(
calls,
[{ method: "pause" }, { method: "seek", time: 1.5, suppressEvents: false }],
"GSAP adapter should keep working with timelines that only expose seek()",
);
}
testSeekUsesDeterministicGsapPath();
testGsapAdapterPreservesTotalTime();
testGsapAdapterFallsBackToSeek();
console.log(
JSON.stringify({
event: "hyperframe_runtime_seek_verified",
assertions: 3,
}),
);