hyperframes 0.7.50 → 0.7.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.7.50" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.52" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -4944,7 +4944,7 @@ var require_util = __commonJS({
4944
4944
  exports.isAbsolute = function(aPath) {
4945
4945
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
4946
4946
  };
4947
- function relative20(aRoot, aPath) {
4947
+ function relative21(aRoot, aPath) {
4948
4948
  if (aRoot === "") {
4949
4949
  aRoot = ".";
4950
4950
  }
@@ -4963,7 +4963,7 @@ var require_util = __commonJS({
4963
4963
  }
4964
4964
  return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
4965
4965
  }
4966
- exports.relative = relative20;
4966
+ exports.relative = relative21;
4967
4967
  var supportsNullProto = (function() {
4968
4968
  var obj = /* @__PURE__ */ Object.create(null);
4969
4969
  return !("__proto__" in obj);
@@ -15839,9 +15839,9 @@ var require_printer = __commonJS({
15839
15839
  }
15840
15840
  case "ForStatement": {
15841
15841
  var init = path2.call(print2, "init");
15842
- var sep9 = init.length > 1 ? ";\n" : "; ";
15842
+ var sep10 = init.length > 1 ? ";\n" : "; ";
15843
15843
  var forParen = "for (";
15844
- var indented = (0, lines_1.fromString)(sep9).join([init, path2.call(print2, "test"), path2.call(print2, "update")]).indentTail(forParen.length);
15844
+ var indented = (0, lines_1.fromString)(sep10).join([init, path2.call(print2, "test"), path2.call(print2, "update")]).indentTail(forParen.length);
15845
15845
  var head = (0, lines_1.concat)([forParen, indented, ")"]);
15846
15846
  var clause = adjustClause(path2.call(print2, "body"), options);
15847
15847
  parts.push(head);
@@ -41411,10 +41411,10 @@ function compareDocumentPosition(nodeA, nodeB) {
41411
41411
  function uniqueSort(nodes) {
41412
41412
  nodes = nodes.filter((node, i2, arr) => !arr.includes(node, i2 + 1));
41413
41413
  nodes.sort((a, b2) => {
41414
- const relative20 = compareDocumentPosition(a, b2);
41415
- if (relative20 & DocumentPosition.PRECEDING) {
41414
+ const relative21 = compareDocumentPosition(a, b2);
41415
+ if (relative21 & DocumentPosition.PRECEDING) {
41416
41416
  return -1;
41417
- } else if (relative20 & DocumentPosition.FOLLOWING) {
41417
+ } else if (relative21 & DocumentPosition.FOLLOWING) {
41418
41418
  return 1;
41419
41419
  }
41420
41420
  return 0;
@@ -47629,12 +47629,12 @@ var require_CSSValueExpression = __commonJS({
47629
47629
  return false;
47630
47630
  }
47631
47631
  };
47632
- CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep9) {
47633
- var endIdx = this._findMatchedIdx(token, idx, sep9), text2;
47632
+ CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep10) {
47633
+ var endIdx = this._findMatchedIdx(token, idx, sep10), text2;
47634
47634
  if (endIdx === -1) {
47635
47635
  return false;
47636
47636
  } else {
47637
- text2 = token.substring(idx, endIdx + sep9.length);
47637
+ text2 = token.substring(idx, endIdx + sep10.length);
47638
47638
  return {
47639
47639
  idx: endIdx,
47640
47640
  text: text2
@@ -47674,15 +47674,15 @@ var require_CSSValueExpression = __commonJS({
47674
47674
  if (!isLegal) {
47675
47675
  return false;
47676
47676
  } else {
47677
- var sep9 = "/";
47678
- return this._parseJSString(token, idx, sep9);
47677
+ var sep10 = "/";
47678
+ return this._parseJSString(token, idx, sep10);
47679
47679
  }
47680
47680
  };
47681
- CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep9) {
47681
+ CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep10) {
47682
47682
  var startIdx = idx, endIdx;
47683
47683
  var NOT_FOUND = -1;
47684
47684
  while (true) {
47685
- endIdx = token.indexOf(sep9, startIdx + 1);
47685
+ endIdx = token.indexOf(sep10, startIdx + 1);
47686
47686
  if (endIdx === -1) {
47687
47687
  endIdx = NOT_FOUND;
47688
47688
  break;
@@ -50624,8 +50624,8 @@ var init_esm10 = __esm({
50624
50624
  });
50625
50625
 
50626
50626
  // ../../node_modules/.bun/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
50627
- function encodeInteger(builder, num2, relative20) {
50628
- let delta = num2 - relative20;
50627
+ function encodeInteger(builder, num2, relative21) {
50628
+ let delta = num2 - relative21;
50629
50629
  delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
50630
50630
  do {
50631
50631
  let clamped = delta & 31;
@@ -53463,21 +53463,36 @@ function mintHfId(el, assigned) {
53463
53463
  assigned.add(id);
53464
53464
  return id;
53465
53465
  }
53466
+ function getChildElements(parent) {
53467
+ const directChildren = Array.from(parent.children);
53468
+ if (directChildren.length || parent.tagName.toLowerCase() !== "template") return directChildren;
53469
+ const content = parent.content;
53470
+ if (content?.children.length) return Array.from(content.children);
53471
+ return directChildren;
53472
+ }
53466
53473
  function isCompositionTemplate(el) {
53467
53474
  if (el.tagName.toLowerCase() !== "template") return false;
53468
53475
  if (el.getAttribute("data-composition-id") !== null) return true;
53469
- for (const child of Array.from(el.children)) {
53476
+ for (const child of getChildElements(el)) {
53470
53477
  if (child.getAttribute("data-composition-id") !== null) return true;
53471
53478
  }
53472
53479
  return false;
53473
53480
  }
53481
+ function walkCompositionDescendants(root, visit) {
53482
+ const rootElement = root.nodeType === 9 ? root.documentElement : root;
53483
+ if (!rootElement) return;
53484
+ const walk = (parent) => {
53485
+ for (const child of getChildElements(parent)) {
53486
+ const isTemplate = child.tagName.toLowerCase() === "template";
53487
+ if (isTemplate && !isCompositionTemplate(child)) continue;
53488
+ visit(child);
53489
+ walk(child);
53490
+ }
53491
+ };
53492
+ walk(rootElement);
53493
+ }
53474
53494
  function walkElements(root, visit) {
53475
- for (const child of Array.from(root.children)) {
53476
- const isTemplate = child.tagName.toLowerCase() === "template";
53477
- if (isTemplate && !isCompositionTemplate(child)) continue;
53478
- visit(child);
53479
- walkElements(child, visit);
53480
- }
53495
+ walkCompositionDescendants(root, visit);
53481
53496
  }
53482
53497
  function ensureHfIds(html) {
53483
53498
  const hasDocumentShell = /<!doctype|<html[\s>]/i.test(html);
@@ -53797,7 +53812,7 @@ function parseHtml(html) {
53797
53812
  elements.push(mediaElement);
53798
53813
  }
53799
53814
  });
53800
- const scriptTags = doc.querySelectorAll("script");
53815
+ const scriptTags = findScriptElementsDeep(doc);
53801
53816
  let gsapScript = null;
53802
53817
  for (const script of scriptTags) {
53803
53818
  const src = script.getAttribute("src");
@@ -54042,7 +54057,7 @@ function stripGsapForId(script, elementId) {
54042
54057
  }
54043
54058
  }
54044
54059
  function cascadeRemoveGsapById(doc, elementId) {
54045
- for (const script of Array.from(doc.querySelectorAll("script"))) {
54060
+ for (const script of findScriptElementsDeep(doc)) {
54046
54061
  const text2 = script.textContent ?? "";
54047
54062
  if (!text2.includes("gsap") && !text2.includes("ScrollTrigger")) continue;
54048
54063
  const updated = stripGsapForId(text2, elementId);
@@ -54116,12 +54131,11 @@ function validateCompositionHtml(html) {
54116
54131
  if (/javascript\s*:/i.test(html)) {
54117
54132
  errors.push("javascript: URLs not allowed");
54118
54133
  }
54119
- const scripts = doc.querySelectorAll("script");
54134
+ const scripts = findScriptElementsDeep(doc);
54120
54135
  if (scripts.length > 2) {
54121
54136
  warnings.push("Multiple script tags detected - only GSAP CDN and main script expected");
54122
54137
  }
54123
- const gsapScript = extractGsapScript(doc);
54124
- if (gsapScript) {
54138
+ for (const gsapScript of extractGsapScripts(doc)) {
54125
54139
  const gsapValidation = validateCompositionGsap(gsapScript);
54126
54140
  errors.push(...gsapValidation.errors);
54127
54141
  warnings.push(...gsapValidation.warnings);
@@ -54132,15 +54146,23 @@ function validateCompositionHtml(html) {
54132
54146
  warnings
54133
54147
  };
54134
54148
  }
54135
- function extractGsapScript(doc) {
54136
- const scripts = doc.querySelectorAll("script");
54149
+ function findScriptElementsDeep(doc) {
54150
+ const scripts = [];
54151
+ walkCompositionDescendants(doc, (el) => {
54152
+ if (el.tagName.toLowerCase() === "script") scripts.push(el);
54153
+ });
54154
+ return scripts;
54155
+ }
54156
+ function extractGsapScripts(doc) {
54157
+ const scripts = findScriptElementsDeep(doc);
54158
+ const gsapScripts = [];
54137
54159
  for (const script of scripts) {
54138
54160
  const content = script.textContent || "";
54139
54161
  if (content.includes("gsap.timeline") || content.includes(".set(") || content.includes(".to(")) {
54140
- return content;
54162
+ gsapScripts.push(content);
54141
54163
  }
54142
54164
  }
54143
- return null;
54165
+ return gsapScripts;
54144
54166
  }
54145
54167
  function suggestMatchingPreset(compositionWidth, compositionHeight, chosen) {
54146
54168
  const aspectMatches = VALID_CANVAS_RESOLUTIONS.filter((preset2) => {
@@ -60146,7 +60168,7 @@ var init_dist3 = __esm({
60146
60168
  });
60147
60169
 
60148
60170
  // src/telemetry/config.ts
60149
- import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
60171
+ import { existsSync as existsSync2, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
60150
60172
  import { join as join3 } from "path";
60151
60173
  import { homedir } from "os";
60152
60174
  import { randomUUID } from "crypto";
@@ -60174,7 +60196,15 @@ function readConfig() {
60174
60196
  lastSkillsCheck: parsed.lastSkillsCheck,
60175
60197
  skillsUpdateAvailable: parsed.skillsUpdateAvailable,
60176
60198
  skillsOutdatedCount: parsed.skillsOutdatedCount,
60177
- skillsMissingCount: parsed.skillsMissingCount
60199
+ skillsMissingCount: parsed.skillsMissingCount,
60200
+ skillsRemovedCount: parsed.skillsRemovedCount,
60201
+ // Explicit `=== true`/typeof-number checks rather than a truthy/nullish
60202
+ // read — a hand-edited or corrupted config could plausibly carry a
60203
+ // non-boolean/non-number JSON value (e.g. the STRING "false", which is
60204
+ // truthy in JS) for these two fields specifically, since they're read
60205
+ // with a bare truthy check at the call site (review finding).
60206
+ deParallelRouterTrialFired: parsed.deParallelRouterTrialFired === true ? true : void 0,
60207
+ deParallelRouterTrialRenderCount: typeof parsed.deParallelRouterTrialRenderCount === "number" ? parsed.deParallelRouterTrialRenderCount : void 0
60178
60208
  };
60179
60209
  cachedConfig = config;
60180
60210
  return { ...config };
@@ -60184,12 +60214,20 @@ function readConfig() {
60184
60214
  return config;
60185
60215
  }
60186
60216
  }
60217
+ function readConfigFresh() {
60218
+ cachedConfig = null;
60219
+ return readConfig();
60220
+ }
60187
60221
  function writeConfig(config) {
60188
60222
  try {
60189
60223
  mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
60190
- writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
60224
+ const tmpFile = `${CONFIG_FILE}.${process.pid}.tmp`;
60225
+ writeFileSync(tmpFile, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
60226
+ renameSync(tmpFile, CONFIG_FILE);
60191
60227
  cachedConfig = { ...config };
60228
+ return true;
60192
60229
  } catch {
60230
+ return false;
60193
60231
  }
60194
60232
  }
60195
60233
  function incrementCommandCount() {
@@ -64649,9 +64687,11 @@ function isTransientBrowserError(error) {
64649
64687
  }
64650
64688
  function isMemoryExhaustionError(error) {
64651
64689
  const message = error instanceof Error ? error.message : String(error);
64690
+ if (BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE.test(message.trim())) return true;
64691
+ if (BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE.test(message)) return true;
64652
64692
  return MEMORY_EXHAUSTION_ERROR_PATTERNS.some((pattern) => pattern.test(message));
64653
64693
  }
64654
- var DrawElementVerificationError, BROWSER_CONSOLE_BUFFER_SIZE, CAPTURE_SESSION_CLOSE_TIMEOUT_MS, LOCKED_WARMUP_TICKS, realSleep, HF_READY_DIAGNOSTIC_EXPR, STATIC_VERIFY_REFERENCE_STRIDE, TRANSIENT_BROWSER_ERROR_PATTERNS, MEMORY_EXHAUSTION_ERROR_PATTERNS;
64694
+ var DrawElementVerificationError, BROWSER_CONSOLE_BUFFER_SIZE, CAPTURE_SESSION_CLOSE_TIMEOUT_MS, LOCKED_WARMUP_TICKS, realSleep, HF_READY_DIAGNOSTIC_EXPR, STATIC_VERIFY_REFERENCE_STRIDE, TRANSIENT_BROWSER_ERROR_PATTERNS, MEMORY_EXHAUSTION_ERROR_PATTERNS, BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE, BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE;
64655
64695
  var init_frameCapture = __esm({
64656
64696
  "../engine/src/services/frameCapture.ts"() {
64657
64697
  "use strict";
@@ -64721,6 +64761,8 @@ var init_frameCapture = __esm({
64721
64761
  /Reached heap limit/i,
64722
64762
  /JavaScript heap out of memory/i
64723
64763
  ];
64764
+ BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE = /^out of memory\.?$/i;
64765
+ BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE = /\bworker \d+: out of memory\.?(?:;|$)/i;
64724
64766
  }
64725
64767
  });
64726
64768
 
@@ -70400,7 +70442,9 @@ async function lintProject(projectDir) {
70400
70442
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
70401
70443
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
70402
70444
  if (entry.isDirectory()) out.push(...collectHtmlFiles(join10(dir, entry.name), relPath));
70403
- else if (entry.isFile() && entry.name.endsWith(".html")) out.push(relPath);
70445
+ else if (entry.isFile() && entry.name.endsWith(".html") && !entry.name.startsWith("._")) {
70446
+ out.push(relPath);
70447
+ }
70404
70448
  }
70405
70449
  return out;
70406
70450
  };
@@ -70581,7 +70625,9 @@ function lintTextureMaskAssetNotFound(projectDir, htmlSources) {
70581
70625
  function lintMultipleRootCompositions(projectDir) {
70582
70626
  const findings = [];
70583
70627
  try {
70584
- const rootHtmlFiles = readdirSync3(projectDir).filter((f3) => f3.endsWith(".html"));
70628
+ const rootHtmlFiles = readdirSync3(projectDir).filter(
70629
+ (file) => file.endsWith(".html") && !file.startsWith("._")
70630
+ );
70585
70631
  const rootCompositions = [];
70586
70632
  for (const file of rootHtmlFiles) {
70587
70633
  if (file === "caption-skin.html") continue;
@@ -73304,7 +73350,7 @@ var init_inlineSubCompositions = __esm({
73304
73350
 
73305
73351
  // ../core/dist/compiler/htmlBundler.js
73306
73352
  import { readFileSync as readFileSync5, existsSync as existsSync10 } from "fs";
73307
- import { join as join11, resolve as resolve8, relative as relative3, dirname as dirname7, isAbsolute as isAbsolute3, sep as sep2 } from "path";
73353
+ import { resolve as resolve8, relative as relative3, dirname as dirname7, isAbsolute as isAbsolute3, sep as sep2 } from "path";
73308
73354
  import { transformSync } from "esbuild";
73309
73355
  function getRuntimeScriptUrl() {
73310
73356
  const configured = (process.env.HYPERFRAME_RUNTIME_URL || "").trim();
@@ -73388,6 +73434,87 @@ function rebaseCssUrls(css, cssFileDir, projectDir) {
73388
73434
  return `url(${quote || ""}${rebased}${suffix}${quote || ""})`;
73389
73435
  });
73390
73436
  }
73437
+ function rebaseRelativePath(urlValue, fromDir, toDir) {
73438
+ const { basePath, suffix } = splitUrlSuffix(urlValue.trim());
73439
+ if (!basePath)
73440
+ return urlValue;
73441
+ const absolutePath = resolve8(fromDir, basePath);
73442
+ const rebased = relative3(resolve8(toDir), absolutePath).split(sep2).join("/");
73443
+ return appendSuffixToUrl(rebased, suffix);
73444
+ }
73445
+ function rebaseSrcsetPaths(srcsetValue, fromDir, toDir) {
73446
+ if (!srcsetValue)
73447
+ return srcsetValue;
73448
+ return srcsetValue.split(",").map((rawCandidate) => {
73449
+ const candidate = rawCandidate.trim();
73450
+ if (!candidate)
73451
+ return candidate;
73452
+ const parts = candidate.split(/\s+/);
73453
+ const first = parts[0] ?? "";
73454
+ if (parts.length === 0 || !isRelativeUrl(first))
73455
+ return candidate;
73456
+ parts[0] = rebaseRelativePath(first, fromDir, toDir);
73457
+ return parts.join(" ");
73458
+ }).join(", ");
73459
+ }
73460
+ function rebaseColorGradingLutPath(value, fromDir, toDir) {
73461
+ if (!value.trim().startsWith("{"))
73462
+ return value;
73463
+ let parsed;
73464
+ try {
73465
+ parsed = JSON.parse(value);
73466
+ } catch {
73467
+ return value;
73468
+ }
73469
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
73470
+ return value;
73471
+ const lut = Reflect.get(parsed, "lut");
73472
+ if (typeof lut === "string") {
73473
+ if (!isRelativeUrl(lut))
73474
+ return value;
73475
+ Reflect.set(parsed, "lut", rebaseRelativePath(lut, fromDir, toDir));
73476
+ return JSON.stringify(parsed);
73477
+ }
73478
+ if (typeof lut !== "object" || lut === null || Array.isArray(lut))
73479
+ return value;
73480
+ const lutSrc = Reflect.get(lut, "src");
73481
+ if (typeof lutSrc !== "string" || !isRelativeUrl(lutSrc))
73482
+ return value;
73483
+ Reflect.set(lut, "src", rebaseRelativePath(lutSrc, fromDir, toDir));
73484
+ return JSON.stringify(parsed);
73485
+ }
73486
+ function rebaseEntryAuthoredAssetPaths(document2, sourceDir, projectDir) {
73487
+ for (const styleEl of [...document2.querySelectorAll("style")]) {
73488
+ styleEl.textContent = rebaseCssUrls(styleEl.textContent || "", sourceDir, projectDir);
73489
+ }
73490
+ for (const el of [...document2.querySelectorAll("[style]")]) {
73491
+ const styleAttr = el.getAttribute("style");
73492
+ if (styleAttr)
73493
+ el.setAttribute("style", rebaseCssUrls(styleAttr, sourceDir, projectDir));
73494
+ }
73495
+ for (const el of [...document2.querySelectorAll("[src], [href], [poster], [xlink\\:href]")]) {
73496
+ if (el.tagName === "LINK" && (el.getAttribute("rel") || "").toLowerCase() === "stylesheet")
73497
+ continue;
73498
+ if (el.tagName === "SCRIPT" && el.hasAttribute("src"))
73499
+ continue;
73500
+ for (const attr2 of ["src", "href", "poster", "xlink:href"]) {
73501
+ const value = el.getAttribute(attr2);
73502
+ if (!value || !isRelativeUrl(value))
73503
+ continue;
73504
+ el.setAttribute(attr2, rebaseRelativePath(value, sourceDir, projectDir));
73505
+ }
73506
+ }
73507
+ for (const el of [...document2.querySelectorAll("[srcset]")]) {
73508
+ const srcset = el.getAttribute("srcset");
73509
+ if (srcset)
73510
+ el.setAttribute("srcset", rebaseSrcsetPaths(srcset, sourceDir, projectDir));
73511
+ }
73512
+ for (const el of [...document2.querySelectorAll(`[${HF_COLOR_GRADING_ATTR}]`)]) {
73513
+ const value = el.getAttribute(HF_COLOR_GRADING_ATTR);
73514
+ if (value)
73515
+ el.setAttribute(HF_COLOR_GRADING_ATTR, rebaseColorGradingLutPath(value, sourceDir, projectDir));
73516
+ }
73517
+ }
73391
73518
  function inlineCssFile(css, cssFileDir, projectDir, visited = /* @__PURE__ */ new Set()) {
73392
73519
  const { result: strippedCss, restore: restoreComments } = withCommentsStripped(css, (s2) => s2);
73393
73520
  const importPlaceholders = [];
@@ -73806,24 +73933,34 @@ function hoistCompositionScripts(container, opts) {
73806
73933
  }
73807
73934
  }
73808
73935
  async function bundleToSingleHtml(projectDir, options) {
73809
- const indexPath2 = join11(projectDir, "index.html");
73810
- if (!existsSync10(indexPath2))
73811
- throw new Error("index.html not found in project directory");
73936
+ const entryFile = options?.entryFile ?? "index.html";
73937
+ const indexPath2 = resolveWithinProject(projectDir, entryFile);
73938
+ if (!indexPath2 || !existsSync10(indexPath2)) {
73939
+ throw new Error(`${entryFile} not found in project directory`);
73940
+ }
73941
+ const sourceDir = dirname7(indexPath2);
73942
+ const resolveEntryPath = (relativePath) => {
73943
+ const resolved2 = resolve8(sourceDir, relativePath);
73944
+ return isSafePath(projectDir, resolved2) ? resolved2 : null;
73945
+ };
73812
73946
  const rawHtml = readFileSync5(indexPath2, "utf-8");
73813
- const compiled = await compileHtml(rawHtml, projectDir, options?.probeMediaDuration);
73947
+ const compiled = await compileHtml(rawHtml, sourceDir, options?.probeMediaDuration);
73814
73948
  const staticGuard = await validateHyperframeHtmlContract(compiled);
73815
73949
  if (!staticGuard.isValid) {
73816
73950
  console.warn(`[StaticGuard] Invalid HyperFrame contract: ${staticGuard.missingKeys.join("; ")}`);
73817
73951
  }
73818
73952
  const withInterceptor = injectInterceptor(compiled, options?.runtime ?? "inline");
73819
73953
  const document2 = parseHTMLContent(withInterceptor);
73954
+ if (resolve8(sourceDir) !== resolve8(projectDir)) {
73955
+ rebaseEntryAuthoredAssetPaths(document2, sourceDir, projectDir);
73956
+ }
73820
73957
  const localCssChunks = [];
73821
73958
  let cssAnchorPlaced = false;
73822
73959
  for (const el of [...document2.querySelectorAll('link[rel="stylesheet"]')]) {
73823
73960
  const href = el.getAttribute("href");
73824
73961
  if (!href || !isRelativeUrl(href))
73825
73962
  continue;
73826
- const cssPath = resolveWithinProject(projectDir, href);
73963
+ const cssPath = resolveEntryPath(href);
73827
73964
  if (!cssPath)
73828
73965
  continue;
73829
73966
  const css = safeReadFile(cssPath);
@@ -73856,7 +73993,7 @@ async function bundleToSingleHtml(projectDir, options) {
73856
73993
  const src = el.getAttribute("src");
73857
73994
  if (!src || !isRelativeUrl(src))
73858
73995
  continue;
73859
- const jsPath = resolveWithinProject(projectDir, src);
73996
+ const jsPath = resolveEntryPath(src);
73860
73997
  const js = jsPath ? safeReadFile(jsPath) : null;
73861
73998
  if (js == null)
73862
73999
  continue;
@@ -73889,7 +74026,7 @@ async function bundleToSingleHtml(projectDir, options) {
73889
74026
  resolveHtml: (srcPath) => {
73890
74027
  if (!isRelativeUrl(srcPath))
73891
74028
  return null;
73892
- const compPath = resolveWithinProject(projectDir, srcPath);
74029
+ const compPath = resolveEntryPath(srcPath);
73893
74030
  return compPath ? safeReadFile(compPath) : null;
73894
74031
  },
73895
74032
  parseHtml: parseHTMLContent,
@@ -73921,7 +74058,7 @@ async function bundleToSingleHtml(projectDir, options) {
73921
74058
  continue;
73922
74059
  seenCompScriptSrcs.add(extSrc);
73923
74060
  if (isRelativeUrl(extSrc)) {
73924
- const jsPath = resolveWithinProject(projectDir, extSrc);
74061
+ const jsPath = resolveEntryPath(extSrc);
73925
74062
  const js = jsPath ? safeReadFile(jsPath) : null;
73926
74063
  if (js != null) {
73927
74064
  compScriptChunks.push(js);
@@ -74291,13 +74428,13 @@ import {
74291
74428
  lstatSync,
74292
74429
  mkdirSync as mkdirSync6,
74293
74430
  readdirSync as readdirSync4,
74294
- renameSync,
74431
+ renameSync as renameSync2,
74295
74432
  rmSync,
74296
74433
  statSync as statSync3,
74297
74434
  utimesSync,
74298
74435
  writeFileSync as writeFileSync4
74299
74436
  } from "fs";
74300
- import { join as join12 } from "path";
74437
+ import { join as join11 } from "path";
74301
74438
  function readKeyStat(videoPath) {
74302
74439
  try {
74303
74440
  const stat3 = statSync3(videoPath);
@@ -74328,8 +74465,8 @@ function cacheEntryDirName(keyHash) {
74328
74465
  }
74329
74466
  function lookupCacheEntry(rootDir, input2) {
74330
74467
  const keyHash = computeCacheKey(input2);
74331
- const dir = join12(rootDir, cacheEntryDirName(keyHash));
74332
- const complete = existsSync11(join12(dir, COMPLETE_SENTINEL));
74468
+ const dir = join11(rootDir, cacheEntryDirName(keyHash));
74469
+ const complete = existsSync11(join11(dir, COMPLETE_SENTINEL));
74333
74470
  return { entry: { dir, keyHash }, hit: complete };
74334
74471
  }
74335
74472
  function partialCacheEntryDir(entry) {
@@ -74340,18 +74477,18 @@ function isTargetExistsRenameError(err) {
74340
74477
  return code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM";
74341
74478
  }
74342
74479
  function adoptPublishedWinner(entry, partialDir) {
74343
- if (!existsSync11(join12(entry.dir, COMPLETE_SENTINEL))) return null;
74480
+ if (!existsSync11(join11(entry.dir, COMPLETE_SENTINEL))) return null;
74344
74481
  removeDir(partialDir);
74345
74482
  return { dir: entry.dir, published: true };
74346
74483
  }
74347
74484
  function publishCacheEntry(entry, partialDir) {
74348
74485
  try {
74349
- writeFileSync4(join12(partialDir, COMPLETE_SENTINEL), "", "utf-8");
74486
+ writeFileSync4(join11(partialDir, COMPLETE_SENTINEL), "", "utf-8");
74350
74487
  } catch {
74351
74488
  return { dir: partialDir, published: false };
74352
74489
  }
74353
74490
  try {
74354
- renameSync(partialDir, entry.dir);
74491
+ renameSync2(partialDir, entry.dir);
74355
74492
  return { dir: entry.dir, published: true };
74356
74493
  } catch (err) {
74357
74494
  if (!isTargetExistsRenameError(err)) return { dir: partialDir, published: false };
@@ -74364,7 +74501,7 @@ function publishCacheEntry(entry, partialDir) {
74364
74501
  return { dir: partialDir, published: false };
74365
74502
  }
74366
74503
  try {
74367
- renameSync(partialDir, entry.dir);
74504
+ renameSync2(partialDir, entry.dir);
74368
74505
  return { dir: entry.dir, published: true };
74369
74506
  } catch {
74370
74507
  return adoptPublishedWinner(entry, partialDir) ?? { dir: partialDir, published: false };
@@ -74373,7 +74510,7 @@ function publishCacheEntry(entry, partialDir) {
74373
74510
  function touchCacheEntry(entry) {
74374
74511
  try {
74375
74512
  const now = /* @__PURE__ */ new Date();
74376
- utimesSync(join12(entry.dir, COMPLETE_SENTINEL), now, now);
74513
+ utimesSync(join11(entry.dir, COMPLETE_SENTINEL), now, now);
74377
74514
  } catch {
74378
74515
  }
74379
74516
  }
@@ -74398,7 +74535,7 @@ function directorySizeBytes(path2) {
74398
74535
  return 0;
74399
74536
  }
74400
74537
  for (const child of children) {
74401
- const childPath = join12(path2, child);
74538
+ const childPath = join11(path2, child);
74402
74539
  try {
74403
74540
  const stat3 = lstatSync(childPath);
74404
74541
  if (stat3.isDirectory()) {
@@ -74427,7 +74564,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
74427
74564
  }
74428
74565
  let lastUseMs = dirStat.mtimeMs;
74429
74566
  try {
74430
- lastUseMs = statSync3(join12(dir, COMPLETE_SENTINEL)).mtimeMs;
74567
+ lastUseMs = statSync3(join11(dir, COMPLETE_SENTINEL)).mtimeMs;
74431
74568
  } catch {
74432
74569
  }
74433
74570
  return { dir, size: directorySizeBytes(dir), lastUseMs, ageMs: now - lastUseMs };
@@ -74437,7 +74574,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
74437
74574
  }
74438
74575
  function gcSweepDue(rootDir, maxAgeMs) {
74439
74576
  try {
74440
- return Date.now() - statSync3(join12(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
74577
+ return Date.now() - statSync3(join11(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
74441
74578
  } catch {
74442
74579
  return true;
74443
74580
  }
@@ -74445,7 +74582,7 @@ function gcSweepDue(rootDir, maxAgeMs) {
74445
74582
  function gcExtractionCache(rootDir, opts) {
74446
74583
  const stats = { evictedEntries: 0, evictedBytes: 0, agedPartialsRemoved: 0 };
74447
74584
  try {
74448
- writeFileSync4(join12(rootDir, GC_MARKER), "", "utf-8");
74585
+ writeFileSync4(join11(rootDir, GC_MARKER), "", "utf-8");
74449
74586
  } catch {
74450
74587
  }
74451
74588
  try {
@@ -74454,7 +74591,7 @@ function gcExtractionCache(rootDir, opts) {
74454
74591
  for (const child of readdirSync4(rootDir, { withFileTypes: true })) {
74455
74592
  if (!child.isDirectory() || !isCacheLikeChild(child.name)) continue;
74456
74593
  const entry = collectGcEntry(
74457
- join12(rootDir, child.name),
74594
+ join11(rootDir, child.name),
74458
74595
  child.name,
74459
74596
  now,
74460
74597
  opts.minAgeMs,
@@ -74483,7 +74620,7 @@ function rehydrateCacheEntry(entry, options) {
74483
74620
  const suffix = `.${options.format}`;
74484
74621
  const files = readdirSync4(entry.dir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(suffix)).sort();
74485
74622
  files.forEach((file, idx) => {
74486
- framePaths.set(idx, join12(entry.dir, file));
74623
+ framePaths.set(idx, join11(entry.dir, file));
74487
74624
  });
74488
74625
  return {
74489
74626
  videoId: options.videoId,
@@ -74512,7 +74649,7 @@ var init_extractionCache = __esm({
74512
74649
  // ../engine/src/services/videoFrameExtractor.ts
74513
74650
  import { spawn as spawn6 } from "child_process";
74514
74651
  import { copyFileSync as copyFileSync2, existsSync as existsSync12, linkSync, mkdirSync as mkdirSync7, readdirSync as readdirSync5, rmSync as rmSync2 } from "fs";
74515
- import { isAbsolute as isAbsolute4, join as join13, posix as posix3, resolve as resolve9, sep as sep3 } from "path";
74652
+ import { isAbsolute as isAbsolute4, join as join12, posix as posix3, resolve as resolve9, sep as sep3 } from "path";
74516
74653
  function isVideoFrameFormat(value) {
74517
74654
  return typeof value === "string" && VIDEO_FRAME_FORMATS.includes(value);
74518
74655
  }
@@ -74592,12 +74729,12 @@ function parseImageElements(html) {
74592
74729
  async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config, outputDirOverride) {
74593
74730
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
74594
74731
  const { fps, outputDir, quality = 95 } = options;
74595
- const videoOutputDir = outputDirOverride ?? join13(outputDir, videoId);
74732
+ const videoOutputDir = outputDirOverride ?? join12(outputDir, videoId);
74596
74733
  if (!existsSync12(videoOutputDir)) mkdirSync7(videoOutputDir, { recursive: true });
74597
74734
  const metadata = await extractMediaMetadata(videoPath);
74598
74735
  const format = resolveFrameFormat(metadata, options.format);
74599
74736
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
74600
- const outputPattern = join13(videoOutputDir, framePattern);
74737
+ const outputPattern = join12(videoOutputDir, framePattern);
74601
74738
  const isHdr = isHdrColorSpace(metadata.colorSpace);
74602
74739
  const isMacOS = process.platform === "darwin";
74603
74740
  const args = [];
@@ -74658,7 +74795,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
74658
74795
  const framePaths = /* @__PURE__ */ new Map();
74659
74796
  const files = readdirSync5(videoOutputDir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(`.${format}`)).sort();
74660
74797
  files.forEach((file, index) => {
74661
- framePaths.set(index, join13(videoOutputDir, file));
74798
+ framePaths.set(index, join12(videoOutputDir, file));
74662
74799
  });
74663
74800
  resolve64({
74664
74801
  videoId,
@@ -74709,7 +74846,7 @@ function extractedFramesFromDirectory(work, outputDir, srcPath, fps) {
74709
74846
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${work.format}`;
74710
74847
  const framePaths = /* @__PURE__ */ new Map();
74711
74848
  extractedFrameFileNames(outputDir, work.format).forEach((file, index) => {
74712
- framePaths.set(index, join13(outputDir, file));
74849
+ framePaths.set(index, join12(outputDir, file));
74713
74850
  });
74714
74851
  return {
74715
74852
  videoId: work.video.id,
@@ -74818,7 +74955,7 @@ function sliceSupersetMember(member, superset, outputDir, fps) {
74818
74955
  for (let i2 = 0; i2 < frameCount; i2 += 1) {
74819
74956
  const sourceFrame = superset.framePaths.get(member.offsetFrames + i2);
74820
74957
  if (!sourceFrame) throw new Error(`superset frame ${member.offsetFrames + i2} missing`);
74821
- linkOrCopyFrame(sourceFrame, join13(outputDir, frameFileName(i2 + 1, work.format)));
74958
+ linkOrCopyFrame(sourceFrame, join12(outputDir, frameFileName(i2 + 1, work.format)));
74822
74959
  }
74823
74960
  return extractedFramesFromDirectory(work, outputDir, work.videoPath, fps);
74824
74961
  }
@@ -74830,22 +74967,22 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
74830
74967
  if (!candidates.includes(candidate)) candidates.push(candidate);
74831
74968
  };
74832
74969
  for (const variant of decodeUrlPathVariants(cleanSrc)) {
74833
- const fromCompiled = compiledDir ? join13(compiledDir, variant) : null;
74834
- const fromBase = join13(baseDir, variant);
74970
+ const fromCompiled = compiledDir ? join12(compiledDir, variant) : null;
74971
+ const fromBase = join12(baseDir, variant);
74835
74972
  const baseAbs = resolve9(baseDir);
74836
74973
  const fromBaseAbs = resolve9(fromBase);
74837
74974
  if (!fromBaseAbs.startsWith(baseAbs + sep3) && fromBaseAbs !== baseAbs) {
74838
74975
  const normalized = posix3.normalize(variant.replace(/\\/g, "/"));
74839
74976
  const stripped = normalized.replace(/^(\.\.\/)+/, "");
74840
74977
  if (stripped && stripped !== variant && !stripped.startsWith("..")) {
74841
- if (compiledDir) addCandidate2(join13(compiledDir, stripped));
74842
- addCandidate2(join13(baseDir, stripped));
74978
+ if (compiledDir) addCandidate2(join12(compiledDir, stripped));
74979
+ addCandidate2(join12(baseDir, stripped));
74843
74980
  }
74844
74981
  }
74845
74982
  if (fromCompiled) addCandidate2(fromCompiled);
74846
74983
  addCandidate2(fromBase);
74847
74984
  }
74848
- return candidates.find(existsSync12) ?? join13(baseDir, cleanSrc);
74985
+ return candidates.find(existsSync12) ?? join12(baseDir, cleanSrc);
74849
74986
  }
74850
74987
  async function extractAllVideoFrames(videos, baseDir, options, signal, config, compiledDir) {
74851
74988
  const startTime = Date.now();
@@ -74879,7 +75016,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
74879
75016
  videoPath = resolveProjectRelativeSrc(video.src, baseDir, compiledDir);
74880
75017
  }
74881
75018
  if (isHttpUrl(videoPath)) {
74882
- const downloadDir = join13(options.outputDir, "_downloads");
75019
+ const downloadDir = join12(options.outputDir, "_downloads");
74883
75020
  mkdirSync7(downloadDir, { recursive: true });
74884
75021
  videoPath = await downloadToTemp(videoPath, downloadDir);
74885
75022
  }
@@ -75073,7 +75210,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
75073
75210
  return sliceSupersetMember(
75074
75211
  member,
75075
75212
  superset,
75076
- join13(options.outputDir, work.video.id),
75213
+ join12(options.outputDir, work.video.id),
75077
75214
  options.fps
75078
75215
  );
75079
75216
  }
@@ -75089,7 +75226,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
75089
75226
  async function executeSupersetGroup(group) {
75090
75227
  const first = group.members[0]?.miss.work;
75091
75228
  if (!first) return [];
75092
- const tempDir = cacheRootDir ? join13(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join13(options.outputDir, group.groupId);
75229
+ const tempDir = cacheRootDir ? join12(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join12(options.outputDir, group.groupId);
75093
75230
  try {
75094
75231
  rmSync2(tempDir, { recursive: true, force: true });
75095
75232
  const superset = await extractVideoFramesRange(
@@ -75859,7 +75996,7 @@ var init_mediaVolumeEnvelope = __esm({
75859
75996
  });
75860
75997
 
75861
75998
  // ../engine/src/services/audioVolumeEnvelope.ts
75862
- import { readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
75999
+ import { readFileSync as readFileSync6, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "fs";
75863
76000
  import { randomBytes } from "crypto";
75864
76001
  function parseWavLayout(buffer) {
75865
76002
  if (buffer.length < 12 || buffer.toString("ascii", 0, 4) !== "RIFF") return null;
@@ -75921,7 +76058,7 @@ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
75921
76058
  }
75922
76059
  const tempPath = `${wavPath}.${randomBytes(6).toString("hex")}.tmp`;
75923
76060
  writeFileSync5(tempPath, buffer);
75924
- renameSync2(tempPath, wavPath);
76061
+ renameSync3(tempPath, wavPath);
75925
76062
  return true;
75926
76063
  } catch {
75927
76064
  return false;
@@ -75939,7 +76076,7 @@ var init_audioVolumeEnvelope = __esm({
75939
76076
 
75940
76077
  // ../engine/src/services/audioMixer.ts
75941
76078
  import { closeSync, existsSync as existsSync13, mkdirSync as mkdirSync8, mkdtempSync, openSync, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
75942
- import { isAbsolute as isAbsolute5, join as join14, dirname as dirname8 } from "path";
76079
+ import { isAbsolute as isAbsolute5, join as join13, dirname as dirname8 } from "path";
75943
76080
  function clampVolume(volume) {
75944
76081
  if (!Number.isFinite(volume)) return 1;
75945
76082
  return Math.max(0, Math.min(1, volume));
@@ -76191,8 +76328,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
76191
76328
  const runMix = (ignoreAutomation) => {
76192
76329
  const inputs = [];
76193
76330
  tracks.forEach((track) => inputs.push("-i", track.srcPath));
76194
- const scriptDir = mkdtempSync(join14(outputDir, ".filter-complex-"));
76195
- const scriptPath = join14(scriptDir, "graph.txt");
76331
+ const scriptDir = mkdtempSync(join13(outputDir, ".filter-complex-"));
76332
+ const scriptPath = join13(scriptDir, "graph.txt");
76196
76333
  const fd = openSync(scriptPath, "wx", 384);
76197
76334
  try {
76198
76335
  writeFileSync6(fd, buildFilterComplex(ignoreAutomation));
@@ -76291,7 +76428,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
76291
76428
  }
76292
76429
  let audioSrcPath = srcPath;
76293
76430
  if (element.type === "video") {
76294
- const extractedPath = join14(workDir, `${element.id}-extracted.wav`);
76431
+ const extractedPath = join13(workDir, `${element.id}-extracted.wav`);
76295
76432
  const extractResult = await extractAudioFromVideo(
76296
76433
  srcPath,
76297
76434
  extractedPath,
@@ -76308,7 +76445,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
76308
76445
  }
76309
76446
  audioSrcPath = extractedPath;
76310
76447
  } else {
76311
- const trimmedPath = join14(workDir, `${element.id}-trimmed.wav`);
76448
+ const trimmedPath = join13(workDir, `${element.id}-trimmed.wav`);
76312
76449
  const prepResult = await prepareAudioTrack(
76313
76450
  srcPath,
76314
76451
  trimmedPath,
@@ -76462,7 +76599,7 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
76462
76599
  import { cpus, freemem } from "os";
76463
76600
  import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync6 } from "fs";
76464
76601
  import { copyFile, rename } from "fs/promises";
76465
- import { join as join15 } from "path";
76602
+ import { join as join14 } from "path";
76466
76603
  function defaultSafeMaxWorkers() {
76467
76604
  return Math.max(6, Math.min(16, Math.floor(cpus().length / 8)));
76468
76605
  }
@@ -76541,7 +76678,7 @@ function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
76541
76678
  workerId: i2,
76542
76679
  startFrame,
76543
76680
  endFrame,
76544
- outputDir: join15(workDir, `worker-${i2}`),
76681
+ outputDir: join14(workDir, `worker-${i2}`),
76545
76682
  outputFrameOffset: rangeStart
76546
76683
  });
76547
76684
  }
@@ -76555,7 +76692,7 @@ function distributeFramesInterleaved(totalFrames, workerCount, workDir, rangeSta
76555
76692
  startFrame: rangeStart + i2,
76556
76693
  endFrame: rangeStart + totalFrames,
76557
76694
  frameStride: workerCount,
76558
- outputDir: join15(workDir, `worker-${i2}`),
76695
+ outputDir: join14(workDir, `worker-${i2}`),
76559
76696
  outputFrameOffset: rangeStart
76560
76697
  });
76561
76698
  }
@@ -76750,8 +76887,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
76750
76887
  }
76751
76888
  const files = readdirSync6(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
76752
76889
  const copyTasks = files.map(async (file) => {
76753
- const sourcePath = join15(task.outputDir, file);
76754
- const targetPath = join15(outputDir, file);
76890
+ const sourcePath = join14(task.outputDir, file);
76891
+ const targetPath = join14(outputDir, file);
76755
76892
  try {
76756
76893
  await rename(sourcePath, targetPath);
76757
76894
  } catch {
@@ -76793,7 +76930,7 @@ var init_parallelCoordinator = __esm({
76793
76930
  import { Hono } from "hono";
76794
76931
  import { serve } from "@hono/node-server";
76795
76932
  import { readFileSync as readFileSync7, existsSync as existsSync15, statSync as statSync4 } from "fs";
76796
- import { join as join16, extname as extname5 } from "path";
76933
+ import { join as join15, extname as extname5 } from "path";
76797
76934
  function createFileServer(options) {
76798
76935
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
76799
76936
  const headScripts = options.headScripts ?? [];
@@ -76803,11 +76940,11 @@ function createFileServer(options) {
76803
76940
  let requestPath = c3.req.path;
76804
76941
  if (requestPath === "/") requestPath = "/index.html";
76805
76942
  const relativePath = requestPath.replace(/^\//, "");
76806
- const compiledPath = compiledDir ? join16(compiledDir, relativePath) : null;
76943
+ const compiledPath = compiledDir ? join15(compiledDir, relativePath) : null;
76807
76944
  const hasCompiledFile = Boolean(
76808
76945
  compiledPath && existsSync15(compiledPath) && statSync4(compiledPath).isFile()
76809
76946
  );
76810
- const filePath = hasCompiledFile ? compiledPath : join16(projectDir, relativePath);
76947
+ const filePath = hasCompiledFile ? compiledPath : join15(projectDir, relativePath);
76811
76948
  if (!existsSync15(filePath) || !statSync4(filePath).isFile()) {
76812
76949
  return c3.text("Not found", 404);
76813
76950
  }
@@ -78122,7 +78259,7 @@ var init_shaderTransitions = __esm({
78122
78259
 
78123
78260
  // ../engine/src/services/hdrCapture.ts
78124
78261
  import { existsSync as existsSync16, readdirSync as readdirSync7 } from "fs";
78125
- import { join as join17 } from "path";
78262
+ import { join as join16 } from "path";
78126
78263
  import { homedir as homedir3 } from "os";
78127
78264
  function linearToPQ(L2) {
78128
78265
  const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
@@ -78238,12 +78375,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
78238
78375
  return output;
78239
78376
  }
78240
78377
  function resolveHeadedChromePath() {
78241
- const baseDir = join17(homedir3(), ".cache", "puppeteer", "chrome");
78378
+ const baseDir = join16(homedir3(), ".cache", "puppeteer", "chrome");
78242
78379
  if (!existsSync16(baseDir)) return void 0;
78243
78380
  const versions = readdirSync7(baseDir).sort().reverse();
78244
78381
  for (const version2 of versions) {
78245
78382
  const candidates = [
78246
- join17(
78383
+ join16(
78247
78384
  baseDir,
78248
78385
  version2,
78249
78386
  "chrome-mac-arm64",
@@ -78252,7 +78389,7 @@ function resolveHeadedChromePath() {
78252
78389
  "MacOS",
78253
78390
  "Google Chrome for Testing"
78254
78391
  ),
78255
- join17(
78392
+ join16(
78256
78393
  baseDir,
78257
78394
  version2,
78258
78395
  "chrome-mac-x64",
@@ -78261,8 +78398,8 @@ function resolveHeadedChromePath() {
78261
78398
  "MacOS",
78262
78399
  "Google Chrome for Testing"
78263
78400
  ),
78264
- join17(baseDir, version2, "chrome-linux64", "chrome"),
78265
- join17(baseDir, version2, "chrome-win64", "chrome.exe")
78401
+ join16(baseDir, version2, "chrome-linux64", "chrome"),
78402
+ join16(baseDir, version2, "chrome-win64", "chrome.exe")
78266
78403
  ];
78267
78404
  for (const binary of candidates) {
78268
78405
  if (existsSync16(binary)) return binary;
@@ -79102,6 +79239,12 @@ function renderObservabilityEventProperties(props) {
79102
79239
  capture_player_ready_timeout_ms: props.capturePlayerReadyTimeoutMs,
79103
79240
  capture_transient_retries: props.captureTransientRetries,
79104
79241
  capture_memory_exhaustion_detected: props.captureMemoryExhaustionDetected,
79242
+ de_worker_inversion: props.captureDeWorkerInversion,
79243
+ de_pre_inversion_workers: props.captureDePreInversionWorkers,
79244
+ de_parallel_router: props.captureDeParallelRouter,
79245
+ de_pre_router_workers: props.captureDePreRouterWorkers,
79246
+ de_self_verify_fallback: props.captureDeSelfVerifyFallback,
79247
+ de_fallback_reason: props.captureDeFallbackReason,
79105
79248
  observability_extract_video_count: props.observabilityExtractVideoCount,
79106
79249
  observability_extracted_video_count: props.observabilityExtractedVideoCount,
79107
79250
  observability_extract_total_frames: props.observabilityExtractTotalFrames,
@@ -79129,6 +79272,11 @@ function trackRenderComplete(props) {
79129
79272
  trackEvent(
79130
79273
  "render_complete",
79131
79274
  {
79275
+ // Spread first: explicit de_* keys below (sourced from the more
79276
+ // authoritative perfSummary.drawElement, always present on this
79277
+ // success path) must win over the observability-capture fallback
79278
+ // this shares with trackRenderError's failure path.
79279
+ ...renderObservabilityEventProperties(props),
79132
79280
  duration_ms: props.durationMs,
79133
79281
  fps: props.fps,
79134
79282
  quality: props.quality,
@@ -79191,8 +79339,7 @@ function trackRenderComplete(props) {
79191
79339
  extract_vfr_preflight_count: props.extractVfrPreflightCount,
79192
79340
  extract_phase3_ms: props.extractPhase3Ms,
79193
79341
  extract_cache_hits: props.extractCacheHits,
79194
- extract_cache_misses: props.extractCacheMisses,
79195
- ...renderObservabilityEventProperties(props)
79342
+ extract_cache_misses: props.extractCacheMisses
79196
79343
  },
79197
79344
  props.distinctId
79198
79345
  );
@@ -81522,11 +81669,11 @@ var init_banner = __esm({
81522
81669
 
81523
81670
  // src/registry/remote.ts
81524
81671
  import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
81525
- import { join as join18, dirname as dirname9 } from "path";
81672
+ import { join as join17, dirname as dirname9 } from "path";
81526
81673
  import { homedir as homedir4 } from "os";
81527
81674
  function cachePath(baseUrl, key2) {
81528
81675
  const slug = baseUrl.replace(/[^a-zA-Z0-9]/g, "_");
81529
- return join18(CACHE_DIR, `${slug}__${key2}.json`);
81676
+ return join17(CACHE_DIR, `${slug}__${key2}.json`);
81530
81677
  }
81531
81678
  function readCache(path2) {
81532
81679
  try {
@@ -81597,7 +81744,7 @@ var init_remote = __esm({
81597
81744
  init_dist3();
81598
81745
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry";
81599
81746
  FETCH_TIMEOUT_MS = 1e4;
81600
- CACHE_DIR = join18(homedir4(), ".hyperframes", "cache");
81747
+ CACHE_DIR = join17(homedir4(), ".hyperframes", "cache");
81601
81748
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
81602
81749
  }
81603
81750
  });
@@ -81875,7 +82022,7 @@ var init_compatibility = __esm({
81875
82022
 
81876
82023
  // src/templates/remote.ts
81877
82024
  import { existsSync as existsSync19 } from "fs";
81878
- import { join as join19 } from "path";
82025
+ import { join as join18 } from "path";
81879
82026
  async function fetchRemoteTemplate(templateId, destDir) {
81880
82027
  const items = await resolveItemWithDependencies(templateId);
81881
82028
  const warnings = gateRegistryItemsCompatibility(items);
@@ -81886,7 +82033,7 @@ async function fetchRemoteTemplate(templateId, destDir) {
81886
82033
  for (const item of items) {
81887
82034
  await installItem(item, { destDir });
81888
82035
  }
81889
- if (!existsSync19(join19(destDir, "index.html"))) {
82036
+ if (!existsSync19(join18(destDir, "index.html"))) {
81890
82037
  throw new Error(
81891
82038
  `Example "${templateId}" installed but missing index.html. The registry item may be malformed.`
81892
82039
  );
@@ -82198,7 +82345,7 @@ var init_ffmpeg = __esm({
82198
82345
  });
82199
82346
 
82200
82347
  // src/utils/download.ts
82201
- import { createWriteStream as createWriteStream2, renameSync as renameSync3, unlinkSync } from "fs";
82348
+ import { createWriteStream as createWriteStream2, renameSync as renameSync4, unlinkSync } from "fs";
82202
82349
  import { get as httpsGet } from "https";
82203
82350
  import { pipeline } from "stream/promises";
82204
82351
  function downloadFile(url, dest) {
@@ -82219,7 +82366,7 @@ function downloadFile(url, dest) {
82219
82366
  }
82220
82367
  const file = createWriteStream2(tmp);
82221
82368
  pipeline(res, file).then(() => {
82222
- renameSync3(tmp, dest);
82369
+ renameSync4(tmp, dest);
82223
82370
  resolve64();
82224
82371
  }).catch((err) => {
82225
82372
  try {
@@ -82261,7 +82408,7 @@ __export(manager_exports, {
82261
82408
  import { execFileSync as execFileSync3 } from "child_process";
82262
82409
  import { existsSync as existsSync22, mkdirSync as mkdirSync11, rmSync as rmSync4 } from "fs";
82263
82410
  import { homedir as homedir5, platform as platform4 } from "os";
82264
- import { join as join20 } from "path";
82411
+ import { join as join19 } from "path";
82265
82412
  function isWhisperUnavailable(err) {
82266
82413
  if (err instanceof WhisperUnavailableError) return true;
82267
82414
  return err instanceof Error && "code" in err && err.code === "WHISPER_UNAVAILABLE";
@@ -82304,8 +82451,8 @@ function findFromSystem() {
82304
82451
  }
82305
82452
  function findBuiltBinary() {
82306
82453
  for (const p2 of [
82307
- join20(BUILD_DIR, "build", "bin", "whisper-cli"),
82308
- join20(BUILD_DIR, "build", "whisper-cli")
82454
+ join19(BUILD_DIR, "build", "bin", "whisper-cli"),
82455
+ join19(BUILD_DIR, "build", "whisper-cli")
82309
82456
  ]) {
82310
82457
  if (existsSync22(p2)) return { executablePath: p2, source: "build" };
82311
82458
  }
@@ -82317,7 +82464,7 @@ function buildFromSource(onProgress) {
82317
82464
  }
82318
82465
  if (!existsSync22(BUILD_DIR)) {
82319
82466
  onProgress?.("Downloading whisper.cpp...");
82320
- mkdirSync11(join20(homedir5(), ".cache", "hyperframes", "whisper"), {
82467
+ mkdirSync11(join19(homedir5(), ".cache", "hyperframes", "whisper"), {
82321
82468
  recursive: true
82322
82469
  });
82323
82470
  execFileSync3("git", ["clone", "--depth", "1", WHISPER_REPO, BUILD_DIR], {
@@ -82402,7 +82549,7 @@ async function ensureWhisper(options) {
82402
82549
  throw new WhisperUnavailableError(`whisper-cpp not found. Install: ${getInstallInstructions()}`);
82403
82550
  }
82404
82551
  async function ensureModel(model = DEFAULT_MODEL, options) {
82405
- const modelPath2 = join20(MODELS_DIR, `ggml-${model}.bin`);
82552
+ const modelPath2 = join19(MODELS_DIR, `ggml-${model}.bin`);
82406
82553
  if (existsSync22(modelPath2)) return modelPath2;
82407
82554
  mkdirSync11(MODELS_DIR, { recursive: true });
82408
82555
  options?.onProgress?.(`Downloading model ${model}...`);
@@ -82421,7 +82568,7 @@ var init_manager = __esm({
82421
82568
  "use strict";
82422
82569
  init_ffmpeg();
82423
82570
  init_download();
82424
- MODELS_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "models");
82571
+ MODELS_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "models");
82425
82572
  DEFAULT_MODEL = "small.en";
82426
82573
  WhisperUnavailableError = class extends Error {
82427
82574
  code = "WHISPER_UNAVAILABLE";
@@ -82430,7 +82577,7 @@ var init_manager = __esm({
82430
82577
  this.name = "WhisperUnavailableError";
82431
82578
  }
82432
82579
  };
82433
- BUILD_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
82580
+ BUILD_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
82434
82581
  WHISPER_REPO = "https://github.com/ggml-org/whisper.cpp.git";
82435
82582
  }
82436
82583
  });
@@ -82447,7 +82594,7 @@ __export(normalize_exports, {
82447
82594
  wordsToCues: () => wordsToCues
82448
82595
  });
82449
82596
  import { readFileSync as readFileSync14, readdirSync as readdirSync8, writeFileSync as writeFileSync9 } from "fs";
82450
- import { extname as extname6, join as join21 } from "path";
82597
+ import { extname as extname6, join as join20 } from "path";
82451
82598
  function detectFormat(filePath) {
82452
82599
  const ext = extname6(filePath).toLowerCase();
82453
82600
  if (ext === ".srt") return "srt";
@@ -82649,8 +82796,8 @@ function entriesToCues(words) {
82649
82796
  function joinTokens(left, right) {
82650
82797
  const a = left.at(-1) ?? "";
82651
82798
  const b2 = right[0] ?? "";
82652
- const sep9 = CJK_CHAR.test(a) || CJK_CHAR.test(b2) ? "" : " ";
82653
- return `${left}${sep9}${right}`;
82799
+ const sep10 = CJK_CHAR.test(a) || CJK_CHAR.test(b2) ? "" : " ";
82800
+ return `${left}${sep10}${right}`;
82654
82801
  }
82655
82802
  function wordsToCues(words, opts = {}) {
82656
82803
  const preGrouped = opts.preGrouped ?? words.some((w3) => /\s/.test(w3.text.trim()));
@@ -82724,7 +82871,7 @@ function patchCaptionHtml(dir, words) {
82724
82871
  const wordsJson = JSON.stringify(words, null, 2).replace(/\n/g, "\n ");
82725
82872
  let htmlFiles;
82726
82873
  try {
82727
- htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join21(e3.parentPath, e3.name));
82874
+ htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join20(e3.parentPath, e3.name));
82728
82875
  } catch {
82729
82876
  return;
82730
82877
  }
@@ -82765,9 +82912,9 @@ __export(projectConfig_exports, {
82765
82912
  writeProjectConfig: () => writeProjectConfig
82766
82913
  });
82767
82914
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
82768
- import { join as join22, resolve as resolve12 } from "path";
82915
+ import { join as join21, resolve as resolve12 } from "path";
82769
82916
  function projectConfigPath(projectDir) {
82770
- return join22(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
82917
+ return join21(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
82771
82918
  }
82772
82919
  function readProjectConfig(projectDir) {
82773
82920
  const path2 = projectConfigPath(projectDir);
@@ -83058,9 +83205,16 @@ var init_updateCheck = __esm({
83058
83205
  // src/utils/skillsManifest.ts
83059
83206
  import { execFile } from "child_process";
83060
83207
  import { createHash as createHash3 } from "crypto";
83061
- import { existsSync as existsSync23, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync6 } from "fs";
83208
+ import {
83209
+ existsSync as existsSync23,
83210
+ readdirSync as readdirSync9,
83211
+ readFileSync as readFileSync16,
83212
+ renameSync as renameSync5,
83213
+ statSync as statSync6,
83214
+ writeFileSync as writeFileSync11
83215
+ } from "fs";
83062
83216
  import { homedir as homedir6 } from "os";
83063
- import { isAbsolute as isAbsolute7, join as join23, relative as relative5, resolve as resolve13, sep as sep4 } from "path";
83217
+ import { isAbsolute as isAbsolute7, join as join22, relative as relative5, resolve as resolve13, sep as sep4 } from "path";
83064
83218
  import { promisify } from "util";
83065
83219
  function isCoreSkill(name) {
83066
83220
  return name === ENTRY_SKILL || name.startsWith("hyperframes-") || name === "media-use";
@@ -83070,7 +83224,7 @@ function listFilesSorted(dir) {
83070
83224
  const walk = (d2) => {
83071
83225
  for (const name of readdirSync9(d2)) {
83072
83226
  if (name === ".DS_Store") continue;
83073
- const p2 = join23(d2, name);
83227
+ const p2 = join22(d2, name);
83074
83228
  if (statSync6(p2).isDirectory()) walk(p2);
83075
83229
  else out.push(p2);
83076
83230
  }
@@ -83094,9 +83248,9 @@ function hashSkillBundle(skillDir) {
83094
83248
  return { hash: h3.digest("hex").slice(0, 16), files: files.length };
83095
83249
  }
83096
83250
  function buildManifest(skillsRoot, meta) {
83097
- const names = readdirSync9(skillsRoot).filter((n2) => existsSync23(join23(skillsRoot, n2, "SKILL.md"))).sort();
83251
+ const names = readdirSync9(skillsRoot).filter((n2) => existsSync23(join22(skillsRoot, n2, "SKILL.md"))).sort();
83098
83252
  const skills = {};
83099
- for (const name of names) skills[name] = hashSkillBundle(join23(skillsRoot, name));
83253
+ for (const name of names) skills[name] = hashSkillBundle(join22(skillsRoot, name));
83100
83254
  return { source: meta.source, skills };
83101
83255
  }
83102
83256
  function agentLabel(hostDir) {
@@ -83118,12 +83272,12 @@ function listSubdirs(dir) {
83118
83272
  function discoverSkillRoots(base2, scope) {
83119
83273
  const candidates = [];
83120
83274
  const add2 = (hostBase, host) => {
83121
- const dir = join23(hostBase, host, "skills");
83275
+ const dir = join22(hostBase, host, "skills");
83122
83276
  if (existsSync23(dir) && statSync6(dir).isDirectory())
83123
83277
  candidates.push({ dir, agent: agentLabel(host), scope });
83124
83278
  };
83125
83279
  for (const host of listSubdirs(base2)) add2(base2, host);
83126
- const xdg = join23(base2, ".config");
83280
+ const xdg = join22(base2, ".config");
83127
83281
  for (const host of listSubdirs(xdg)) add2(xdg, host);
83128
83282
  return candidates.sort((a, b2) => {
83129
83283
  if (a.agent !== b2.agent) {
@@ -83157,20 +83311,20 @@ function locateInstall(skillNames, opts = {}) {
83157
83311
  ...discoverSkillRoots(opts.cwd ?? process.cwd(), "project")
83158
83312
  ];
83159
83313
  for (const root of roots) {
83160
- if (skillNames.some((n2) => existsSync23(join23(root.dir, n2, "SKILL.md")))) return root;
83314
+ if (skillNames.some((n2) => existsSync23(join22(root.dir, n2, "SKILL.md")))) return root;
83161
83315
  }
83162
83316
  return null;
83163
83317
  }
83164
83318
  function presentSkills(skillNames, opts = {}) {
83165
83319
  const root = locateInstall([...skillNames], opts);
83166
83320
  if (!root) return [];
83167
- return skillNames.filter((name) => existsSync23(join23(root.dir, name, "SKILL.md")));
83321
+ return skillNames.filter((name) => existsSync23(join22(root.dir, name, "SKILL.md")));
83168
83322
  }
83169
83323
  function hashInstalled(root, skillNames) {
83170
83324
  const out = {};
83171
83325
  for (const name of skillNames) {
83172
- const skillDir = join23(root.dir, name);
83173
- if (existsSync23(join23(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
83326
+ const skillDir = join22(root.dir, name);
83327
+ if (existsSync23(join22(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
83174
83328
  }
83175
83329
  return out;
83176
83330
  }
@@ -83219,10 +83373,10 @@ function skillsAttributedToSource(lock, source) {
83219
83373
  return Object.entries(lock.skills).filter(([, e3]) => repoSlug(e3.source) === want || repoSlug(e3.sourceUrl) === want).map(([name]) => name);
83220
83374
  }
83221
83375
  function lockPathForScope(scope, opts) {
83222
- if (scope === "project") return join23(opts.cwd ?? process.cwd(), "skills-lock.json");
83376
+ if (scope === "project") return join22(opts.cwd ?? process.cwd(), "skills-lock.json");
83223
83377
  const xdgStateHome = process.env.XDG_STATE_HOME;
83224
- if (xdgStateHome) return join23(xdgStateHome, "skills", ".skill-lock.json");
83225
- return join23(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
83378
+ if (xdgStateHome) return join22(xdgStateHome, "skills", ".skill-lock.json");
83379
+ return join22(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
83226
83380
  }
83227
83381
  function readSkillLock(path2) {
83228
83382
  try {
@@ -83240,12 +83394,25 @@ function detectRemoved(root, latest, opts) {
83240
83394
  const removed = skillsAttributedToSource(lock, latest.source).filter((name) => !(name in latest.skills)).sort().map((name) => ({ name, status: "removed" }));
83241
83395
  return { removed, lockMissing: lock === null };
83242
83396
  }
83397
+ function pruneOrphanedLockEntries(names, scope, opts = {}) {
83398
+ const path2 = lockPathForScope(scope, opts);
83399
+ const lock = readSkillLock(path2);
83400
+ if (!lock?.skills) return [];
83401
+ const pruned = names.filter((name) => name in lock.skills);
83402
+ if (pruned.length === 0) return [];
83403
+ for (const name of pruned) delete lock.skills[name];
83404
+ const mode = statSync6(path2).mode & 511;
83405
+ const tmp = `${path2}.tmp`;
83406
+ writeFileSync11(tmp, JSON.stringify(lock, null, 2), { mode });
83407
+ renameSync5(tmp, path2);
83408
+ return pruned;
83409
+ }
83243
83410
  function findRepoManifest(cwd = process.cwd()) {
83244
83411
  let dir = cwd;
83245
83412
  for (let i2 = 0; i2 < 16; i2++) {
83246
- const p2 = join23(dir, MANIFEST_FILE);
83413
+ const p2 = join22(dir, MANIFEST_FILE);
83247
83414
  if (existsSync23(p2)) return p2;
83248
- const parent = join23(dir, "..");
83415
+ const parent = join22(dir, "..");
83249
83416
  if (parent === dir) break;
83250
83417
  dir = parent;
83251
83418
  }
@@ -83283,9 +83450,9 @@ async function remoteHeadSha(repoSlug2) {
83283
83450
  }
83284
83451
  }
83285
83452
  function resolveLocalManifest(source) {
83286
- const direct = source.endsWith(".json") ? source : join23(source, MANIFEST_FILE);
83453
+ const direct = source.endsWith(".json") ? source : join22(source, MANIFEST_FILE);
83287
83454
  if (existsSync23(direct)) return JSON.parse(readFileSync16(direct, "utf8"));
83288
- const skillsRoot = source.endsWith("skills") ? source : join23(source, "skills");
83455
+ const skillsRoot = source.endsWith("skills") ? source : join22(source, "skills");
83289
83456
  if (existsSync23(skillsRoot)) return buildManifest(skillsRoot, { source: skillsRoot });
83290
83457
  throw new Error(`No skills manifest found at: ${source}`);
83291
83458
  }
@@ -83303,18 +83470,18 @@ async function fetchRemoteManifest(source) {
83303
83470
  }
83304
83471
  return fetchManifest(`https://raw.githubusercontent.com/${repoSlug2}/main/${MANIFEST_FILE}`);
83305
83472
  }
83306
- async function resolveLatestManifest(source, cwd = process.cwd()) {
83473
+ async function resolveLatestManifest(source, cwd = process.cwd(), opts = {}) {
83307
83474
  if (source && (source.startsWith(".") || isAbsolute7(source))) {
83308
83475
  return resolveLocalManifest(source);
83309
83476
  }
83310
- if (!source) {
83477
+ if (!source && !opts.canonical) {
83311
83478
  const repoManifest = findRepoManifest(cwd);
83312
83479
  if (repoManifest) return JSON.parse(readFileSync16(repoManifest, "utf8"));
83313
83480
  }
83314
83481
  return fetchRemoteManifest(source);
83315
83482
  }
83316
83483
  async function checkSkills(opts = {}) {
83317
- const latest = await resolveLatestManifest(opts.source, opts.cwd);
83484
+ const latest = await resolveLatestManifest(opts.source, opts.cwd, { canonical: opts.canonical });
83318
83485
  const skillNames = Object.keys(latest.skills);
83319
83486
  const root = locateInstall(skillNames, { dir: opts.dir, cwd: opts.cwd, home: opts.home });
83320
83487
  const installed = root ? hashInstalled(root, skillNames) : {};
@@ -83455,22 +83622,22 @@ var init_agentDirs_generated = __esm({
83455
83622
  // src/utils/skillsMirror.ts
83456
83623
  import { cpSync, existsSync as existsSync24, mkdirSync as mkdirSync12, readdirSync as readdirSync10, rmSync as rmSync5, symlinkSync } from "fs";
83457
83624
  import { homedir as homedir7 } from "os";
83458
- import { dirname as dirname10, isAbsolute as isAbsolute8, join as join24, relative as relative6 } from "path";
83625
+ import { dirname as dirname10, isAbsolute as isAbsolute8, join as join23, relative as relative6 } from "path";
83459
83626
  function resolveBases(home, env) {
83460
83627
  const xdg = env["XDG_CONFIG_HOME"]?.trim();
83461
83628
  return {
83462
83629
  home,
83463
- configHome: xdg && isAbsolute8(xdg) ? xdg : join24(home, ".config"),
83464
- codexHome: env["CODEX_HOME"]?.trim() || join24(home, ".codex"),
83465
- claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join24(home, ".claude"),
83466
- vibeHome: env["VIBE_HOME"]?.trim() || join24(home, ".vibe"),
83467
- hermesHome: env["HERMES_HOME"]?.trim() || join24(home, ".hermes"),
83468
- autohandHome: env["AUTOHAND_HOME"]?.trim() || join24(home, ".autohand")
83630
+ configHome: xdg && isAbsolute8(xdg) ? xdg : join23(home, ".config"),
83631
+ codexHome: env["CODEX_HOME"]?.trim() || join23(home, ".codex"),
83632
+ claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join23(home, ".claude"),
83633
+ vibeHome: env["VIBE_HOME"]?.trim() || join23(home, ".vibe"),
83634
+ hermesHome: env["HERMES_HOME"]?.trim() || join23(home, ".hermes"),
83635
+ autohandHome: env["AUTOHAND_HOME"]?.trim() || join23(home, ".autohand")
83469
83636
  };
83470
83637
  }
83471
83638
  function listSkillDirs(store) {
83472
83639
  return readdirSync10(store, { withFileTypes: true }).filter(
83473
- (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync24(join24(store, e3.name, "SKILL.md"))
83640
+ (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync24(join23(store, e3.name, "SKILL.md"))
83474
83641
  ).map((e3) => e3.name);
83475
83642
  }
83476
83643
  function linkOrCopy(sourceSkill, targetSkill, platform10) {
@@ -83489,7 +83656,7 @@ function mirrorInto(targetDir, source, skills, platform10) {
83489
83656
  }
83490
83657
  for (const skill of skills) {
83491
83658
  try {
83492
- linkOrCopy(join24(source, skill), join24(targetDir, skill), platform10);
83659
+ linkOrCopy(join23(source, skill), join23(targetDir, skill), platform10);
83493
83660
  } catch {
83494
83661
  }
83495
83662
  }
@@ -83499,15 +83666,15 @@ function mirrorGlobalSkills(opts) {
83499
83666
  const home = opts.home ?? homedir7();
83500
83667
  const platform10 = opts.platform ?? process.platform;
83501
83668
  const bases = resolveBases(home, opts.env ?? process.env);
83502
- const source = join24(bases.claudeHome, "skills");
83503
- const universalStore = join24(home, ".agents", "skills");
83669
+ const source = join23(bases.claudeHome, "skills");
83670
+ const universalStore = join23(home, ".agents", "skills");
83504
83671
  if (!existsSync24(source)) return { source: null, mirrored: [] };
83505
83672
  const allowed = new Set(opts.skills);
83506
83673
  const skills = listSkillDirs(source).filter((name) => allowed.has(name));
83507
83674
  if (skills.length === 0) return { source, mirrored: [] };
83508
83675
  const mirrored = [];
83509
83676
  for (const { agent, base: base2, sub } of AGENT_GLOBAL_DIRS) {
83510
- const targetDir = join24(bases[base2], ...sub.split("/").filter(Boolean));
83677
+ const targetDir = join23(bases[base2], ...sub.split("/").filter(Boolean));
83511
83678
  if (targetDir === source || targetDir === universalStore) continue;
83512
83679
  if (!existsSync24(dirname10(targetDir))) continue;
83513
83680
  if (mirrorInto(targetDir, source, skills, platform10)) mirrored.push({ agent, dir: targetDir });
@@ -83653,8 +83820,15 @@ async function updateSkills(opts = {}) {
83653
83820
  const strict = opts.strict ?? false;
83654
83821
  let check = null;
83655
83822
  try {
83656
- check = await checkSkills({ cwd: opts.cwd });
83657
- } catch {
83823
+ check = await checkSkills({ cwd: opts.cwd, canonical: true });
83824
+ } catch (err) {
83825
+ if (err instanceof Error && err.message.startsWith("Malformed skills manifest")) {
83826
+ R2.warn(
83827
+ c.warn(
83828
+ "Canonical skills manifest was malformed \u2014 falling back to presence-only mode (an upstream/CDN issue, not your network)."
83829
+ )
83830
+ );
83831
+ }
83658
83832
  check = null;
83659
83833
  }
83660
83834
  if (!check) return updateSkillsOffline(requested, { strict, cwd: opts.cwd });
@@ -83929,6 +84103,15 @@ var init_skills = __esm({
83929
84103
  c.dim(`Removing ${removed.length} skill(s) no longer published: ${removed.join(", ")}`)
83930
84104
  );
83931
84105
  await runSkillsRemove(removed, { global: scope === "global" });
84106
+ const scopeForPrune = scope ?? "global";
84107
+ const stillOrphaned = pruneOrphanedLockEntries(removed, scopeForPrune);
84108
+ if (stillOrphaned.length) {
84109
+ console.log(
84110
+ c.dim(
84111
+ `Reconciled ${stillOrphaned.length} orphaned lock entr${stillOrphaned.length === 1 ? "y" : "ies"} with no on-disk bundle: ${stillOrphaned.join(", ")}`
84112
+ )
84113
+ );
84114
+ }
83932
84115
  }
83933
84116
  } catch (err) {
83934
84117
  R2.warn(c.warn(`Skipped removed-skill cleanup: ${err.message}`));
@@ -83961,7 +84144,7 @@ __export(transcribe_exports, {
83961
84144
  });
83962
84145
  import { execFileSync as execFileSync5 } from "child_process";
83963
84146
  import { existsSync as existsSync25, readFileSync as readFileSync17, mkdirSync as mkdirSync13, unlinkSync as unlinkSync2 } from "fs";
83964
- import { join as join25, extname as extname7 } from "path";
84147
+ import { join as join24, extname as extname7 } from "path";
83965
84148
  import { tmpdir as tmpdir2 } from "os";
83966
84149
  import { randomUUID as randomUUID3 } from "crypto";
83967
84150
  function detectLanguage(whisperPath, modelPath2, wavPath) {
@@ -84041,7 +84224,7 @@ function isVideoFile(filePath) {
84041
84224
  return VIDEO_EXTENSIONS.has(extname7(filePath).toLowerCase());
84042
84225
  }
84043
84226
  function tempWavPath() {
84044
- return join25(tmpdir2(), `hyperframes-audio-${process.pid}-${randomUUID3()}.wav`);
84227
+ return join24(tmpdir2(), `hyperframes-audio-${process.pid}-${randomUUID3()}.wav`);
84045
84228
  }
84046
84229
  function extractAudio(videoPath) {
84047
84230
  const ffmpegPath = findFFmpeg();
@@ -84135,7 +84318,7 @@ async function transcribe(inputPath, outputDir, options) {
84135
84318
  effectiveModel = multilingualModel;
84136
84319
  }
84137
84320
  options?.onProgress?.("Transcribing...");
84138
- const outputBase = join25(outputDir, "transcript");
84321
+ const outputBase = join24(outputDir, "transcript");
84139
84322
  mkdirSync13(outputDir, { recursive: true });
84140
84323
  const whisperArgs = [
84141
84324
  "--model",
@@ -85102,6 +85285,12 @@ function renderObservabilityTelemetryPayload(observability) {
85102
85285
  capturePlayerReadyTimeoutMs: capture2.playerReadyTimeoutMs,
85103
85286
  captureTransientRetries: capture2.transientRetries,
85104
85287
  captureMemoryExhaustionDetected: capture2.memoryExhaustionDetected,
85288
+ captureDeWorkerInversion: capture2.deWorkerInversion,
85289
+ captureDePreInversionWorkers: capture2.dePreInversionWorkers,
85290
+ captureDeParallelRouter: capture2.deParallelRouter,
85291
+ captureDePreRouterWorkers: capture2.dePreRouterWorkers,
85292
+ captureDeSelfVerifyFallback: capture2.deSelfVerifyFallback,
85293
+ captureDeFallbackReason: capture2.deFallbackReason,
85105
85294
  observabilityExtractVideoCount: extraction?.videoCount,
85106
85295
  observabilityExtractedVideoCount: extraction?.extractedVideoCount,
85107
85296
  observabilityExtractTotalFrames: extraction?.totalFramesExtracted,
@@ -86627,8 +86816,8 @@ function upsertProp(ms, objNode, key2, value) {
86627
86816
  if (existing) {
86628
86817
  ms.overwrite(existing.value.start, existing.value.end, valueToCode(value));
86629
86818
  } else {
86630
- const sep9 = objNode.properties.length > 0 ? ", " : "";
86631
- ms.appendLeft(objNode.end - 1, `${sep9}${safeKey(key2)}: ${valueToCode(value)}`);
86819
+ const sep10 = objNode.properties.length > 0 ? ", " : "";
86820
+ ms.appendLeft(objNode.end - 1, `${sep10}${safeKey(key2)}: ${valueToCode(value)}`);
86632
86821
  }
86633
86822
  }
86634
86823
  function isEditableVarKey(key2) {
@@ -87141,8 +87330,8 @@ function insertNewKeyframe(ms, kfNode, percentage, pctKey, valueCode) {
87141
87330
  if (insertBeforeProp) {
87142
87331
  ms.appendLeft(insertBeforeProp.start, `${JSON.stringify(pctKey)}: ${valueCode}, `);
87143
87332
  } else {
87144
- const sep9 = allProps.length > 0 ? ", " : "";
87145
- ms.appendLeft(kfNode.end - 1, `${sep9}${JSON.stringify(pctKey)}: ${valueCode}`);
87333
+ const sep10 = allProps.length > 0 ? ", " : "";
87334
+ ms.appendLeft(kfNode.end - 1, `${sep10}${JSON.stringify(pctKey)}: ${valueCode}`);
87146
87335
  }
87147
87336
  }
87148
87337
  function collapseKeyframesToFlat(ms, varsNode, source, remainingRecord) {
@@ -87595,8 +87784,8 @@ function enableArcPath(ms, call, animation, config) {
87595
87784
  const k2 = propKeyName22(p2);
87596
87785
  return k2 !== "x" && k2 !== "y";
87597
87786
  });
87598
- const sep9 = survivesRemoval ? ", " : "";
87599
- ms.appendRight(vars.start + 1, ` motionPath: ${motionPathCode}${sep9}`);
87787
+ const sep10 = survivesRemoval ? ", " : "";
87788
+ ms.appendRight(vars.start + 1, ` motionPath: ${motionPathCode}${sep10}`);
87600
87789
  stripXYFromKeyframes(ms, findPropertyNode22(call.varsArg, "keyframes"));
87601
87790
  removePropsByKey(ms, call.varsArg, /* @__PURE__ */ new Set(["x", "y"]));
87602
87791
  return true;
@@ -91830,21 +92019,36 @@ function mintHfId2(el, assigned) {
91830
92019
  assigned.add(id);
91831
92020
  return id;
91832
92021
  }
92022
+ function getChildElements2(parent) {
92023
+ const directChildren = Array.from(parent.children);
92024
+ if (directChildren.length || parent.tagName.toLowerCase() !== "template") return directChildren;
92025
+ const content = parent.content;
92026
+ if (content?.children.length) return Array.from(content.children);
92027
+ return directChildren;
92028
+ }
91833
92029
  function isCompositionTemplate2(el) {
91834
92030
  if (el.tagName.toLowerCase() !== "template") return false;
91835
92031
  if (el.getAttribute("data-composition-id") !== null) return true;
91836
- for (const child of Array.from(el.children)) {
92032
+ for (const child of getChildElements2(el)) {
91837
92033
  if (child.getAttribute("data-composition-id") !== null) return true;
91838
92034
  }
91839
92035
  return false;
91840
92036
  }
92037
+ function walkCompositionDescendants2(root, visit) {
92038
+ const rootElement = root.nodeType === 9 ? root.documentElement : root;
92039
+ if (!rootElement) return;
92040
+ const walk = (parent) => {
92041
+ for (const child of getChildElements2(parent)) {
92042
+ const isTemplate = child.tagName.toLowerCase() === "template";
92043
+ if (isTemplate && !isCompositionTemplate2(child)) continue;
92044
+ visit(child);
92045
+ walk(child);
92046
+ }
92047
+ };
92048
+ walk(rootElement);
92049
+ }
91841
92050
  function walkElements2(root, visit) {
91842
- for (const child of Array.from(root.children)) {
91843
- const isTemplate = child.tagName.toLowerCase() === "template";
91844
- if (isTemplate && !isCompositionTemplate2(child)) continue;
91845
- visit(child);
91846
- walkElements2(child, visit);
91847
- }
92051
+ walkCompositionDescendants2(root, visit);
91848
92052
  }
91849
92053
  function ensureHfIds2(html) {
91850
92054
  const hasDocumentShell = /<!doctype|<html[\s>]/i.test(html);
@@ -91885,7 +92089,7 @@ var init_hfIds = __esm({
91885
92089
  import { execFileSync as execFileSync6 } from "child_process";
91886
92090
  import { existsSync as existsSync29, lstatSync as lstatSync2, readdirSync as readdirSync11, realpathSync as realpathSync4 } from "fs";
91887
92091
  import { homedir as homedir8, platform as platform5 } from "os";
91888
- import { join as join26, resolve as resolve18 } from "path";
92092
+ import { join as join25, resolve as resolve18 } from "path";
91889
92093
  function getAllowedFontDirs() {
91890
92094
  if (allowedDirsCache)
91891
92095
  return allowedDirsCache;
@@ -91954,7 +92158,7 @@ function fontDirectories() {
91954
92158
  const home = homedir8();
91955
92159
  if (platform5() === "darwin") {
91956
92160
  return [
91957
- join26(home, "Library", "Fonts"),
92161
+ join25(home, "Library", "Fonts"),
91958
92162
  "/Library/Fonts",
91959
92163
  "/System/Library/Fonts",
91960
92164
  "/System/Library/Fonts/Supplemental"
@@ -91962,13 +92166,13 @@ function fontDirectories() {
91962
92166
  }
91963
92167
  if (platform5() === "win32") {
91964
92168
  return [
91965
- join26(process.env.WINDIR || "C:\\Windows", "Fonts"),
91966
- join26(process.env.LOCALAPPDATA || join26(homedir8(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
92169
+ join25(process.env.WINDIR || "C:\\Windows", "Fonts"),
92170
+ join25(process.env.LOCALAPPDATA || join25(homedir8(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
91967
92171
  ];
91968
92172
  }
91969
92173
  return [
91970
- join26(home, ".fonts"),
91971
- join26(home, ".local", "share", "fonts"),
92174
+ join25(home, ".fonts"),
92175
+ join25(home, ".local", "share", "fonts"),
91972
92176
  "/usr/local/share/fonts",
91973
92177
  "/usr/share/fonts"
91974
92178
  ];
@@ -91979,7 +92183,7 @@ function collectFontFileEntries(dir, depth = 0) {
91979
92183
  const entries2 = [];
91980
92184
  try {
91981
92185
  for (const entry of readdirSync11(dir, { withFileTypes: true })) {
91982
- const fullPath = join26(dir, entry.name);
92186
+ const fullPath = join25(dir, entry.name);
91983
92187
  if (entry.isDirectory()) {
91984
92188
  entries2.push(...collectFontFileEntries(fullPath, depth + 1));
91985
92189
  continue;
@@ -94790,8 +94994,8 @@ var init_gsapParser = __esm({
94790
94994
  // ../studio-server/dist/index.js
94791
94995
  import { Hono as Hono2 } from "hono";
94792
94996
  import { readFile } from "fs/promises";
94997
+ import { join as join26 } from "path";
94793
94998
  import { join as join27 } from "path";
94794
- import { join as join28 } from "path";
94795
94999
  import { readdirSync as readdirSync12 } from "fs";
94796
95000
  import { existsSync as existsSync30, readFileSync as readFileSync19 } from "fs";
94797
95001
  import { bodyLimit } from "hono/body-limit";
@@ -94803,12 +95007,12 @@ import {
94803
95007
  unlinkSync as unlinkSync22,
94804
95008
  rmSync as rmSync22,
94805
95009
  statSync as statSync8,
94806
- renameSync as renameSync4,
95010
+ renameSync as renameSync6,
94807
95011
  readdirSync as readdirSync32
94808
95012
  } from "fs";
94809
95013
  import { resolve as resolve22, dirname as dirname12, join as join62 } from "path";
94810
95014
  import { spawn as spawn9 } from "child_process";
94811
- import { existsSync as existsSync210, writeFileSync as writeFileSync11, mkdirSync as mkdirSync14 } from "fs";
95015
+ import { existsSync as existsSync210, writeFileSync as writeFileSync12, mkdirSync as mkdirSync14 } from "fs";
94812
95016
  import { join as join32, resolve as resolve19 } from "path";
94813
95017
  import { spawnSync } from "child_process";
94814
95018
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as writeFileSync22 } from "fs";
@@ -94868,7 +95072,7 @@ function walkDir(dir, prefix = "") {
94868
95072
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
94869
95073
  if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;
94870
95074
  if (entry.isDirectory()) {
94871
- files.push(...walkDir(join28(dir, entry.name), rel));
95075
+ files.push(...walkDir(join27(dir, entry.name), rel));
94872
95076
  } else {
94873
95077
  files.push(rel);
94874
95078
  }
@@ -94880,7 +95084,7 @@ async function filterCompositionFiles(projectDir, files) {
94880
95084
  const checks = await Promise.all(
94881
95085
  htmlFiles.map(async (f3) => {
94882
95086
  try {
94883
- const content = await readFile(join27(projectDir, f3), "utf-8");
95087
+ const content = await readFile(join26(projectDir, f3), "utf-8");
94884
95088
  return COMPOSITION_ID_RE.test(content);
94885
95089
  } catch {
94886
95090
  return false;
@@ -95041,7 +95245,7 @@ async function generateWaveformCache(projectDir, assetPath) {
95041
95245
  if (existsSync210(cachePath2)) return;
95042
95246
  const peaks = await decodeAudioPeaks(audioPath);
95043
95247
  mkdirSync14(cacheDir, { recursive: true });
95044
- writeFileSync11(cachePath2, JSON.stringify(peaks));
95248
+ writeFileSync12(cachePath2, JSON.stringify(peaks));
95045
95249
  }
95046
95250
  function validateUploadedMedia(filePath, runner = spawnSync) {
95047
95251
  const isVideo2 = VIDEO_EXT.test(filePath);
@@ -96790,7 +96994,7 @@ function registerFileRoutes(api, adapter2) {
96790
96994
  return c3.json({ error: "already exists" }, 409);
96791
96995
  }
96792
96996
  ensureDir(newAbs);
96793
- renameSync4(res.absPath, newAbs);
96997
+ renameSync6(res.absPath, newAbs);
96794
96998
  const updatedFiles = updateReferences(res.project.dir, res.filePath, body.newPath);
96795
96999
  return c3.json({ ok: true, path: body.newPath, updatedReferences: updatedFiles });
96796
97000
  });
@@ -99682,7 +99886,7 @@ import { serve as serve2 } from "@hono/node-server";
99682
99886
  import { existsSync as existsSync33, realpathSync as realpathSync5, statSync as statSync9, createReadStream } from "fs";
99683
99887
  import { readFile as readFile2 } from "fs/promises";
99684
99888
  import { Readable as Readable2 } from "stream";
99685
- import { join as join29, extname as extname9, resolve as resolve21, sep as sep5 } from "path";
99889
+ import { join as join28, extname as extname9, resolve as resolve21, sep as sep5 } from "path";
99686
99890
  function isPathInside2(child, parent, options = {}) {
99687
99891
  const { resolveSymlinks = false, pathModule } = options;
99688
99892
  const resolveFn = pathModule?.resolve ?? resolve21;
@@ -100026,13 +100230,13 @@ function createFileServer2(options) {
100026
100230
  }).join("/");
100027
100231
  let filePath = null;
100028
100232
  if (compiledDir) {
100029
- const candidate = join29(compiledDir, relativePath);
100233
+ const candidate = join28(compiledDir, relativePath);
100030
100234
  if (existsSync33(candidate) && isPathInside2(candidate, compiledDir) && statSync9(candidate).isFile()) {
100031
100235
  filePath = candidate;
100032
100236
  }
100033
100237
  }
100034
100238
  if (!filePath) {
100035
- const candidate = join29(projectDir, relativePath);
100239
+ const candidate = join28(projectDir, relativePath);
100036
100240
  if (existsSync33(candidate) && isPathInside2(candidate, projectDir) && statSync9(candidate).isFile()) {
100037
100241
  filePath = candidate;
100038
100242
  }
@@ -100257,7 +100461,7 @@ var init_fileServer2 = __esm({
100257
100461
  // ../producer/src/utils/paths.ts
100258
100462
  import {
100259
100463
  basename as basename4,
100260
- join as join30,
100464
+ join as join29,
100261
100465
  resolve as nodeResolve,
100262
100466
  relative as nodeRelative,
100263
100467
  isAbsolute as nodeIsAbsolute
@@ -100292,7 +100496,7 @@ function formatExportFrameName(index, ext) {
100292
100496
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
100293
100497
  const absoluteProjectDir = nodeResolve(projectDir);
100294
100498
  const projectName = basename4(absoluteProjectDir);
100295
- const resolvedOutputPath = outputPath ?? join30(rendersDir, `${projectName}.mp4`);
100499
+ const resolvedOutputPath = outputPath ?? join29(rendersDir, `${projectName}.mp4`);
100296
100500
  const absoluteOutputPath = nodeResolve(resolvedOutputPath);
100297
100501
  return { absoluteProjectDir, absoluteOutputPath };
100298
100502
  }
@@ -100314,12 +100518,12 @@ import {
100314
100518
  mkdirSync as mkdirSync15,
100315
100519
  rmSync as rmSync7,
100316
100520
  symlinkSync as symlinkSync2,
100317
- writeFileSync as writeFileSync12
100521
+ writeFileSync as writeFileSync13
100318
100522
  } from "fs";
100319
- import { basename as basename5, dirname as dirname14, isAbsolute as isAbsolute10, join as join31, relative as relative8, resolve as resolve23 } from "path";
100523
+ import { basename as basename5, dirname as dirname14, isAbsolute as isAbsolute10, join as join30, relative as relative8, resolve as resolve23 } from "path";
100320
100524
  function writeFileExclusiveSync(path2, data2) {
100321
100525
  try {
100322
- writeFileSync12(path2, data2, { flag: "wx", mode: 384 });
100526
+ writeFileSync13(path2, data2, { flag: "wx", mode: 384 });
100323
100527
  } catch (error) {
100324
100528
  if (error && typeof error === "object" && "code" in error && error.code === "EEXIST") {
100325
100529
  return;
@@ -100344,16 +100548,16 @@ function resolveDeviceScaleFactor(input2) {
100344
100548
  return target.width / input2.compositionWidth;
100345
100549
  }
100346
100550
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
100347
- const compileDir = join31(workDir, "compiled");
100551
+ const compileDir = join30(workDir, "compiled");
100348
100552
  mkdirSync15(compileDir, { recursive: true });
100349
- writeFileSync12(join31(compileDir, "index.html"), compiled.html, "utf-8");
100553
+ writeFileSync13(join30(compileDir, "index.html"), compiled.html, "utf-8");
100350
100554
  for (const [srcPath, html] of compiled.subCompositions) {
100351
- const outPath = join31(compileDir, srcPath);
100555
+ const outPath = join30(compileDir, srcPath);
100352
100556
  mkdirSync15(dirname14(outPath), { recursive: true });
100353
- writeFileSync12(outPath, html, "utf-8");
100557
+ writeFileSync13(outPath, html, "utf-8");
100354
100558
  }
100355
100559
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
100356
- const outPath = resolve23(join31(compileDir, relativePath));
100560
+ const outPath = resolve23(join30(compileDir, relativePath));
100357
100561
  if (!isPathInside3(outPath, compileDir)) {
100358
100562
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
100359
100563
  continue;
@@ -100384,7 +100588,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
100384
100588
  renderModeHints: compiled.renderModeHints,
100385
100589
  hasShaderTransitions: compiled.hasShaderTransitions
100386
100590
  };
100387
- writeFileSync12(join31(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
100591
+ writeFileSync13(join30(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
100388
100592
  }
100389
100593
  }
100390
100594
  function applyRenderModeHints(alreadyForced, compiled, log2 = defaultLogger) {
@@ -100507,7 +100711,7 @@ var init_shared = __esm({
100507
100711
  BROWSER_MEDIA_EPSILON = 1e-4;
100508
100712
  materializePathModule = {
100509
100713
  resolve: resolve23,
100510
- join: join31,
100714
+ join: join30,
100511
100715
  dirname: dirname14,
100512
100716
  basename: basename5,
100513
100717
  relative: relative8,
@@ -100931,7 +101135,7 @@ var init_captureBeyondViewport = __esm({
100931
101135
  });
100932
101136
 
100933
101137
  // ../producer/src/services/render/captureCost.ts
100934
- import { join as join33 } from "path";
101138
+ import { join as join31 } from "path";
100935
101139
  function estimateCaptureCostMultiplier(compiled) {
100936
101140
  let multiplier = 1;
100937
101141
  const reasons = [];
@@ -101158,7 +101362,7 @@ async function runCaptureCalibration(input2) {
101158
101362
  });
101159
101363
  let calibration;
101160
101364
  try {
101161
- calibration = await runOneCalibration(join33(workDir, "capture-calibration"), calibrationCfg);
101365
+ calibration = await runOneCalibration(join31(workDir, "capture-calibration"), calibrationCfg);
101162
101366
  } catch (error) {
101163
101367
  const shouldFallback = !forceScreenshot && shouldFallbackToScreenshotAfterCalibrationError(error);
101164
101368
  if (!shouldFallback) {
@@ -101191,7 +101395,7 @@ async function runCaptureCalibration(input2) {
101191
101395
  const screenshotCfg = createCaptureCalibrationConfig({ ...cfg, forceScreenshot: true });
101192
101396
  try {
101193
101397
  calibration = await runOneCalibration(
101194
- join33(workDir, "capture-calibration-screenshot"),
101398
+ join31(workDir, "capture-calibration-screenshot"),
101195
101399
  screenshotCfg
101196
101400
  );
101197
101401
  } catch (fallbackError) {
@@ -104705,9 +104909,9 @@ __export(deterministicFonts_exports, {
104705
104909
  resolveFontFamilyDeclarationFamilies: () => resolveFontFamilyDeclarationFamilies
104706
104910
  });
104707
104911
  import { createHash as createHash8 } from "crypto";
104708
- import { existsSync as existsSync35, mkdirSync as mkdirSync16, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
104912
+ import { existsSync as existsSync35, mkdirSync as mkdirSync16, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
104709
104913
  import { homedir as homedir10, tmpdir as tmpdir4 } from "os";
104710
- import { join as join34 } from "path";
104914
+ import { join as join33 } from "path";
104711
104915
  import postcss4 from "postcss";
104712
104916
  function parseFontFamilyValue(value) {
104713
104917
  return value.split(",").map((piece) => piece.trim().replace(/^['"]/, "").replace(/['"]$/, "").trim()).filter((piece) => piece.length > 0);
@@ -105024,13 +105228,13 @@ function warnUnresolvedFonts(unresolved) {
105024
105228
  );
105025
105229
  }
105026
105230
  function resolveFontCacheRoot() {
105027
- return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join34(tmpdir4(), "hyperframes", "fonts") : join34(homedir10(), ".cache", "hyperframes", "fonts"));
105231
+ return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join33(tmpdir4(), "hyperframes", "fonts") : join33(homedir10(), ".cache", "hyperframes", "fonts"));
105028
105232
  }
105029
105233
  function fontSlug(familyName) {
105030
105234
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
105031
105235
  }
105032
105236
  function fontCacheDir(slug) {
105033
- const dir = join34(GOOGLE_FONTS_CACHE_DIR, slug);
105237
+ const dir = join33(GOOGLE_FONTS_CACHE_DIR, slug);
105034
105238
  if (!existsSync35(dir)) {
105035
105239
  mkdirSync16(dir, { recursive: true });
105036
105240
  }
@@ -105040,7 +105244,7 @@ function subsetToken(woff2Url) {
105040
105244
  return createHash8("sha1").update(woff2Url).digest("hex").slice(0, 12);
105041
105245
  }
105042
105246
  function cachedWoff2Path(slug, weight, style, subset) {
105043
- return join34(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
105247
+ return join33(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
105044
105248
  }
105045
105249
  function fontFetchError(familyName, url, what, cause) {
105046
105250
  const reason = "status" in cause ? `returned HTTP ${cause.status}` : `failed: ${cause.error.message}`;
@@ -105061,7 +105265,7 @@ async function ensureWoff2DataUri(cachePath2, woff2Url, familyName, weight, styl
105061
105265
  }
105062
105266
  return null;
105063
105267
  }
105064
- writeFileSync13(cachePath2, Buffer.from(await fontRes.arrayBuffer()), { flag: "wx", mode: 420 });
105268
+ writeFileSync14(cachePath2, Buffer.from(await fontRes.arrayBuffer()), { flag: "wx", mode: 420 });
105065
105269
  } catch (err) {
105066
105270
  if (err instanceof FontFetchError) throw err;
105067
105271
  if (err.code === "EEXIST") {
@@ -105307,11 +105511,11 @@ import {
105307
105511
  existsSync as existsSync36,
105308
105512
  mkdirSync as mkdirSync17,
105309
105513
  readFileSync as readFileSync23,
105310
- renameSync as renameSync5,
105514
+ renameSync as renameSync7,
105311
105515
  rmSync as rmSync9,
105312
105516
  statSync as statSync10
105313
105517
  } from "fs";
105314
- import { dirname as dirname15, isAbsolute as isAbsolute11, join as join35, resolve as resolve24 } from "path";
105518
+ import { dirname as dirname15, isAbsolute as isAbsolute11, join as join34, resolve as resolve24 } from "path";
105315
105519
  function splitUrlSuffix2(src) {
105316
105520
  const queryIdx = src.indexOf("?");
105317
105521
  const hashIdx = src.indexOf("#");
@@ -105497,7 +105701,7 @@ async function ensurePreparedWebm(input2) {
105497
105701
  throw new Error("Animated GIF transcode produced an empty output");
105498
105702
  }
105499
105703
  if (!isUsableFile(input2.cachePath)) {
105500
- renameSync5(tmpPath, input2.cachePath);
105704
+ renameSync7(tmpPath, input2.cachePath);
105501
105705
  } else {
105502
105706
  rmSync9(tmpPath, { force: true });
105503
105707
  }
@@ -105558,7 +105762,7 @@ function replaceImageWithVideo(input2) {
105558
105762
  return video;
105559
105763
  }
105560
105764
  async function prepareAnimatedGifInputs(html, options) {
105561
- const outputDir = options.outputDir ?? join35(options.downloadDir, PREPARED_GIF_SUBDIR);
105765
+ const outputDir = options.outputDir ?? join34(options.downloadDir, PREPARED_GIF_SUBDIR);
105562
105766
  const outputSrcPrefix = normalizeRelPath(options.outputSrcPrefix ?? PREPARED_GIF_SUBDIR);
105563
105767
  const cacheDir = options.cacheDir ?? outputDir;
105564
105768
  const { document: document2 } = parseHTML(html);
@@ -105580,8 +105784,8 @@ async function prepareAnimatedGifInputs(html, options) {
105580
105784
  const { loopIterations, padSeconds } = resolvePreparedPlayback(metadata, loop, windowSeconds);
105581
105785
  const hash2 = computePreparedGifHash(bytes, loopIterations, padSeconds);
105582
105786
  const filename = `${CACHE_SCHEMA}-${hash2.slice(0, 24)}.webm`;
105583
- const cachePath2 = join35(cacheDir, filename);
105584
- const outputPath = join35(outputDir, filename);
105787
+ const cachePath2 = join34(cacheDir, filename);
105788
+ const outputPath = join34(outputDir, filename);
105585
105789
  const outputSrc = `${outputSrcPrefix}/${filename}`;
105586
105790
  await ensurePreparedWebm({
105587
105791
  sourcePath,
@@ -105937,7 +106141,7 @@ var init_position_edits_render_inline = __esm({
105937
106141
 
105938
106142
  // ../producer/src/services/htmlCompiler.ts
105939
106143
  import { readFileSync as readFileSync24, existsSync as existsSync37, mkdirSync as mkdirSync18 } from "fs";
105940
- import { join as join36, dirname as dirname16, resolve as resolve25, basename as basename6 } from "path";
106144
+ import { join as join35, dirname as dirname16, resolve as resolve25, basename as basename6 } from "path";
105941
106145
  function parseSubCompHtmlForValidity(html) {
105942
106146
  return parseHTML(html).document;
105943
106147
  }
@@ -106069,7 +106273,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
106069
106273
  return { duration: 0, resolvedPath: src };
106070
106274
  }
106071
106275
  } else if (!filePath.startsWith("/")) {
106072
- filePath = join36(baseDir, filePath);
106276
+ filePath = join35(baseDir, filePath);
106073
106277
  }
106074
106278
  if (!existsSync37(filePath)) {
106075
106279
  return { duration: 0, resolvedPath: filePath };
@@ -106611,7 +106815,7 @@ async function localizeRemoteMediaSources(html, downloadDir) {
106611
106815
  return downloadAndRewriteUrls(
106612
106816
  urlSet,
106613
106817
  html,
106614
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
106818
+ join35(downloadDir, REMOTE_MEDIA_SUBDIR),
106615
106819
  "Remote media download failed for",
106616
106820
  "Localized remote media source(s)"
106617
106821
  );
@@ -106626,7 +106830,7 @@ async function localizeRemoteImageSources(html, downloadDir) {
106626
106830
  return downloadAndRewriteUrls(
106627
106831
  urlSet,
106628
106832
  html,
106629
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
106833
+ join35(downloadDir, REMOTE_MEDIA_SUBDIR),
106630
106834
  "Remote image download failed for",
106631
106835
  "Localized remote image source(s)"
106632
106836
  );
@@ -106641,7 +106845,7 @@ async function localizeRemoteBackgroundImages(html, downloadDir) {
106641
106845
  return downloadAndRewriteUrls(
106642
106846
  urlSet,
106643
106847
  html,
106644
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
106848
+ join35(downloadDir, REMOTE_MEDIA_SUBDIR),
106645
106849
  "Remote background-image download failed for",
106646
106850
  "Localized remote background-image(s)",
106647
106851
  // Quoted url('..')/url("..") are rewritten by downloadAndRewriteUrls' default
@@ -106793,7 +106997,7 @@ async function localizeRemoteFontFaces(html, downloadDir) {
106793
106997
  return downloadAndRewriteUrls(
106794
106998
  urlSet,
106795
106999
  processed,
106796
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
107000
+ join35(downloadDir, REMOTE_MEDIA_SUBDIR),
106797
107001
  "Remote font download failed for",
106798
107002
  "Localized remote font face(s)",
106799
107003
  (h3, url, relPath) => h3.replaceAll(`url(${url})`, `url("${relPath}")`)
@@ -107275,7 +107479,7 @@ Check that each file referenced by data-composition-src contains valid HTML with
107275
107479
  });
107276
107480
 
107277
107481
  // ../producer/src/services/render/stages/compileStage.ts
107278
- import { join as join37 } from "path";
107482
+ import { join as join36 } from "path";
107279
107483
  async function runCompileStage(input2) {
107280
107484
  const {
107281
107485
  projectDir,
@@ -107291,12 +107495,12 @@ async function runCompileStage(input2) {
107291
107495
  allowSystemFontCapture
107292
107496
  } = input2;
107293
107497
  const compileStart = Date.now();
107294
- const compiled = await compileForRender(projectDir, htmlPath, join37(workDir, "downloads"), {
107498
+ const compiled = await compileForRender(projectDir, htmlPath, join36(workDir, "downloads"), {
107295
107499
  log: log2,
107296
107500
  failClosedFontFetch: failClosedFontFetch === true,
107297
107501
  allowSystemFontCapture,
107298
107502
  variables: input2.variables,
107299
- animatedGifCacheDir: cfg.extractCacheDir ? join37(cfg.extractCacheDir, "animated-gif") : void 0,
107503
+ animatedGifCacheDir: cfg.extractCacheDir ? join36(cfg.extractCacheDir, "animated-gif") : void 0,
107300
107504
  ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
107301
107505
  });
107302
107506
  assertNotAborted();
@@ -107389,7 +107593,7 @@ var init_compileStage = __esm({
107389
107593
  });
107390
107594
 
107391
107595
  // ../producer/src/services/render/stages/probeStage.ts
107392
- import { join as join38 } from "path";
107596
+ import { join as join37 } from "path";
107393
107597
  function hasScriptedAudioVolumeAutomation(html, audioCount) {
107394
107598
  if (audioCount <= 0) return false;
107395
107599
  const { document: document2 } = parseHTML(html);
@@ -107443,7 +107647,7 @@ async function runProbeStage(input2) {
107443
107647
  });
107444
107648
  fileServer = await createFileServer2({
107445
107649
  projectDir,
107446
- compiledDir: join38(workDir, "compiled"),
107650
+ compiledDir: join37(workDir, "compiled"),
107447
107651
  port: 0,
107448
107652
  preHeadScripts: [VIRTUAL_TIME_SHIM],
107449
107653
  fps: job.config.fps
@@ -107464,7 +107668,7 @@ async function runProbeStage(input2) {
107464
107668
  log2.info("Creating capture session...", { attempt, maxAttempts: PROBE_MAX_ATTEMPTS });
107465
107669
  probeSession = await createCaptureSession(
107466
107670
  fileServer.url,
107467
- join38(workDir, "probe"),
107671
+ join37(workDir, "probe"),
107468
107672
  captureOpts,
107469
107673
  null,
107470
107674
  probeCfg
@@ -107548,7 +107752,7 @@ async function runProbeStage(input2) {
107548
107752
  });
107549
107753
  probeSession = await createCaptureSession(
107550
107754
  fileServer.url,
107551
- join38(workDir, "probe-screenshot"),
107755
+ join37(workDir, "probe-screenshot"),
107552
107756
  captureOpts,
107553
107757
  null,
107554
107758
  { ...probeCfg, forceScreenshot: true }
@@ -107583,7 +107787,7 @@ async function runProbeStage(input2) {
107583
107787
  compiled,
107584
107788
  resolutions,
107585
107789
  projectDir,
107586
- join38(workDir, "downloads")
107790
+ join37(workDir, "downloads")
107587
107791
  );
107588
107792
  assertNotAborted();
107589
107793
  composition.videos = compiled.videos;
@@ -107817,7 +108021,7 @@ var init_probeStage = __esm({
107817
108021
 
107818
108022
  // ../producer/src/services/render/stages/extractVideosStage.ts
107819
108023
  import { existsSync as existsSync38 } from "fs";
107820
- import { isAbsolute as isAbsolute12, join as join39 } from "path";
108024
+ import { isAbsolute as isAbsolute12, join as join38 } from "path";
107821
108025
  function shouldCopyExtractedFrames(platform10) {
107822
108026
  return platform10 === "win32";
107823
108027
  }
@@ -107863,7 +108067,7 @@ async function runExtractVideosStage(input2) {
107863
108067
  composition.images.map(async (img) => {
107864
108068
  let imgPath = img.src;
107865
108069
  if (!imgPath.startsWith("/")) {
107866
- const fromCompiled = existsSync38(join39(compiledDir, imgPath)) ? join39(compiledDir, imgPath) : join39(projectDir, imgPath);
108070
+ const fromCompiled = existsSync38(join38(compiledDir, imgPath)) ? join38(compiledDir, imgPath) : join38(projectDir, imgPath);
107867
108071
  imgPath = fromCompiled;
107868
108072
  }
107869
108073
  if (!existsSync38(imgPath)) return null;
@@ -107893,7 +108097,7 @@ async function runExtractVideosStage(input2) {
107893
108097
  // output framerate exact.
107894
108098
  {
107895
108099
  fps: fpsToNumber(job.config.fps),
107896
- outputDir: join39(compiledDir, "__hyperframes_video_frames"),
108100
+ outputDir: join38(compiledDir, "__hyperframes_video_frames"),
107897
108101
  format: job.config.videoFrameFormat ?? "auto"
107898
108102
  },
107899
108103
  abortSignal,
@@ -107959,18 +108163,18 @@ var init_extractVideosStage = __esm({
107959
108163
  });
107960
108164
 
107961
108165
  // ../producer/src/services/render/stages/audioStage.ts
107962
- import { join as join40 } from "path";
108166
+ import { join as join39 } from "path";
107963
108167
  async function runAudioStage(input2) {
107964
108168
  const { projectDir, workDir, compiledDir, duration, audios, abortSignal, assertNotAborted } = input2;
107965
108169
  const stage3Start = Date.now();
107966
- const audioOutputPath = join40(workDir, "audio.aac");
108170
+ const audioOutputPath = join39(workDir, "audio.aac");
107967
108171
  let hasAudio = false;
107968
108172
  let audioError;
107969
108173
  if (audios.length > 0) {
107970
108174
  const audioResult = await processCompositionAudio(
107971
108175
  audios,
107972
108176
  projectDir,
107973
- join40(workDir, "audio-work"),
108177
+ join39(workDir, "audio-work"),
107974
108178
  audioOutputPath,
107975
108179
  duration,
107976
108180
  abortSignal,
@@ -108156,7 +108360,7 @@ var init_captureStage = __esm({
108156
108360
 
108157
108361
  // ../producer/src/services/hdrCompositor.ts
108158
108362
  import { readSync as readSync2, closeSync as closeSync3 } from "fs";
108159
- import { join as join41 } from "path";
108363
+ import { join as join40 } from "path";
108160
108364
  function countNonZeroAlpha(rgba) {
108161
108365
  let n2 = 0;
108162
108366
  for (let p2 = 3; p2 < rgba.length; p2 += 4) {
@@ -108550,7 +108754,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
108550
108754
  if (shouldLog && debugDumpDir) {
108551
108755
  const after2 = countNonZeroRgb48(canvas);
108552
108756
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
108553
- const dumpPath = join41(debugDumpDir, dumpName);
108757
+ const dumpPath = join40(debugDumpDir, dumpName);
108554
108758
  writeFileExclusiveSync(dumpPath, domPng);
108555
108759
  log2.info("[diag] dom layer blit", {
108556
108760
  frame: debugFrameIndex,
@@ -108852,13 +109056,13 @@ var init_captureHdrFrameShared = __esm({
108852
109056
  import { execFile as execFile3 } from "child_process";
108853
109057
  import { mkdtemp, rm, writeFile } from "fs/promises";
108854
109058
  import { tmpdir as tmpdir5 } from "os";
108855
- import { join as join43 } from "path";
109059
+ import { join as join41 } from "path";
108856
109060
  import { promisify as promisify3 } from "util";
108857
109061
  async function psnrDb(a, b2) {
108858
- const dir = await mkdtemp(join43(tmpdir5(), "hf-de-verify-"));
109062
+ const dir = await mkdtemp(join41(tmpdir5(), "hf-de-verify-"));
108859
109063
  try {
108860
- const pa = join43(dir, "a.jpg");
108861
- const pb = join43(dir, "b.jpg");
109064
+ const pa = join41(dir, "a.jpg");
109065
+ const pb = join41(dir, "b.jpg");
108862
109066
  await Promise.all([writeFile(pa, a), writeFile(pb, b2)]);
108863
109067
  const { stderr } = await execFileP(
108864
109068
  getFfmpegBinary(),
@@ -108945,11 +109149,11 @@ function createDrainFrameGuard(args) {
108945
109149
  return buf;
108946
109150
  }
108947
109151
  if (db < verifyMinDb) {
108948
- const dumpDir = await mkdtemp(join43(tmpdir5(), "hf-de-verify-fail-")).catch(() => null);
109152
+ const dumpDir = await mkdtemp(join41(tmpdir5(), "hf-de-verify-fail-")).catch(() => null);
108949
109153
  if (dumpDir) {
108950
109154
  await Promise.all([
108951
- writeFile(join43(dumpDir, `frame-${idx}-de.jpg`), buf),
108952
- writeFile(join43(dumpDir, `frame-${idx}-truth.jpg`), truth)
109155
+ writeFile(join41(dumpDir, `frame-${idx}-de.jpg`), buf),
109156
+ writeFile(join41(dumpDir, `frame-${idx}-truth.jpg`), truth)
108953
109157
  ]).catch(() => {
108954
109158
  });
108955
109159
  }
@@ -109364,7 +109568,7 @@ import {
109364
109568
  openSync as openSync3,
109365
109569
  readFileSync as readFileSync25
109366
109570
  } from "fs";
109367
- import { join as join44 } from "path";
109571
+ import { join as join43 } from "path";
109368
109572
  function tempDirSafePrefix(id) {
109369
109573
  const safe = id.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
109370
109574
  return safe || "video";
@@ -109377,8 +109581,8 @@ function planHdrResources(args) {
109377
109581
  if (!hdrVideoIds.includes(v2.id)) continue;
109378
109582
  let srcPath = v2.src;
109379
109583
  if (!srcPath.startsWith("/")) {
109380
- const fromCompiled = join44(compiledDir, srcPath);
109381
- srcPath = args.existsSync(fromCompiled) ? fromCompiled : join44(projectDir, srcPath);
109584
+ const fromCompiled = join43(compiledDir, srcPath);
109585
+ srcPath = args.existsSync(fromCompiled) ? fromCompiled : join43(projectDir, srcPath);
109382
109586
  }
109383
109587
  hdrVideoSrcPaths.set(v2.id, srcPath);
109384
109588
  }
@@ -109452,10 +109656,10 @@ async function extractHdrVideoFrames(args) {
109452
109656
  const video = composition.videos.find((v2) => v2.id === videoId);
109453
109657
  if (!video) continue;
109454
109658
  mkdirSync19(framesDir, { recursive: true });
109455
- const frameDir = mkdtempSync3(join44(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
109659
+ const frameDir = mkdtempSync3(join43(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
109456
109660
  const duration = video.end - video.start;
109457
109661
  const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
109458
- const rawPath = join44(frameDir, "frames.rgb48le");
109662
+ const rawPath = join43(frameDir, "frames.rgb48le");
109459
109663
  const ffmpegArgs = [
109460
109664
  "-ss",
109461
109665
  String(video.mediaStart),
@@ -109566,7 +109770,7 @@ var init_captureHdrResources = __esm({
109566
109770
  });
109567
109771
 
109568
109772
  // ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
109569
- import { join as join45 } from "path";
109773
+ import { join as join44 } from "path";
109570
109774
  async function runSequentialLayeredFrameLoop(input2) {
109571
109775
  const {
109572
109776
  job,
@@ -109687,7 +109891,7 @@ async function runSequentialLayeredFrameLoop(input2) {
109687
109891
  );
109688
109892
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
109689
109893
  writeFileExclusiveSync(
109690
- join45(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
109894
+ join44(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
109691
109895
  normalCanvas
109692
109896
  );
109693
109897
  }
@@ -109734,7 +109938,7 @@ var init_captureHdrSequentialLoop = __esm({
109734
109938
  // ../producer/src/services/shaderTransitionWorkerPool.ts
109735
109939
  import { Worker as Worker2 } from "worker_threads";
109736
109940
  import { fileURLToPath as fileURLToPath4, pathToFileURL } from "url";
109737
- import { dirname as dirname17, join as join46 } from "path";
109941
+ import { dirname as dirname17, join as join45 } from "path";
109738
109942
  import { createRequire } from "module";
109739
109943
  import { existsSync as existsSync39 } from "fs";
109740
109944
  import { cpus as cpus3 } from "os";
@@ -109748,9 +109952,9 @@ function resolveWorkerEntry(explicit) {
109748
109952
  return { path: override, isTs };
109749
109953
  }
109750
109954
  const moduleDir = dirname17(fileURLToPath4(import.meta.url));
109751
- const jsPath = join46(moduleDir, "shaderTransitionWorker.js");
109955
+ const jsPath = join45(moduleDir, "shaderTransitionWorker.js");
109752
109956
  if (existsSync39(jsPath)) return { path: jsPath, isTs: false };
109753
- const tsPath = join46(moduleDir, "shaderTransitionWorker.ts");
109957
+ const tsPath = join45(moduleDir, "shaderTransitionWorker.ts");
109754
109958
  return { path: tsPath, isTs: true };
109755
109959
  }
109756
109960
  function buildExecArgv(entryIsTs) {
@@ -109933,7 +110137,7 @@ var init_shaderTransitionWorkerPool = __esm({
109933
110137
  });
109934
110138
 
109935
110139
  // ../producer/src/services/render/stages/captureHdrHybridLoop.ts
109936
- import { join as join47 } from "path";
110140
+ import { join as join46 } from "path";
109937
110141
  async function runHybridLayeredFrameLoop(input2) {
109938
110142
  const {
109939
110143
  job,
@@ -110126,7 +110330,7 @@ async function runHybridLayeredFrameLoop(input2) {
110126
110330
  );
110127
110331
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
110128
110332
  writeFileExclusiveSync(
110129
- join47(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
110333
+ join46(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
110130
110334
  canvas
110131
110335
  );
110132
110336
  }
@@ -110171,7 +110375,7 @@ var init_captureHdrHybridLoop = __esm({
110171
110375
 
110172
110376
  // ../producer/src/services/render/stages/captureHdrStage.ts
110173
110377
  import { existsSync as existsSync40, mkdirSync as mkdirSync20 } from "fs";
110174
- import { join as join48 } from "path";
110378
+ import { join as join47 } from "path";
110175
110379
  async function runCaptureHdrStage(input2) {
110176
110380
  const {
110177
110381
  job,
@@ -110330,7 +110534,7 @@ async function runCaptureHdrStage(input2) {
110330
110534
  if (hdrVideoFrameSources.has(v2.id)) hdrVideoEndTimes.set(v2.id, v2.end);
110331
110535
  }
110332
110536
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
110333
- const debugDumpDir = debugDumpEnabled ? join48(framesDir, "debug-composite") : null;
110537
+ const debugDumpDir = debugDumpEnabled ? join47(framesDir, "debug-composite") : null;
110334
110538
  if (debugDumpDir && !existsSync40(debugDumpDir)) {
110335
110539
  mkdirSync20(debugDumpDir, { recursive: true });
110336
110540
  }
@@ -110492,7 +110696,7 @@ var init_captureHdrStage = __esm({
110492
110696
  });
110493
110697
 
110494
110698
  // ../producer/src/services/render/stages/gifEncodeArgs.ts
110495
- import { join as join49 } from "path";
110699
+ import { join as join48 } from "path";
110496
110700
  function fpsToFfmpegArg2(fps) {
110497
110701
  return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
110498
110702
  }
@@ -110503,7 +110707,7 @@ function buildGifPalettegenArgs(input2) {
110503
110707
  "-framerate",
110504
110708
  fpsArg,
110505
110709
  "-i",
110506
- join49(input2.framesDir, input2.framePattern),
110710
+ join48(input2.framesDir, input2.framePattern),
110507
110711
  "-vf",
110508
110712
  `fps=${fpsArg},palettegen=stats_mode=diff`,
110509
110713
  input2.palettePath
@@ -110516,7 +110720,7 @@ function buildGifPaletteuseArgs(input2) {
110516
110720
  "-framerate",
110517
110721
  fpsArg,
110518
110722
  "-i",
110519
- join49(input2.framesDir, input2.framePattern),
110723
+ join48(input2.framesDir, input2.framePattern),
110520
110724
  "-i",
110521
110725
  input2.palettePath,
110522
110726
  "-lavfi",
@@ -110534,7 +110738,7 @@ var init_gifEncodeArgs = __esm({
110534
110738
 
110535
110739
  // ../producer/src/services/render/stages/encodeStage.ts
110536
110740
  import { copyFileSync as copyFileSync5, existsSync as existsSync41, mkdirSync as mkdirSync21, readdirSync as readdirSync13, rmSync as rmSync11, statSync as statSync11 } from "fs";
110537
- import { dirname as dirname18, join as join50 } from "path";
110741
+ import { dirname as dirname18, join as join49 } from "path";
110538
110742
  function resolveGifLoop(loop) {
110539
110743
  const resolved2 = loop ?? 0;
110540
110744
  if (!Number.isInteger(resolved2) || resolved2 < 0 || resolved2 > 65535) {
@@ -110639,11 +110843,11 @@ async function runEncodeStage(input2) {
110639
110843
  );
110640
110844
  }
110641
110845
  captured.forEach((name, i2) => {
110642
- const dst = join50(outputPath, formatExportFrameName(i2, "png"));
110643
- copyFileSync5(join50(framesDir, name), dst);
110846
+ const dst = join49(outputPath, formatExportFrameName(i2, "png"));
110847
+ copyFileSync5(join49(framesDir, name), dst);
110644
110848
  });
110645
110849
  if (hasAudio && audioOutputPath && existsSync41(audioOutputPath)) {
110646
- copyFileSync5(audioOutputPath, join50(outputPath, "audio.aac"));
110850
+ copyFileSync5(audioOutputPath, join49(outputPath, "audio.aac"));
110647
110851
  log2.info(`[Render] png-sequence: audio.aac sidecar written to ${outputPath}/audio.aac`);
110648
110852
  }
110649
110853
  return { encodeMs: Date.now() - stage5Start };
@@ -110659,7 +110863,7 @@ async function runEncodeStage(input2) {
110659
110863
  const encodeResult2 = await encodeGifFromDir(framesDir, framePattern2, outputPath, {
110660
110864
  fps: job.config.fps,
110661
110865
  loop,
110662
- palettePath: join50(dirname18(videoOnlyPath), "gif-palette.png"),
110866
+ palettePath: join49(dirname18(videoOnlyPath), "gif-palette.png"),
110663
110867
  signal: abortSignal,
110664
110868
  timeout: engineCfg.ffmpegEncodeTimeout
110665
110869
  });
@@ -110781,11 +110985,11 @@ import {
110781
110985
  readdirSync as readdirSync14,
110782
110986
  rmSync as rmSync12,
110783
110987
  statSync as statSync12,
110784
- writeFileSync as writeFileSync14,
110988
+ writeFileSync as writeFileSync15,
110785
110989
  copyFileSync as copyFileSync6,
110786
110990
  appendFileSync
110787
110991
  } from "fs";
110788
- import { join as join51, dirname as dirname19, resolve as resolve26 } from "path";
110992
+ import { join as join50, dirname as dirname19, resolve as resolve26 } from "path";
110789
110993
  import { randomUUID as randomUUID4 } from "crypto";
110790
110994
  import { fileURLToPath as fileURLToPath5 } from "url";
110791
110995
  function sampleDirectoryBytes(dir) {
@@ -110801,7 +111005,7 @@ function sampleDirectoryBytes(dir) {
110801
111005
  continue;
110802
111006
  }
110803
111007
  for (const name of entries2) {
110804
- const full2 = join51(current2, name);
111008
+ const full2 = join50(current2, name);
110805
111009
  try {
110806
111010
  const st3 = statSync12(full2);
110807
111011
  if (st3.isDirectory()) {
@@ -110890,7 +111094,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
110890
111094
  const ranges = [];
110891
111095
  let rangeStart = null;
110892
111096
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
110893
- const framePath = join51(framesDir, formatCaptureFrameName(frameIndex, frameExt));
111097
+ const framePath = join50(framesDir, formatCaptureFrameName(frameIndex, frameExt));
110894
111098
  const missing = !existsSync43(framePath);
110895
111099
  if (missing && rangeStart === null) {
110896
111100
  rangeStart = frameIndex;
@@ -110913,7 +111117,7 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
110913
111117
  workerId,
110914
111118
  startFrame: rangeStart + range.startFrame,
110915
111119
  endFrame: rangeStart + range.endFrame,
110916
- outputDir: join51(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
111120
+ outputDir: join50(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
110917
111121
  outputFrameOffset: rangeStart
110918
111122
  }));
110919
111123
  batches.push(batch);
@@ -110946,7 +111150,7 @@ The composition is too large for the available memory. To reduce memory pressure
110946
111150
  function countCapturedFrames(totalFrames, framesDir, frameExt) {
110947
111151
  let captured = 0;
110948
111152
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
110949
- const framePath = join51(framesDir, formatCaptureFrameName(frameIndex, frameExt));
111153
+ const framePath = join50(framesDir, formatCaptureFrameName(frameIndex, frameExt));
110950
111154
  if (existsSync43(framePath)) captured++;
110951
111155
  }
110952
111156
  return captured;
@@ -110971,7 +111175,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
110971
111175
  reason: attempt === 0 ? "initial" : pendingTransientRetry ? "transient-retry" : "retry"
110972
111176
  });
110973
111177
  pendingTransientRetry = false;
110974
- const attemptWorkDir = join51(options.workDir, `capture-attempt-${attempt}`);
111178
+ const attemptWorkDir = join50(options.workDir, `capture-attempt-${attempt}`);
110975
111179
  const batches = missingRanges ? buildMissingFrameRetryBatches(
110976
111180
  missingRanges,
110977
111181
  currentWorkers,
@@ -111135,12 +111339,13 @@ function shouldPreferSingleWorkerDrawElement(args) {
111135
111339
  }
111136
111340
  function resolveInversionRetryPlan(args) {
111137
111341
  if (args.deWorkerInversion !== "inverted") return null;
111342
+ const workerCount = args.isMemoryExhaustion ? 1 : args.preInversionWorkerCount;
111138
111343
  return {
111139
- workerCount: args.preInversionWorkerCount,
111344
+ workerCount,
111140
111345
  useStreamingEncode: shouldUseStreamingEncode(
111141
111346
  args.cfg,
111142
111347
  args.outputFormat,
111143
- args.preInversionWorkerCount,
111348
+ workerCount,
111144
111349
  args.durationSeconds
111145
111350
  ),
111146
111351
  deWorkerInversion: "reverted"
@@ -111151,17 +111356,23 @@ function shouldPreferParallelDrawElement(args) {
111151
111356
  }
111152
111357
  function resolveParallelRouterRetryPlan(args) {
111153
111358
  if (args.deParallelRouter !== "routed") return null;
111359
+ const workerCount = args.isMemoryExhaustion ? 1 : args.preRouterWorkerCount;
111154
111360
  return {
111155
- workerCount: args.preRouterWorkerCount,
111361
+ workerCount,
111156
111362
  useStreamingEncode: shouldUseStreamingEncode(
111157
111363
  args.cfg,
111158
111364
  args.outputFormat,
111159
- args.preRouterWorkerCount,
111365
+ workerCount,
111160
111366
  args.durationSeconds
111161
111367
  ),
111162
111368
  deParallelRouter: "reverted"
111163
111369
  };
111164
111370
  }
111371
+ function shouldRetryViaPinnedFallback(args) {
111372
+ if (args.isCancellation) return false;
111373
+ if (args.isVerifyError) return true;
111374
+ return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
111375
+ }
111165
111376
  function resolveCaptureForceScreenshotForPageSideCompositing(args) {
111166
111377
  return args.usePageSideCompositing ? true : args.forceScreenshot;
111167
111378
  }
@@ -111189,10 +111400,10 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
111189
111400
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
111190
111401
  const moduleDir = dirname19(fileURLToPath5(import.meta.url));
111191
111402
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve26(process.env.PRODUCER_RENDERS_DIR, "..") : resolve26(moduleDir, "../..");
111192
- const debugDir = join51(producerRoot, ".debug");
111403
+ const debugDir = join50(producerRoot, ".debug");
111193
111404
  const outputDir = dirname19(outputPath);
111194
111405
  if (!existsSync43(outputDir)) mkdirSync23(outputDir, { recursive: true });
111195
- const workDir = job.config.debug ? join51(debugDir, job.id) : mkdtempSync4(join51(outputDir, `work-${job.id}-`));
111406
+ const workDir = job.config.debug ? join50(debugDir, job.id) : mkdtempSync4(join50(outputDir, `work-${job.id}-`));
111196
111407
  const pipelineStart = Date.now();
111197
111408
  const log2 = job.config.logger ?? defaultLogger;
111198
111409
  let fileServer = null;
@@ -111208,7 +111419,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111208
111419
  imageDecodeFailures: 0
111209
111420
  };
111210
111421
  let hdrPerf;
111211
- const perfOutputPath = join51(workDir, "perf-summary.json");
111422
+ const perfOutputPath = join50(workDir, "perf-summary.json");
111212
111423
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
111213
111424
  const observability = new RenderObservabilityRecorder({
111214
111425
  pipelineStartMs: pipelineStart,
@@ -111257,7 +111468,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111257
111468
  assertConfiguredFfmpegBinariesExist();
111258
111469
  if (!existsSync43(workDir)) mkdirSync23(workDir, { recursive: true });
111259
111470
  if (job.config.debug) {
111260
- const logPath = join51(workDir, "render.log");
111471
+ const logPath = join50(workDir, "render.log");
111261
111472
  restoreLogger = installDebugLogger(logPath, log2);
111262
111473
  log2.info("[Render] Debug artifacts enabled", { workDir, logPath });
111263
111474
  }
@@ -111286,15 +111497,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111286
111497
  requestedWorkers: job.config.workers ?? "auto"
111287
111498
  });
111288
111499
  const entryFile = job.config.entryFile || "index.html";
111289
- let htmlPath = join51(projectDir, entryFile);
111500
+ let htmlPath = join50(projectDir, entryFile);
111290
111501
  if (!existsSync43(htmlPath)) {
111291
111502
  throw new Error(`Entry file not found: ${htmlPath}`);
111292
111503
  }
111293
111504
  assertNotAborted();
111294
111505
  const rawEntry = readFileSync26(htmlPath, "utf-8");
111295
111506
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
111296
- const wrapperPath = join51(workDir, "standalone-entry.html");
111297
- const projectIndexPath = join51(projectDir, "index.html");
111507
+ const wrapperPath = join50(workDir, "standalone-entry.html");
111508
+ const projectIndexPath = join50(projectDir, "index.html");
111298
111509
  if (!existsSync43(projectIndexPath)) {
111299
111510
  throw new Error(
111300
111511
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
@@ -111309,7 +111520,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111309
111520
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
111310
111521
  );
111311
111522
  }
111312
- writeFileSync14(wrapperPath, standaloneHtml, "utf-8");
111523
+ writeFileSync15(wrapperPath, standaloneHtml, "utf-8");
111313
111524
  htmlPath = wrapperPath;
111314
111525
  log2.info("Extracted standalone entry from index.html host context", {
111315
111526
  entryFile
@@ -111430,7 +111641,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111430
111641
  beginFrameStalled: probeResult.beginFrameStalled
111431
111642
  });
111432
111643
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
111433
- const compiledDir = join51(workDir, "compiled");
111644
+ const compiledDir = join50(workDir, "compiled");
111434
111645
  const extractResult = await observeRenderStage(
111435
111646
  observability,
111436
111647
  "video_extract",
@@ -111517,7 +111728,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111517
111728
  try {
111518
111729
  fileServer = await createFileServer2({
111519
111730
  projectDir,
111520
- compiledDir: join51(workDir, "compiled"),
111731
+ compiledDir: join50(workDir, "compiled"),
111521
111732
  port: 0,
111522
111733
  preHeadScripts: [VIRTUAL_TIME_SHIM],
111523
111734
  fps: job.config.fps
@@ -111535,7 +111746,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111535
111746
  if (!activeFileServer) {
111536
111747
  throw new Error("File server failed to initialize before frame capture");
111537
111748
  }
111538
- const framesDir = join51(workDir, "captured-frames");
111749
+ const framesDir = join50(workDir, "captured-frames");
111539
111750
  if (!existsSync43(framesDir)) mkdirSync23(framesDir, { recursive: true });
111540
111751
  const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
111541
111752
  chromePath: resolveHeadlessShellPath(cfg),
@@ -111682,7 +111893,18 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111682
111893
  );
111683
111894
  workerCount = 1;
111684
111895
  }
111685
- updateCaptureObservability({ workerCount, deWorkerInversion, deParallelRouter });
111896
+ updateCaptureObservability({
111897
+ workerCount,
111898
+ deWorkerInversion,
111899
+ deParallelRouter,
111900
+ // Recorded here (not just in the success-path perfSummary) so a hard
111901
+ // failure while routed/inverted still tells us what worker count the
111902
+ // resolver would have used absent the experiment — the DE-router pin
111903
+ // to 3 workers regardless of calibration is the leading suspect for
111904
+ // any resource-pressure failure unique to this cohort.
111905
+ dePreInversionWorkers: deWorkerInversion ? preRoutingWorkerCount : void 0,
111906
+ dePreRouterWorkers: deParallelRouter ? preRoutingWorkerCount : void 0
111907
+ });
111686
111908
  observability.checkpoint("worker_resolution", "resolved", {
111687
111909
  workerCount,
111688
111910
  deWorkerInversion: deWorkerInversion ?? "none",
@@ -111728,7 +111950,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111728
111950
  gif: ".gif"
111729
111951
  };
111730
111952
  const videoExt = FORMAT_EXT3[outputFormat] ?? ".mp4";
111731
- const videoOnlyPath = join51(workDir, `video-only${videoExt}`);
111953
+ const videoOnlyPath = join50(workDir, `video-only${videoExt}`);
111732
111954
  const usePageSideCompositingForTransitions = (cfg.enablePageSideCompositing || isGif) && compiled.hasShaderTransitions && !hasHdrContent && !isPngSequence && !needsAlpha;
111733
111955
  if (usePageSideCompositingForTransitions) {
111734
111956
  activeFileServer.addPreHeadScript(HF_PAGE_SIDE_COMPOSITING_STUB);
@@ -111880,20 +112102,31 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111880
112102
  try {
111881
112103
  streamingRes = await invokeStreaming();
111882
112104
  } catch (err) {
111883
- if (!isDrawElementVerificationError(err)) throw err;
111884
- deSelfVerifyFallback = true;
111885
- deFallbackReason = /blank/i.test(err instanceof Error ? err.message : "") ? "blank" : "psnr";
111886
- log2.warn("[Render] drawElement self-verification failed; re-rendering via screenshot", {
111887
- error: err instanceof Error ? err.message : String(err)
111888
- });
112105
+ const isVerifyError = isDrawElementVerificationError(err);
112106
+ const isCancellation = err instanceof RenderCancelledError || abortSignal?.aborted === true;
112107
+ if (!shouldRetryViaPinnedFallback({
112108
+ isVerifyError,
112109
+ isCancellation,
112110
+ deWorkerInversion,
112111
+ deParallelRouter
112112
+ }))
112113
+ throw err;
112114
+ const isMemoryExhaustion = !isVerifyError && isMemoryExhaustionError(err);
112115
+ deSelfVerifyFallback = isVerifyError;
112116
+ deFallbackReason = isVerifyError ? /blank/i.test(err instanceof Error ? err.message : "") ? "blank" : "psnr" : isMemoryExhaustion ? "oom" : "capture_error";
112117
+ log2.warn(
112118
+ isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : "[Render] capture failed on the pinned worker count; re-rendering via screenshot",
112119
+ { error: err instanceof Error ? err.message : String(err) }
112120
+ );
111889
112121
  observability.checkpoint(
111890
112122
  "capture_streaming",
111891
- "drawElement self-verify failed; retrying with forceScreenshot"
112123
+ isVerifyError ? "drawElement self-verify failed; retrying with forceScreenshot" : "capture failed on pinned worker count; retrying with forceScreenshot"
111892
112124
  );
111893
112125
  captureForceScreenshot = true;
111894
112126
  updateCaptureObservability({
111895
112127
  forceScreenshot: true,
111896
- deSelfVerifyFallback: true
112128
+ deSelfVerifyFallback,
112129
+ deFallbackReason
111897
112130
  });
111898
112131
  probeSession = null;
111899
112132
  if (deParallelRouter === "routed") deParallelStreamForced = false;
@@ -111902,14 +112135,16 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111902
112135
  preInversionWorkerCount: preRoutingWorkerCount,
111903
112136
  cfg,
111904
112137
  outputFormat,
111905
- durationSeconds: job.duration
112138
+ durationSeconds: job.duration,
112139
+ isMemoryExhaustion
111906
112140
  });
111907
112141
  const parallelRouterRetryPlan = resolveParallelRouterRetryPlan({
111908
112142
  deParallelRouter,
111909
112143
  preRouterWorkerCount: preRoutingWorkerCount,
111910
112144
  cfg,
111911
112145
  outputFormat,
111912
- durationSeconds: job.duration
112146
+ durationSeconds: job.duration,
112147
+ isMemoryExhaustion
111913
112148
  });
111914
112149
  if (inversionRetryPlan) {
111915
112150
  deWorkerInversion = inversionRetryPlan.deWorkerInversion;
@@ -112128,7 +112363,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
112128
112363
  job.perfSummary = perfSummary;
112129
112364
  if (job.config.debug) {
112130
112365
  try {
112131
- writeFileSync14(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
112366
+ writeFileSync15(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
112132
112367
  } catch (err) {
112133
112368
  log2.debug("Failed to write perf summary", {
112134
112369
  perfOutputPath,
@@ -112138,7 +112373,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
112138
112373
  }
112139
112374
  if (job.config.debug) {
112140
112375
  if (!isPngSequence && existsSync43(outputPath)) {
112141
- const debugOutput = join51(workDir, `output${videoExt}`);
112376
+ const debugOutput = join50(workDir, `output${videoExt}`);
112142
112377
  copyFileSync6(outputPath, debugOutput);
112143
112378
  }
112144
112379
  } else if (process.env.KEEP_TEMP === "1") {
@@ -112301,7 +112536,7 @@ var init_config3 = __esm({
112301
112536
 
112302
112537
  // ../producer/src/services/hyperframeLint.ts
112303
112538
  import { existsSync as existsSync44, readFileSync as readFileSync27, statSync as statSync13 } from "fs";
112304
- import { resolve as resolve27, join as join53 } from "path";
112539
+ import { resolve as resolve27, join as join51 } from "path";
112305
112540
  function isStringRecord2(value) {
112306
112541
  if (!value || typeof value !== "object" || Array.isArray(value)) {
112307
112542
  return false;
@@ -112349,7 +112584,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
112349
112584
  }
112350
112585
  }
112351
112586
  return {
112352
- error: `No HTML entry file found in project directory: ${join53(absProjectDir, preferredEntryFile || "index.html")}`
112587
+ error: `No HTML entry file found in project directory: ${join51(absProjectDir, preferredEntryFile || "index.html")}`
112353
112588
  };
112354
112589
  }
112355
112590
  function prepareHyperframeLintBody(body) {
@@ -112398,7 +112633,7 @@ var init_hyperframeLint = __esm({
112398
112633
  // ../producer/src/services/healthWorker.ts
112399
112634
  import { Worker as Worker3 } from "worker_threads";
112400
112635
  import { fileURLToPath as fileURLToPath6 } from "url";
112401
- import { dirname as dirname20, join as join54 } from "path";
112636
+ import { dirname as dirname20, join as join53 } from "path";
112402
112637
  import { existsSync as existsSync45 } from "fs";
112403
112638
  async function startHealthWorker(options = {}) {
112404
112639
  const log2 = options.logger ?? defaultLogger2();
@@ -112473,7 +112708,7 @@ function defaultLogger2() {
112473
112708
  }
112474
112709
  function resolveWorkerEntry2() {
112475
112710
  const here = dirname20(fileURLToPath6(import.meta.url));
112476
- const candidates = [join54(here, "healthWorkerThread.js"), join54(here, "healthWorkerThread.ts")];
112711
+ const candidates = [join53(here, "healthWorkerThread.js"), join53(here, "healthWorkerThread.ts")];
112477
112712
  for (const candidate of candidates) {
112478
112713
  if (existsSync45(candidate)) return candidate;
112479
112714
  }
@@ -112534,11 +112769,11 @@ import {
112534
112769
  mkdirSync as mkdirSync24,
112535
112770
  statSync as statSync14,
112536
112771
  mkdtempSync as mkdtempSync5,
112537
- writeFileSync as writeFileSync15,
112772
+ writeFileSync as writeFileSync16,
112538
112773
  rmSync as rmSync13,
112539
112774
  createReadStream as createReadStream2
112540
112775
  } from "fs";
112541
- import { resolve as resolve28, dirname as dirname21, join as join55 } from "path";
112776
+ import { resolve as resolve28, dirname as dirname21, join as join54 } from "path";
112542
112777
  import { tmpdir as tmpdir6 } from "os";
112543
112778
  import { parseArgs as parseArgs2 } from "util";
112544
112779
  import crypto2 from "crypto";
@@ -112658,8 +112893,8 @@ async function prepareRenderBody(body) {
112658
112893
  }
112659
112894
  }
112660
112895
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir6();
112661
- const tempProjectDir = mkdtempSync5(join55(tempRoot, "producer-project-"));
112662
- writeFileSync15(join55(tempProjectDir, "index.html"), htmlContent, "utf-8");
112896
+ const tempProjectDir = mkdtempSync5(join54(tempRoot, "producer-project-"));
112897
+ writeFileSync16(join54(tempProjectDir, "index.html"), htmlContent, "utf-8");
112663
112898
  return {
112664
112899
  prepared: {
112665
112900
  input: {
@@ -113139,8 +113374,8 @@ var init_planHash = __esm({
113139
113374
  });
113140
113375
 
113141
113376
  // ../producer/src/services/render/stages/freezePlan.ts
113142
- import { existsSync as existsSync47, mkdirSync as mkdirSync25, readFileSync as readFileSync28, readdirSync as readdirSync15, writeFileSync as writeFileSync16 } from "fs";
113143
- import { join as join56, relative as relative9, resolve as resolve29 } from "path";
113377
+ import { existsSync as existsSync47, mkdirSync as mkdirSync25, readFileSync as readFileSync28, readdirSync as readdirSync15, writeFileSync as writeFileSync17 } from "fs";
113378
+ import { join as join55, relative as relative9, resolve as resolve29 } from "path";
113144
113379
  function stripUndefined(value) {
113145
113380
  if (Array.isArray(value)) return value.map(stripUndefined);
113146
113381
  if (value !== null && typeof value === "object") {
@@ -113161,7 +113396,7 @@ function listPlanFiles(planDir) {
113161
113396
  function walk(dir) {
113162
113397
  const entries2 = readdirSync15(dir, { withFileTypes: true });
113163
113398
  for (const entry of entries2) {
113164
- const full2 = join56(dir, entry.name);
113399
+ const full2 = join55(dir, entry.name);
113165
113400
  if (entry.isDirectory()) {
113166
113401
  walk(full2);
113167
113402
  } else if (entry.isFile()) {
@@ -113197,8 +113432,8 @@ function collectPlanAssetShas(planDir) {
113197
113432
  return { compositionHtml, assets };
113198
113433
  }
113199
113434
  function recomputePlanHashFromPlanDir(planDir) {
113200
- const planJsonPath = join56(planDir, "plan.json");
113201
- const encoderJsonPath = join56(planDir, "meta", "encoder.json");
113435
+ const planJsonPath = join55(planDir, "plan.json");
113436
+ const encoderJsonPath = join55(planDir, "meta", "encoder.json");
113202
113437
  if (!existsSync47(planJsonPath)) {
113203
113438
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
113204
113439
  }
@@ -113234,18 +113469,18 @@ async function freezePlan(input2) {
113234
113469
  if (!existsSync47(planDir)) {
113235
113470
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
113236
113471
  }
113237
- const metaDir = join56(planDir, "meta");
113472
+ const metaDir = join55(planDir, "meta");
113238
113473
  if (!existsSync47(metaDir)) mkdirSync25(metaDir, { recursive: true });
113239
- writeFileSync16(
113240
- join56(metaDir, "composition.json"),
113474
+ writeFileSync17(
113475
+ join55(metaDir, "composition.json"),
113241
113476
  `${JSON.stringify(composition, null, 2)}
113242
113477
  `,
113243
113478
  "utf-8"
113244
113479
  );
113245
113480
  const encoderForCanonical = stripUndefined(encoder);
113246
113481
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
113247
- writeFileSync16(join56(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
113248
- writeFileSync16(join56(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
113482
+ writeFileSync17(join55(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
113483
+ writeFileSync17(join55(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
113249
113484
  `, "utf-8");
113250
113485
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
113251
113486
  const planHash = computePlanHash({
@@ -113268,8 +113503,8 @@ async function freezePlan(input2) {
113268
113503
  duration: durationSeconds,
113269
113504
  hasAudio
113270
113505
  };
113271
- const planJsonPath = join56(planDir, "plan.json");
113272
- writeFileSync16(planJsonPath, `${JSON.stringify(planJson, null, 2)}
113506
+ const planJsonPath = join55(planDir, "plan.json");
113507
+ writeFileSync17(planJsonPath, `${JSON.stringify(planJson, null, 2)}
113273
113508
  `, "utf-8");
113274
113509
  return { planJsonPath, planHash };
113275
113510
  }
@@ -113391,7 +113626,7 @@ var init_runtimeEnvSnapshot = __esm({
113391
113626
 
113392
113627
  // ../producer/src/services/distributed/shared.ts
113393
113628
  import { execFile as execFileCallback } from "child_process";
113394
- import { dirname as dirname23, join as join57 } from "path";
113629
+ import { dirname as dirname23, join as join56 } from "path";
113395
113630
  import { existsSync as existsSync48, readFileSync as readFileSync29 } from "fs";
113396
113631
  import { fileURLToPath as fileURLToPath7 } from "url";
113397
113632
  import { promisify as promisify4 } from "util";
@@ -113430,7 +113665,7 @@ function readProducerVersion() {
113430
113665
  const startDir = dirname23(fileURLToPath7(import.meta.url));
113431
113666
  let current2 = startDir;
113432
113667
  for (let i2 = 0; i2 < 10; i2++) {
113433
- const candidate = join57(current2, "package.json");
113668
+ const candidate = join56(current2, "package.json");
113434
113669
  if (existsSync48(candidate)) {
113435
113670
  try {
113436
113671
  const pkg = JSON.parse(readFileSync29(candidate, "utf-8"));
@@ -113467,12 +113702,12 @@ import {
113467
113702
  existsSync as existsSync49,
113468
113703
  mkdirSync as mkdirSync26,
113469
113704
  readdirSync as readdirSync16,
113470
- renameSync as renameSync6,
113705
+ renameSync as renameSync8,
113471
113706
  rmSync as rmSync14,
113472
113707
  statSync as statSync15,
113473
- writeFileSync as writeFileSync17
113708
+ writeFileSync as writeFileSync18
113474
113709
  } from "fs";
113475
- import { join as join58, relative as relative10, sep as sep6 } from "path";
113710
+ import { join as join57, relative as relative10, sep as sep6 } from "path";
113476
113711
  function formatBytes2(bytes) {
113477
113712
  if (bytes < 1024) return `${bytes} B`;
113478
113713
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
@@ -113497,7 +113732,7 @@ function measurePlanDirBytes(planDir) {
113497
113732
  return;
113498
113733
  }
113499
113734
  for (const entry of entries2) {
113500
- const full2 = join58(dir, entry.name);
113735
+ const full2 = join57(dir, entry.name);
113501
113736
  if (entry.isDirectory()) {
113502
113737
  walk(full2);
113503
113738
  } else if (entry.isFile()) {
@@ -113665,13 +113900,13 @@ async function plan(projectDir, config, planDir) {
113665
113900
  producerConfig: config.producerConfig
113666
113901
  });
113667
113902
  const entryFile = config.entryFile ?? "index.html";
113668
- const htmlPath = join58(projectDir, entryFile);
113903
+ const htmlPath = join57(projectDir, entryFile);
113669
113904
  if (!existsSync49(htmlPath)) {
113670
113905
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
113671
113906
  }
113672
- const workDir = join58(planDir, ".plan-work");
113907
+ const workDir = join57(planDir, ".plan-work");
113673
113908
  if (!existsSync49(workDir)) mkdirSync26(workDir, { recursive: true });
113674
- const compiledDir = join58(workDir, "compiled");
113909
+ const compiledDir = join57(workDir, "compiled");
113675
113910
  mkdirSync26(compiledDir, { recursive: true });
113676
113911
  cpSync3(projectDir, compiledDir, {
113677
113912
  recursive: true,
@@ -113683,7 +113918,7 @@ async function plan(projectDir, config, planDir) {
113683
113918
  return firstSegment === void 0 || !PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(firstSegment);
113684
113919
  }
113685
113920
  });
113686
- const finalCompiledDir = join58(planDir, "compiled");
113921
+ const finalCompiledDir = join57(planDir, "compiled");
113687
113922
  const needsAlpha = config.format === "png-sequence" || config.format === "mov" || config.format === "webm";
113688
113923
  const compileResult = await runCompileStage({
113689
113924
  projectDir,
@@ -113769,16 +114004,16 @@ async function plan(projectDir, config, planDir) {
113769
114004
  if (audioResult.audioError) {
113770
114005
  log2.warn(`[Render] Audio mix failed \u2014 output will be video-only: ${audioResult.audioError}`);
113771
114006
  }
113772
- const stagedVideoFrames = join58(compiledDir, "__hyperframes_video_frames");
113773
- const videoFramesDst = join58(planDir, "video-frames");
114007
+ const stagedVideoFrames = join57(compiledDir, "__hyperframes_video_frames");
114008
+ const videoFramesDst = join57(planDir, "video-frames");
113774
114009
  if (existsSync49(videoFramesDst)) rmSync14(videoFramesDst, { recursive: true, force: true });
113775
114010
  if (existsSync49(stagedVideoFrames)) {
113776
- renameSync6(stagedVideoFrames, videoFramesDst);
114011
+ renameSync8(stagedVideoFrames, videoFramesDst);
113777
114012
  } else {
113778
114013
  mkdirSync26(videoFramesDst, { recursive: true });
113779
114014
  }
113780
114015
  if (existsSync49(finalCompiledDir)) rmSync14(finalCompiledDir, { recursive: true, force: true });
113781
- renameSync6(compiledDir, finalCompiledDir);
114016
+ renameSync8(compiledDir, finalCompiledDir);
113782
114017
  const planVideosJson = {
113783
114018
  videos: composition.videos,
113784
114019
  extracted: (extractResult.extractionResult?.extracted ?? []).map((ext) => ({
@@ -113790,15 +114025,15 @@ async function plan(projectDir, config, planDir) {
113790
114025
  metadata: ext.metadata
113791
114026
  }))
113792
114027
  };
113793
- mkdirSync26(join58(planDir, "meta"), { recursive: true });
113794
- writeFileSync17(
113795
- join58(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
114028
+ mkdirSync26(join57(planDir, "meta"), { recursive: true });
114029
+ writeFileSync18(
114030
+ join57(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
113796
114031
  JSON.stringify(planVideosJson, null, 2),
113797
114032
  "utf-8"
113798
114033
  );
113799
- const planAudioPath = join58(planDir, "audio.aac");
114034
+ const planAudioPath = join57(planDir, "audio.aac");
113800
114035
  if (audioResult.hasAudio && existsSync49(audioResult.audioOutputPath)) {
113801
- renameSync6(audioResult.audioOutputPath, planAudioPath);
114036
+ renameSync8(audioResult.audioOutputPath, planAudioPath);
113802
114037
  }
113803
114038
  const maxParallel = config.maxParallelChunks ?? DEFAULT_MAX_PARALLEL_CHUNKS;
113804
114039
  const { chunkCount, effectiveChunkSize } = resolveChunkPlan(
@@ -113941,12 +114176,12 @@ var init_plan = __esm({
113941
114176
 
113942
114177
  // ../producer/src/services/distributed/renderChunk.ts
113943
114178
  import { randomBytes as randomBytes2 } from "crypto";
113944
- import { existsSync as existsSync50, mkdirSync as mkdirSync27, readFileSync as readFileSync30, readdirSync as readdirSync17, rmSync as rmSync15, writeFileSync as writeFileSync18 } from "fs";
113945
- import { extname as extname10, join as join59 } from "path";
114179
+ import { existsSync as existsSync50, mkdirSync as mkdirSync27, readFileSync as readFileSync30, readdirSync as readdirSync17, rmSync as rmSync15, writeFileSync as writeFileSync19 } from "fs";
114180
+ import { extname as extname10, join as join58 } from "path";
113946
114181
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
113947
114182
  const result = [];
113948
114183
  for (const v2 of videos) {
113949
- const outputDir = join59(planDir, "video-frames", v2.videoId);
114184
+ const outputDir = join58(planDir, "video-frames", v2.videoId);
113950
114185
  if (!existsSync50(outputDir)) {
113951
114186
  throw new Error(
113952
114187
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v2.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
@@ -113958,7 +114193,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
113958
114193
  for (let i2 = 0; i2 < frames.length; i2++) {
113959
114194
  const frameName = frames[i2];
113960
114195
  if (!frameName) continue;
113961
- framePaths.set(i2, join59(outputDir, frameName));
114196
+ framePaths.set(i2, join58(outputDir, frameName));
113962
114197
  }
113963
114198
  result.push({
113964
114199
  videoId: v2.videoId,
@@ -113983,7 +114218,7 @@ function hashChunkOutput(outputPath, kind) {
113983
114218
  if (kind === "file") return sha256Hex(readFileSync30(outputPath));
113984
114219
  const entries2 = readdirSync17(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
113985
114220
  const lines = entries2.map(
113986
- (name) => `${name}\0${sha256Hex(readFileSync30(join59(outputPath, name)))}`
114221
+ (name) => `${name}\0${sha256Hex(readFileSync30(join58(outputPath, name)))}`
113987
114222
  );
113988
114223
  return sha256Hex(lines.join("\0"));
113989
114224
  }
@@ -114000,9 +114235,9 @@ function resolveLockedVp9CpuUsed(lockedEncoder) {
114000
114235
  async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114001
114236
  const start = Date.now();
114002
114237
  const log2 = defaultLogger;
114003
- const planJsonPath = join59(planDir, "plan.json");
114004
- const encoderJsonPath = join59(planDir, "meta", "encoder.json");
114005
- const chunksJsonPath = join59(planDir, "meta", "chunks.json");
114238
+ const planJsonPath = join58(planDir, "plan.json");
114239
+ const encoderJsonPath = join58(planDir, "meta", "encoder.json");
114240
+ const chunksJsonPath = join58(planDir, "meta", "chunks.json");
114006
114241
  for (const required of [planJsonPath, encoderJsonPath, chunksJsonPath]) {
114007
114242
  if (!existsSync50(required)) {
114008
114243
  throw new RenderChunkValidationError(
@@ -114014,7 +114249,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114014
114249
  const plan2 = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
114015
114250
  const encoder = JSON.parse(readFileSync30(encoderJsonPath, "utf-8"));
114016
114251
  const chunks = JSON.parse(readFileSync30(chunksJsonPath, "utf-8"));
114017
- const videosJsonPath = join59(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
114252
+ const videosJsonPath = join58(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
114018
114253
  let planVideos = null;
114019
114254
  if (existsSync50(videosJsonPath)) {
114020
114255
  try {
@@ -114043,7 +114278,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114043
114278
  `[renderChunk] chunk ${chunkIndex} has non-positive frame count: ${framesInChunk}`
114044
114279
  );
114045
114280
  }
114046
- const compiledDir = join59(planDir, "compiled");
114281
+ const compiledDir = join58(planDir, "compiled");
114047
114282
  if (!existsSync50(compiledDir)) {
114048
114283
  throw new RenderChunkValidationError(
114049
114284
  MISSING_PLAN_ARTIFACT,
@@ -114108,7 +114343,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114108
114343
  );
114109
114344
  const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
114110
114345
  mkdirSync27(workDir, { recursive: true });
114111
- const framesDir = join59(workDir, "captured-frames");
114346
+ const framesDir = join58(workDir, "captured-frames");
114112
114347
  mkdirSync27(framesDir, { recursive: true });
114113
114348
  const fileServer = await createFileServer2({
114114
114349
  projectDir: compiledDir,
@@ -114190,7 +114425,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114190
114425
  if (isPngSequence) {
114191
114426
  if (!existsSync50(outputChunkPath)) mkdirSync27(outputChunkPath, { recursive: true });
114192
114427
  } else {
114193
- const outDir = join59(outputChunkPath, "..");
114428
+ const outDir = join58(outputChunkPath, "..");
114194
114429
  if (!existsSync50(outDir)) mkdirSync27(outDir, { recursive: true });
114195
114430
  }
114196
114431
  const encodeStarted = Date.now();
@@ -114265,7 +114500,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
114265
114500
  producerVersion: plan2.producerVersion,
114266
114501
  ffmpegVersion
114267
114502
  };
114268
- writeFileSync18(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
114503
+ writeFileSync19(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
114269
114504
  `, "utf-8");
114270
114505
  try {
114271
114506
  rmSync15(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
@@ -114635,16 +114870,16 @@ import {
114635
114870
  readdirSync as readdirSync18,
114636
114871
  rmSync as rmSync17,
114637
114872
  statSync as statSync16,
114638
- writeFileSync as writeFileSync19
114873
+ writeFileSync as writeFileSync20
114639
114874
  } from "fs";
114640
- import { dirname as dirname24, join as join60 } from "path";
114875
+ import { dirname as dirname24, join as join59 } from "path";
114641
114876
  async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114642
114877
  const start = Date.now();
114643
114878
  const log2 = options?.logger ?? defaultLogger;
114644
114879
  const abortSignal = options?.abortSignal;
114645
114880
  const cfr = options?.cfr === true;
114646
- const planJsonPath = join60(planDir, "plan.json");
114647
- const chunksJsonPath = join60(planDir, "meta", "chunks.json");
114881
+ const planJsonPath = join59(planDir, "plan.json");
114882
+ const chunksJsonPath = join59(planDir, "meta", "chunks.json");
114648
114883
  if (!existsSync51(planJsonPath)) {
114649
114884
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
114650
114885
  }
@@ -114673,7 +114908,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114673
114908
  if (existsSync51(workDir)) rmSync17(workDir, { recursive: true, force: true });
114674
114909
  mkdirSync28(workDir, { recursive: true });
114675
114910
  try {
114676
- const concatOutputPath = join60(workDir, `concat.${plan2.dimensions.format}`);
114911
+ const concatOutputPath = join59(workDir, `concat.${plan2.dimensions.format}`);
114677
114912
  const fpsArg = fpsToFfmpegArg({
114678
114913
  num: plan2.dimensions.fpsNum,
114679
114914
  den: plan2.dimensions.fpsDen
@@ -114687,9 +114922,9 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114687
114922
  );
114688
114923
  }
114689
114924
  } else {
114690
- const concatListPath = join60(workDir, "concat-list.txt");
114925
+ const concatListPath = join59(workDir, "concat-list.txt");
114691
114926
  const concatBody = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
114692
- writeFileSync19(concatListPath, `${concatBody}
114927
+ writeFileSync20(concatListPath, `${concatBody}
114693
114928
  `, "utf-8");
114694
114929
  const concatArgs = [
114695
114930
  "-r",
@@ -114719,7 +114954,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114719
114954
  `[assemble] cfr=true is only supported for format="mp4" (got "${plan2.dimensions.format}"). Stream-copy paths for webm and mov already produce exact avg_frame_rate; cfr re-encode is not needed.`
114720
114955
  );
114721
114956
  }
114722
- const encoderJsonPath = join60(planDir, "meta", "encoder.json");
114957
+ const encoderJsonPath = join59(planDir, "meta", "encoder.json");
114723
114958
  if (!existsSync51(encoderJsonPath)) {
114724
114959
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
114725
114960
  }
@@ -114729,7 +114964,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114729
114964
  `[assemble] cfr=true is not yet supported with codec: "h265". The cfr re-encode pass uses libx264 and would silently transcode the h265 chunks. Either disable cfr or render with codec: "h264".`
114730
114965
  );
114731
114966
  }
114732
- const cfrOutputPath = join60(workDir, `cfr.${plan2.dimensions.format}`);
114967
+ const cfrOutputPath = join59(workDir, `cfr.${plan2.dimensions.format}`);
114733
114968
  const cfrArgs = [
114734
114969
  "-i",
114735
114970
  concatOutputPath,
@@ -114763,7 +114998,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114763
114998
  }
114764
114999
  let audioForMux = null;
114765
115000
  if (audioPath !== null && existsSync51(audioPath)) {
114766
- const paddedAudioPath = join60(workDir, "audio-padded.aac");
115001
+ const paddedAudioPath = join59(workDir, "audio-padded.aac");
114767
115002
  const padTrimResult = await padOrTrimAudioToVideoFrameCount({
114768
115003
  videoPath: postConcatPath,
114769
115004
  audioPath,
@@ -114779,7 +115014,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
114779
115014
  sourceDurationSeconds: padTrimResult.sourceDurationSeconds
114780
115015
  });
114781
115016
  }
114782
- const muxOutputPath = audioForMux !== null ? join60(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
115017
+ const muxOutputPath = audioForMux !== null ? join59(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
114783
115018
  if (audioForMux !== null) {
114784
115019
  const muxResult = await muxVideoWithAudio(
114785
115020
  postConcatPath,
@@ -114839,8 +115074,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
114839
115074
  throw new Error(`[assemble] png-sequence chunk has no frames: ${chunkDir}`);
114840
115075
  }
114841
115076
  for (const frame of frames) {
114842
- const dst = join60(outputPath, formatExportFrameName(globalIdx, "png"));
114843
- cpSync4(join60(chunkDir, frame), dst);
115077
+ const dst = join59(outputPath, formatExportFrameName(globalIdx, "png"));
115078
+ cpSync4(join59(chunkDir, frame), dst);
114844
115079
  globalIdx += 1;
114845
115080
  }
114846
115081
  }
@@ -114850,13 +115085,13 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
114850
115085
  );
114851
115086
  }
114852
115087
  if (audioPath !== null && existsSync51(audioPath)) {
114853
- const sidecar = join60(outputPath, "audio.aac");
115088
+ const sidecar = join59(outputPath, "audio.aac");
114854
115089
  cpSync4(audioPath, sidecar);
114855
115090
  }
114856
115091
  let fileSize = 0;
114857
115092
  for (const name of readdirSync18(outputPath)) {
114858
115093
  try {
114859
- fileSize += statSync16(join60(outputPath, name)).size;
115094
+ fileSize += statSync16(join59(outputPath, name)).size;
114860
115095
  } catch {
114861
115096
  }
114862
115097
  }
@@ -114889,7 +115124,7 @@ var init_renderConfigValidation = __esm({
114889
115124
  // ../producer/src/services/distributed/projectHash.ts
114890
115125
  import { readdirSync as readdirSync19, readFileSync as readFileSync33 } from "fs";
114891
115126
  import { createHash as createHash11 } from "crypto";
114892
- import { join as join61, relative as relative11 } from "path";
115127
+ import { join as join60, relative as relative11 } from "path";
114893
115128
  var init_projectHash = __esm({
114894
115129
  "../producer/src/services/distributed/projectHash.ts"() {
114895
115130
  "use strict";
@@ -114982,7 +115217,7 @@ import { execSync as execSync5, spawnSync as spawnSync3 } from "child_process";
114982
115217
  import { existsSync as existsSync53, mkdirSync as mkdirSync29, readdirSync as readdirSync20, rmSync as rmSync18, statSync as statSync17, utimesSync as utimesSync2 } from "fs";
114983
115218
  import { basename as basename7 } from "path";
114984
115219
  import { homedir as homedir11 } from "os";
114985
- import { join as join63 } from "path";
115220
+ import { join as join61 } from "path";
114986
115221
  async function loadPuppeteerBrowsers() {
114987
115222
  try {
114988
115223
  return await import("@puppeteer/browsers");
@@ -115160,15 +115395,15 @@ function findFromPuppeteerCache() {
115160
115395
  }
115161
115396
  for (const version2 of versions) {
115162
115397
  const candidates = [
115163
- join63(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
115164
- join63(
115398
+ join61(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
115399
+ join61(
115165
115400
  PUPPETEER_CACHE_DIR,
115166
115401
  version2,
115167
115402
  "chrome-headless-shell-mac-arm64",
115168
115403
  "chrome-headless-shell"
115169
115404
  ),
115170
- join63(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
115171
- join63(
115405
+ join61(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
115406
+ join61(
115172
115407
  PUPPETEER_CACHE_DIR,
115173
115408
  version2,
115174
115409
  "chrome-headless-shell-win64",
@@ -115373,11 +115608,11 @@ var init_manager2 = __esm({
115373
115608
  "use strict";
115374
115609
  init_errorMessage();
115375
115610
  CHROME_VERSION = "152.0.7928.2";
115376
- CACHE_ROOT_DIR = join63(homedir11(), ".cache", "hyperframes");
115377
- CACHE_DIR2 = join63(homedir11(), ".cache", "hyperframes", "chrome");
115378
- PUPPETEER_CACHE_DIR = join63(homedir11(), ".cache", "puppeteer", "chrome-headless-shell");
115379
- INSTALL_LOCK_DIR = join63(CACHE_ROOT_DIR, ".chrome.install.lock");
115380
- INSTALL_RECLAIM_LOCK_DIR = join63(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
115611
+ CACHE_ROOT_DIR = join61(homedir11(), ".cache", "hyperframes");
115612
+ CACHE_DIR2 = join61(homedir11(), ".cache", "hyperframes", "chrome");
115613
+ PUPPETEER_CACHE_DIR = join61(homedir11(), ".cache", "puppeteer", "chrome-headless-shell");
115614
+ INSTALL_LOCK_DIR = join61(CACHE_ROOT_DIR, ".chrome.install.lock");
115615
+ INSTALL_RECLAIM_LOCK_DIR = join61(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
115381
115616
  INSTALL_LOCK_TIMINGS = {
115382
115617
  staleMs: 12e4,
115383
115618
  pollMs: 200,
@@ -115409,7 +115644,7 @@ __export(manager_exports3, {
115409
115644
  });
115410
115645
  import { existsSync as existsSync54, mkdirSync as mkdirSync30 } from "fs";
115411
115646
  import { homedir as homedir12, platform as platform6, arch } from "os";
115412
- import { join as join64 } from "path";
115647
+ import { join as join63 } from "path";
115413
115648
  function isDevice(value) {
115414
115649
  return typeof value === "string" && DEVICES2.includes(value);
115415
115650
  }
@@ -115449,7 +115684,7 @@ function listAvailableProviders() {
115449
115684
  return out;
115450
115685
  }
115451
115686
  function modelPath(model = DEFAULT_MODEL2) {
115452
- return join64(MODELS_DIR2, `${model}.onnx`);
115687
+ return join63(MODELS_DIR2, `${model}.onnx`);
115453
115688
  }
115454
115689
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
115455
115690
  const dest = modelPath(model);
@@ -115467,7 +115702,7 @@ var init_manager3 = __esm({
115467
115702
  "src/background-removal/manager.ts"() {
115468
115703
  "use strict";
115469
115704
  init_download();
115470
- MODELS_DIR2 = join64(homedir12(), ".cache", "hyperframes", "background-removal", "models");
115705
+ MODELS_DIR2 = join63(homedir12(), ".cache", "hyperframes", "background-removal", "models");
115471
115706
  DEFAULT_MODEL2 = "u2net_human_seg";
115472
115707
  MODEL_URLS = {
115473
115708
  u2net_human_seg: "https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2net_human_seg.onnx"
@@ -115966,8 +116201,8 @@ __export(studioServer_exports, {
115966
116201
  });
115967
116202
  import { Hono as Hono5 } from "hono";
115968
116203
  import { streamSSE as streamSSE4 } from "hono/streaming";
115969
- import { existsSync as existsSync55, readFileSync as readFileSync34, writeFileSync as writeFileSync20, statSync as statSync18, unlinkSync as unlinkSync4 } from "fs";
115970
- import { resolve as resolve30, join as join65, basename as basename8 } from "path";
116204
+ import { existsSync as existsSync55, readFileSync as readFileSync34, writeFileSync as writeFileSync21, statSync as statSync18, unlinkSync as unlinkSync4 } from "fs";
116205
+ import { resolve as resolve30, join as join64, basename as basename8 } from "path";
115971
116206
  async function loadStudioProducer() {
115972
116207
  return isDevMode() ? await Promise.resolve().then(() => (init_src2(), src_exports2)) : await Promise.resolve().then(() => (init_src2(), src_exports2));
115973
116208
  }
@@ -116015,7 +116250,7 @@ function resolveRuntimePath() {
116015
116250
  return builtPath;
116016
116251
  }
116017
116252
  function readStudioManualEditManifestContent(projectDir) {
116018
- const manifestPath2 = join65(projectDir, STUDIO_MANUAL_EDITS_PATH2);
116253
+ const manifestPath2 = join64(projectDir, STUDIO_MANUAL_EDITS_PATH2);
116019
116254
  if (!existsSync55(manifestPath2)) return "";
116020
116255
  try {
116021
116256
  return readFileSync34(manifestPath2, "utf-8");
@@ -116121,7 +116356,7 @@ async function loadPreviewServerBuildSignature() {
116121
116356
  ]);
116122
116357
  }
116123
116358
  function rewriteWrittenToHostViewport(projectDir, written) {
116124
- const indexPath2 = join65(projectDir, "index.html");
116359
+ const indexPath2 = join64(projectDir, "index.html");
116125
116360
  if (!existsSync55(indexPath2)) return;
116126
116361
  const indexHtml = readFileSync34(indexPath2, "utf-8");
116127
116362
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
@@ -116143,7 +116378,7 @@ function rewriteWrittenToHostViewport(projectDir, written) {
116143
116378
  return match;
116144
116379
  }
116145
116380
  );
116146
- writeFileSync20(absPath, content, "utf-8");
116381
+ writeFileSync21(absPath, content, "utf-8");
116147
116382
  }
116148
116383
  }
116149
116384
  function createStudioServer(options) {
@@ -116181,8 +116416,8 @@ function createStudioServer(options) {
116181
116416
  const { injectDeterministicFontFaces: injectDeterministicFontFaces2 } = await Promise.resolve().then(() => (init_deterministicFonts(), deterministicFonts_exports));
116182
116417
  const { prepareAnimatedGifInputs: prepareAnimatedGifInputs2 } = await Promise.resolve().then(() => (init_animatedGifPrep(), animatedGifPrep_exports));
116183
116418
  const { downloadToTemp: downloadToTemp2 } = await Promise.resolve().then(() => (init_urlDownloader2(), urlDownloader_exports));
116184
- const gifOutputDir = join65(project2.dir, ".hyperframes", "prepared-assets", "gif");
116185
- const gifDownloadDir = join65(project2.dir, ".hyperframes", "prepared-assets", "downloads");
116419
+ const gifOutputDir = join64(project2.dir, ".hyperframes", "prepared-assets", "gif");
116420
+ const gifDownloadDir = join64(project2.dir, ".hyperframes", "prepared-assets", "downloads");
116186
116421
  const prepared = await prepareAnimatedGifInputs2(html, {
116187
116422
  projectDir: project2.dir,
116188
116423
  downloadDir: gifDownloadDir,
@@ -116203,7 +116438,7 @@ function createStudioServer(options) {
116203
116438
  return await lintHyperframeHtml2(html, opts);
116204
116439
  },
116205
116440
  runtimeUrl: "/api/runtime.js",
116206
- rendersDir: () => join65(projectDir, "renders"),
116441
+ rendersDir: () => join64(projectDir, "renders"),
116207
116442
  startRender(opts) {
116208
116443
  const abortController = new AbortController();
116209
116444
  const state = {
@@ -116268,7 +116503,7 @@ function createStudioServer(options) {
116268
116503
  state.status = "complete";
116269
116504
  state.progress = 100;
116270
116505
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
116271
- writeFileSync20(
116506
+ writeFileSync21(
116272
116507
  metaPath,
116273
116508
  JSON.stringify({ status: "complete", durationMs: Date.now() - startTime })
116274
116509
  );
@@ -116283,7 +116518,7 @@ function createStudioServer(options) {
116283
116518
  emitStudioRenderError(opts, Date.now() - startTime, state.stage, err, renderJob);
116284
116519
  try {
116285
116520
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
116286
- writeFileSync20(metaPath, JSON.stringify({ status: "failed" }));
116521
+ writeFileSync21(metaPath, JSON.stringify({ status: "failed" }));
116287
116522
  } catch {
116288
116523
  }
116289
116524
  }
@@ -116577,7 +116812,7 @@ __export(preview_exports, {
116577
116812
  });
116578
116813
  import { spawn as spawn13 } from "child_process";
116579
116814
  import { existsSync as existsSync56, lstatSync as lstatSync4, symlinkSync as symlinkSync3, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync31 } from "fs";
116580
- import { resolve as resolve31, dirname as dirname25, basename as basename9, join as join66 } from "path";
116815
+ import { resolve as resolve31, dirname as dirname25, basename as basename9, join as join65 } from "path";
116581
116816
  import { fileURLToPath as fileURLToPath8 } from "url";
116582
116817
  import { createRequire as createRequire2 } from "module";
116583
116818
  function previewBaseUrl(port, host = "127.0.0.1") {
@@ -116883,7 +117118,7 @@ function printStudioSummary(projectName, url, opts = {}) {
116883
117118
  console.log();
116884
117119
  }
116885
117120
  function linkProjectIntoStudioData(dir, projectsDir, projectName) {
116886
- const symlinkPath = join66(projectsDir, projectName);
117121
+ const symlinkPath = join65(projectsDir, projectName);
116887
117122
  mkdirSync31(projectsDir, { recursive: true });
116888
117123
  let createdSymlink = false;
116889
117124
  if (dir !== symlinkPath) {
@@ -116946,13 +117181,13 @@ function attachStudioReadyHandler(child, spinner, projectName, options) {
116946
117181
  async function runDevMode(dir, options) {
116947
117182
  const thisFile = fileURLToPath8(import.meta.url);
116948
117183
  const repoRoot2 = resolve31(dirname25(thisFile), "..", "..", "..", "..");
116949
- const projectsDir = join66(repoRoot2, "packages", "studio", "data", "projects");
117184
+ const projectsDir = join65(repoRoot2, "packages", "studio", "data", "projects");
116950
117185
  const pName = options?.projectName ?? basename9(dir);
116951
117186
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
116952
117187
  ge(c.bold("hyperframes preview"));
116953
117188
  const s2 = ft();
116954
117189
  s2.start("Starting studio...");
116955
- const studioPkgDir = join66(repoRoot2, "packages", "studio");
117190
+ const studioPkgDir = join65(repoRoot2, "packages", "studio");
116956
117191
  const child = spawn13("bun", ["run", "dev"], {
116957
117192
  cwd: studioPkgDir,
116958
117193
  stdio: ["ignore", "pipe", "pipe"]
@@ -116964,7 +117199,7 @@ async function runDevMode(dir, options) {
116964
117199
  }
116965
117200
  function hasLocalStudio(dir) {
116966
117201
  try {
116967
- const req = createRequire2(join66(dir, "package.json"));
117202
+ const req = createRequire2(join65(dir, "package.json"));
116968
117203
  req.resolve("@hyperframes/studio/package.json");
116969
117204
  return true;
116970
117205
  } catch {
@@ -116972,10 +117207,10 @@ function hasLocalStudio(dir) {
116972
117207
  }
116973
117208
  }
116974
117209
  async function runLocalStudioMode(dir, options) {
116975
- const req = createRequire2(join66(dir, "package.json"));
117210
+ const req = createRequire2(join65(dir, "package.json"));
116976
117211
  const studioPkgPath = dirname25(req.resolve("@hyperframes/studio/package.json"));
116977
117212
  const pName = options?.projectName ?? basename9(dir);
116978
- const projectsDir = join66(studioPkgPath, "data", "projects");
117213
+ const projectsDir = join65(studioPkgPath, "data", "projects");
116979
117214
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
116980
117215
  ge(c.bold("hyperframes preview") + c.dim(" (local studio)"));
116981
117216
  const s2 = ft();
@@ -117334,11 +117569,11 @@ import {
117334
117569
  mkdirSync as mkdirSync33,
117335
117570
  copyFileSync as copyFileSync7,
117336
117571
  cpSync as cpSync5,
117337
- writeFileSync as writeFileSync21,
117572
+ writeFileSync as writeFileSync23,
117338
117573
  readFileSync as readFileSync35,
117339
117574
  readdirSync as readdirSync21
117340
117575
  } from "fs";
117341
- import { resolve as resolve33, basename as basename10, join as join67, dirname as dirname26 } from "path";
117576
+ import { resolve as resolve33, basename as basename10, join as join66, dirname as dirname26 } from "path";
117342
117577
  import { fileURLToPath as fileURLToPath9 } from "url";
117343
117578
  import { execFileSync as execFileSync7, spawn as spawn14 } from "child_process";
117344
117579
  function probeVideo(filePath) {
@@ -117451,7 +117686,7 @@ function buildPackageScripts() {
117451
117686
  function writeDefaultPackageJson(destDir, projectName) {
117452
117687
  const packageJsonPath = resolve33(destDir, "package.json");
117453
117688
  if (existsSync57(packageJsonPath)) return;
117454
- writeFileSync21(
117689
+ writeFileSync23(
117455
117690
  packageJsonPath,
117456
117691
  `${JSON.stringify(
117457
117692
  {
@@ -117472,7 +117707,7 @@ function listHtmlFiles(dir) {
117472
117707
  const ignoredDirs = /* @__PURE__ */ new Set([".git", "dist", "node_modules"]);
117473
117708
  function walk(currentDir) {
117474
117709
  for (const entry of readdirSync21(currentDir, { withFileTypes: true })) {
117475
- const entryPath = join67(currentDir, entry.name);
117710
+ const entryPath = join66(currentDir, entry.name);
117476
117711
  if (entry.isDirectory()) {
117477
117712
  if (!ignoredDirs.has(entry.name)) walk(entryPath);
117478
117713
  continue;
@@ -117513,11 +117748,11 @@ ${html}`;
117513
117748
  function writeTailwindSupport(destDir) {
117514
117749
  for (const file of listHtmlFiles(destDir)) {
117515
117750
  const html = readFileSync35(file, "utf-8");
117516
- writeFileSync21(file, injectTailwindBrowserScript(html), "utf-8");
117751
+ writeFileSync23(file, injectTailwindBrowserScript(html), "utf-8");
117517
117752
  }
117518
117753
  }
117519
117754
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
117520
- const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join67(e3.parentPath, e3.name));
117755
+ const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join66(e3.parentPath, e3.name));
117521
117756
  for (const file of htmlFiles) {
117522
117757
  let content = readFileSync35(file, "utf-8");
117523
117758
  if (videoFilename) {
@@ -117530,7 +117765,7 @@ function patchVideoSrc(dir, videoFilename, durationSeconds) {
117530
117765
  }
117531
117766
  const dur = durationSeconds ? String(Math.round(durationSeconds * 100) / 100) : "10";
117532
117767
  content = content.replaceAll("__VIDEO_DURATION__", dur);
117533
- writeFileSync21(file, content, "utf-8");
117768
+ writeFileSync23(file, content, "utf-8");
117534
117769
  }
117535
117770
  }
117536
117771
  async function patchTranscript(dir, transcriptPath) {
@@ -117666,13 +117901,13 @@ function applyResolutionPreset(destDir, resolution) {
117666
117901
  html = html.replace(viewportRe, `$1width=${width}, height=${height}`);
117667
117902
  changed = true;
117668
117903
  }
117669
- if (changed) writeFileSync21(file, html, "utf-8");
117904
+ if (changed) writeFileSync23(file, html, "utf-8");
117670
117905
  }
117671
117906
  }
117672
117907
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
117673
117908
  mkdirSync33(destDir, { recursive: true });
117674
117909
  const templateDir = getStaticTemplateDir(templateId);
117675
- if (existsSync57(join67(templateDir, "index.html"))) {
117910
+ if (existsSync57(join66(templateDir, "index.html"))) {
117676
117911
  cpSync5(templateDir, destDir, { recursive: true });
117677
117912
  } else {
117678
117913
  await fetchRemoteTemplate(templateId, destDir);
@@ -117680,7 +117915,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
117680
117915
  patchVideoSrc(destDir, localVideoName, durationSeconds);
117681
117916
  if (tailwind) writeTailwindSupport(destDir);
117682
117917
  if (resolution) applyResolutionPreset(destDir, resolution);
117683
- writeFileSync21(
117918
+ writeFileSync23(
117684
117919
  resolve33(destDir, "meta.json"),
117685
117920
  JSON.stringify(
117686
117921
  {
@@ -117701,7 +117936,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
117701
117936
  const sharedDir = getSharedTemplateDir();
117702
117937
  if (existsSync57(sharedDir)) {
117703
117938
  for (const entry of readdirSync21(sharedDir, { withFileTypes: true })) {
117704
- const src = join67(sharedDir, entry.name);
117939
+ const src = join66(sharedDir, entry.name);
117705
117940
  const dest = resolve33(destDir, entry.name);
117706
117941
  if (entry.isFile() || entry.isSymbolicLink()) {
117707
117942
  copyFileSync7(src, dest);
@@ -119212,7 +119447,7 @@ var init_present = __esm({
119212
119447
  });
119213
119448
 
119214
119449
  // src/utils/publishProject.ts
119215
- import { basename as basename11, dirname as dirname28, join as join68, posix as posix5, relative as relative13, resolve as resolve39 } from "path";
119450
+ import { basename as basename11, dirname as dirname28, join as join67, posix as posix5, relative as relative13, resolve as resolve39 } from "path";
119216
119451
  import { existsSync as existsSync63, readdirSync as readdirSync23, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
119217
119452
  import AdmZip from "adm-zip";
119218
119453
  function isRecord4(value) {
@@ -119313,7 +119548,7 @@ function shouldIgnoreSegment(segment) {
119313
119548
  function collectProjectFiles(rootDir, currentDir, paths) {
119314
119549
  for (const entry of readdirSync23(currentDir, { withFileTypes: true })) {
119315
119550
  if (shouldIgnoreSegment(entry.name)) continue;
119316
- const absolutePath = join68(currentDir, entry.name);
119551
+ const absolutePath = join67(currentDir, entry.name);
119317
119552
  const relativePath = relative13(rootDir, absolutePath).replaceAll("\\", "/");
119318
119553
  if (!relativePath) continue;
119319
119554
  if (entry.isDirectory()) {
@@ -119443,7 +119678,7 @@ function createPublishArchive(projectDir) {
119443
119678
  }
119444
119679
  const fileContents = /* @__PURE__ */ new Map();
119445
119680
  for (const filePath of filePaths) {
119446
- fileContents.set(filePath, readFileSync38(join68(absProjectDir, filePath)));
119681
+ fileContents.set(filePath, readFileSync38(join67(absProjectDir, filePath)));
119447
119682
  }
119448
119683
  localizeExternalAssets(absProjectDir, fileContents);
119449
119684
  const archive = new AdmZip();
@@ -119576,7 +119811,7 @@ __export(publish_exports, {
119576
119811
  });
119577
119812
  import { resolve as resolve40 } from "path";
119578
119813
  import { existsSync as existsSync64 } from "fs";
119579
- import { join as join69 } from "path";
119814
+ import { join as join68 } from "path";
119580
119815
  var examples8, publish_default;
119581
119816
  var init_publish = __esm({
119582
119817
  "src/commands/publish.ts"() {
@@ -119615,7 +119850,7 @@ var init_publish = __esm({
119615
119850
  async run({ args }) {
119616
119851
  const rawArg = args.dir;
119617
119852
  const dir = resolve40(rawArg ?? ".");
119618
- const indexPath2 = join69(dir, "index.html");
119853
+ const indexPath2 = join68(dir, "index.html");
119619
119854
  if (existsSync64(indexPath2)) {
119620
119855
  const lintResult = await lintProject(dir);
119621
119856
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
@@ -119821,7 +120056,7 @@ var init_variables = __esm({
119821
120056
 
119822
120057
  // src/utils/compositionFps.ts
119823
120058
  import { readFileSync as readFileSync40 } from "fs";
119824
- import { join as join70 } from "path";
120059
+ import { join as join69 } from "path";
119825
120060
  function readCompositionFps(html) {
119826
120061
  let doc;
119827
120062
  try {
@@ -119839,7 +120074,7 @@ function readCompositionFps(html) {
119839
120074
  function readAllowedCompositionFpsFromDir(projectDir, allowed) {
119840
120075
  let html;
119841
120076
  try {
119842
- html = readFileSync40(join70(projectDir, "index.html"), "utf8");
120077
+ html = readFileSync40(join69(projectDir, "index.html"), "utf8");
119843
120078
  } catch {
119844
120079
  return null;
119845
120080
  }
@@ -120489,8 +120724,8 @@ __export(batchRender_exports, {
120489
120724
  resolveOutputTemplate: () => resolveOutputTemplate,
120490
120725
  runBatchRender: () => runBatchRender
120491
120726
  });
120492
- import { mkdirSync as mkdirSync34, readFileSync as readFileSync43, writeFileSync as writeFileSync23 } from "fs";
120493
- import { dirname as dirname29, join as join71, resolve as resolve43, sep as sep8 } from "path";
120727
+ import { mkdirSync as mkdirSync34, readFileSync as readFileSync43, writeFileSync as writeFileSync24 } from "fs";
120728
+ import { dirname as dirname29, join as join70, resolve as resolve43, sep as sep8 } from "path";
120494
120729
  function isRecord5(value) {
120495
120730
  return value !== null && typeof value === "object" && !Array.isArray(value);
120496
120731
  }
@@ -120626,7 +120861,7 @@ function prepareBatchRender(options) {
120626
120861
  variables,
120627
120862
  outputPath: resolve43(resolveOutputTemplate(options.outputTemplate, variables, index))
120628
120863
  }));
120629
- const manifestPath2 = join71(
120864
+ const manifestPath2 = join70(
120630
120865
  commonOutputDirectory(rows.map((row) => row.outputPath)),
120631
120866
  "manifest.json"
120632
120867
  );
@@ -120675,7 +120910,7 @@ function summarizeManifest(manifest) {
120675
120910
  function writeManifest(manifest) {
120676
120911
  summarizeManifest(manifest);
120677
120912
  mkdirSync34(dirname29(manifest.manifestPath), { recursive: true });
120678
- writeFileSync23(manifest.manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
120913
+ writeFileSync24(manifest.manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
120679
120914
  }
120680
120915
  function emitJsonEvent(event, json) {
120681
120916
  if (json) console.log(JSON.stringify(event));
@@ -120831,15 +121066,16 @@ var init_batchRender = __esm({
120831
121066
  // src/commands/render.ts
120832
121067
  var render_exports = {};
120833
121068
  __export(render_exports, {
121069
+ __resetDeParallelRouterTrialStateForTests: () => __resetDeParallelRouterTrialStateForTests,
120834
121070
  checkRenderResolutionPreflight: () => checkRenderResolutionPreflight,
120835
121071
  default: () => render_default,
120836
121072
  examples: () => examples9,
120837
121073
  renderLocal: () => renderLocal,
120838
121074
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
120839
121075
  });
120840
- import { mkdirSync as mkdirSync35, readdirSync as readdirSync24, readFileSync as readFileSync44, statSync as statSync20, writeFileSync as writeFileSync24, rmSync as rmSync19 } from "fs";
121076
+ import { mkdirSync as mkdirSync35, readdirSync as readdirSync24, readFileSync as readFileSync44, statSync as statSync20, writeFileSync as writeFileSync25, rmSync as rmSync19 } from "fs";
120841
121077
  import { cpus as cpus4, freemem as freemem5, tmpdir as tmpdir7 } from "os";
120842
- import { resolve as resolve44, dirname as dirname30, join as join73, basename as basename12 } from "path";
121078
+ import { resolve as resolve44, dirname as dirname30, join as join71, basename as basename12 } from "path";
120843
121079
  import { execFileSync as execFileSync10, spawn as spawn15 } from "child_process";
120844
121080
  function formatFpsParseError(input2, reason) {
120845
121081
  switch (reason) {
@@ -120931,9 +121167,9 @@ function ensureDockerImage(version2, platform10, quiet) {
120931
121167
  }
120932
121168
  if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform10})...`));
120933
121169
  const dockerfilePath = resolveDockerfilePath();
120934
- const tmpDir = join73(tmpdir7(), `hyperframes-docker-${Date.now()}`);
121170
+ const tmpDir = join71(tmpdir7(), `hyperframes-docker-${Date.now()}`);
120935
121171
  mkdirSync35(tmpDir, { recursive: true });
120936
- writeFileSync24(join73(tmpDir, "Dockerfile"), readFileSync44(dockerfilePath));
121172
+ writeFileSync25(join71(tmpDir, "Dockerfile"), readFileSync44(dockerfilePath));
120937
121173
  const targetArch = platform10 === "linux/arm64" ? "arm64" : "amd64";
120938
121174
  try {
120939
121175
  execFileSync10(
@@ -121095,6 +121331,10 @@ async function renderLocal(projectDir, outputPath, options) {
121095
121331
  process.env.PRODUCER_HEADLESS_SHELL_PATH = preflight.browser.executablePath;
121096
121332
  }
121097
121333
  const producer = await loadProducer();
121334
+ const deParallelRouterTrialArmed = maybeEnableDeParallelRouterTrial(
121335
+ options.quiet,
121336
+ options.enableDeParallelRouterTrial === true
121337
+ );
121098
121338
  const startTime = Date.now();
121099
121339
  const logger = createRenderTelemetryLogger(
121100
121340
  producer.createConsoleLogger?.(options.debug ? "debug" : "info") ?? createNoopProducerLogger()
@@ -121129,6 +121369,7 @@ async function renderLocal(projectDir, outputPath, options) {
121129
121369
  try {
121130
121370
  await producer.executeRenderJob(job, projectDir, outputPath, onProgress);
121131
121371
  } catch (error) {
121372
+ maybeConsumeDeParallelRouterTrial(deParallelRouterTrialArmed, job, options.quiet);
121132
121373
  handleRenderError(
121133
121374
  error,
121134
121375
  options,
@@ -121139,6 +121380,7 @@ async function renderLocal(projectDir, outputPath, options) {
121139
121380
  job
121140
121381
  );
121141
121382
  }
121383
+ maybeConsumeDeParallelRouterTrial(deParallelRouterTrialArmed, job, options.quiet);
121142
121384
  const elapsed = Date.now() - startTime;
121143
121385
  trackRenderMetrics(job, elapsed, options, false);
121144
121386
  printRenderComplete(
@@ -121253,6 +121495,86 @@ function createNoopProducerLogger() {
121253
121495
  }
121254
121496
  };
121255
121497
  }
121498
+ function __resetDeParallelRouterTrialStateForTests() {
121499
+ deParallelRouterTrialManagedByUs = false;
121500
+ deParallelRouterTrialFiredThisProcess = false;
121501
+ }
121502
+ function isDeParallelRouterTrialBlocked(config) {
121503
+ const overRenderCap = (config.deParallelRouterTrialRenderCount ?? 0) >= DE_PARALLEL_ROUTER_TRIAL_MAX_RENDERS;
121504
+ return deParallelRouterTrialFiredThisProcess || Boolean(config.deParallelRouterTrialFired) || overRenderCap || !config.telemetryEnabled || !shouldTrack() || // cli.ts shows the first-run telemetry disclosure via a fire-and-forget,
121505
+ // unawaited dynamic import — there's no guarantee it has printed before
121506
+ // this render command reaches this point. Requiring telemetryNoticeShown
121507
+ // means the trial simply never offers itself on a fresh install's very
121508
+ // first invocation (before the disclosure is guaranteed to have run at
121509
+ // least once), rather than racing an experimental opt-in message against
121510
+ // the disclosure it depends on (review finding).
121511
+ !config.telemetryNoticeShown;
121512
+ }
121513
+ function stopManagingDeParallelRouterTrial() {
121514
+ if (!deParallelRouterTrialManagedByUs) return;
121515
+ delete process.env.HF_DE_PARALLEL_ROUTER;
121516
+ deParallelRouterTrialManagedByUs = false;
121517
+ }
121518
+ function maybeEnableDeParallelRouterTrial(quiet, enabled) {
121519
+ if (!enabled) return false;
121520
+ if (deParallelRouterTrialFiredThisProcess) {
121521
+ stopManagingDeParallelRouterTrial();
121522
+ return false;
121523
+ }
121524
+ const userSetIt = process.env.HF_DE_PARALLEL_ROUTER !== void 0 && !deParallelRouterTrialManagedByUs;
121525
+ if (userSetIt) return false;
121526
+ if (isDeParallelRouterTrialBlocked(readConfigFresh())) {
121527
+ stopManagingDeParallelRouterTrial();
121528
+ return false;
121529
+ }
121530
+ if (deParallelRouterTrialManagedByUs) return true;
121531
+ deParallelRouterTrialManagedByUs = true;
121532
+ process.env.HF_DE_PARALLEL_ROUTER = "true";
121533
+ if (!quiet) {
121534
+ console.log(
121535
+ c.dim(
121536
+ " Trying the experimental parallel drawElement capture path for this install (disabled automatically if it ever needs to fall back; opt out anytime: HF_DE_PARALLEL_ROUTER=false)"
121537
+ )
121538
+ );
121539
+ }
121540
+ return true;
121541
+ }
121542
+ function resolveDeParallelRouterOutcome(job) {
121543
+ const outcome = job.perfSummary?.drawElement?.parallelRouter ?? job.errorDetails?.observability?.capture.deParallelRouter;
121544
+ return outcome === "none" ? void 0 : outcome;
121545
+ }
121546
+ function persistDeParallelRouterTrialFired() {
121547
+ const MAX_ATTEMPTS = 3;
121548
+ for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
121549
+ const config = readConfigFresh();
121550
+ if (config.deParallelRouterTrialFired) return true;
121551
+ config.deParallelRouterTrialFired = true;
121552
+ if (!writeConfig(config)) return false;
121553
+ }
121554
+ return Boolean(readConfigFresh().deParallelRouterTrialFired);
121555
+ }
121556
+ function maybeConsumeDeParallelRouterTrial(trialArmed, job, quiet) {
121557
+ if (!trialArmed) return;
121558
+ const outcome = resolveDeParallelRouterOutcome(job);
121559
+ if (outcome === void 0) return;
121560
+ const config = readConfigFresh();
121561
+ const renderCount = (config.deParallelRouterTrialRenderCount ?? 0) + 1;
121562
+ config.deParallelRouterTrialRenderCount = renderCount;
121563
+ const fired = outcome === "reverted" || renderCount >= DE_PARALLEL_ROUTER_TRIAL_MAX_RENDERS;
121564
+ if (fired) {
121565
+ config.deParallelRouterTrialFired = true;
121566
+ deParallelRouterTrialFiredThisProcess = true;
121567
+ stopManagingDeParallelRouterTrial();
121568
+ }
121569
+ writeConfig(config);
121570
+ if (fired && !persistDeParallelRouterTrialFired() && !quiet) {
121571
+ console.warn(
121572
+ c.warn(
121573
+ " Could not persist the parallel drawElement trial's off-switch to ~/.hyperframes/config.json (unwritable?). The experiment stays off for this process; future runs may retry it. Set HF_DE_PARALLEL_ROUTER=false to opt out."
121574
+ )
121575
+ );
121576
+ }
121577
+ }
121256
121578
  function handleRenderError(error, options, startTime, docker, hint2, failedStage, job) {
121257
121579
  const message = normalizeErrorMessage(error);
121258
121580
  trackRenderError({
@@ -121363,7 +121685,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
121363
121685
  for (const entry of readdirSync24(outputPath, { withFileTypes: true })) {
121364
121686
  if (!entry.isFile()) continue;
121365
121687
  try {
121366
- total += statSync20(join73(outputPath, entry.name)).size;
121688
+ total += statSync20(join71(outputPath, entry.name)).size;
121367
121689
  } catch {
121368
121690
  }
121369
121691
  }
@@ -121383,7 +121705,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
121383
121705
  console.log(c.success("\u25C7") + " " + c.accent(outputPath));
121384
121706
  console.log(" " + c.bold(fileSize) + c.dim(" \xB7 " + detail));
121385
121707
  }
121386
- var examples9, VALID_QUALITY, RENDER_FORMATS, VALID_FORMAT, RENDER_FORMAT_LABEL, FORMAT_EXT, CPU_CORE_COUNT, render_default, DOCKER_IMAGE_PREFIX;
121708
+ var examples9, VALID_QUALITY, RENDER_FORMATS, VALID_FORMAT, RENDER_FORMAT_LABEL, FORMAT_EXT, CPU_CORE_COUNT, render_default, DOCKER_IMAGE_PREFIX, DE_PARALLEL_ROUTER_TRIAL_MAX_RENDERS, deParallelRouterTrialManagedByUs, deParallelRouterTrialFiredThisProcess;
121387
121709
  var init_render = __esm({
121388
121710
  "src/commands/render.ts"() {
121389
121711
  "use strict";
@@ -121400,6 +121722,8 @@ var init_render = __esm({
121400
121722
  init_progress();
121401
121723
  init_events();
121402
121724
  init_feedback();
121725
+ init_config();
121726
+ init_client();
121403
121727
  init_renderObservability();
121404
121728
  init_skill();
121405
121729
  init_system();
@@ -121797,8 +122121,8 @@ var init_render = __esm({
121797
122121
  const now = /* @__PURE__ */ new Date();
121798
122122
  const datePart = now.toISOString().slice(0, 10);
121799
122123
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
121800
- const batchOutputTemplate = args.output ? args.output : join73(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
121801
- const outputPath = args.output ? resolve44(args.output) : join73(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
122124
+ const batchOutputTemplate = args.output ? args.output : join71(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
122125
+ const outputPath = args.output ? resolve44(args.output) : join71(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
121802
122126
  if (!batchPath) mkdirSync35(dirname30(outputPath), { recursive: true });
121803
122127
  const useDocker = args.docker ?? false;
121804
122128
  const useGpu = args.gpu ?? false;
@@ -122014,7 +122338,11 @@ var init_render = __esm({
122014
122338
  debug,
122015
122339
  exitAfterComplete: false,
122016
122340
  throwOnError: true,
122017
- skipFeedback: true
122341
+ skipFeedback: true,
122342
+ // Sequential batch rows may trial; real concurrent workers
122343
+ // (batchConcurrency > 1) can't safely share the trial's process-wide
122344
+ // env var/flags — see enableDeParallelRouterTrial's own doc comment.
122345
+ enableDeParallelRouterTrial: batchConcurrency <= 1
122018
122346
  };
122019
122347
  const manifest = await batchModule.runBatchRender({
122020
122348
  prepared: preparedBatch,
@@ -122091,12 +122419,18 @@ var init_render = __esm({
122091
122419
  pageNavigationTimeoutMs,
122092
122420
  protocolTimeout,
122093
122421
  playerReadyTimeout,
122094
- exitAfterComplete: true
122422
+ exitAfterComplete: true,
122423
+ // The single top-level CLI render is sequential by construction — the
122424
+ // one place the trial's process-wide state is unconditionally safe.
122425
+ enableDeParallelRouterTrial: true
122095
122426
  });
122096
122427
  }
122097
122428
  }
122098
122429
  });
122099
122430
  DOCKER_IMAGE_PREFIX = "hyperframes-renderer";
122431
+ DE_PARALLEL_ROUTER_TRIAL_MAX_RENDERS = 25;
122432
+ deParallelRouterTrialManagedByUs = false;
122433
+ deParallelRouterTrialFiredThisProcess = false;
122100
122434
  }
122101
122435
  });
122102
122436
 
@@ -122695,7 +123029,7 @@ var init_motionAudit = __esm({
122695
123029
 
122696
123030
  // src/utils/motionSpec.ts
122697
123031
  import { existsSync as existsSync67, readFileSync as readFileSync45, readdirSync as readdirSync25 } from "fs";
122698
- import { basename as basename13, join as join74 } from "path";
123032
+ import { basename as basename13, join as join73 } from "path";
122699
123033
  function isObject2(value) {
122700
123034
  return typeof value === "object" && value !== null && !Array.isArray(value);
122701
123035
  }
@@ -122741,7 +123075,7 @@ function findMotionSpec(projectDir) {
122741
123075
  const entries2 = readdirSync25(projectDir);
122742
123076
  const sidecars = entries2.filter((name) => name.endsWith(".motion.json")).sort();
122743
123077
  if (!sidecars[0]) return null;
122744
- if (sidecars.length === 1) return join74(projectDir, sidecars[0]);
123078
+ if (sidecars.length === 1) return join73(projectDir, sidecars[0]);
122745
123079
  const htmlBases = new Set(
122746
123080
  entries2.filter((name) => name.endsWith(".html")).map((name) => basename13(name, ".html"))
122747
123081
  );
@@ -122751,7 +123085,7 @@ function findMotionSpec(projectDir) {
122751
123085
  `ambiguous motion sidecars in ${projectDir}: ${matched.join(", ")} each match a composition \u2014 remove the sidecars you do not need, or use one composition per project`
122752
123086
  );
122753
123087
  }
122754
- return join74(projectDir, matched[0] ?? sidecars[0]);
123088
+ return join73(projectDir, matched[0] ?? sidecars[0]);
122755
123089
  }
122756
123090
  function readMotionSpec(path2) {
122757
123091
  let raw;
@@ -123110,7 +123444,7 @@ __export(layout_exports, {
123110
123444
  parseAt: () => parseAt
123111
123445
  });
123112
123446
  import { existsSync as existsSync68, readFileSync as readFileSync46 } from "fs";
123113
- import { dirname as dirname31, join as join75 } from "path";
123447
+ import { dirname as dirname31, join as join74 } from "path";
123114
123448
  import { fileURLToPath as fileURLToPath11 } from "url";
123115
123449
  function buildMotionSampleTimes(duration) {
123116
123450
  if (!Number.isFinite(duration) || duration <= 0) return [];
@@ -123252,7 +123586,7 @@ async function runLayoutAudit(projectDir, opts) {
123252
123586
  }
123253
123587
  }
123254
123588
  function loadBrowserScript(name) {
123255
- const candidates = [join75(__dirname2, name), join75(__dirname2, "commands", name)];
123589
+ const candidates = [join74(__dirname2, name), join74(__dirname2, "commands", name)];
123256
123590
  for (const candidate of candidates) {
123257
123591
  if (existsSync68(candidate)) return readFileSync46(candidate, "utf-8");
123258
123592
  }
@@ -123649,7 +123983,7 @@ __export(validate_exports, {
123649
123983
  });
123650
123984
  import { existsSync as existsSync69, mkdtempSync as mkdtempSync6, readFileSync as readFileSync47, rmSync as rmSync20 } from "fs";
123651
123985
  import { tmpdir as tmpdir8 } from "os";
123652
- import { join as join76, dirname as dirname32 } from "path";
123986
+ import { join as join75, dirname as dirname32 } from "path";
123653
123987
  import { fileURLToPath as fileURLToPath12 } from "url";
123654
123988
  function resolveNavigationTimeoutMs(optTimeout) {
123655
123989
  return Math.max(NAV_TIMEOUT_FLOOR_MS, optTimeout ?? 0);
@@ -123794,8 +124128,8 @@ async function runContrastAudit(page) {
123794
124128
  }
123795
124129
  function loadContrastAuditScript() {
123796
124130
  const candidates = [
123797
- join76(__dirname3, "contrast-audit.browser.js"),
123798
- join76(__dirname3, "commands", "contrast-audit.browser.js")
124131
+ join75(__dirname3, "contrast-audit.browser.js"),
124132
+ join75(__dirname3, "commands", "contrast-audit.browser.js")
123799
124133
  ];
123800
124134
  for (const candidate of candidates) {
123801
124135
  if (existsSync69(candidate)) return readFileSync47(candidate, "utf-8");
@@ -123810,7 +124144,7 @@ async function localizeRemoteAssets(html) {
123810
124144
  try {
123811
124145
  const { loadProducer: loadProducer2 } = await Promise.resolve().then(() => (init_producer(), producer_exports));
123812
124146
  const { localizeRemoteMediaSources: localizeRemoteMediaSources2, localizeRemoteImageSources: localizeRemoteImageSources2, localizeRemoteFontFaces: localizeRemoteFontFaces2 } = await loadProducer2();
123813
- dir = mkdtempSync6(join76(tmpdir8(), "hf-validate-assets-"));
124147
+ dir = mkdtempSync6(join75(tmpdir8(), "hf-validate-assets-"));
123814
124148
  const assetDir = dir;
123815
124149
  const media = await localizeRemoteMediaSources2(html, assetDir);
123816
124150
  const images = await localizeRemoteImageSources2(media.html, assetDir);
@@ -124070,8 +124404,8 @@ __export(checkBrowser_exports, {
124070
124404
  captureOverviewShot: () => captureOverviewShot,
124071
124405
  runBrowserCheck: () => runBrowserCheck
124072
124406
  });
124073
- import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync25 } from "fs";
124074
- import { join as join77 } from "path";
124407
+ import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync26 } from "fs";
124408
+ import { join as join76 } from "path";
124075
124409
  async function runBrowserCheck(project, options, motion, runGrid) {
124076
124410
  const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
124077
124411
  const html = await bundleToSingleHtml2(project.dir);
@@ -124126,7 +124460,7 @@ async function captureFindingCrops(project, options, requests) {
124126
124460
  chromeBrowser = session.browser;
124127
124461
  const page = session.page;
124128
124462
  await waitForPreferredSeekTarget(page);
124129
- const snapshotDir = join77(project.dir, "snapshots");
124463
+ const snapshotDir = join76(project.dir, "snapshots");
124130
124464
  mkdirSync36(snapshotDir, { recursive: true });
124131
124465
  for (const request of requests) {
124132
124466
  await seekCompositionTimeline(page, request.time, AUDIT_SEEK_OPTIONS);
@@ -124136,8 +124470,8 @@ async function captureFindingCrops(project, options, requests) {
124136
124470
  }));
124137
124471
  const region = padCropRegion(request.bbox, canvas, DEFAULT_ZOOM_PADDING_PX);
124138
124472
  const buffer = await captureRegionCrop(page, region, DEFAULT_ZOOM_SCALE);
124139
- writeFileSync25(join77(snapshotDir, request.filename), buffer);
124140
- written.push(join77("snapshots", request.filename));
124473
+ writeFileSync26(join76(snapshotDir, request.filename), buffer);
124474
+ written.push(join76("snapshots", request.filename));
124141
124475
  }
124142
124476
  return written;
124143
124477
  } finally {
@@ -124809,8 +125143,8 @@ var init_checkBrowser = __esm({
124809
125143
  });
124810
125144
 
124811
125145
  // src/utils/checkPipeline.ts
124812
- import { mkdirSync as mkdirSync37, writeFileSync as writeFileSync26 } from "fs";
124813
- import { join as join78, relative as relative15 } from "path";
125146
+ import { mkdirSync as mkdirSync37, writeFileSync as writeFileSync27 } from "fs";
125147
+ import { join as join77, relative as relative15 } from "path";
124814
125148
  function selectContrastTimes(grid) {
124815
125149
  if (grid.length <= 5) return [...grid];
124816
125150
  return Array.from({ length: 5 }, (_, index) => {
@@ -125406,12 +125740,12 @@ async function runBrowserCheck2(project, options, motion) {
125406
125740
  return module.runBrowserCheck(project, options, motion, runAuditGrid);
125407
125741
  }
125408
125742
  async function writeSnapshot(projectDir, index, time, pngBase64) {
125409
- const snapshotDir = join78(projectDir, "snapshots");
125743
+ const snapshotDir = join77(projectDir, "snapshots");
125410
125744
  mkdirSync37(snapshotDir, { recursive: true });
125411
125745
  const filename = `frame-${String(index).padStart(2, "0")}-at-${time.toFixed(1)}s.png`;
125412
- const path2 = join78(snapshotDir, filename);
125413
- writeFileSync26(path2, Buffer.from(pngBase64, "base64"));
125414
- return join78("snapshots", filename);
125746
+ const path2 = join77(snapshotDir, filename);
125747
+ writeFileSync27(path2, Buffer.from(pngBase64, "base64"));
125748
+ return join77("snapshots", filename);
125415
125749
  }
125416
125750
  async function captureFindingCrops2(project, options, requests) {
125417
125751
  const module = await Promise.resolve().then(() => (init_checkBrowser(), checkBrowser_exports));
@@ -125915,16 +126249,16 @@ var init_beats = __esm({
125915
126249
  // src/beats/headlessAnalyzer.ts
125916
126250
  import { existsSync as existsSync70, readFileSync as readFileSync48 } from "fs";
125917
126251
  import { createRequire as createRequire3 } from "module";
125918
- import { dirname as dirname33, join as join79 } from "path";
126252
+ import { dirname as dirname33, join as join78 } from "path";
125919
126253
  import { fileURLToPath as fileURLToPath13 } from "url";
125920
126254
  function findPrebuiltBundle() {
125921
126255
  const here = dirname33(fileURLToPath13(import.meta.url));
125922
126256
  const candidates = [
125923
- join79(here, "beat-analyzer.global.js"),
126257
+ join78(here, "beat-analyzer.global.js"),
125924
126258
  // dist root (tsup-bundled cli)
125925
- join79(here, "../beat-analyzer.global.js"),
126259
+ join78(here, "../beat-analyzer.global.js"),
125926
126260
  // dist/beats → dist
125927
- join79(here, "../dist/beat-analyzer.global.js")
126261
+ join78(here, "../dist/beat-analyzer.global.js")
125928
126262
  ];
125929
126263
  for (const p2 of candidates) {
125930
126264
  if (existsSync70(p2)) return p2;
@@ -125934,7 +126268,7 @@ function findPrebuiltBundle() {
125934
126268
  async function buildFromCoreSource() {
125935
126269
  const esbuild = await import("esbuild");
125936
126270
  const coreRoot = dirname33(require2.resolve("@hyperframes/core/package.json"));
125937
- const entry = join79(coreRoot, "src/beats/beatDetection.ts");
126271
+ const entry = join78(coreRoot, "src/beats/beatDetection.ts");
125938
126272
  const result = await esbuild.build({
125939
126273
  stdin: {
125940
126274
  contents: `import { analyzeMusicFromBuffer } from ${JSON.stringify(entry)};
@@ -126034,8 +126368,8 @@ __export(beats_exports, {
126034
126368
  default: () => beats_default,
126035
126369
  examples: () => examples13
126036
126370
  });
126037
- import { existsSync as existsSync71, readFileSync as readFileSync49, mkdirSync as mkdirSync38, writeFileSync as writeFileSync27 } from "fs";
126038
- import { resolve as resolve46, join as join80, dirname as dirname34 } from "path";
126371
+ import { existsSync as existsSync71, readFileSync as readFileSync49, mkdirSync as mkdirSync38, writeFileSync as writeFileSync28 } from "fs";
126372
+ import { resolve as resolve46, join as join79, dirname as dirname34 } from "path";
126039
126373
  function fail(message) {
126040
126374
  console.error(c.error(message));
126041
126375
  process.exit(1);
@@ -126105,9 +126439,9 @@ var init_beats2 = __esm({
126105
126439
  if (result.beatTimes.length === 0) {
126106
126440
  fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
126107
126441
  }
126108
- const outPath = join80(project.dir, "beats", `${rel}.json`);
126442
+ const outPath = join79(project.dir, "beats", `${rel}.json`);
126109
126443
  mkdirSync38(dirname34(outPath), { recursive: true });
126110
- writeFileSync27(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
126444
+ writeFileSync28(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
126111
126445
  report(`beats/${rel}.json`, result, Boolean(args.json));
126112
126446
  }
126113
126447
  });
@@ -127818,7 +128152,7 @@ var motionShot_exports = {};
127818
128152
  __export(motionShot_exports, {
127819
128153
  captureMotionPathShot: () => captureMotionPathShot
127820
128154
  });
127821
- import { writeFileSync as writeFileSync28 } from "fs";
128155
+ import { writeFileSync as writeFileSync29 } from "fs";
127822
128156
  function applyOrbitCamera(selectors, cam) {
127823
128157
  const first = document.querySelector(selectors[0] ?? "");
127824
128158
  const root = first?.closest("[data-composition-id]") ?? document.querySelector("#stage") ?? document.body.firstElementChild ?? document.body;
@@ -128123,7 +128457,7 @@ async function captureGhostOnionSkin(page, requests, times, size, camera, outPat
128123
128457
  );
128124
128458
  const b64 = String(dataUrl).replace(/^data:image\/png;base64,/, "");
128125
128459
  if (!b64) throw new Error("ghost composite returned no data");
128126
- writeFileSync28(outPath, Buffer.from(b64, "base64"));
128460
+ writeFileSync29(outPath, Buffer.from(b64, "base64"));
128127
128461
  return outPath;
128128
128462
  }
128129
128463
  async function captureMarkerOnionSkin(page, requests, times, size, camera, frame, outPath) {
@@ -128193,7 +128527,7 @@ async function captureMarkerOnionSkin(page, requests, times, size, camera, frame
128193
128527
  await new Promise((r2) => setTimeout(r2, 60));
128194
128528
  const buf = await page.screenshot({ type: "png" });
128195
128529
  if (!buf) throw new Error("screenshot returned no data");
128196
- writeFileSync28(outPath, buf);
128530
+ writeFileSync29(outPath, buf);
128197
128531
  return outPath;
128198
128532
  }
128199
128533
  async function captureMotionPathShot(projectDir, requestsIn, outPath, opts = {}) {
@@ -128205,7 +128539,7 @@ async function captureMotionPathShot(projectDir, requestsIn, outPath, opts = {})
128205
128539
  const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
128206
128540
  const { serveStaticProjectHtml: serveStaticProjectHtml2 } = await Promise.resolve().then(() => (init_staticProjectServer(), staticProjectServer_exports));
128207
128541
  const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
128208
- const html = await bundleToSingleHtml2(projectDir);
128542
+ const html = await bundleToSingleHtml2(projectDir, { entryFile: opts.entryFile });
128209
128543
  const server = await serveStaticProjectHtml2(
128210
128544
  projectDir,
128211
128545
  html,
@@ -128258,10 +128592,11 @@ __export(keyframes_exports, {
128258
128592
  collectShotSelectors: () => collectShotSelectors,
128259
128593
  default: () => keyframes_default,
128260
128594
  examples: () => examples15,
128595
+ resolveScope: () => resolveScope,
128261
128596
  surfaceComposition: () => surfaceComposition
128262
128597
  });
128263
128598
  import { existsSync as existsSync73, readFileSync as readFileSync50, statSync as statSync23 } from "fs";
128264
- import { resolve as resolve47, dirname as dirname35, basename as basename14 } from "path";
128599
+ import { resolve as resolve47, dirname as dirname35, basename as basename14, join as join80, relative as relative16, sep as sep9 } from "path";
128265
128600
  function inlineScriptText(html) {
128266
128601
  const doc = new DOMParser().parseFromString(html, "text/html");
128267
128602
  return Array.from(doc.querySelectorAll("script")).filter((s2) => !s2.getAttribute("src")).map((s2) => s2.textContent ?? "").join("\n");
@@ -128720,7 +129055,7 @@ function printOnionShotSaved(saved, elementCount) {
128720
129055
  );
128721
129056
  console.log();
128722
129057
  }
128723
- async function runOnionShot(comps, allComps, projectDir, args) {
129058
+ async function runOnionShot(comps, allComps, projectDir, entryFile, args) {
128724
129059
  const { captureMotionPathShot: captureMotionPathShot2 } = await Promise.resolve().then(() => (init_motionShot(), motionShot_exports));
128725
129060
  const requests = collectShotSelectors(args.selector ? allComps : comps);
128726
129061
  const guardError = onionShotGuardError(projectDir, requests, args.ghost ?? false);
@@ -128728,12 +129063,10 @@ async function runOnionShot(comps, allComps, projectDir, args) {
128728
129063
  console.log(c.dim(guardError));
128729
129064
  return true;
128730
129065
  }
128731
- const saved = await captureMotionPathShot2(
128732
- projectDir,
128733
- requests,
128734
- resolve47(args.shot),
128735
- onionShotOptions(args)
128736
- );
129066
+ const saved = await captureMotionPathShot2(projectDir, requests, resolve47(args.shot), {
129067
+ ...onionShotOptions(args),
129068
+ entryFile
129069
+ });
128737
129070
  printOnionShotSaved(saved, requests.length);
128738
129071
  return false;
128739
129072
  }
@@ -128742,10 +129075,13 @@ function resolveScope(args) {
128742
129075
  let comps;
128743
129076
  let projectName;
128744
129077
  let projectDir;
129078
+ let entryFile;
128745
129079
  if (raw && raw.endsWith(".html") && existsSync73(raw) && statSync23(raw).isFile()) {
128746
- comps = [surfaceComposition(readFileSync50(raw, "utf-8"), basename14(raw), raw)];
128747
- projectName = basename14(raw);
128748
- projectDir = dirname35(raw);
129080
+ const entryPath = resolve47(raw);
129081
+ comps = [surfaceComposition(readFileSync50(entryPath, "utf-8"), basename14(entryPath), entryPath)];
129082
+ projectName = basename14(entryPath);
129083
+ projectDir = findProjectRoot(entryPath);
129084
+ entryFile = relative16(projectDir, entryPath).split(sep9).join("/");
128749
129085
  } else {
128750
129086
  const project = resolveProject(raw);
128751
129087
  comps = collectCompositions(project.indexPath);
@@ -128766,7 +129102,18 @@ function resolveScope(args) {
128766
129102
  (cmp) => cmp.tweens.length > 0 || cmp.traces.length > 0 || cmp.cssKeyframes.length > 0 || cmp.anime.length > 0
128767
129103
  );
128768
129104
  }
128769
- return { comps, allComps, projectName, projectDir };
129105
+ return { comps, allComps, projectName, projectDir, entryFile };
129106
+ }
129107
+ function findProjectRoot(entryPath) {
129108
+ const entryDir = dirname35(entryPath);
129109
+ let candidate = entryDir;
129110
+ for (; ; ) {
129111
+ if (existsSync73(join80(candidate, "index.html"))) return candidate;
129112
+ if (existsSync73(join80(candidate, ".git"))) return entryDir;
129113
+ const parent = dirname35(candidate);
129114
+ if (parent === candidate) return entryDir;
129115
+ candidate = parent;
129116
+ }
128770
129117
  }
128771
129118
  function isEmptyComposition(cmp) {
128772
129119
  return cmp.tweens.length === 0 && cmp.traces.length === 0 && cmp.cssKeyframes.length === 0 && cmp.anime.length === 0;
@@ -128866,9 +129213,9 @@ function createKeyframesCommand(options = {}) {
128866
129213
  );
128867
129214
  console.log();
128868
129215
  }
128869
- const { comps: rawComps, allComps, projectName, projectDir } = resolveScope(args);
129216
+ const { comps: rawComps, allComps, projectName, projectDir, entryFile } = resolveScope(args);
128870
129217
  const comps = filterCompositionsByRuntime(rawComps, runtime);
128871
- if (args.shot && await runOnionShot(comps, allComps, projectDir, args)) return;
129218
+ if (args.shot && await runOnionShot(comps, allComps, projectDir, entryFile, args)) return;
128872
129219
  if (args.json) {
128873
129220
  console.log(
128874
129221
  JSON.stringify(withMeta({ project: projectName, runtime, compositions: comps }), null, 2)
@@ -129811,7 +130158,7 @@ var init_remove_background = __esm({
129811
130158
 
129812
130159
  // src/whisper/parakeet.ts
129813
130160
  import { execFileSync as execFileSync11 } from "child_process";
129814
- import { existsSync as existsSync77, mkdtempSync as mkdtempSync7, readFileSync as readFileSync54, rmSync as rmSync21, writeFileSync as writeFileSync29 } from "fs";
130161
+ import { existsSync as existsSync77, mkdtempSync as mkdtempSync7, readFileSync as readFileSync54, rmSync as rmSync21, writeFileSync as writeFileSync30 } from "fs";
129815
130162
  import { homedir as homedir13, tmpdir as tmpdir9 } from "os";
129816
130163
  import { basename as basename15, extname as extname12, join as join84 } from "path";
129817
130164
  function isRunnable(bin) {
@@ -129890,7 +130237,7 @@ function transcribeWithParakeet(inputPath, dir, options) {
129890
130237
  if (!existsSync77(produced)) throw new Error("Parakeet did not produce output.");
129891
130238
  const words = mergeTokensToWords(JSON.parse(readFileSync54(produced, "utf-8")));
129892
130239
  const transcriptPath = join84(dir, "transcript.json");
129893
- writeFileSync29(transcriptPath, JSON.stringify(words, null, 2));
130240
+ writeFileSync30(transcriptPath, JSON.stringify(words, null, 2));
129894
130241
  const durationSeconds = words.length > 0 ? words[words.length - 1].end : 0;
129895
130242
  return { transcriptPath, wordCount: words.length, durationSeconds, speechOnsetSeconds: null };
129896
130243
  } finally {
@@ -129912,7 +130259,7 @@ __export(transcribe_exports2, {
129912
130259
  default: () => transcribe_default,
129913
130260
  examples: () => examples21
129914
130261
  });
129915
- import { existsSync as existsSync78, writeFileSync as writeFileSync30 } from "fs";
130262
+ import { existsSync as existsSync78, writeFileSync as writeFileSync31 } from "fs";
129916
130263
  import { resolve as resolve51, join as join85, extname as extname13, dirname as dirname37 } from "path";
129917
130264
  function failWith(message, json) {
129918
130265
  trackCommandFailure("transcribe", message);
@@ -129937,7 +130284,7 @@ async function importTranscript(inputPath, dir, json) {
129937
130284
  const { words, format } = loadTranscript2(inputPath);
129938
130285
  if (words.length === 0) exitNoWords(json);
129939
130286
  const outPath = join85(dir, "transcript.json");
129940
- writeFileSync30(outPath, JSON.stringify(words, null, 2));
130287
+ writeFileSync31(outPath, JSON.stringify(words, null, 2));
129941
130288
  patchCaptionHtml2(dir, words);
129942
130289
  if (json) {
129943
130290
  console.log(
@@ -129956,7 +130303,7 @@ async function exportTranscript(inputPath, dir, to, output, json, preserveCues)
129956
130303
  const preGrouped = preserveCues || format === "srt" || format === "vtt" || void 0;
129957
130304
  const outPath = resolve51(output ?? join85(dir, `transcript.${to}`));
129958
130305
  const content = to === "srt" ? formatSrt2(words, { preGrouped }) : formatVtt2(words, { preGrouped });
129959
- writeFileSync30(outPath, content);
130306
+ writeFileSync31(outPath, content);
129960
130307
  if (json) {
129961
130308
  console.log(
129962
130309
  JSON.stringify({ ok: true, format: to, wordCount: words.length, outputPath: outPath })
@@ -130004,7 +130351,7 @@ async function transcribeAudio(inputPath, dir, opts) {
130004
130351
  );
130005
130352
  }
130006
130353
  }
130007
- writeFileSync30(result.transcriptPath, JSON.stringify(words, null, 2));
130354
+ writeFileSync31(result.transcriptPath, JSON.stringify(words, null, 2));
130008
130355
  patchCaptionHtml2(dir, words);
130009
130356
  if (opts.json) {
130010
130357
  console.log(
@@ -130340,13 +130687,13 @@ __export(synthesize_exports, {
130340
130687
  synthesize: () => synthesize
130341
130688
  });
130342
130689
  import { execFileSync as execFileSync13 } from "child_process";
130343
- import { existsSync as existsSync80, writeFileSync as writeFileSync31, mkdirSync as mkdirSync40, readdirSync as readdirSync27, unlinkSync as unlinkSync6 } from "fs";
130690
+ import { existsSync as existsSync80, writeFileSync as writeFileSync33, mkdirSync as mkdirSync40, readdirSync as readdirSync27, unlinkSync as unlinkSync6 } from "fs";
130344
130691
  import { join as join87, dirname as dirname38, basename as basename16 } from "path";
130345
130692
  import { homedir as homedir15 } from "os";
130346
130693
  function ensureSynthScript() {
130347
130694
  if (!existsSync80(SCRIPT_PATH)) {
130348
130695
  mkdirSync40(SCRIPT_DIR, { recursive: true });
130349
- writeFileSync31(SCRIPT_PATH, SYNTH_SCRIPT);
130696
+ writeFileSync33(SCRIPT_PATH, SYNTH_SCRIPT);
130350
130697
  const currentName = basename16(SCRIPT_PATH);
130351
130698
  try {
130352
130699
  for (const entry of readdirSync27(SCRIPT_DIR)) {
@@ -131656,7 +132003,7 @@ __export(contactSheet_exports, {
131656
132003
  createSvgContactSheet: () => createSvgContactSheet
131657
132004
  });
131658
132005
  import sharp from "sharp";
131659
- import { readdirSync as readdirSync28, readFileSync as readFileSync57, writeFileSync as writeFileSync33, unlinkSync as unlinkSync7, existsSync as existsSync84 } from "fs";
132006
+ import { readdirSync as readdirSync28, readFileSync as readFileSync57, writeFileSync as writeFileSync34, unlinkSync as unlinkSync7, existsSync as existsSync84 } from "fs";
131660
132007
  import { join as join89, extname as extname15, basename as basename17, dirname as dirname40 } from "path";
131661
132008
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
131662
132009
  const {
@@ -131817,7 +132164,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
131817
132164
  fit: "contain",
131818
132165
  background: { r: 245, g: 245, b: 245, alpha: 1 }
131819
132166
  }).flatten({ background: { r: 245, g: 245, b: 245 } }).png().toBuffer();
131820
- writeFileSync33(tmpPath, thumb);
132167
+ writeFileSync34(tmpPath, thumb);
131821
132168
  tmpPaths.push(tmpPath);
131822
132169
  labels.push(svgFileNames[i2].replace(".svg", ""));
131823
132170
  } catch {
@@ -171592,9 +171939,9 @@ __export(snapshot_exports, {
171592
171939
  parseZoomScale: () => parseZoomScale,
171593
171940
  tailFrameTime: () => tailFrameTime
171594
171941
  });
171595
- import { existsSync as existsSync85, mkdtempSync as mkdtempSync8, readFileSync as readFileSync58, mkdirSync as mkdirSync41, rmSync as rmSync23, writeFileSync as writeFileSync34 } from "fs";
171942
+ import { existsSync as existsSync85, mkdtempSync as mkdtempSync8, readFileSync as readFileSync58, mkdirSync as mkdirSync41, rmSync as rmSync23, writeFileSync as writeFileSync35 } from "fs";
171596
171943
  import { tmpdir as tmpdir10 } from "os";
171597
- import { resolve as resolve55, join as join90, relative as relative16, isAbsolute as isAbsolute14, basename as basename20 } from "path";
171944
+ import { resolve as resolve55, join as join90, relative as relative17, isAbsolute as isAbsolute14, basename as basename20 } from "path";
171598
171945
  function orbitStageSource() {
171599
171946
  return `function(cam) {
171600
171947
  var root = document.querySelector("[data-composition-id]")
@@ -171801,7 +172148,7 @@ async function captureSnapshots(projectDir, opts) {
171801
172148
  const url = new URL(v2.src);
171802
172149
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
171803
172150
  const candidate = resolve55(projectDir, decodedPath);
171804
- const rel2 = relative16(projectDir, candidate);
172151
+ const rel2 = relative17(projectDir, candidate);
171805
172152
  if (!rel2.startsWith("..") && !isAbsolute14(rel2) && existsSync85(candidate)) {
171806
172153
  ffmpegInput = candidate;
171807
172154
  inputIsLocal = true;
@@ -171854,11 +172201,11 @@ async function captureSnapshots(projectDir, opts) {
171854
172201
  region,
171855
172202
  opts.zoomScale ?? DEFAULT_ZOOM_SCALE
171856
172203
  );
171857
- writeFileSync34(framePath, buffer);
172204
+ writeFileSync35(framePath, buffer);
171858
172205
  } else {
171859
172206
  await page.screenshot({ path: framePath, type: "png" });
171860
172207
  }
171861
- const rel = relative16(projectDir, framePath);
172208
+ const rel = relative17(projectDir, framePath);
171862
172209
  savedPaths.push(rel.startsWith("..") || isAbsolute14(rel) ? framePath : rel);
171863
172210
  }
171864
172211
  } finally {
@@ -172062,7 +172409,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
172062
172409
  }
172063
172410
  }
172064
172411
  const descPath = join90(snapshotDir, "descriptions.md");
172065
- writeFileSync34(descPath, descriptions.join("\n"));
172412
+ writeFileSync35(descPath, descriptions.join("\n"));
172066
172413
  console.log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
172067
172414
  }
172068
172415
  } catch (descErr) {
@@ -172082,7 +172429,7 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
172082
172429
  });
172083
172430
 
172084
172431
  // src/utils/pathArgs.ts
172085
- import { isAbsolute as isAbsolute15, relative as relative17, resolve as resolve56 } from "path";
172432
+ import { isAbsolute as isAbsolute15, relative as relative18, resolve as resolve56 } from "path";
172086
172433
  function readOptionalString(value) {
172087
172434
  if (typeof value !== "string") return void 0;
172088
172435
  const trimmed = value.trim();
@@ -172092,7 +172439,7 @@ function resolveFromBase(baseDir, input2) {
172092
172439
  return isAbsolute15(input2) ? input2 : resolve56(baseDir, input2);
172093
172440
  }
172094
172441
  function displayPathFromBase(baseDir, filePath) {
172095
- const rel = relative17(baseDir, filePath);
172442
+ const rel = relative18(baseDir, filePath);
172096
172443
  if (rel && !rel.startsWith("..") && !isAbsolute15(rel)) return rel;
172097
172444
  return filePath;
172098
172445
  }
@@ -172127,7 +172474,7 @@ import {
172127
172474
  mkdtempSync as mkdtempSync9,
172128
172475
  readFileSync as readFileSync59,
172129
172476
  rmSync as rmSync24,
172130
- writeFileSync as writeFileSync35
172477
+ writeFileSync as writeFileSync36
172131
172478
  } from "fs";
172132
172479
  import { tmpdir as tmpdir11 } from "os";
172133
172480
  import { basename as basename21, dirname as dirname41, extname as extname16, join as join91, resolve as resolve57 } from "path";
@@ -172389,7 +172736,7 @@ async function prepareGradeCompareTempProject(opts) {
172389
172736
  const tempDir = mkdtempSync9(join91(tmpdir11(), "hf-grade-compare-"));
172390
172737
  try {
172391
172738
  const frameFileName2 = opts.frameFileName ?? frameFileNameForPath(opts.framePath);
172392
- writeFileSync35(join91(tempDir, frameFileName2), opts.frameBuffer);
172739
+ writeFileSync36(join91(tempDir, frameFileName2), opts.frameBuffer);
172393
172740
  let lutIndex = 0;
172394
172741
  const stagedCells = opts.cells.map((cell) => {
172395
172742
  const lutSrc = lutSrcFromGrading(cell.grading);
@@ -172421,7 +172768,7 @@ async function prepareGradeCompareTempProject(opts) {
172421
172768
  frameWidth: opts.frameWidth,
172422
172769
  frameHeight: opts.frameHeight
172423
172770
  });
172424
- writeFileSync35(join91(tempDir, "index.html"), html);
172771
+ writeFileSync36(join91(tempDir, "index.html"), html);
172425
172772
  return { tempDir, html, cells: stagedCells };
172426
172773
  } catch (err) {
172427
172774
  rmSync24(tempDir, { recursive: true, force: true });
@@ -172674,7 +173021,7 @@ __export(compare_exports, {
172674
173021
  parseCompareArgs: () => parseCompareArgs,
172675
173022
  prepareCompareVariantProjects: () => prepareCompareVariantProjects
172676
173023
  });
172677
- import { cpSync as cpSync6, existsSync as existsSync87, mkdirSync as mkdirSync44, mkdtempSync as mkdtempSync10, renameSync as renameSync7, rmSync as rmSync25, statSync as statSync27 } from "fs";
173024
+ import { cpSync as cpSync6, existsSync as existsSync87, mkdirSync as mkdirSync44, mkdtempSync as mkdtempSync10, renameSync as renameSync9, rmSync as rmSync25, statSync as statSync27 } from "fs";
172678
173025
  import { tmpdir as tmpdir12 } from "os";
172679
173026
  import { basename as basename23, dirname as dirname42, extname as extname17, join as join93 } from "path";
172680
173027
  function defaultLabelForPath(input2) {
@@ -172786,7 +173133,7 @@ function stageHtmlVariant(variant) {
172786
173133
  });
172787
173134
  const sourceName = basename23(variant.inputPath);
172788
173135
  if (sourceName !== "index.html") {
172789
- renameSync7(join93(stagedDir, sourceName), join93(stagedDir, "index.html"));
173136
+ renameSync9(join93(stagedDir, sourceName), join93(stagedDir, "index.html"));
172790
173137
  }
172791
173138
  return {
172792
173139
  ...variant,
@@ -173005,7 +173352,7 @@ ${c.error("\u2717")} Compare failed: ${message}`);
173005
173352
  });
173006
173353
 
173007
173354
  // src/capture/assetDownloader.ts
173008
- import { writeFileSync as writeFileSync36, mkdirSync as mkdirSync45 } from "fs";
173355
+ import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync45 } from "fs";
173009
173356
  import { join as join94, extname as extname18 } from "path";
173010
173357
  import { createHash as createHash12 } from "crypto";
173011
173358
  function svgContentHashSlug(svgSource, isLogo) {
@@ -173033,7 +173380,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
173033
173380
  const name = `${finalSlug}.svg`;
173034
173381
  const localPath = `assets/svgs/${name}`;
173035
173382
  try {
173036
- writeFileSync36(join94(outputDir, localPath), svg.outerHTML, "utf-8");
173383
+ writeFileSync37(join94(outputDir, localPath), svg.outerHTML, "utf-8");
173037
173384
  assets.push({ url: "", localPath, type: "svg" });
173038
173385
  } catch {
173039
173386
  }
@@ -173046,7 +173393,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
173046
173393
  const localPath = `assets/${name}`;
173047
173394
  const buffer = await fetchBuffer(icon.href);
173048
173395
  if (buffer) {
173049
- writeFileSync36(join94(outputDir, localPath), buffer);
173396
+ writeFileSync37(join94(outputDir, localPath), buffer);
173050
173397
  assets.push({ url: icon.href, localPath, type: "favicon" });
173051
173398
  break;
173052
173399
  }
@@ -173111,7 +173458,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
173111
173458
  const name = `${slug}${ext}`;
173112
173459
  usedNames.add(slug);
173113
173460
  const localPath = `assets/${name}`;
173114
- writeFileSync36(join94(outputDir, localPath), buffer);
173461
+ writeFileSync37(join94(outputDir, localPath), buffer);
173115
173462
  assets.push({ url, localPath, type: "image" });
173116
173463
  imgIdx++;
173117
173464
  } catch {
@@ -173124,7 +173471,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
173124
173471
  const localPath = `assets/og-image${ext}`;
173125
173472
  const buffer = await fetchBuffer(tokens.ogImage);
173126
173473
  if (buffer && buffer.length > 5e3) {
173127
- writeFileSync36(join94(outputDir, localPath), buffer);
173474
+ writeFileSync37(join94(outputDir, localPath), buffer);
173128
173475
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
173129
173476
  }
173130
173477
  } catch {
@@ -173187,7 +173534,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
173187
173534
  const relativePath = `assets/fonts/${filename}`;
173188
173535
  const buffer = await fetchBuffer(fontUrl);
173189
173536
  if (buffer) {
173190
- writeFileSync36(localPath, buffer);
173537
+ writeFileSync37(localPath, buffer);
173191
173538
  rewritten = rewritten.split(fontUrl).join(relativePath);
173192
173539
  familyCounts.set(family, familyCount + 1);
173193
173540
  count++;
@@ -173716,7 +174063,7 @@ async function extractHtml(page, opts = {}) {
173716
174063
  (_match, pre, urls, post) => {
173717
174064
  const fixed = urls.replace(/&amp;/g, "&").replace(
173718
174065
  /(^|,\s*)(\/[^\s,]+)/g,
173719
- (_m, sep9, path2) => sep9 + pageOrigin + path2
174066
+ (_m, sep10, path2) => sep10 + pageOrigin + path2
173720
174067
  );
173721
174068
  return pre + fixed + post;
173722
174069
  }
@@ -174762,7 +175109,7 @@ var init_designStyleExtractor = __esm({
174762
175109
  });
174763
175110
 
174764
175111
  // src/capture/fontMetadataExtractor.ts
174765
- import { readdirSync as readdirSync29, readFileSync as readFileSync61, writeFileSync as writeFileSync37, existsSync as existsSync89 } from "fs";
175112
+ import { readdirSync as readdirSync29, readFileSync as readFileSync61, writeFileSync as writeFileSync38, existsSync as existsSync89 } from "fs";
174766
175113
  import { join as join96 } from "path";
174767
175114
  import * as fontkit from "fontkit";
174768
175115
  function isFontCollection(value) {
@@ -174796,7 +175143,7 @@ function extractFontMetadata(fontsDir, outputPath) {
174796
175143
  tool: "fontkit"
174797
175144
  }
174798
175145
  };
174799
- writeFileSync37(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
175146
+ writeFileSync38(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
174800
175147
  return manifest;
174801
175148
  }
174802
175149
  function readSingleFont(fullPath, filename) {
@@ -175085,7 +175432,7 @@ var init_animationCataloger = __esm({
175085
175432
  });
175086
175433
 
175087
175434
  // src/capture/mediaCapture.ts
175088
- import { mkdirSync as mkdirSync47, writeFileSync as writeFileSync38, readdirSync as readdirSync30, readFileSync as readFileSync63, statSync as statSync28 } from "fs";
175435
+ import { mkdirSync as mkdirSync47, writeFileSync as writeFileSync39, readdirSync as readdirSync30, readFileSync as readFileSync63, statSync as statSync28 } from "fs";
175089
175436
  import { join as join97, extname as extname19 } from "path";
175090
175437
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
175091
175438
  let savedCount = 0;
@@ -175118,7 +175465,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
175118
175465
  const hash2 = buf.toString("base64").slice(0, 100);
175119
175466
  if (savedHashes.has(hash2)) continue;
175120
175467
  savedHashes.add(hash2);
175121
- writeFileSync38(join97(lottieDir, `animation-${savedCount}.lottie`), buf);
175468
+ writeFileSync39(join97(lottieDir, `animation-${savedCount}.lottie`), buf);
175122
175469
  savedCount++;
175123
175470
  continue;
175124
175471
  }
@@ -175136,7 +175483,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
175136
175483
  } catch {
175137
175484
  continue;
175138
175485
  }
175139
- writeFileSync38(join97(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
175486
+ writeFileSync39(join97(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
175140
175487
  savedCount++;
175141
175488
  }
175142
175489
  } catch {
@@ -175214,7 +175561,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
175214
175561
  }
175215
175562
  }
175216
175563
  if (manifest.length > 0) {
175217
- writeFileSync38(
175564
+ writeFileSync39(
175218
175565
  join97(outputDir, "extracted", "lottie-manifest.json"),
175219
175566
  JSON.stringify(manifest, null, 2),
175220
175567
  "utf-8"
@@ -175250,7 +175597,7 @@ async function downloadVideoBody(srcUrl, filename, videosDir) {
175250
175597
  }
175251
175598
  if (total < 1024) return null;
175252
175599
  const safe = /\.[a-z0-9]+$/i.test(filename) ? filename.replace(/[^\w.-]/g, "_") : `video${ext}`;
175253
- writeFileSync38(join97(videosDir, safe), Buffer.concat(chunks));
175600
+ writeFileSync39(join97(videosDir, safe), Buffer.concat(chunks));
175254
175601
  return `assets/videos/${safe}`;
175255
175602
  } catch {
175256
175603
  return null;
@@ -175368,7 +175715,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
175368
175715
  });
175369
175716
  }
175370
175717
  if (videoManifest.length > 0) {
175371
- writeFileSync38(
175718
+ writeFileSync39(
175372
175719
  join97(outputDir, "extracted", "video-manifest.json"),
175373
175720
  JSON.stringify(videoManifest, null, 2),
175374
175721
  "utf-8"
@@ -175821,7 +176168,7 @@ var agentPromptGenerator_exports = {};
175821
176168
  __export(agentPromptGenerator_exports, {
175822
176169
  generateAgentPrompt: () => generateAgentPrompt
175823
176170
  });
175824
- import { writeFileSync as writeFileSync39, readdirSync as readdirSync33, existsSync as existsSync91 } from "fs";
176171
+ import { writeFileSync as writeFileSync40, readdirSync as readdirSync33, existsSync as existsSync91 } from "fs";
175825
176172
  import { join as join99 } from "path";
175826
176173
  function inferColorRole(hex) {
175827
176174
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
@@ -175841,9 +176188,9 @@ function inferColorRole(hex) {
175841
176188
  }
175842
176189
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
175843
176190
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
175844
- writeFileSync39(join99(outputDir, "AGENTS.md"), prompt, "utf-8");
175845
- writeFileSync39(join99(outputDir, "CLAUDE.md"), prompt, "utf-8");
175846
- writeFileSync39(join99(outputDir, ".cursorrules"), prompt, "utf-8");
176191
+ writeFileSync40(join99(outputDir, "AGENTS.md"), prompt, "utf-8");
176192
+ writeFileSync40(join99(outputDir, "CLAUDE.md"), prompt, "utf-8");
176193
+ writeFileSync40(join99(outputDir, ".cursorrules"), prompt, "utf-8");
175847
176194
  }
175848
176195
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
175849
176196
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -175956,7 +176303,7 @@ var init_agentPromptGenerator = __esm({
175956
176303
  });
175957
176304
 
175958
176305
  // src/capture/scaffolding.ts
175959
- import { existsSync as existsSync93, writeFileSync as writeFileSync40, readFileSync as readFileSync65 } from "fs";
176306
+ import { existsSync as existsSync93, writeFileSync as writeFileSync41, readFileSync as readFileSync65 } from "fs";
175960
176307
  import { join as join100, resolve as resolve59 } from "path";
175961
176308
  function loadEnvFile(startDir) {
175962
176309
  try {
@@ -175986,7 +176333,7 @@ async function generateProjectScaffold(outputDir, url, tokens, animationCatalog,
175986
176333
  const metaPath = join100(outputDir, "meta.json");
175987
176334
  if (!existsSync93(metaPath)) {
175988
176335
  const hostname = new URL(url).hostname.replace(/^www\./, "");
175989
- writeFileSync40(
176336
+ writeFileSync41(
175990
176337
  metaPath,
175991
176338
  JSON.stringify({ id: hostname + "-video", name: tokens.title || hostname }, null, 2),
175992
176339
  "utf-8"
@@ -176021,7 +176368,7 @@ var screenshotCapture_exports = {};
176021
176368
  __export(screenshotCapture_exports, {
176022
176369
  captureScrollScreenshots: () => captureScrollScreenshots
176023
176370
  });
176024
- import { writeFileSync as writeFileSync41, mkdirSync as mkdirSync48 } from "fs";
176371
+ import { writeFileSync as writeFileSync43, mkdirSync as mkdirSync48 } from "fs";
176025
176372
  import { join as join101 } from "path";
176026
176373
  async function captureScrollScreenshots(page, outputDir) {
176027
176374
  const screenshotsDir = join101(outputDir, "screenshots");
@@ -176118,7 +176465,7 @@ async function captureScrollScreenshots(page, outputDir) {
176118
176465
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
176119
176466
  const filePath = join101(screenshotsDir, filename);
176120
176467
  const buffer = await page.screenshot({ type: "png" });
176121
- writeFileSync41(filePath, buffer);
176468
+ writeFileSync43(filePath, buffer);
176122
176469
  filePaths.push(`screenshots/${filename}`);
176123
176470
  }
176124
176471
  await page.evaluate(`window.scrollTo(0, 0)`);
@@ -176465,7 +176812,7 @@ var capture_exports = {};
176465
176812
  __export(capture_exports, {
176466
176813
  captureWebsite: () => captureWebsite
176467
176814
  });
176468
- import { mkdirSync as mkdirSync49, writeFileSync as writeFileSync43, existsSync as existsSync94 } from "fs";
176815
+ import { mkdirSync as mkdirSync49, writeFileSync as writeFileSync44, existsSync as existsSync94 } from "fs";
176469
176816
  import { join as join103 } from "path";
176470
176817
  async function captureWebsite(opts, onProgress) {
176471
176818
  const {
@@ -176664,7 +177011,7 @@ async function captureWebsite(opts, onProgress) {
176664
177011
  return true;
176665
177012
  });
176666
177013
  capturedShaders = unique;
176667
- writeFileSync43(
177014
+ writeFileSync44(
176668
177015
  join103(outputDir, "extracted", "shaders.json"),
176669
177016
  JSON.stringify(unique, null, 2),
176670
177017
  "utf-8"
@@ -176679,7 +177026,7 @@ async function captureWebsite(opts, onProgress) {
176679
177026
  ...tokens,
176680
177027
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
176681
177028
  };
176682
- writeFileSync43(
177029
+ writeFileSync44(
176683
177030
  join103(outputDir, "extracted", "tokens.json"),
176684
177031
  JSON.stringify(tokensForDisk, null, 2),
176685
177032
  "utf-8"
@@ -176687,7 +177034,7 @@ async function captureWebsite(opts, onProgress) {
176687
177034
  progress("style", "Extracting design styles...");
176688
177035
  try {
176689
177036
  const designStyles = await extractDesignStyles(page1);
176690
- writeFileSync43(
177037
+ writeFileSync44(
176691
177038
  join103(outputDir, "extracted", "design-styles.json"),
176692
177039
  JSON.stringify(designStyles, null, 2),
176693
177040
  "utf-8"
@@ -176794,7 +177141,7 @@ ${err.stack}` : normalizeErrorMessage(err);
176794
177141
  scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
176795
177142
  representativeAnimations: representativeAnims
176796
177143
  };
176797
- writeFileSync43(
177144
+ writeFileSync44(
176798
177145
  join103(outputDir, "extracted", "animations.json"),
176799
177146
  JSON.stringify(leanCatalog, null, 2),
176800
177147
  "utf-8"
@@ -176825,7 +177172,7 @@ ${err.stack}` : normalizeErrorMessage(err);
176825
177172
  ...tokens,
176826
177173
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
176827
177174
  };
176828
- writeFileSync43(
177175
+ writeFileSync44(
176829
177176
  join103(outputDir, "extracted", "tokens.json"),
176830
177177
  JSON.stringify(tokensForDisk2, null, 2),
176831
177178
  "utf-8"
@@ -176842,12 +177189,12 @@ ${extracted.bodyHtml}
176842
177189
  </body>
176843
177190
  </html>
176844
177191
  `;
176845
- writeFileSync43(join103(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
177192
+ writeFileSync44(join103(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
176846
177193
  } catch (err) {
176847
177194
  warnings.push(`page.html write failed: ${err}`);
176848
177195
  }
176849
177196
  if (visibleTextContent) {
176850
- writeFileSync43(join103(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
177197
+ writeFileSync44(join103(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
176851
177198
  }
176852
177199
  const geminiCaptions = await captionImagesWithGemini(outputDir, progress, warnings);
176853
177200
  progress("design", "Generating asset descriptions...");
@@ -176856,7 +177203,7 @@ ${extracted.bodyHtml}
176856
177203
  if (lines.length > 0) {
176857
177204
  const hasGeminiKey = !!(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY);
176858
177205
  const header = hasGeminiKey ? "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\nTo find a specific brand or icon, **grep this file for the brand name in the description text** (e.g. `grep -i 'autodesk' asset-descriptions.md`). The Gemini Vision captions identify what's actually in each file \u2014 that's the agent's selector.\n\nThe `logo-<hash>.svg` filename prefix is a cheap structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). It is NOT a content claim \u2014 many `logo-*` files are nav icons or decorative shapes. Trust the captions, not the filename prefix.\n\n" : "# Asset Descriptions\n\n\u26A0\uFE0F GEMINI_API_KEY not set \u2014 descriptions below are catalog-derived (alt text, headings, section context, filename) instead of Vision-generated. To get richer Vision descriptions on the next capture, set GEMINI_API_KEY (or GOOGLE_API_KEY) and re-run.\n\nThe `logo-<hash>.svg` filename prefix is a structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). To pick the actual brand logo without Vision, open the `logo-*` candidates in a previewer or rasterize them with `sharp` before referencing \u2014 composing a fake logo ships off-brand in the final video.\n\n";
176859
- writeFileSync43(
177206
+ writeFileSync44(
176860
177207
  join103(outputDir, "extracted", "asset-descriptions.md"),
176861
177208
  header + lines.map((l) => "- " + l).join("\n") + "\n",
176862
177209
  "utf-8"
@@ -177148,11 +177495,11 @@ var init_capture2 = __esm({
177148
177495
  } catch (err) {
177149
177496
  const errMsg = normalizeErrorMessage(err);
177150
177497
  try {
177151
- const { mkdirSync: mkdirSync60, writeFileSync: writeFileSync53 } = await import("fs");
177498
+ const { mkdirSync: mkdirSync60, writeFileSync: writeFileSync54 } = await import("fs");
177152
177499
  mkdirSync60(outputDir, { recursive: true });
177153
177500
  const isTimeout = /timeout|timed out/i.test(errMsg);
177154
177501
  const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
177155
- writeFileSync53(
177502
+ writeFileSync54(
177156
177503
  `${outputDir}/BLOCKED.md`,
177157
177504
  `# Capture Failed
177158
177505
 
@@ -177195,7 +177542,7 @@ __export(state_exports, {
177195
177542
  stateFilePath: () => stateFilePath,
177196
177543
  writeStackOutputs: () => writeStackOutputs
177197
177544
  });
177198
- import { existsSync as existsSync95, mkdirSync as mkdirSync50, readdirSync as readdirSync34, readFileSync as readFileSync66, rmSync as rmSync26, writeFileSync as writeFileSync44 } from "fs";
177545
+ import { existsSync as existsSync95, mkdirSync as mkdirSync50, readdirSync as readdirSync34, readFileSync as readFileSync66, rmSync as rmSync26, writeFileSync as writeFileSync45 } from "fs";
177199
177546
  import { dirname as dirname43, join as join104 } from "path";
177200
177547
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
177201
177548
  return join104(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
@@ -177203,7 +177550,7 @@ function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
177203
177550
  function writeStackOutputs(outputs, cwd = process.cwd()) {
177204
177551
  const path2 = stateFilePath(outputs.stackName, cwd);
177205
177552
  mkdirSync50(dirname43(path2), { recursive: true });
177206
- writeFileSync44(path2, JSON.stringify(outputs, null, 2) + "\n");
177553
+ writeFileSync45(path2, JSON.stringify(outputs, null, 2) + "\n");
177207
177554
  return path2;
177208
177555
  }
177209
177556
  function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
@@ -178756,7 +179103,7 @@ __export(cloudrun_exports, {
178756
179103
  });
178757
179104
  import { spawnSync as spawnSync7 } from "child_process";
178758
179105
  import { createRequire as createRequire4 } from "module";
178759
- import { existsSync as existsSync101, mkdirSync as mkdirSync51, readFileSync as readFileSync70, writeFileSync as writeFileSync45 } from "fs";
179106
+ import { existsSync as existsSync101, mkdirSync as mkdirSync51, readFileSync as readFileSync70, writeFileSync as writeFileSync46 } from "fs";
178760
179107
  import { homedir as homedir16 } from "os";
178761
179108
  import { dirname as dirname45, join as join110, resolve as resolve63 } from "path";
178762
179109
  function stateDir() {
@@ -178767,7 +179114,7 @@ function statePath() {
178767
179114
  }
178768
179115
  function writeState(state) {
178769
179116
  mkdirSync51(stateDir(), { recursive: true });
178770
- writeFileSync45(statePath(), JSON.stringify(state, null, 2));
179117
+ writeFileSync46(statePath(), JSON.stringify(state, null, 2));
178771
179118
  }
178772
179119
  function readState(args) {
178773
179120
  const overrides = {
@@ -178930,7 +179277,7 @@ function findRepoRoot(tfDir) {
178930
179277
  function writeCloudBuildConfig(image) {
178931
179278
  const cfgPath = join110(stateDir(), "cloudrun-cloudbuild.yaml");
178932
179279
  mkdirSync51(stateDir(), { recursive: true });
178933
- writeFileSync45(
179280
+ writeFileSync46(
178934
179281
  cfgPath,
178935
179282
  [
178936
179283
  "steps:",
@@ -183030,7 +183377,7 @@ var init_parseFigmaRef = __esm({
183030
183377
  });
183031
183378
 
183032
183379
  // ../core/dist/figma/freeze.js
183033
- import { copyFileSync as copyFileSync9, mkdirSync as mkdirSync54, rmSync as rmSync27, statSync as statSync30, writeFileSync as writeFileSync46 } from "fs";
183380
+ import { copyFileSync as copyFileSync9, mkdirSync as mkdirSync54, rmSync as rmSync27, statSync as statSync30, writeFileSync as writeFileSync47 } from "fs";
183034
183381
  import { dirname as dirname48 } from "path";
183035
183382
  function exceedsFreezeCap(byteLength) {
183036
183383
  return byteLength > MAX_FREEZE_BYTES;
@@ -183042,12 +183389,12 @@ function freezeBytes(bytes, destPath) {
183042
183389
  throw new Error(`freeze failed: ${bytes.length} bytes exceeds ${MAX_FREEZE_BYTES} cap`);
183043
183390
  mkdirSync54(dirname48(destPath), { recursive: true });
183044
183391
  try {
183045
- writeFileSync46(destPath, bytes, { flag: "wx" });
183392
+ writeFileSync47(destPath, bytes, { flag: "wx" });
183046
183393
  } catch (err) {
183047
183394
  if (err.code !== "EEXIST")
183048
183395
  throw err;
183049
183396
  rmSync27(destPath);
183050
- writeFileSync46(destPath, bytes, { flag: "wx" });
183397
+ writeFileSync47(destPath, bytes, { flag: "wx" });
183051
183398
  }
183052
183399
  return bytes.length;
183053
183400
  }
@@ -183084,7 +183431,7 @@ var init_jsonl = __esm({
183084
183431
  });
183085
183432
 
183086
183433
  // ../core/dist/figma/manifest.js
183087
- import { appendFileSync as appendFileSync2, existsSync as existsSync105, mkdirSync as mkdirSync55, readFileSync as readFileSync74, writeFileSync as writeFileSync47 } from "fs";
183434
+ import { appendFileSync as appendFileSync2, existsSync as existsSync105, mkdirSync as mkdirSync55, readFileSync as readFileSync74, writeFileSync as writeFileSync48 } from "fs";
183088
183435
  import { join as join113 } from "path";
183089
183436
  function mediaDir(projectDir) {
183090
183437
  return join113(projectDir, ".media");
@@ -183138,7 +183485,7 @@ function updateRecord(projectDir, record) {
183138
183485
  }
183139
183486
  return line2;
183140
183487
  });
183141
- writeFileSync47(p2, out.join("\n"));
183488
+ writeFileSync48(p2, out.join("\n"));
183142
183489
  }
183143
183490
  function nextId(projectDir, type) {
183144
183491
  const re2 = new RegExp(`^${type}_(\\d+)$`);
@@ -183179,7 +183526,7 @@ var init_manifest = __esm({
183179
183526
  });
183180
183527
 
183181
183528
  // ../core/dist/figma/mediaIndex.js
183182
- import { mkdirSync as mkdirSync56, writeFileSync as writeFileSync48 } from "fs";
183529
+ import { mkdirSync as mkdirSync56, writeFileSync as writeFileSync49 } from "fs";
183183
183530
  import { dirname as dirname49, join as join114 } from "path";
183184
183531
  function isRow(value) {
183185
183532
  return typeof value === "object" && value !== null;
@@ -183231,7 +183578,7 @@ function regenerateIndex(projectDir) {
183231
183578
  const content = generateIndexContent(records);
183232
183579
  const p2 = indexPath(projectDir);
183233
183580
  mkdirSync56(dirname49(p2), { recursive: true });
183234
- writeFileSync48(p2, content);
183581
+ writeFileSync49(p2, content);
183235
183582
  return content;
183236
183583
  }
183237
183584
  var init_mediaIndex = __esm({
@@ -183296,7 +183643,7 @@ var init_sanitizeSvg = __esm({
183296
183643
  });
183297
183644
 
183298
183645
  // ../core/dist/figma/bindings.js
183299
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync57, writeFileSync as writeFileSync49 } from "fs";
183646
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync57, writeFileSync as writeFileSync50 } from "fs";
183300
183647
  import { join as join115 } from "path";
183301
183648
  function bindingsPath(projectDir) {
183302
183649
  return join115(mediaDir(projectDir), BINDINGS_FILE);
@@ -183318,7 +183665,7 @@ function upsertBindings(projectDir, records) {
183318
183665
  const survivors = readLines(projectDir).filter((line2) => !(isBindingRecord(line2) && incoming.has(line2.figmaId)));
183319
183666
  mkdirSync57(mediaDir(projectDir), { recursive: true });
183320
183667
  const lines = [...survivors, ...records].map((r2) => JSON.stringify(r2)).join("\n");
183321
- writeFileSync49(bindingsPath(projectDir), lines.length > 0 ? lines + "\n" : "");
183668
+ writeFileSync50(bindingsPath(projectDir), lines.length > 0 ? lines + "\n" : "");
183322
183669
  }
183323
183670
  var BINDINGS_FILE;
183324
183671
  var init_bindings = __esm({
@@ -183898,7 +184245,7 @@ __export(asset_exports, {
183898
184245
  runAssetImportMany: () => runAssetImportMany
183899
184246
  });
183900
184247
  import { existsSync as existsSync106 } from "fs";
183901
- import { join as join116, relative as relative18 } from "path";
184248
+ import { join as join116, relative as relative19 } from "path";
183902
184249
  function gatherAssetRefs(positionals) {
183903
184250
  return positionals.flatMap((r2) => /^https?:/i.test(r2.trim()) ? [r2] : r2.split(",")).map((r2) => r2.trim()).filter((r2) => r2.length > 0);
183904
184251
  }
@@ -183940,7 +184287,7 @@ async function freezeAndRecord(fileKey, nodeId, url, ext, opts, version2, deps,
183940
184287
  const record = {
183941
184288
  id,
183942
184289
  type: "image",
183943
- path: relative18(deps.projectDir, destAbs),
184290
+ path: relative19(deps.projectDir, destAbs),
183944
184291
  source: `figma:${fileKey}/${nodeId}`,
183945
184292
  ...description !== void 0 && { description },
183946
184293
  ...entity !== void 0 && { entity },
@@ -184102,7 +184449,7 @@ __export(tokens_exports, {
184102
184449
  default: () => tokens_default,
184103
184450
  runTokensImport: () => runTokensImport
184104
184451
  });
184105
- import { writeFileSync as writeFileSync50 } from "fs";
184452
+ import { writeFileSync as writeFileSync51 } from "fs";
184106
184453
  import { join as join117 } from "path";
184107
184454
  async function runTokensImport(refInput, deps) {
184108
184455
  const { fileKey } = parseFigmaRef(refInput);
@@ -184117,7 +184464,7 @@ async function runTokensImport(refInput, deps) {
184117
184464
  if (vars !== null) {
184118
184465
  const out = tokensToVariables(vars, { fileKey, version: version2 });
184119
184466
  upsertBindings(deps.projectDir, out.bindings);
184120
- writeFileSync50(sidecarPath, JSON.stringify(out.sidecar, null, 2) + "\n");
184467
+ writeFileSync51(sidecarPath, JSON.stringify(out.sidecar, null, 2) + "\n");
184121
184468
  return { mode: "variables", entries: out.entries, sidecarPath };
184122
184469
  }
184123
184470
  const styles = await deps.client.styles(fileKey);
@@ -184131,7 +184478,7 @@ async function runTokensImport(refInput, deps) {
184131
184478
  value: null
184132
184479
  }))
184133
184480
  };
184134
- writeFileSync50(sidecarPath, JSON.stringify(sidecar, null, 2) + "\n");
184481
+ writeFileSync51(sidecarPath, JSON.stringify(sidecar, null, 2) + "\n");
184135
184482
  return { mode: "styles", entries: [], sidecarPath, styleCount: styles.length };
184136
184483
  }
184137
184484
  var tokens_default;
@@ -184181,8 +184528,8 @@ __export(component_exports, {
184181
184528
  default: () => component_default,
184182
184529
  runComponentImport: () => runComponentImport
184183
184530
  });
184184
- import { existsSync as existsSync107, mkdirSync as mkdirSync58, writeFileSync as writeFileSync51 } from "fs";
184185
- import { join as join118, relative as relative19 } from "path";
184531
+ import { existsSync as existsSync107, mkdirSync as mkdirSync58, writeFileSync as writeFileSync53 } from "fs";
184532
+ import { join as join118, relative as relative20 } from "path";
184186
184533
  function escapeAttr2(value) {
184187
184534
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
184188
184535
  }
@@ -184206,7 +184553,7 @@ async function runComponentImport(refInput, deps) {
184206
184553
  deps
184207
184554
  );
184208
184555
  const htmlFile = join118(componentDir, `${name}.html`);
184209
- writeFileSync51(htmlFile, html + "\n");
184556
+ writeFileSync53(htmlFile, html + "\n");
184210
184557
  const registryItem = {
184211
184558
  name,
184212
184559
  type: "hyperframes:component",
@@ -184226,13 +184573,13 @@ async function runComponentImport(refInput, deps) {
184226
184573
  }))
184227
184574
  ]
184228
184575
  };
184229
- writeFileSync51(
184576
+ writeFileSync53(
184230
184577
  join118(componentDir, "registry-item.json"),
184231
184578
  JSON.stringify(registryItem, null, 2) + "\n"
184232
184579
  );
184233
184580
  return {
184234
184581
  name,
184235
- htmlPath: relative19(deps.projectDir, htmlFile),
184582
+ htmlPath: relative20(deps.projectDir, htmlFile),
184236
184583
  unresolved: bindings.unresolved,
184237
184584
  rasterized: mapped.rasterize,
184238
184585
  failedRasterize
@@ -184252,7 +184599,7 @@ async function rasterizeFallback(mapped, fileKey, componentDir, deps) {
184252
184599
  continue;
184253
184600
  }
184254
184601
  frozenAssets.push(asset.record.path);
184255
- const srcRel = relative19(componentDir, join118(deps.projectDir, asset.record.path)).replaceAll(
184602
+ const srcRel = relative20(componentDir, join118(deps.projectDir, asset.record.path)).replaceAll(
184256
184603
  "\\",
184257
184604
  "/"
184258
184605
  );
@@ -184562,7 +184909,8 @@ function getSkillsUpdateMeta() {
184562
184909
  return {
184563
184910
  updateAvailable: config.skillsUpdateAvailable ?? false,
184564
184911
  outdated: config.skillsOutdatedCount ?? 0,
184565
- missing: config.skillsMissingCount ?? 0
184912
+ missing: config.skillsMissingCount ?? 0,
184913
+ removed: config.skillsRemovedCount ?? 0
184566
184914
  };
184567
184915
  }
184568
184916
  function cacheFresh(lastSkillsCheck, now) {
@@ -184570,19 +184918,21 @@ function cacheFresh(lastSkillsCheck, now) {
184570
184918
  return now - new Date(lastSkillsCheck).getTime() < CHECK_INTERVAL_MS2;
184571
184919
  }
184572
184920
  async function refreshSkillsCache() {
184573
- const result = await checkSkills();
184921
+ const result = await checkSkills({ canonical: true });
184574
184922
  if (result.location) {
184575
184923
  const config = readConfig();
184576
184924
  config.lastSkillsCheck = (/* @__PURE__ */ new Date()).toISOString();
184577
184925
  config.skillsUpdateAvailable = result.updateAvailable;
184578
184926
  config.skillsOutdatedCount = result.summary.outdated;
184579
184927
  config.skillsMissingCount = result.summary.coreMissing;
184928
+ config.skillsRemovedCount = result.summary.removed;
184580
184929
  writeConfig(config);
184581
184930
  }
184582
184931
  return {
184583
184932
  updateAvailable: result.updateAvailable,
184584
184933
  outdated: result.summary.outdated,
184585
- missing: result.summary.coreMissing
184934
+ missing: result.summary.coreMissing,
184935
+ removed: result.summary.removed
184586
184936
  };
184587
184937
  }
184588
184938
  async function checkSkillsForUpdate(force) {
@@ -184594,7 +184944,7 @@ async function checkSkillsForUpdate(force) {
184594
184944
  }
184595
184945
  }
184596
184946
  function skillsNoticeText(meta) {
184597
- const total = meta.outdated + meta.missing;
184947
+ const total = meta.outdated + meta.missing + meta.removed;
184598
184948
  if (total < 1) return null;
184599
184949
  const noun = total === 1 ? "skill" : "skills";
184600
184950
  return `
@@ -185017,7 +185367,7 @@ if (!isHelp && command !== "telemetry" && command !== "events" && command !== "u
185017
185367
  if (mod.shouldTrack()) mod.incrementCommandCount();
185018
185368
  });
185019
185369
  }
185020
- if (!isHelp && !hasJsonFlag && command !== "upgrade" && command !== "events") {
185370
+ if (!isHelp && !hasJsonFlag && command !== "upgrade" && command !== "events" && command !== "skills") {
185021
185371
  Promise.resolve().then(() => (init_autoUpdate(), autoUpdate_exports)).then((mod) => mod.reportCompletedUpdate()).catch(() => {
185022
185372
  });
185023
185373
  Promise.resolve().then(() => (init_updateCheck(), updateCheck_exports)).then(async (mod) => {