@hyperframes/producer 0.8.227 → 0.8.229

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.
@@ -3,13 +3,13 @@ import { audioFailureDiagnostics as audioFailureDiagnostics3 } from "@hyperframe
3
3
  import {
4
4
  copyFileSync as copyFileSync6,
5
5
  cpSync as cpSync2,
6
- existsSync as existsSync15,
6
+ existsSync as existsSync16,
7
7
  linkSync,
8
8
  mkdirSync as mkdirSync10,
9
9
  rmSync as rmSync7,
10
10
  writeFileSync as writeFileSync7
11
11
  } from "node:fs";
12
- import { extname as extname4, isAbsolute as isAbsolute3, join as join22, relative as relative5, sep as sep2 } from "node:path";
12
+ import { extname as extname4, isAbsolute as isAbsolute3, join as join23, relative as relative5, sep as sep2 } from "node:path";
13
13
  import {
14
14
  fpsToNumber as fpsToNumber9,
15
15
  HF_COLOR_GRADING_ATTR as HF_COLOR_GRADING_ATTR2
@@ -20,7 +20,7 @@ import {
20
20
  normalizeVp9CpuUsed,
21
21
  resolveConfig as resolveConfig3,
22
22
  declareContentAddressedUrl,
23
- renameWithRetry as renameWithRetry7,
23
+ renameWithRetry as renameWithRetry8,
24
24
  declareProbeFactsUrl
25
25
  } from "@hyperframes/engine";
26
26
 
@@ -66,7 +66,7 @@ var defaultLogger = createConsoleLogger("info");
66
66
  // src/services/renderOrchestrator.ts
67
67
  import { audioFailureDiagnostics as audioFailureDiagnostics2 } from "@hyperframes/engine";
68
68
  import {
69
- existsSync as existsSync10,
69
+ existsSync as existsSync11,
70
70
  mkdirSync as mkdirSync6,
71
71
  readdirSync as readdirSync3,
72
72
  rmSync as rmSync5,
@@ -120,7 +120,7 @@ import {
120
120
  augmentProtocolTimeoutError,
121
121
  augmentPageNavigationTimeoutError
122
122
  } from "@hyperframes/engine";
123
- import { join as join14, dirname as dirname8, resolve as resolve7 } from "path";
123
+ import { join as join15, dirname as dirname9, resolve as resolve7 } from "path";
124
124
  import { randomUUID } from "crypto";
125
125
 
126
126
  // src/services/fileServer.ts
@@ -5873,7 +5873,7 @@ import {
5873
5873
  } from "@hyperframes/engine";
5874
5874
 
5875
5875
  // src/services/render/stages/audioStage.ts
5876
- import { join as join11 } from "node:path";
5876
+ import { join as join12 } from "node:path";
5877
5877
  import {
5878
5878
  MIXED_AUDIO_FILENAME,
5879
5879
  audioFailureDiagnostics,
@@ -5882,6 +5882,16 @@ import {
5882
5882
  collectScratchLeftovers
5883
5883
  } from "@hyperframes/engine";
5884
5884
 
5885
+ // src/services/render/audioDeliveryLimit.ts
5886
+ import { existsSync as existsSync8 } from "node:fs";
5887
+ import { dirname as dirname7, join as join11 } from "node:path";
5888
+ import {
5889
+ applyAudioFxChain,
5890
+ describeFfmpegFailure as describeFfmpegFailure3,
5891
+ encodeAac as encodeAac2,
5892
+ renameWithRetry as renameWithRetry6
5893
+ } from "@hyperframes/engine";
5894
+
5885
5895
  // src/services/render/audioPadTrim.ts
5886
5896
  import { spawn } from "node:child_process";
5887
5897
  import { mkdtempSync } from "node:fs";
@@ -6342,6 +6352,48 @@ async function runFfprobeJson(args, signal) {
6342
6352
  }
6343
6353
  }
6344
6354
 
6355
+ // src/services/render/audioDeliveryLimit.ts
6356
+ var LIMIT_CEILING_DBTP = AAC_DELIVERY_TRUE_PEAK_DBFS - 2;
6357
+ var LIMIT_CHAIN = {
6358
+ version: 1,
6359
+ nodes: [{ type: "truepeak", id: "delivery", params: { ceiling: LIMIT_CEILING_DBTP } }]
6360
+ };
6361
+ async function limitDeliveryPeaks(input, deps = {
6362
+ measure: measureTruePeakDbfs,
6363
+ applyChain: applyAudioFxChain,
6364
+ encode: encodeAac2,
6365
+ rename: renameWithRetry6,
6366
+ sourceExists: existsSync8
6367
+ }) {
6368
+ const { audioPath, sourcePath, signal, timeoutMs } = input;
6369
+ if (!deps.sourceExists(sourcePath)) return { success: true };
6370
+ const peak = await deps.measure(audioPath, { timeoutMs, signal });
6371
+ if (peak <= AAC_DELIVERY_TRUE_PEAK_DBFS) return { success: true };
6372
+ const limitedPath = join11(dirname7(sourcePath), "audio-source-limited.wav");
6373
+ try {
6374
+ await deps.applyChain(sourcePath, LIMIT_CHAIN, limitedPath, { trackId: "delivery", signal });
6375
+ } catch (error) {
6376
+ if (signal?.aborted) throw error;
6377
+ input.warn?.("[audio] true-peak limit failed, the whole-mix cut applies", {
6378
+ error: error instanceof Error ? error.message : String(error)
6379
+ });
6380
+ return { success: true };
6381
+ }
6382
+ const encoded = await deps.encode(limitedPath, audioPath, input.targetDurationSeconds, {
6383
+ signal,
6384
+ timeout: timeoutMs
6385
+ });
6386
+ if (!encoded.success) {
6387
+ return {
6388
+ success: false,
6389
+ error: `[audioDeliveryLimit] ${describeFfmpegFailure3(encoded, timeoutMs)}`,
6390
+ failureReason: encoded.failureReason
6391
+ };
6392
+ }
6393
+ deps.rename(limitedPath, sourcePath, { copyFallback: true });
6394
+ return { success: true };
6395
+ }
6396
+
6345
6397
  // src/services/render/stages/audioStage.ts
6346
6398
  function assertAudioNotInterrupted(failures) {
6347
6399
  const interrupted = failures?.find((failure) => failure.reason === "external_interruption");
@@ -6365,13 +6417,22 @@ function runAudioStage(input) {
6365
6417
  }
6366
6418
  async function runAudioStageScoped(input) {
6367
6419
  const stageStart = Date.now();
6368
- const pcmSourcePath = join11(input.workDir, "audio-source.wav");
6420
+ const pcmSourcePath = join12(input.workDir, "audio-source.wav");
6369
6421
  const duration = input.totalFrames * input.fps.den / input.fps.num;
6370
6422
  try {
6371
6423
  const result = await mixAudioForDelivery(input, duration, pcmSourcePath);
6372
6424
  let audioLoweredDb;
6373
6425
  if (result.hasAudio) {
6374
6426
  const guardStart = Date.now();
6427
+ const limited = await limitDeliveryPeaks({
6428
+ audioPath: result.audioOutputPath,
6429
+ sourcePath: pcmSourcePath,
6430
+ targetDurationSeconds: duration,
6431
+ signal: input.abortSignal,
6432
+ timeoutMs: input.ffmpegProcessTimeout,
6433
+ warn: (message, details) => input.log?.warn?.(message, details)
6434
+ });
6435
+ if (!limited.success) throw encoderFailureError("Audio true-peak limit failed", limited);
6375
6436
  const peak = await constrainAacTruePeak({
6376
6437
  audioPath: result.audioOutputPath,
6377
6438
  sourcePath: pcmSourcePath,
@@ -6403,7 +6464,7 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
6403
6464
  assertNotAborted,
6404
6465
  log
6405
6466
  } = input;
6406
- const audioOutputPath = join11(workDir, MIXED_AUDIO_FILENAME);
6467
+ const audioOutputPath = join12(workDir, MIXED_AUDIO_FILENAME);
6407
6468
  let hasAudio = false;
6408
6469
  let audioError;
6409
6470
  let audioFailures;
@@ -6414,7 +6475,7 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
6414
6475
  audioResult = await processCompositionAudio(
6415
6476
  audios,
6416
6477
  projectDir,
6417
- join11(workDir, "audio-work"),
6478
+ join12(workDir, "audio-work"),
6418
6479
  audioOutputPath,
6419
6480
  duration,
6420
6481
  abortSignal,
@@ -6482,8 +6543,8 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
6482
6543
  }
6483
6544
 
6484
6545
  // src/services/render/stages/captureStage.ts
6485
- import { existsSync as existsSync8, readdirSync, statfsSync } from "node:fs";
6486
- import { join as join12 } from "node:path";
6546
+ import { existsSync as existsSync9, readdirSync, statfsSync } from "node:fs";
6547
+ import { join as join13 } from "node:path";
6487
6548
  import {
6488
6549
  classifyCaptureFailure as classifyCaptureFailure2,
6489
6550
  frameFileExtension,
@@ -6534,16 +6595,16 @@ function diskCaptureShortfallError(needBytes, freeBytes, framesDir, basis, remed
6534
6595
  }
6535
6596
  function measureCaptureFrameBytes(workDir, framesDir) {
6536
6597
  let total = sampleDirectoryBytes(framesDir);
6537
- if (!existsSync8(workDir)) return total;
6598
+ if (!existsSync9(workDir)) return total;
6538
6599
  for (const attempt of readdirSync(workDir)) {
6539
6600
  if (/^retry-\d+-batch-\d+-worker-\d+$/.test(attempt)) {
6540
- total += sampleDirectoryBytes(join12(workDir, attempt));
6601
+ total += sampleDirectoryBytes(join13(workDir, attempt));
6541
6602
  continue;
6542
6603
  }
6543
6604
  if (!/^capture-attempt-\d+$/.test(attempt)) continue;
6544
- const attemptDir = join12(workDir, attempt);
6605
+ const attemptDir = join13(workDir, attempt);
6545
6606
  for (const name of readdirSync(attemptDir)) {
6546
- if (/^worker-\d+$/.test(name)) total += sampleDirectoryBytes(join12(attemptDir, name));
6607
+ if (/^worker-\d+$/.test(name)) total += sampleDirectoryBytes(join13(attemptDir, name));
6547
6608
  }
6548
6609
  }
6549
6610
  return total;
@@ -6871,7 +6932,7 @@ import {
6871
6932
  // src/services/render/stages/encodeStage.ts
6872
6933
  import {
6873
6934
  copyFileSync as copyFileSync4,
6874
- existsSync as existsSync9,
6935
+ existsSync as existsSync10,
6875
6936
  mkdirSync as mkdirSync5,
6876
6937
  readdirSync as readdirSync2,
6877
6938
  readFileSync as readFileSync4,
@@ -6880,7 +6941,7 @@ import {
6880
6941
  writeFileSync as writeFileSync3
6881
6942
  } from "node:fs";
6882
6943
  import { readFile as readFile2 } from "node:fs/promises";
6883
- import { dirname as dirname7, join as join13 } from "node:path";
6944
+ import { dirname as dirname8, join as join14 } from "node:path";
6884
6945
  import {
6885
6946
  encodeFramesChunkedConcat,
6886
6947
  encodeFramesFromDir,
@@ -7005,7 +7066,7 @@ async function encodeGifFromDir(framesDir, framePattern, outputPath, input) {
7005
7066
  const failure = await reencodeWithClearedWholeFrames(argsInput, run, startTime);
7006
7067
  if (failure) return failure;
7007
7068
  }
7008
- const fileSize = existsSync9(outputPath) ? statSync4(outputPath).size : 0;
7069
+ const fileSize = existsSync10(outputPath) ? statSync4(outputPath).size : 0;
7009
7070
  return {
7010
7071
  success: true,
7011
7072
  outputPath,
@@ -7091,7 +7152,7 @@ function encodeWhileCapturing(input, totalFrames) {
7091
7152
  await new Promise((resolve10) => wake = resolve10);
7092
7153
  }
7093
7154
  if (signal.aborted) return;
7094
- const mergedPath = join13(input.framesDir, formatCaptureFrameName(next, "jpg"));
7155
+ const mergedPath = join14(input.framesDir, formatCaptureFrameName(next, "jpg"));
7095
7156
  const frame = await readLandedFrame(landed.get(next), mergedPath);
7096
7157
  landed.delete(next);
7097
7158
  if (!await stream.writeFrame(frame)) {
@@ -7166,7 +7227,7 @@ async function runEncodeStage(input) {
7166
7227
  const stage5Start = Date.now();
7167
7228
  if (isPngSequence) {
7168
7229
  const encoded = startEncodeProgress(job, "Writing PNG sequence", onProgress);
7169
- if (!existsSync9(outputPath)) mkdirSync5(outputPath, { recursive: true });
7230
+ if (!existsSync10(outputPath)) mkdirSync5(outputPath, { recursive: true });
7170
7231
  const captured = readdirSync2(framesDir).filter((name) => name.endsWith(".png")).sort();
7171
7232
  if (captured.length === 0) {
7172
7233
  throw new Error(
@@ -7174,11 +7235,11 @@ async function runEncodeStage(input) {
7174
7235
  );
7175
7236
  }
7176
7237
  captured.forEach((name, i) => {
7177
- const dst = join13(outputPath, formatExportFrameName(i, "png"));
7178
- copyFileSync4(join13(framesDir, name), dst);
7238
+ const dst = join14(outputPath, formatExportFrameName(i, "png"));
7239
+ copyFileSync4(join14(framesDir, name), dst);
7179
7240
  });
7180
- if (hasAudio && audioOutputPath && existsSync9(audioOutputPath)) {
7181
- copyFileSync4(audioOutputPath, join13(outputPath, MIXED_AUDIO_FILENAME2));
7241
+ if (hasAudio && audioOutputPath && existsSync10(audioOutputPath)) {
7242
+ copyFileSync4(audioOutputPath, join14(outputPath, MIXED_AUDIO_FILENAME2));
7182
7243
  log.info(
7183
7244
  `[Render] png-sequence: ${MIXED_AUDIO_FILENAME2} sidecar written to ${outputPath}/${MIXED_AUDIO_FILENAME2}`
7184
7245
  );
@@ -7198,7 +7259,7 @@ async function runEncodeStage(input) {
7198
7259
  const encodeResult2 = await encodeGifFromDir(framesDir, framePattern2, outputPath, {
7199
7260
  fps: job.config.fps,
7200
7261
  loop,
7201
- palettePath: join13(dirname7(videoOnlyPath), "gif-palette.png"),
7262
+ palettePath: join14(dirname8(videoOnlyPath), "gif-palette.png"),
7202
7263
  preserveAlpha: needsAlpha,
7203
7264
  signal: abortSignal,
7204
7265
  timeout: engineCfg.ffmpegEncodeTimeout
@@ -7257,7 +7318,7 @@ function sampleDirectoryBytes(dir) {
7257
7318
  continue;
7258
7319
  }
7259
7320
  for (const name of entries) {
7260
- const full = join14(current, name);
7321
+ const full = join15(current, name);
7261
7322
  try {
7262
7323
  const st = statSync5(full);
7263
7324
  if (st.isDirectory()) {
@@ -7343,8 +7404,8 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
7343
7404
  const ranges = [];
7344
7405
  let rangeStart = null;
7345
7406
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
7346
- const framePath = join14(framesDir, formatCaptureFrameName(frameIndex, frameExt));
7347
- const missing = !existsSync10(framePath) || statSync5(framePath).size <= 8;
7407
+ const framePath = join15(framesDir, formatCaptureFrameName(frameIndex, frameExt));
7408
+ const missing = !existsSync11(framePath) || statSync5(framePath).size <= 8;
7348
7409
  if (missing && rangeStart === null) {
7349
7410
  rangeStart = frameIndex;
7350
7411
  } else if (!missing && rangeStart !== null) {
@@ -7360,7 +7421,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
7360
7421
  function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, rangeStart = 0, stride = 1) {
7361
7422
  const workersPerBatch = Math.max(1, Math.floor(maxWorkers));
7362
7423
  const batches = [];
7363
- const outputDirFor = (batchIndex, workerId) => join14(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`);
7424
+ const outputDirFor = (batchIndex, workerId) => join15(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`);
7364
7425
  if (stride > 1) {
7365
7426
  const spans = /* @__PURE__ */ new Map();
7366
7427
  for (const range of ranges) {
@@ -7433,8 +7494,8 @@ function isRecoverableParallelCaptureError(error) {
7433
7494
  function countCapturedFrames(totalFrames, framesDir, frameExt) {
7434
7495
  let captured = 0;
7435
7496
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
7436
- const framePath = join14(framesDir, formatCaptureFrameName(frameIndex, frameExt));
7437
- if (existsSync10(framePath)) captured++;
7497
+ const framePath = join15(framesDir, formatCaptureFrameName(frameIndex, frameExt));
7498
+ if (existsSync11(framePath)) captured++;
7438
7499
  }
7439
7500
  return captured;
7440
7501
  }
@@ -7459,7 +7520,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
7459
7520
  reason: attempt === 0 ? "initial" : pendingTransientRetry ? "transient-retry" : "retry"
7460
7521
  });
7461
7522
  pendingTransientRetry = false;
7462
- const attemptWorkDir = join14(options.workDir, `capture-attempt-${attempt}`);
7523
+ const attemptWorkDir = join15(options.workDir, `capture-attempt-${attempt}`);
7463
7524
  const batches = missingRanges ? buildMissingFrameRetryBatches(
7464
7525
  missingRanges,
7465
7526
  currentWorkers,
@@ -7651,7 +7712,7 @@ function explainStreamingEncodeGate(cfg, outputFormat, workerCount, durationSeco
7651
7712
  var DEFAULT_SEGMENTED_MIN_SECONDS = Number.POSITIVE_INFINITY;
7652
7713
 
7653
7714
  // src/services/distributed/planFrameCost.ts
7654
- import { join as join17 } from "node:path";
7715
+ import { join as join18 } from "node:path";
7655
7716
  import {
7656
7717
  closeCaptureSession as closeCaptureSession9,
7657
7718
  createCaptureSession as createCaptureSession9,
@@ -7660,8 +7721,8 @@ import {
7660
7721
  } from "@hyperframes/engine";
7661
7722
 
7662
7723
  // src/services/distributed/chunkFrames.ts
7663
- import { existsSync as existsSync12, readdirSync as readdirSync4 } from "node:fs";
7664
- import { extname as extname2, join as join16 } from "node:path";
7724
+ import { existsSync as existsSync13, readdirSync as readdirSync4 } from "node:fs";
7725
+ import { extname as extname2, join as join17 } from "node:path";
7665
7726
  import {
7666
7727
  compositionRequiresWebGpu as compositionRequiresWebGpu3,
7667
7728
  createFrameLookupTable as createFrameLookupTable2,
@@ -7671,8 +7732,8 @@ import {
7671
7732
 
7672
7733
  // src/services/distributed/shared.ts
7673
7734
  import { execFile as execFileCallback } from "node:child_process";
7674
- import { dirname as dirname9, join as join15 } from "node:path";
7675
- import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
7735
+ import { dirname as dirname10, join as join16 } from "node:path";
7736
+ import { existsSync as existsSync12, readFileSync as readFileSync5 } from "node:fs";
7676
7737
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7677
7738
  import { promisify as promisify2 } from "node:util";
7678
7739
  import {
@@ -7687,8 +7748,8 @@ function isPlanAudioArtifactPath(path) {
7687
7748
  }
7688
7749
  function resolvePlanAudioPath(planDir) {
7689
7750
  for (const name of [PLAN_AUDIO_RELATIVE_PATH, PLAN_AUDIO_LEGACY_RELATIVE_PATH]) {
7690
- const candidate = join15(planDir, name);
7691
- if (existsSync11(candidate)) return candidate;
7751
+ const candidate = join16(planDir, name);
7752
+ if (existsSync12(candidate)) return candidate;
7692
7753
  }
7693
7754
  return null;
7694
7755
  }
@@ -7945,11 +8006,11 @@ function buildSyntheticRenderJob(input) {
7945
8006
  var cachedProducerVersion = null;
7946
8007
  function readProducerVersion() {
7947
8008
  if (cachedProducerVersion !== null) return cachedProducerVersion;
7948
- const startDir = dirname9(fileURLToPath3(import.meta.url));
8009
+ const startDir = dirname10(fileURLToPath3(import.meta.url));
7949
8010
  let current = startDir;
7950
8011
  for (let i = 0; i < 10; i++) {
7951
- const candidate = join15(current, "package.json");
7952
- if (existsSync11(candidate)) {
8012
+ const candidate = join16(current, "package.json");
8013
+ if (existsSync12(candidate)) {
7953
8014
  try {
7954
8015
  const pkg = JSON.parse(readFileSync5(candidate, "utf-8"));
7955
8016
  if (pkg.name === "@hyperframes/producer" && typeof pkg.version === "string") {
@@ -7959,7 +8020,7 @@ function readProducerVersion() {
7959
8020
  } catch {
7960
8021
  }
7961
8022
  }
7962
- const parent = dirname9(current);
8023
+ const parent = dirname10(current);
7963
8024
  if (parent === current) break;
7964
8025
  current = parent;
7965
8026
  }
@@ -8002,8 +8063,8 @@ function frameNumberFromFileName(name) {
8002
8063
  function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v1") {
8003
8064
  const result = [];
8004
8065
  for (const v of videos) {
8005
- const outputDir = join16(planDir, "video-frames", v.videoId);
8006
- if (!existsSync12(outputDir)) {
8066
+ const outputDir = join17(planDir, "video-frames", v.videoId);
8067
+ if (!existsSync13(outputDir)) {
8007
8068
  throw new Error(
8008
8069
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
8009
8070
  );
@@ -8021,7 +8082,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
8021
8082
  if (!frameName) continue;
8022
8083
  const frameNumber = indexMode === "sparse-v2" ? frameNumberFromFileName(frameName) : null;
8023
8084
  const frameIndex = frameNumber === null ? i : frameNumber - 1;
8024
- framePaths.set(frameIndex, join16(outputDir, frameName));
8085
+ framePaths.set(frameIndex, join17(outputDir, frameName));
8025
8086
  }
8026
8087
  result.push({
8027
8088
  videoId: v.videoId,
@@ -8111,15 +8172,15 @@ async function extractDeferredVideoFramesForChunk(input) {
8111
8172
  const shown = shownDeferredFrameIndexes(input.planVideos, input.frames, input.fps);
8112
8173
  return Promise.all(
8113
8174
  deferred.map(async (video) => {
8114
- const outputDir = join16(input.outputRoot, video.videoId);
8175
+ const outputDir = join17(input.outputRoot, video.videoId);
8115
8176
  const indexes = [...shown.get(video.videoId) ?? []].sort((a, b) => a - b);
8116
8177
  if (indexes.length === 0) {
8117
8178
  return { ...video, outputDir, framePaths: /* @__PURE__ */ new Map(), ownedByLookup: false };
8118
8179
  }
8119
8180
  const range = video.deferredRange;
8120
8181
  const remoteUrl = remoteSources[range.sourcePath];
8121
- const sourcePath = remoteUrl ?? join16(input.planDir, ...range.sourcePath.split("/"));
8122
- if (remoteUrl === void 0 && !existsSync12(sourcePath)) {
8182
+ const sourcePath = remoteUrl ?? join17(input.planDir, ...range.sourcePath.split("/"));
8183
+ if (remoteUrl === void 0 && !existsSync13(sourcePath)) {
8123
8184
  throw new RenderChunkValidationError(
8124
8185
  MISSING_PLAN_ARTIFACT,
8125
8186
  `[renderChunk] planDir is missing the source for video ${JSON.stringify(video.videoId)}: ${range.sourcePath}`
@@ -8167,12 +8228,12 @@ async function measurePlanSecondsPerFrame(input) {
8167
8228
  planVideos,
8168
8229
  frames: sampled,
8169
8230
  fps: fpsRatio,
8170
- outputRoot: join17(workDir, "frame-cost-video-frames"),
8231
+ outputRoot: join18(workDir, "frame-cost-video-frames"),
8171
8232
  cfg: input.cfg
8172
8233
  })
8173
8234
  ];
8174
8235
  const lookup = extracted.length > 0 ? createFrameLookupTable3(planVideos.videos, extracted, resolveRenderFpsConfig(fpsRatio).value) : null;
8175
- const compiledDir = join17(planDir, "compiled");
8236
+ const compiledDir = join18(planDir, "compiled");
8176
8237
  const fileServer = await createFileServer({
8177
8238
  projectDir: compiledDir,
8178
8239
  compiledDir,
@@ -8184,7 +8245,7 @@ async function measurePlanSecondsPerFrame(input) {
8184
8245
  try {
8185
8246
  session = await createCaptureSession9(
8186
8247
  fileServer.url,
8187
- join17(workDir, "frame-cost"),
8248
+ join18(workDir, "frame-cost"),
8188
8249
  buildChunkCaptureOptions({
8189
8250
  dimensions: { ...input, fpsNum: fps, fpsDen: 1 },
8190
8251
  encoder: input,
@@ -8281,8 +8342,8 @@ function buildWeightedChunkSlices(weights, chunkCount, minFrames, maxFrames) {
8281
8342
  }
8282
8343
 
8283
8344
  // src/services/render/stages/freezePlan.ts
8284
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync6, readdirSync as readdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
8285
- import { join as join18, relative as relative3, resolve as resolve8 } from "node:path";
8345
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync6, readdirSync as readdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
8346
+ import { join as join19, relative as relative3, resolve as resolve8 } from "node:path";
8286
8347
 
8287
8348
  // src/services/distributed/planProtocol.ts
8288
8349
  var PLAN_SCHEMA_VERSION = 1;
@@ -8475,7 +8536,7 @@ function planFileSha256(absolutePath, digests) {
8475
8536
  return sha256;
8476
8537
  }
8477
8538
  async function prehashPlanFiles(dir, digests) {
8478
- if (!existsSync13(dir)) return;
8539
+ if (!existsSync14(dir)) return;
8479
8540
  for (const { absolutePath } of listPlanFiles(dir)) {
8480
8541
  if (!digests.has(absolutePath)) digests.set(absolutePath, await sha256FileAsync(absolutePath));
8481
8542
  }
@@ -8500,7 +8561,7 @@ function listPlanFiles(planDir) {
8500
8561
  function walk(dir) {
8501
8562
  const entries = readdirSync5(dir, { withFileTypes: true });
8502
8563
  for (const entry of entries) {
8503
- const full = join18(dir, entry.name);
8564
+ const full = join19(dir, entry.name);
8504
8565
  if (entry.isDirectory()) {
8505
8566
  walk(full);
8506
8567
  } else if (entry.isFile()) {
@@ -8541,19 +8602,19 @@ var PLAN_REMOTE_FILES_RELATIVE_PATH = "meta/remote-files.json";
8541
8602
  function writePlanRemoteFiles(planDir, files) {
8542
8603
  if (files.length === 0) return;
8543
8604
  const sorted = [...files].sort((a, b) => a.path < b.path ? -1 : 1);
8544
- writeFileSync5(join18(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH), JSON.stringify(sorted), "utf-8");
8605
+ writeFileSync5(join19(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH), JSON.stringify(sorted), "utf-8");
8545
8606
  }
8546
8607
  function readPlanRemoteFiles(planDir) {
8547
- const path = join18(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH);
8548
- return existsSync13(path) ? JSON.parse(readFileSync6(path, "utf-8")) : [];
8608
+ const path = join19(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH);
8609
+ return existsSync14(path) ? JSON.parse(readFileSync6(path, "utf-8")) : [];
8549
8610
  }
8550
8611
  function recomputePlanHashFromPlanDir(planDir, digests) {
8551
- const planJsonPath = join18(planDir, "plan.json");
8552
- const encoderJsonPath = join18(planDir, "meta", "encoder.json");
8553
- if (!existsSync13(planJsonPath)) {
8612
+ const planJsonPath = join19(planDir, "plan.json");
8613
+ const encoderJsonPath = join19(planDir, "meta", "encoder.json");
8614
+ if (!existsSync14(planJsonPath)) {
8554
8615
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
8555
8616
  }
8556
- if (!existsSync13(encoderJsonPath)) {
8617
+ if (!existsSync14(encoderJsonPath)) {
8557
8618
  throw new Error(`[freezePlan] meta/encoder.json missing: ${encoderJsonPath}`);
8558
8619
  }
8559
8620
  const planJson = JSON.parse(readFileSync6(planJsonPath, "utf-8"));
@@ -8583,21 +8644,21 @@ async function freezePlan(input) {
8583
8644
  hasAudio,
8584
8645
  digests
8585
8646
  } = input;
8586
- if (!existsSync13(planDir)) {
8647
+ if (!existsSync14(planDir)) {
8587
8648
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
8588
8649
  }
8589
- const metaDir = join18(planDir, "meta");
8590
- if (!existsSync13(metaDir)) mkdirSync7(metaDir, { recursive: true });
8650
+ const metaDir = join19(planDir, "meta");
8651
+ if (!existsSync14(metaDir)) mkdirSync7(metaDir, { recursive: true });
8591
8652
  writeFileSync5(
8592
- join18(metaDir, "composition.json"),
8653
+ join19(metaDir, "composition.json"),
8593
8654
  `${JSON.stringify(composition, null, 2)}
8594
8655
  `,
8595
8656
  "utf-8"
8596
8657
  );
8597
8658
  const encoderForCanonical = stripUndefined(encoder);
8598
8659
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
8599
- writeFileSync5(join18(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
8600
- writeFileSync5(join18(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
8660
+ writeFileSync5(join19(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
8661
+ writeFileSync5(join19(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
8601
8662
  `, "utf-8");
8602
8663
  const { compositionHtml, assets } = collectPlanAssetShas(planDir, digests);
8603
8664
  const planHash = computePlanHash({
@@ -8621,7 +8682,7 @@ async function freezePlan(input) {
8621
8682
  duration: durationSeconds,
8622
8683
  hasAudio
8623
8684
  };
8624
- const planJsonPath = join18(planDir, "plan.json");
8685
+ const planJsonPath = join19(planDir, "plan.json");
8625
8686
  writeFileSync5(planJsonPath, `${JSON.stringify(planJson, null, 2)}
8626
8687
  `, "utf-8");
8627
8688
  return { planJsonPath, planHash };
@@ -8663,16 +8724,16 @@ function applyRuntimeEnvSnapshot(snapshot, env = process.env) {
8663
8724
  }
8664
8725
 
8665
8726
  // src/services/distributed/chunkAudio.ts
8666
- import { closeSync as closeSync4, existsSync as existsSync14, ftruncateSync, mkdirSync as mkdirSync9, openSync as openSync4, readFileSync as readFileSync7 } from "node:fs";
8727
+ import { closeSync as closeSync4, existsSync as existsSync15, ftruncateSync, mkdirSync as mkdirSync9, openSync as openSync4, readFileSync as readFileSync7 } from "node:fs";
8667
8728
  import { writeFileSync as writeFileSync6, writeSync } from "node:fs";
8668
- import { join as join20 } from "node:path";
8669
- import { appendRenderProvenanceArgs, describeFfmpegFailure as describeFfmpegFailure3, runFfmpeg as runFfmpeg7 } from "@hyperframes/engine";
8729
+ import { join as join21 } from "node:path";
8730
+ import { appendRenderProvenanceArgs, describeFfmpegFailure as describeFfmpegFailure4, runFfmpeg as runFfmpeg7 } from "@hyperframes/engine";
8670
8731
 
8671
8732
  // src/services/distributed/mp4Stitch.ts
8672
8733
  import { createReadStream as createReadStream4, createWriteStream, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, rmSync as rmSync6 } from "node:fs";
8673
8734
  import { open } from "node:fs/promises";
8674
- import { renameWithRetry as renameWithRetry6 } from "@hyperframes/engine";
8675
- import { dirname as dirname10, join as join19 } from "node:path";
8735
+ import { renameWithRetry as renameWithRetry7 } from "@hyperframes/engine";
8736
+ import { dirname as dirname11, join as join20 } from "node:path";
8676
8737
  import { finished, pipeline } from "node:stream/promises";
8677
8738
  function boxAt(src, off, at, limit) {
8678
8739
  let size = src.readUInt32BE(off);
@@ -9036,15 +9097,15 @@ async function writeStitchedMp4(chunkPaths, outputPath, audioPath) {
9036
9097
  const sourcePaths = audioPath ? [audioPath, ...chunkPaths] : chunkPaths;
9037
9098
  const layouts = await Promise.all(sourcePaths.map((path) => readMp4Layout(fileRange(path))));
9038
9099
  const header = audioPath ? buildStitchedHeader(layouts.slice(1), layouts[0]) : buildStitchedHeader(layouts);
9039
- mkdirSync8(dirname10(outputPath), { recursive: true });
9100
+ mkdirSync8(dirname11(outputPath), { recursive: true });
9040
9101
  const workDir = mkdtempSync2(`${outputPath}.stitch-`);
9041
- const out = createWriteStream(join19(workDir, "out.mp4"));
9102
+ const out = createWriteStream(join20(workDir, "out.mp4"));
9042
9103
  try {
9043
9104
  out.write(header);
9044
9105
  for (const [i, path] of sourcePaths.entries()) await copyPayload(path, layouts[i], i, out);
9045
9106
  out.end();
9046
9107
  await finished(out);
9047
- renameWithRetry6(join19(workDir, "out.mp4"), outputPath);
9108
+ renameWithRetry7(join20(workDir, "out.mp4"), outputPath);
9048
9109
  } finally {
9049
9110
  out.destroy();
9050
9111
  rmSync6(workDir, { recursive: true, force: true });
@@ -9138,7 +9199,7 @@ async function writeChunkAudioSlices(input) {
9138
9199
  });
9139
9200
  const bytes = readFileSync7(input.audioPath);
9140
9201
  const layout = { sizeBytes: bytes.length, payloadStart, payloadEnd, partStarts: {} };
9141
- mkdirSync9(join20(input.planDir, SLICE_DIR), { recursive: true });
9202
+ mkdirSync9(join21(input.planDir, SLICE_DIR), { recursive: true });
9142
9203
  input.chunks.forEach((_, index) => {
9143
9204
  const cut = audioCutForChunk(grid, input.chunks, index, input.fps);
9144
9205
  if (!cut) return;
@@ -9146,17 +9207,17 @@ async function writeChunkAudioSlices(input) {
9146
9207
  const start = offsets[cut.firstPacket];
9147
9208
  layout.partStarts[index] = start;
9148
9209
  const end = offsets[last] + track.sizes[last];
9149
- writeFileSync6(join20(input.planDir, chunkAudioSlicePath(index)), bytes.subarray(start, end));
9210
+ writeFileSync6(join21(input.planDir, chunkAudioSlicePath(index)), bytes.subarray(start, end));
9150
9211
  });
9151
9212
  const frame = [bytes.subarray(0, payloadStart), bytes.subarray(payloadEnd)];
9152
- writeFileSync6(join20(input.planDir, SLICE_FRAME), Buffer.concat(frame));
9153
- writeFileSync6(join20(input.planDir, SLICE_LAYOUT), JSON.stringify(layout));
9213
+ writeFileSync6(join21(input.planDir, SLICE_FRAME), Buffer.concat(frame));
9214
+ writeFileSync6(join21(input.planDir, SLICE_LAYOUT), JSON.stringify(layout));
9154
9215
  }
9155
9216
  function chunkAudioSource(planDir, chunkIndex, scratchPath) {
9156
- const layoutPath = join20(planDir, SLICE_LAYOUT);
9157
- if (!existsSync14(layoutPath)) return resolvePlanAudioPath(planDir);
9217
+ const layoutPath = join21(planDir, SLICE_LAYOUT);
9218
+ if (!existsSync15(layoutPath)) return resolvePlanAudioPath(planDir);
9158
9219
  const layout = JSON.parse(readFileSync7(layoutPath, "utf-8"));
9159
- const frame = readFileSync7(join20(planDir, SLICE_FRAME));
9220
+ const frame = readFileSync7(join21(planDir, SLICE_FRAME));
9160
9221
  const fd = openSync4(scratchPath, "w");
9161
9222
  try {
9162
9223
  writeSync(fd, frame, 0, layout.payloadStart, 0);
@@ -9169,7 +9230,7 @@ function chunkAudioSource(planDir, chunkIndex, scratchPath) {
9169
9230
  );
9170
9231
  const start = layout.partStarts[chunkIndex];
9171
9232
  if (start !== void 0) {
9172
- const part = readFileSync7(join20(planDir, chunkAudioSlicePath(chunkIndex)));
9233
+ const part = readFileSync7(join21(planDir, chunkAudioSlicePath(chunkIndex)));
9173
9234
  writeSync(fd, part, 0, part.length, start);
9174
9235
  }
9175
9236
  ftruncateSync(fd, layout.sizeBytes);
@@ -9197,7 +9258,7 @@ async function muxChunkWithAudio(input) {
9197
9258
  const result = await runFfmpeg7(args, { signal: input.signal, timeout: input.timeoutMs });
9198
9259
  if (!result.success) {
9199
9260
  throw new Error(
9200
- `[chunkAudio] chunk mux failed: ${describeFfmpegFailure3(result, input.timeoutMs)}`
9261
+ `[chunkAudio] chunk mux failed: ${describeFfmpegFailure4(result, input.timeoutMs)}`
9201
9262
  );
9202
9263
  }
9203
9264
  const slice = input.chunks[input.chunkIndex];
@@ -9225,7 +9286,7 @@ async function muxChunkWithAudio(input) {
9225
9286
  // src/services/distributed/planSize.ts
9226
9287
  import { createHash as createHash7 } from "node:crypto";
9227
9288
  import { lstatSync, readdirSync as readdirSync6 } from "node:fs";
9228
- import { extname as extname3, join as join21, relative as relative4 } from "node:path";
9289
+ import { extname as extname3, join as join22, relative as relative4 } from "node:path";
9229
9290
  var MAX_TOP_COMPONENTS = 10;
9230
9291
  var SOURCE_MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
9231
9292
  ".aac",
@@ -9337,7 +9398,7 @@ function walkRegularFiles(dir, visit) {
9337
9398
  return;
9338
9399
  }
9339
9400
  for (const entry of entries) {
9340
- const full = join21(dir, entry.name);
9401
+ const full = join22(dir, entry.name);
9341
9402
  if (entry.isDirectory()) {
9342
9403
  walkRegularFiles(full, visit);
9343
9404
  } else if (entry.isFile()) {
@@ -9553,13 +9614,13 @@ function assertPositiveInteger(name, value) {
9553
9614
  }
9554
9615
  var FREEZE_OWNED_PLAN_FILES = [
9555
9616
  "plan.json",
9556
- join22("meta", "composition.json"),
9557
- join22("meta", "encoder.json"),
9558
- join22("meta", "chunks.json")
9617
+ join23("meta", "composition.json"),
9618
+ join23("meta", "encoder.json"),
9619
+ join23("meta", "chunks.json")
9559
9620
  ];
9560
9621
  function removeFreezeOwnedPlanFiles(planDir) {
9561
9622
  for (const relativePath of FREEZE_OWNED_PLAN_FILES) {
9562
- rmSync7(join22(planDir, relativePath), { force: true });
9623
+ rmSync7(join23(planDir, relativePath), { force: true });
9563
9624
  }
9564
9625
  }
9565
9626
  function buildChunkSlices(totalFrames, chunkCount, effectiveChunkSize) {
@@ -9714,19 +9775,19 @@ function createVideoSourceShipper(input) {
9714
9775
  const known = shipped.get(srcPath);
9715
9776
  if (known) return known;
9716
9777
  const stagedRel = pathInside(input.workVideoFramesDir, srcPath);
9717
- const current = stagedRel === null ? srcPath : join22(input.planDir, "video-frames", stagedRel);
9778
+ const current = stagedRel === null ? srcPath : join23(input.planDir, "video-frames", stagedRel);
9718
9779
  let result = null;
9719
9780
  for (const root of stagedRel === null ? [input.workCompiledDir, input.projectDir] : []) {
9720
9781
  const rel = pathInside(root, srcPath);
9721
- if (rel !== null && (existsSync15(join22(input.planDir, "compiled", rel)) || input.isRemote(srcPath))) {
9782
+ if (rel !== null && (existsSync16(join23(input.planDir, "compiled", rel)) || input.isRemote(srcPath))) {
9722
9783
  result = ["compiled", ...rel.split(sep2)].join("/");
9723
9784
  break;
9724
9785
  }
9725
9786
  }
9726
9787
  if (result === null) {
9727
9788
  result = `video-sources/${shipped.size}${extname4(current)}`;
9728
- const destination = join22(input.planDir, ...result.split("/"));
9729
- mkdirSync10(join22(input.planDir, "video-sources"), { recursive: true });
9789
+ const destination = join23(input.planDir, ...result.split("/"));
9790
+ mkdirSync10(join23(input.planDir, "video-sources"), { recursive: true });
9730
9791
  try {
9731
9792
  linkSync(current, destination);
9732
9793
  } catch {
@@ -9746,7 +9807,7 @@ async function compilePlanComposition(projectDir, config, planDir, options) {
9746
9807
  useGpu: false,
9747
9808
  browserGpuMode: "software"
9748
9809
  });
9749
- if (!existsSync15(planDir)) mkdirSync10(planDir, { recursive: true });
9810
+ if (!existsSync16(planDir)) mkdirSync10(planDir, { recursive: true });
9750
9811
  const log = config.logger ?? defaultLogger;
9751
9812
  const sizeLimitBytes = options.executionPlanSizeLimitBytes ?? config.planDirSizeLimitBytes ?? PLAN_DIR_SIZE_LIMIT_BYTES;
9752
9813
  const abortSignal = config.abortSignal;
@@ -9775,14 +9836,14 @@ async function compilePlanComposition(projectDir, config, planDir, options) {
9775
9836
  variables: config.variables
9776
9837
  });
9777
9838
  const entryFile = config.entryFile ?? "index.html";
9778
- const htmlPath = join22(projectDir, entryFile);
9779
- if (!existsSync15(htmlPath)) {
9839
+ const htmlPath = join23(projectDir, entryFile);
9840
+ if (!existsSync16(htmlPath)) {
9780
9841
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
9781
9842
  }
9782
- const workDir = join22(planDir, ".plan-work");
9843
+ const workDir = join23(planDir, ".plan-work");
9783
9844
  rmSync7(workDir, { recursive: true, force: true });
9784
9845
  mkdirSync10(workDir, { recursive: true });
9785
- const compiledDir = join22(workDir, "compiled");
9846
+ const compiledDir = join23(workDir, "compiled");
9786
9847
  mkdirSync10(compiledDir, { recursive: true });
9787
9848
  let stageStarted = Date.now();
9788
9849
  cpSync2(projectDir, compiledDir, {
@@ -9796,10 +9857,10 @@ async function compilePlanComposition(projectDir, config, planDir, options) {
9796
9857
  }
9797
9858
  });
9798
9859
  logPlanStage(log, "copy", stageStarted);
9799
- const finalCompiledDir = join22(planDir, "compiled");
9860
+ const finalCompiledDir = join23(planDir, "compiled");
9800
9861
  const needsAlpha = outputNeedsAlpha(config.format);
9801
9862
  const remoteFiles = Object.entries(options.remoteFiles ?? {});
9802
- const remoteLocalPath = (rel) => join22(projectDir, ...rel.split("/"));
9863
+ const remoteLocalPath = (rel) => join23(projectDir, ...rel.split("/"));
9803
9864
  for (const [, file] of remoteFiles) {
9804
9865
  declareContentAddressedUrl(file.url, file.sha256);
9805
9866
  if (file.probeFactsUrl) declareProbeFactsUrl(file.url, file.probeFactsUrl);
@@ -9985,18 +10046,18 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
9985
10046
  let stageStarted = Date.now();
9986
10047
  const extractResult = await extractPlanVideos(c, options.deferVideoExtraction);
9987
10048
  logPlanStage(log, "extract", stageStarted);
9988
- const stagedVideoFrames = join22(compiledDir, "__hyperframes_video_frames");
9989
- const videoFramesDst = join22(planDir, "video-frames");
9990
- if (existsSync15(videoFramesDst)) rmSync7(videoFramesDst, { recursive: true, force: true });
9991
- const videoSourcesDir = join22(planDir, "video-sources");
10049
+ const stagedVideoFrames = join23(compiledDir, "__hyperframes_video_frames");
10050
+ const videoFramesDst = join23(planDir, "video-frames");
10051
+ if (existsSync16(videoFramesDst)) rmSync7(videoFramesDst, { recursive: true, force: true });
10052
+ const videoSourcesDir = join23(planDir, "video-sources");
9992
10053
  rmSync7(videoSourcesDir, { recursive: true, force: true });
9993
- if (existsSync15(stagedVideoFrames)) {
9994
- renameWithRetry7(stagedVideoFrames, videoFramesDst);
10054
+ if (existsSync16(stagedVideoFrames)) {
10055
+ renameWithRetry8(stagedVideoFrames, videoFramesDst);
9995
10056
  } else {
9996
10057
  mkdirSync10(videoFramesDst, { recursive: true });
9997
10058
  }
9998
- if (existsSync15(finalCompiledDir)) rmSync7(finalCompiledDir, { recursive: true, force: true });
9999
- renameWithRetry7(compiledDir, finalCompiledDir);
10059
+ if (existsSync16(finalCompiledDir)) rmSync7(finalCompiledDir, { recursive: true, force: true });
10060
+ renameWithRetry8(compiledDir, finalCompiledDir);
10000
10061
  const shipVideoSource = createVideoSourceShipper({
10001
10062
  planDir,
10002
10063
  projectDir,
@@ -10025,7 +10086,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
10025
10086
  };
10026
10087
  })
10027
10088
  });
10028
- mkdirSync10(join22(planDir, "meta"), { recursive: true });
10089
+ mkdirSync10(join23(planDir, "meta"), { recursive: true });
10029
10090
  writePlanRemoteFiles(
10030
10091
  planDir,
10031
10092
  remoteFiles.map(([rel, { sha256, sizeBytes }]) => ({
@@ -10035,7 +10096,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
10035
10096
  }))
10036
10097
  );
10037
10098
  writeFileSync7(
10038
- join22(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
10099
+ join23(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
10039
10100
  JSON.stringify(planVideosJson, null, 2),
10040
10101
  "utf-8"
10041
10102
  );
@@ -10114,11 +10175,11 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
10114
10175
  if (audioResult?.audioError) {
10115
10176
  applyDistributedAudioWarningPolicy(job, audioResult.audioError, audioResult.audioFailures, log);
10116
10177
  }
10117
- const planAudioPath = join22(planDir, PLAN_AUDIO_RELATIVE_PATH);
10118
- if (audioResult?.hasAudio && existsSync15(audioResult.audioOutputPath)) {
10119
- renameWithRetry7(audioResult.audioOutputPath, planAudioPath);
10178
+ const planAudioPath = join23(planDir, PLAN_AUDIO_RELATIVE_PATH);
10179
+ if (audioResult?.hasAudio && existsSync16(audioResult.audioOutputPath)) {
10180
+ renameWithRetry8(audioResult.audioOutputPath, planAudioPath);
10120
10181
  }
10121
- if (chunksCarryAudio && existsSync15(planAudioPath)) {
10182
+ if (chunksCarryAudio && existsSync16(planAudioPath)) {
10122
10183
  if (options.sliceChunkAudio) {
10123
10184
  stageStarted = Date.now();
10124
10185
  await writeChunkAudioSlices({
@@ -10229,8 +10290,8 @@ async function buildPlanAudio(projectDir, config, workRoot, outputPath, options
10229
10290
  if (mixed.audioError) {
10230
10291
  applyDistributedAudioWarningPolicy(c.job, mixed.audioError, mixed.audioFailures, c.log);
10231
10292
  }
10232
- if (!mixed.hasAudio || !existsSync15(mixed.audioOutputPath)) return { hasAudio: false };
10233
- renameWithRetry7(mixed.audioOutputPath, outputPath);
10293
+ if (!mixed.hasAudio || !existsSync16(mixed.audioOutputPath)) return { hasAudio: false };
10294
+ renameWithRetry8(mixed.audioOutputPath, outputPath);
10234
10295
  return { hasAudio: true };
10235
10296
  } finally {
10236
10297
  rmSync7(c.workDir, { recursive: true, force: true });
@@ -10256,7 +10317,7 @@ async function plan(projectDir, config, planDir, options = {}) {
10256
10317
  // src/services/distributed/planV2.ts
10257
10318
  import {
10258
10319
  copyFileSync as copyFileSync8,
10259
- existsSync as existsSync17,
10320
+ existsSync as existsSync18,
10260
10321
  lstatSync as lstatSync2,
10261
10322
  mkdirSync as mkdirSync12,
10262
10323
  mkdtempSync as mkdtempSync4,
@@ -10267,14 +10328,14 @@ import {
10267
10328
  writeFileSync as writeFileSync9
10268
10329
  } from "node:fs";
10269
10330
  import { tmpdir } from "node:os";
10270
- import { dirname as dirname12, isAbsolute as isAbsolute4, join as join25, relative as relative6, resolve as resolve9, sep as sep3 } from "node:path";
10331
+ import { dirname as dirname13, isAbsolute as isAbsolute4, join as join26, relative as relative6, resolve as resolve9, sep as sep3 } from "node:path";
10271
10332
  import { DISTRIBUTED_FPS, isDistributedFps } from "@hyperframes/core";
10272
- import { createFrameLookupTable as createFrameLookupTable4, renameWithRetry as renameWithRetry9 } from "@hyperframes/engine";
10333
+ import { createFrameLookupTable as createFrameLookupTable4, renameWithRetry as renameWithRetry10 } from "@hyperframes/engine";
10273
10334
 
10274
10335
  // src/services/distributed/planV2Publisher.ts
10275
10336
  import {
10276
10337
  copyFileSync as copyFileSync7,
10277
- existsSync as existsSync16,
10338
+ existsSync as existsSync17,
10278
10339
  linkSync as linkSync2,
10279
10340
  mkdirSync as mkdirSync11,
10280
10341
  mkdtempSync as mkdtempSync3,
@@ -10282,8 +10343,8 @@ import {
10282
10343
  statSync as statSync6,
10283
10344
  writeFileSync as writeFileSync8
10284
10345
  } from "node:fs";
10285
- import { renameWithRetry as renameWithRetry8 } from "@hyperframes/engine";
10286
- import { dirname as dirname11, join as join24 } from "node:path";
10346
+ import { renameWithRetry as renameWithRetry9 } from "@hyperframes/engine";
10347
+ import { dirname as dirname12, join as join25 } from "node:path";
10287
10348
 
10288
10349
  // src/services/distributed/planV2Errors.ts
10289
10350
  var PLAN_V2_INTEGRITY_UNRECOVERABLE = "PLAN_V2_INTEGRITY_UNRECOVERABLE";
@@ -10298,7 +10359,7 @@ var PlanV2IntegrityError = class extends Error {
10298
10359
  };
10299
10360
 
10300
10361
  // src/services/distributed/planV2Layout.ts
10301
- import { join as join23 } from "node:path";
10362
+ import { join as join24 } from "node:path";
10302
10363
  var SHA256_PATTERN = /^[0-9a-f]{64}$/;
10303
10364
  function assertPlanV2Sha256(value, field) {
10304
10365
  if (typeof value !== "string" || !SHA256_PATTERN.test(value)) {
@@ -10308,7 +10369,7 @@ function assertPlanV2Sha256(value, field) {
10308
10369
  }
10309
10370
  function planV2BlobPath(root, sha256) {
10310
10371
  const digest = assertPlanV2Sha256(sha256, "artifact sha256");
10311
- return join23(root, "artifacts", "sha256", digest.slice(0, 2), digest);
10372
+ return join24(root, "artifacts", "sha256", digest.slice(0, 2), digest);
10312
10373
  }
10313
10374
 
10314
10375
  // src/services/distributed/planV2Publisher.ts
@@ -10343,13 +10404,13 @@ var LocalPlanV2ArtifactPublisher = class {
10343
10404
  #linkFile;
10344
10405
  #committed = false;
10345
10406
  constructor(destinationDir, options = {}) {
10346
- if (existsSync16(destinationDir)) {
10407
+ if (existsSync17(destinationDir)) {
10347
10408
  throw new PlanV2IntegrityError(`output directory already exists: ${destinationDir}`);
10348
10409
  }
10349
10410
  this.destinationDir = destinationDir;
10350
10411
  this.#linkFile = options.linkFile ?? linkSync2;
10351
- mkdirSync11(dirname11(destinationDir), { recursive: true });
10352
- this.temporaryDir = mkdtempSync3(join24(dirname11(destinationDir), ".plan-v2-publish-"));
10412
+ mkdirSync11(dirname12(destinationDir), { recursive: true });
10413
+ this.temporaryDir = mkdtempSync3(join25(dirname12(destinationDir), ".plan-v2-publish-"));
10353
10414
  }
10354
10415
  async putBlob(blob) {
10355
10416
  const digest = assertPlanV2Sha256(blob.sha256, "published blob sha256");
@@ -10360,10 +10421,10 @@ var LocalPlanV2ArtifactPublisher = class {
10360
10421
  );
10361
10422
  }
10362
10423
  const destinationPath = planV2BlobPath(this.temporaryDir, digest);
10363
- if (existsSync16(destinationPath)) return;
10364
- mkdirSync11(dirname11(destinationPath), { recursive: true });
10365
- const stagingDir = mkdtempSync3(join24(dirname11(destinationPath), ".plan-v2-blob-"));
10366
- const temporaryPath = join24(stagingDir, "blob");
10424
+ if (existsSync17(destinationPath)) return;
10425
+ mkdirSync11(dirname12(destinationPath), { recursive: true });
10426
+ const stagingDir = mkdtempSync3(join25(dirname12(destinationPath), ".plan-v2-blob-"));
10427
+ const temporaryPath = join25(stagingDir, "blob");
10367
10428
  try {
10368
10429
  try {
10369
10430
  this.#linkFile(blob.sourcePath, temporaryPath);
@@ -10371,21 +10432,21 @@ var LocalPlanV2ArtifactPublisher = class {
10371
10432
  if (!canFallbackToCopy(error)) throw error;
10372
10433
  copyFileSync7(blob.sourcePath, temporaryPath);
10373
10434
  }
10374
- renameWithRetry8(temporaryPath, destinationPath);
10435
+ renameWithRetry9(temporaryPath, destinationPath);
10375
10436
  } finally {
10376
10437
  rmSync8(stagingDir, { recursive: true, force: true });
10377
10438
  }
10378
10439
  }
10379
10440
  async commitManifest(manifestBytes) {
10380
10441
  for (const digest of new Set(manifestDigests(manifestBytes))) {
10381
- if (!existsSync16(planV2BlobPath(this.temporaryDir, digest))) {
10442
+ if (!existsSync17(planV2BlobPath(this.temporaryDir, digest))) {
10382
10443
  throw new PlanV2IntegrityError(
10383
10444
  `cannot commit manifest before referenced blob is durable: ${digest}`
10384
10445
  );
10385
10446
  }
10386
10447
  }
10387
- writeFileSync8(join24(this.temporaryDir, "plan.json"), manifestBytes, "utf-8");
10388
- renameWithRetry8(this.temporaryDir, this.destinationDir);
10448
+ writeFileSync8(join25(this.temporaryDir, "plan.json"), manifestBytes, "utf-8");
10449
+ renameWithRetry9(this.temporaryDir, this.destinationDir);
10389
10450
  this.#committed = true;
10390
10451
  }
10391
10452
  async abort() {
@@ -10429,7 +10490,7 @@ function listFiles(root) {
10429
10490
  const rootResolved = resolve9(root);
10430
10491
  function walk(dir) {
10431
10492
  for (const entry of readdirSync7(dir, { withFileTypes: true })) {
10432
- const absolutePath = join25(dir, entry.name);
10493
+ const absolutePath = join26(dir, entry.name);
10433
10494
  if (entry.isDirectory()) {
10434
10495
  walk(absolutePath);
10435
10496
  } else if (entry.isFile()) {
@@ -10456,13 +10517,13 @@ function assertValidExtractionCacheCompleteSentinel(path) {
10456
10517
  }
10457
10518
  }
10458
10519
  function validateExtractionCacheCompleteSentinels(executionPlanDir) {
10459
- const videoRoot = join25(executionPlanDir, "video-frames");
10460
- if (!existsSync17(videoRoot)) return;
10520
+ const videoRoot = join26(executionPlanDir, "video-frames");
10521
+ if (!existsSync18(videoRoot)) return;
10461
10522
  for (const videoEntry of readdirSync7(videoRoot, { withFileTypes: true })) {
10462
10523
  if (!videoEntry.isDirectory()) continue;
10463
- const videoDir = join25(videoRoot, videoEntry.name);
10524
+ const videoDir = join26(videoRoot, videoEntry.name);
10464
10525
  if (readdirSync7(videoDir).includes(EXTRACTION_CACHE_COMPLETE_SENTINEL)) {
10465
- const sentinelPath = join25(videoDir, EXTRACTION_CACHE_COMPLETE_SENTINEL);
10526
+ const sentinelPath = join26(videoDir, EXTRACTION_CACHE_COMPLETE_SENTINEL);
10466
10527
  assertValidExtractionCacheCompleteSentinel(sentinelPath);
10467
10528
  }
10468
10529
  }
@@ -10509,7 +10570,7 @@ function listVideoFramePaths(executionPlanDir, videos) {
10509
10570
  if (video.deferredRange) {
10510
10571
  const framePaths2 = /* @__PURE__ */ new Map();
10511
10572
  for (let index = 0; index < video.totalFrames; index++) {
10512
- framePaths2.set(index, join25(outputDir, String(index)));
10573
+ framePaths2.set(index, join26(outputDir, String(index)));
10513
10574
  }
10514
10575
  return { ...video, outputDir, framePaths: framePaths2, ownedByLookup: false };
10515
10576
  }
@@ -10517,7 +10578,7 @@ function listVideoFramePaths(executionPlanDir, videos) {
10517
10578
  const framePaths = /* @__PURE__ */ new Map();
10518
10579
  for (const frameName of frameNames) {
10519
10580
  if (frameName === EXTRACTION_CACHE_COMPLETE_SENTINEL) {
10520
- assertValidExtractionCacheCompleteSentinel(join25(outputDir, frameName));
10581
+ assertValidExtractionCacheCompleteSentinel(join26(outputDir, frameName));
10521
10582
  continue;
10522
10583
  }
10523
10584
  const match = /(\d+)(?=\.[^.]+$)/.exec(frameName);
@@ -10536,7 +10597,7 @@ function listVideoFramePaths(executionPlanDir, videos) {
10536
10597
  `duplicate extracted frame index ${frameIndex} in ${outputDir}`
10537
10598
  );
10538
10599
  }
10539
- framePaths.set(frameIndex, join25(outputDir, frameName));
10600
+ framePaths.set(frameIndex, join26(outputDir, frameName));
10540
10601
  }
10541
10602
  return {
10542
10603
  ...video,
@@ -10557,8 +10618,8 @@ function parsePlanVideosJson2(value) {
10557
10618
  }
10558
10619
  }
10559
10620
  function materializeExtractedVideoDirectories(planDir) {
10560
- const videosPath = join25(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
10561
- if (!existsSync17(videosPath)) return;
10621
+ const videosPath = join26(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
10622
+ if (!existsSync18(videosPath)) return;
10562
10623
  const videos = parsePlanVideosJson2(readJsonFile(videosPath, PLAN_VIDEOS_META_RELATIVE_PATH));
10563
10624
  for (const video of videos.extracted) {
10564
10625
  mkdirSync12(resolveExtractedVideoOutputDir(planDir, video.videoId), { recursive: true });
@@ -10591,13 +10652,13 @@ function parseChunkSlices(value) {
10591
10652
  });
10592
10653
  }
10593
10654
  function buildVideoChunkDependencies(executionPlanDir, dimensions) {
10594
- const videoRoot = join25(executionPlanDir, "video-frames");
10595
- const hasExtractedFrames = existsSync17(videoRoot) && listFiles(videoRoot).length > 0;
10596
- const videosPath = join25(executionPlanDir, PLAN_VIDEOS_META_RELATIVE_PATH);
10597
- if (!existsSync17(videosPath)) {
10655
+ const videoRoot = join26(executionPlanDir, "video-frames");
10656
+ const hasExtractedFrames = existsSync18(videoRoot) && listFiles(videoRoot).length > 0;
10657
+ const videosPath = join26(executionPlanDir, PLAN_VIDEOS_META_RELATIVE_PATH);
10658
+ if (!existsSync18(videosPath)) {
10598
10659
  return hasExtractedFrames ? { mode: "full-source-pack", dependencies: null } : { mode: "exact-rendered-frames", dependencies: /* @__PURE__ */ new Map() };
10599
10660
  }
10600
- const chunksPath = join25(executionPlanDir, "meta", "chunks.json");
10661
+ const chunksPath = join26(executionPlanDir, "meta", "chunks.json");
10601
10662
  const videos = readJsonFile(videosPath, PLAN_VIDEOS_META_RELATIVE_PATH);
10602
10663
  const chunks = readJsonFile(chunksPath, "meta/chunks.json");
10603
10664
  const parsedVideos = parsePlanVideosJson2(videos);
@@ -10651,13 +10712,13 @@ function computeManifestHash(manifest) {
10651
10712
  return sha256Hex(`${PLAN_V2_HASH_PREFIX}${canonicalJsonStringify(manifestPayload(manifest))}`);
10652
10713
  }
10653
10714
  function writeBlob(sourcePath, destinationPath) {
10654
- if (existsSync17(destinationPath)) return;
10655
- mkdirSync12(dirname12(destinationPath), { recursive: true });
10656
- const temporaryDir = mkdtempSync4(join25(dirname12(destinationPath), ".plan-v2-blob-"));
10657
- const temporaryPath = join25(temporaryDir, "blob");
10715
+ if (existsSync18(destinationPath)) return;
10716
+ mkdirSync12(dirname13(destinationPath), { recursive: true });
10717
+ const temporaryDir = mkdtempSync4(join26(dirname13(destinationPath), ".plan-v2-blob-"));
10718
+ const temporaryPath = join26(temporaryDir, "blob");
10658
10719
  try {
10659
10720
  copyFileSync8(sourcePath, temporaryPath);
10660
- renameWithRetry9(temporaryPath, destinationPath);
10721
+ renameWithRetry10(temporaryPath, destinationPath);
10661
10722
  } finally {
10662
10723
  rmSync9(temporaryDir, { recursive: true, force: true });
10663
10724
  }
@@ -10690,8 +10751,8 @@ async function putTasks(tasks) {
10690
10751
  if (failure) throw failure.reason;
10691
10752
  }
10692
10753
  function buildPlanV2Publication(executionPlanDir, digests) {
10693
- const executionPlanPath = join25(executionPlanDir, "plan.json");
10694
- if (!existsSync17(executionPlanPath)) {
10754
+ const executionPlanPath = join26(executionPlanDir, "plan.json");
10755
+ if (!existsSync18(executionPlanPath)) {
10695
10756
  throw new PlanV2IntegrityError(`execution plan is missing plan.json: ${executionPlanPath}`);
10696
10757
  }
10697
10758
  const executionPlanValue = readJsonFile(executionPlanPath, "execution plan.json");
@@ -10718,7 +10779,7 @@ function buildPlanV2Publication(executionPlanDir, digests) {
10718
10779
  }
10719
10780
  validateExtractionCacheCompleteSentinels(executionPlanDir);
10720
10781
  const videoDependencyPlan = buildVideoChunkDependencies(executionPlanDir, dimensions);
10721
- const encoder = readJsonFile(join25(executionPlanDir, "meta", "encoder.json"), "meta/encoder.json");
10782
+ const encoder = readJsonFile(join26(executionPlanDir, "meta", "encoder.json"), "meta/encoder.json");
10722
10783
  const files = listFiles(executionPlanDir);
10723
10784
  const chunkAudio = !isRecord3(encoder) || encoder.chunksCarryAudio !== true ? "none" : files.some((file) => chunkAudioSliceTarget(file.path) !== null) ? "sliced" : "whole";
10724
10785
  for (const file of files) {
@@ -10771,25 +10832,25 @@ function buildPlanV2Publication(executionPlanDir, digests) {
10771
10832
  };
10772
10833
  }
10773
10834
  function createPlanV2FromExecutionPlan(executionPlanDir, planV2Dir) {
10774
- if (existsSync17(planV2Dir)) {
10835
+ if (existsSync18(planV2Dir)) {
10775
10836
  throw new PlanV2IntegrityError(`output directory already exists: ${planV2Dir}`);
10776
10837
  }
10777
10838
  const publication = buildPlanV2Publication(executionPlanDir);
10778
10839
  if (publication.storedBlobs.length > 0) {
10779
10840
  throw new PlanV2IntegrityError("a local plan v2 directory cannot reference remote files");
10780
10841
  }
10781
- mkdirSync12(dirname12(planV2Dir), { recursive: true });
10782
- const tempDir = mkdtempSync4(join25(dirname12(planV2Dir), ".plan-v2-build-"));
10842
+ mkdirSync12(dirname13(planV2Dir), { recursive: true });
10843
+ const tempDir = mkdtempSync4(join26(dirname13(planV2Dir), ".plan-v2-build-"));
10783
10844
  try {
10784
10845
  for (const blob of publication.blobs) {
10785
10846
  writeBlob(blob.sourcePath, planV2BlobPath(tempDir, blob.sha256));
10786
10847
  }
10787
10848
  writeFileSync9(
10788
- join25(tempDir, "plan.json"),
10849
+ join26(tempDir, "plan.json"),
10789
10850
  canonicalJsonStringify(publication.manifest),
10790
10851
  "utf-8"
10791
10852
  );
10792
- renameWithRetry9(tempDir, planV2Dir);
10853
+ renameWithRetry10(tempDir, planV2Dir);
10793
10854
  return resultFromManifest(planV2Dir, publication.manifest);
10794
10855
  } catch (error) {
10795
10856
  rmSync9(tempDir, { recursive: true, force: true });
@@ -10832,7 +10893,7 @@ async function publishPlanV2FromV1(executionPlanDir, publisher) {
10832
10893
  return publishPlanV2FromExecutionPlan(executionPlanDir, publisher);
10833
10894
  }
10834
10895
  async function planV2WithPublisher(projectDir, config, publisher, options = {}) {
10835
- const stagingRoot = mkdtempSync4(join25(options.stagingParentDir ?? tmpdir(), ".execution-plan-"));
10896
+ const stagingRoot = mkdtempSync4(join26(options.stagingParentDir ?? tmpdir(), ".execution-plan-"));
10836
10897
  const digests = /* @__PURE__ */ new Map();
10837
10898
  try {
10838
10899
  await buildLocalExecutionPlan(projectDir, config, stagingRoot, {
@@ -10843,7 +10904,7 @@ async function planV2WithPublisher(projectDir, config, publisher, options = {})
10843
10904
  // artifactTargets ships every compiled/ file to all chunks, so each is in the manifest.
10844
10905
  whileAudioMixes: () => putBlobs(
10845
10906
  publisher,
10846
- listFiles(join25(stagingRoot, "compiled")).map(
10907
+ listFiles(join26(stagingRoot, "compiled")).map(
10847
10908
  (file) => publishBlobFor(file.absolutePath, digests)
10848
10909
  )
10849
10910
  ),
@@ -10863,19 +10924,19 @@ async function planV2WithPublisher(projectDir, config, publisher, options = {})
10863
10924
  }
10864
10925
  }
10865
10926
  async function planV2(projectDir, config, planV2Dir) {
10866
- if (existsSync17(planV2Dir)) {
10927
+ if (existsSync18(planV2Dir)) {
10867
10928
  throw new PlanV2IntegrityError(`output directory already exists: ${planV2Dir}`);
10868
10929
  }
10869
10930
  const publisher = new LocalPlanV2ArtifactPublisher(planV2Dir);
10870
10931
  const manifest = await planV2WithPublisher(projectDir, config, publisher, {
10871
- stagingParentDir: dirname12(planV2Dir)
10932
+ stagingParentDir: dirname13(planV2Dir)
10872
10933
  });
10873
10934
  return resultFromManifest(planV2Dir, manifest);
10874
10935
  }
10875
10936
  function resultFromManifest(planV2Dir, manifest) {
10876
10937
  return {
10877
10938
  planDir: planV2Dir,
10878
- manifestPath: join25(planV2Dir, "plan.json"),
10939
+ manifestPath: join26(planV2Dir, "plan.json"),
10879
10940
  planProtocol: PLAN_PROTOCOL_V2,
10880
10941
  planHash: manifest.planHash,
10881
10942
  sourcePlanV1Hash: getPlanV2ExecutionPlanHash(manifest),
@@ -11011,8 +11072,8 @@ function parsePlanV2Manifest(value) {
11011
11072
  return parsed;
11012
11073
  }
11013
11074
  function readPlanV2Manifest(planV2Dir) {
11014
- const manifestPath = join25(planV2Dir, "plan.json");
11015
- if (!existsSync17(manifestPath)) {
11075
+ const manifestPath = join26(planV2Dir, "plan.json");
11076
+ if (!existsSync18(manifestPath)) {
11016
11077
  throw new PlanV2IntegrityError(`missing v2 manifest: ${manifestPath}`);
11017
11078
  }
11018
11079
  const value = readJsonFile(manifestPath, "v2 manifest");
@@ -11031,7 +11092,7 @@ function listPlanV2ArtifactsForTarget(manifest, target) {
11031
11092
  }
11032
11093
  function verifyBlob(planV2Dir, artifact) {
11033
11094
  const sourcePath = planV2BlobPath(planV2Dir, artifact.sha256);
11034
- if (!existsSync17(sourcePath)) {
11095
+ if (!existsSync18(sourcePath)) {
11035
11096
  throw new PlanV2IntegrityError(`missing content-addressed artifact ${artifact.sha256}`);
11036
11097
  }
11037
11098
  const stats = statSync7(sourcePath);
@@ -11044,7 +11105,7 @@ function verifyBlob(planV2Dir, artifact) {
11044
11105
  return sourcePath;
11045
11106
  }
11046
11107
  function materializePlanV2Target(planV2Dir, target, destinationDir, options = {}) {
11047
- if (existsSync17(destinationDir)) {
11108
+ if (existsSync18(destinationDir)) {
11048
11109
  throw new PlanV2IntegrityError(`materialization destination already exists: ${destinationDir}`);
11049
11110
  }
11050
11111
  const manifest = readPlanV2Manifest(planV2Dir);
@@ -11056,17 +11117,17 @@ function materializePlanV2Target(planV2Dir, target, destinationDir, options = {}
11056
11117
  artifact,
11057
11118
  sourcePath: verifyBlob(planV2Dir, artifact)
11058
11119
  }));
11059
- mkdirSync12(dirname12(destinationDir), { recursive: true });
11060
- const tempDir = mkdtempSync4(join25(dirname12(destinationDir), ".plan-v2-materialize-"));
11120
+ mkdirSync12(dirname13(destinationDir), { recursive: true });
11121
+ const tempDir = mkdtempSync4(join26(dirname13(destinationDir), ".plan-v2-materialize-"));
11061
11122
  try {
11062
11123
  for (const { artifact, sourcePath } of verified) {
11063
- const destinationPath = join25(tempDir, ...artifact.path.split("/"));
11064
- mkdirSync12(dirname12(destinationPath), { recursive: true });
11124
+ const destinationPath = join26(tempDir, ...artifact.path.split("/"));
11125
+ mkdirSync12(dirname13(destinationPath), { recursive: true });
11065
11126
  copyFileSync8(sourcePath, destinationPath);
11066
11127
  }
11067
11128
  if (target.role === "chunk") materializeExtractedVideoDirectories(tempDir);
11068
11129
  writeFileSync9(
11069
- join25(tempDir, PLAN_V2_MATERIALIZATION_MARKER),
11130
+ join26(tempDir, PLAN_V2_MATERIALIZATION_MARKER),
11070
11131
  canonicalJsonStringify({
11071
11132
  manifest,
11072
11133
  target,
@@ -11074,7 +11135,7 @@ function materializePlanV2Target(planV2Dir, target, destinationDir, options = {}
11074
11135
  }),
11075
11136
  "utf-8"
11076
11137
  );
11077
- renameWithRetry9(tempDir, destinationDir);
11138
+ renameWithRetry10(tempDir, destinationDir);
11078
11139
  } catch (error) {
11079
11140
  rmSync9(tempDir, { recursive: true, force: true });
11080
11141
  throw error;
@@ -11089,7 +11150,7 @@ function materializePlanV2Target(planV2Dir, target, destinationDir, options = {}
11089
11150
  // Join the artifact's OWN name, not the current constant: a plan written
11090
11151
  // before the container change carries the legacy name, and materializing it
11091
11152
  // under the new one would point at a file that was never written.
11092
- audioPath: target.role === "assembler" ? audioArtifact ? join25(destinationDir, audioArtifact.path) : null : null
11153
+ audioPath: target.role === "assembler" ? audioArtifact ? join26(destinationDir, audioArtifact.path) : null : null
11093
11154
  };
11094
11155
  }
11095
11156
  function assertRemoteSources(remoteSources, artifacts) {
@@ -11108,8 +11169,8 @@ function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
11108
11169
  return readValidatedPlanV2Materialization(planDir, expectedTarget)?.manifest ?? null;
11109
11170
  }
11110
11171
  function readValidatedPlanV2Materialization(planDir, expectedTarget) {
11111
- const markerPath = join25(planDir, PLAN_V2_MATERIALIZATION_MARKER);
11112
- if (!existsSync17(markerPath)) return null;
11172
+ const markerPath = join26(planDir, PLAN_V2_MATERIALIZATION_MARKER);
11173
+ if (!existsSync18(markerPath)) return null;
11113
11174
  const marker = readJsonFile(markerPath, "materialization marker");
11114
11175
  if (!isRecord3(marker) || !isRecord3(marker.manifest) || !isRecord3(marker.target)) {
11115
11176
  throw new PlanV2IntegrityError("malformed materialization marker");
@@ -11126,8 +11187,8 @@ function readValidatedPlanV2Materialization(planDir, expectedTarget) {
11126
11187
  assertRemoteSources(remoteSources, required);
11127
11188
  for (const artifact of required) {
11128
11189
  if (Object.hasOwn(remoteSources, artifact.path)) continue;
11129
- const path = join25(planDir, ...artifact.path.split("/"));
11130
- if (!existsSync17(path) || statSync7(path).size !== artifact.sizeBytes) {
11190
+ const path = join26(planDir, ...artifact.path.split("/"));
11191
+ if (!existsSync18(path) || statSync7(path).size !== artifact.sizeBytes) {
11131
11192
  throw new PlanV2IntegrityError(
11132
11193
  `materialized artifact missing or truncated: ${artifact.path}`
11133
11194
  );
@@ -11142,12 +11203,12 @@ function readValidatedPlanV2Materialization(planDir, expectedTarget) {
11142
11203
  // src/services/distributed/planV2Execution.ts
11143
11204
  import { mkdtempSync as mkdtempSync6, rmSync as rmSync12 } from "node:fs";
11144
11205
  import { tmpdir as tmpdir2 } from "node:os";
11145
- import { join as join28 } from "node:path";
11206
+ import { join as join29 } from "node:path";
11146
11207
 
11147
11208
  // src/services/distributed/assemble.ts
11148
11209
  import {
11149
11210
  cpSync as cpSync3,
11150
- existsSync as existsSync18,
11211
+ existsSync as existsSync19,
11151
11212
  mkdirSync as mkdirSync13,
11152
11213
  mkdtempSync as mkdtempSync5,
11153
11214
  readFileSync as readFileSync9,
@@ -11156,18 +11217,18 @@ import {
11156
11217
  statSync as statSync8,
11157
11218
  writeFileSync as writeFileSync10
11158
11219
  } from "node:fs";
11159
- import { dirname as dirname13, join as join26 } from "node:path";
11220
+ import { dirname as dirname14, join as join27 } from "node:path";
11160
11221
  import {
11161
11222
  appendRateCapArgs as appendRateCapArgs2,
11162
11223
  appendRenderProvenanceArgs as appendRenderProvenanceArgs2,
11163
- describeFfmpegFailure as describeFfmpegFailure4,
11224
+ describeFfmpegFailure as describeFfmpegFailure5,
11164
11225
  getEncoderPreset as getEncoderPreset5,
11165
11226
  MIXED_AUDIO_FILENAME as MIXED_AUDIO_FILENAME4,
11166
11227
  muxVideoWithAudio as muxVideoWithAudio2,
11167
11228
  resolveConfig as resolveConfig4,
11168
11229
  runFfmpeg as runFfmpeg8,
11169
11230
  appendSoftwareEncoderThreadsArg,
11170
- renameWithRetry as renameWithRetry10
11231
+ renameWithRetry as renameWithRetry11
11171
11232
  } from "@hyperframes/engine";
11172
11233
  import { fpsToFfmpegArg as fpsToFfmpegArg3 } from "@hyperframes/core";
11173
11234
  function cfrRateControlArgs(locked) {
@@ -11198,8 +11259,8 @@ async function assemble(planDir, chunkOutputs, audioPath, outputPath, options) {
11198
11259
  }
11199
11260
  const format = plan2.dimensions.format;
11200
11261
  const cfrEncoder = cfr ? readCfrEncoder(planDir, format) : null;
11201
- if (!existsSync18(dirname13(outputPath))) {
11202
- mkdirSync13(dirname13(outputPath), { recursive: true });
11262
+ if (!existsSync19(dirname14(outputPath))) {
11263
+ mkdirSync13(dirname14(outputPath), { recursive: true });
11203
11264
  }
11204
11265
  const workDir = mkdtempSync5(`${outputPath}.assemble-work-`);
11205
11266
  const fps = { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen };
@@ -11221,10 +11282,10 @@ async function assemble(planDir, chunkOutputs, audioPath, outputPath, options) {
11221
11282
  };
11222
11283
  try {
11223
11284
  const videoSources = cfrEncoder ? [await reencodeCfr(ctx, chunkPaths, cfrEncoder)] : chunkPaths;
11224
- const finalPath = join26(workDir, `output.${format}`);
11225
- const audio = audioPath !== null && existsSync18(audioPath) ? audioPath : null;
11285
+ const finalPath = join27(workDir, `output.${format}`);
11286
+ const audio = audioPath !== null && existsSync19(audioPath) ? audioPath : null;
11226
11287
  await writeJoined(ctx, videoSources, audio, finalPath);
11227
- renameWithRetry10(finalPath, outputPath);
11288
+ renameWithRetry11(finalPath, outputPath);
11228
11289
  log.info("[assemble] stage timings", {
11229
11290
  ...stageMs,
11230
11291
  chunks: chunkPaths.length,
@@ -11240,7 +11301,7 @@ async function assemble(planDir, chunkOutputs, audioPath, outputPath, options) {
11240
11301
  });
11241
11302
  }
11242
11303
  }
11243
- const fileSize = existsSync18(outputPath) ? statSync8(outputPath).size : 0;
11304
+ const fileSize = existsSync19(outputPath) ? statSync8(outputPath).size : 0;
11244
11305
  return {
11245
11306
  outputPath,
11246
11307
  durationMs: Date.now() - start,
@@ -11249,15 +11310,15 @@ async function assemble(planDir, chunkOutputs, audioPath, outputPath, options) {
11249
11310
  };
11250
11311
  }
11251
11312
  function readAssemblePlan(planDir, chunkPaths) {
11252
- const planJsonPath = join26(planDir, "plan.json");
11253
- const chunksJsonPath = join26(planDir, "meta", "chunks.json");
11254
- if (!existsSync18(planJsonPath)) {
11313
+ const planJsonPath = join27(planDir, "plan.json");
11314
+ const chunksJsonPath = join27(planDir, "meta", "chunks.json");
11315
+ if (!existsSync19(planJsonPath)) {
11255
11316
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
11256
11317
  }
11257
11318
  const plan2 = JSON.parse(readFileSync9(planJsonPath, "utf-8"));
11258
11319
  readPlanProtocolV1(plan2, DISTRIBUTED_RENDER_CAPABILITIES.roles.assembler);
11259
11320
  validatePlanV2MaterializedTarget(planDir, { role: "assembler" });
11260
- if (!existsSync18(chunksJsonPath)) {
11321
+ if (!existsSync19(chunksJsonPath)) {
11261
11322
  throw new Error(`[assemble] planDir missing meta/chunks.json: ${chunksJsonPath}`);
11262
11323
  }
11263
11324
  const chunks = JSON.parse(readFileSync9(chunksJsonPath, "utf-8"));
@@ -11272,7 +11333,7 @@ function readAssemblePlan(planDir, chunkPaths) {
11272
11333
  }
11273
11334
  }
11274
11335
  for (const path of chunkPaths.flat()) {
11275
- if (!existsSync18(path)) {
11336
+ if (!existsSync19(path)) {
11276
11337
  throw new Error(`[assemble] chunk path does not exist: ${path}`);
11277
11338
  }
11278
11339
  }
@@ -11301,7 +11362,7 @@ function cfrEncodeArgs(inputArgs, encoder, fpsArg) {
11301
11362
  return args;
11302
11363
  }
11303
11364
  async function reencodeCfr(ctx, chunkPaths, encoder) {
11304
- const cfrOutputPath = join26(ctx.workDir, `cfr.${ctx.format}`);
11365
+ const cfrOutputPath = join27(ctx.workDir, `cfr.${ctx.format}`);
11305
11366
  const cfrArgs = cfrEncodeArgs(videoInputArgs(ctx, chunkPaths), encoder, ctx.fpsArg);
11306
11367
  appendRenderProvenanceArgs2(cfrArgs, cfrOutputPath);
11307
11368
  cfrArgs.push("-y", cfrOutputPath);
@@ -11328,7 +11389,7 @@ async function writeJoined(ctx, videoSources, audioPath, finalPath) {
11328
11389
  );
11329
11390
  return;
11330
11391
  }
11331
- const paddedAudioPath = join26(ctx.workDir, "audio-padded.m4a");
11392
+ const paddedAudioPath = join27(ctx.workDir, "audio-padded.m4a");
11332
11393
  const padTrimResult = await ctx.timed(
11333
11394
  "audioMs",
11334
11395
  () => padOrTrimAudioToVideoFrameCount({
@@ -11368,7 +11429,7 @@ async function writeJoined(ctx, videoSources, audioPath, finalPath) {
11368
11429
  }
11369
11430
  }
11370
11431
  function concatDemuxerInput(chunkPaths, workDir, fpsArg) {
11371
- const listPath = join26(workDir, "concat-list.txt");
11432
+ const listPath = join27(workDir, "concat-list.txt");
11372
11433
  const body = chunkPaths.map((path) => `file '${path.replace(/'/g, "'\\''")}'`).join("\n");
11373
11434
  writeFileSync10(listPath, `${body}
11374
11435
  `, "utf-8");
@@ -11388,7 +11449,7 @@ async function runAssembleFfmpeg(args, step, signal, timeout) {
11388
11449
  const result = await runFfmpeg8(args, { signal, timeout });
11389
11450
  if (!result.success) {
11390
11451
  throw encoderFailureError(`[assemble] ffmpeg ${step} failed`, {
11391
- error: describeFfmpegFailure4(result, timeout),
11452
+ error: describeFfmpegFailure5(result, timeout),
11392
11453
  failureReason: result.failureReason
11393
11454
  });
11394
11455
  }
@@ -11406,12 +11467,12 @@ function stitchesSeparateAudio(planDir) {
11406
11467
  return lockedAudio(planDir).separateAudio === true;
11407
11468
  }
11408
11469
  function planFormat(planDir) {
11409
- const plan2 = JSON.parse(readFileSync9(join26(planDir, "plan.json"), "utf-8"));
11470
+ const plan2 = JSON.parse(readFileSync9(join27(planDir, "plan.json"), "utf-8"));
11410
11471
  return plan2.dimensions.format;
11411
11472
  }
11412
11473
  function lockedAudio(planDir) {
11413
- const encoderJsonPath = join26(planDir, "meta", "encoder.json");
11414
- if (!existsSync18(encoderJsonPath)) return {};
11474
+ const encoderJsonPath = join27(planDir, "meta", "encoder.json");
11475
+ if (!existsSync19(encoderJsonPath)) return {};
11415
11476
  return JSON.parse(readFileSync9(encoderJsonPath, "utf-8"));
11416
11477
  }
11417
11478
  function readCfrEncoder(planDir, format) {
@@ -11420,8 +11481,8 @@ function readCfrEncoder(planDir, format) {
11420
11481
  `[assemble] cfr=true is only supported for format="mp4" (got "${format}"). Stream-copy paths for webm and mov already produce exact avg_frame_rate; cfr re-encode is not needed.`
11421
11482
  );
11422
11483
  }
11423
- const encoderJsonPath = join26(planDir, "meta", "encoder.json");
11424
- if (!existsSync18(encoderJsonPath)) {
11484
+ const encoderJsonPath = join27(planDir, "meta", "encoder.json");
11485
+ if (!existsSync19(encoderJsonPath)) {
11425
11486
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
11426
11487
  }
11427
11488
  const encoderJson = JSON.parse(readFileSync9(encoderJsonPath, "utf-8"));
@@ -11433,7 +11494,7 @@ function readCfrEncoder(planDir, format) {
11433
11494
  return encoderJson;
11434
11495
  }
11435
11496
  function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, startTimeMs) {
11436
- if (existsSync18(outputPath)) rmSync10(outputPath, { recursive: true, force: true });
11497
+ if (existsSync19(outputPath)) rmSync10(outputPath, { recursive: true, force: true });
11437
11498
  mkdirSync13(outputPath, { recursive: true });
11438
11499
  let globalIdx = 0;
11439
11500
  for (const chunkDir of chunkPaths) {
@@ -11447,8 +11508,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
11447
11508
  throw new Error(`[assemble] png-sequence chunk has no frames: ${chunkDir}`);
11448
11509
  }
11449
11510
  for (const frame of frames) {
11450
- const dst = join26(outputPath, formatExportFrameName(globalIdx, "png"));
11451
- cpSync3(join26(chunkDir, frame), dst);
11511
+ const dst = join27(outputPath, formatExportFrameName(globalIdx, "png"));
11512
+ cpSync3(join27(chunkDir, frame), dst);
11452
11513
  globalIdx += 1;
11453
11514
  }
11454
11515
  }
@@ -11457,14 +11518,14 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
11457
11518
  `[assemble] png-sequence frame count mismatch: merged ${globalIdx} frames vs plan.totalFrames=${totalFrames}. Using on-disk count.`
11458
11519
  );
11459
11520
  }
11460
- if (audioPath !== null && existsSync18(audioPath)) {
11461
- const sidecar = join26(outputPath, MIXED_AUDIO_FILENAME4);
11521
+ if (audioPath !== null && existsSync19(audioPath)) {
11522
+ const sidecar = join27(outputPath, MIXED_AUDIO_FILENAME4);
11462
11523
  cpSync3(audioPath, sidecar);
11463
11524
  }
11464
11525
  let fileSize = 0;
11465
11526
  for (const name of readdirSync8(outputPath)) {
11466
11527
  try {
11467
- fileSize += statSync8(join26(outputPath, name)).size;
11528
+ fileSize += statSync8(join27(outputPath, name)).size;
11468
11529
  } catch {
11469
11530
  }
11470
11531
  }
@@ -11478,9 +11539,9 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
11478
11539
 
11479
11540
  // src/services/distributed/renderChunk.ts
11480
11541
  import { randomBytes } from "node:crypto";
11481
- import { existsSync as existsSync19, mkdirSync as mkdirSync14, readFileSync as readFileSync10, readdirSync as readdirSync9, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
11542
+ import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync10, readdirSync as readdirSync9, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
11482
11543
  import { cpus } from "node:os";
11483
- import { join as join27 } from "node:path";
11544
+ import { join as join28 } from "node:path";
11484
11545
  import {
11485
11546
  assertSwiftShader,
11486
11547
  BROWSER_GPU_NOT_SOFTWARE as BROWSER_GPU_NOT_SOFTWARE4,
@@ -11604,7 +11665,7 @@ function hashChunkOutput(outputPath, kind) {
11604
11665
  if (kind === "file") return sha256Hex(readFileSync10(outputPath));
11605
11666
  const entries = readdirSync9(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
11606
11667
  const lines = entries.map(
11607
- (name) => `${name}\0${sha256Hex(readFileSync10(join27(outputPath, name)))}`
11668
+ (name) => `${name}\0${sha256Hex(readFileSync10(join28(outputPath, name)))}`
11608
11669
  );
11609
11670
  return sha256Hex(lines.join("\0"));
11610
11671
  }
@@ -11621,10 +11682,10 @@ function resolveLockedVp9CpuUsed(lockedEncoder) {
11621
11682
  async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11622
11683
  const start = Date.now();
11623
11684
  const log = defaultLogger;
11624
- const planJsonPath = join27(planDir, "plan.json");
11625
- const encoderJsonPath = join27(planDir, "meta", "encoder.json");
11626
- const chunksJsonPath = join27(planDir, "meta", "chunks.json");
11627
- if (!existsSync19(planJsonPath)) {
11685
+ const planJsonPath = join28(planDir, "plan.json");
11686
+ const encoderJsonPath = join28(planDir, "meta", "encoder.json");
11687
+ const chunksJsonPath = join28(planDir, "meta", "chunks.json");
11688
+ if (!existsSync20(planJsonPath)) {
11628
11689
  throw new RenderChunkValidationError(
11629
11690
  MISSING_PLAN_ARTIFACT,
11630
11691
  `[renderChunk] planDir is missing required artifact: ${planJsonPath}`
@@ -11640,7 +11701,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11640
11701
  const v2Manifest = v2Materialization?.manifest ?? null;
11641
11702
  const remoteSources = v2Materialization?.remoteSources ?? {};
11642
11703
  for (const required of [encoderJsonPath, chunksJsonPath]) {
11643
- if (!existsSync19(required)) {
11704
+ if (!existsSync20(required)) {
11644
11705
  throw new RenderChunkValidationError(
11645
11706
  MISSING_PLAN_ARTIFACT,
11646
11707
  `[renderChunk] planDir is missing required artifact: ${required}`
@@ -11649,9 +11710,9 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11649
11710
  }
11650
11711
  const encoder = JSON.parse(readFileSync10(encoderJsonPath, "utf-8"));
11651
11712
  const chunks = JSON.parse(readFileSync10(chunksJsonPath, "utf-8"));
11652
- const videosJsonPath = join27(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
11713
+ const videosJsonPath = join28(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
11653
11714
  let planVideos = null;
11654
- if (existsSync19(videosJsonPath)) {
11715
+ if (existsSync20(videosJsonPath)) {
11655
11716
  try {
11656
11717
  planVideos = validatePlanVideosForChunk(JSON.parse(readFileSync10(videosJsonPath, "utf-8")));
11657
11718
  } catch (err) {
@@ -11681,8 +11742,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11681
11742
  }
11682
11743
  const range = resolveChunkFrameRange(slice, chunkIndex, options?.frameRange);
11683
11744
  const framesInChunk = range.endFrame - range.startFrame;
11684
- const compiledDir = join27(planDir, "compiled");
11685
- if (!existsSync19(compiledDir)) {
11745
+ const compiledDir = join28(planDir, "compiled");
11746
+ if (!existsSync20(compiledDir)) {
11686
11747
  throw new RenderChunkValidationError(
11687
11748
  MISSING_PLAN_ARTIFACT,
11688
11749
  `[renderChunk] planDir missing compiled/ directory: ${compiledDir}`
@@ -11739,7 +11800,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11739
11800
  };
11740
11801
  const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
11741
11802
  mkdirSync14(workDir, { recursive: true });
11742
- const framesDir = join27(workDir, "captured-frames");
11803
+ const framesDir = join28(workDir, "captured-frames");
11743
11804
  mkdirSync14(framesDir, { recursive: true });
11744
11805
  const videoFramesDir = `${workDir}.video-frames`;
11745
11806
  const chunkFrameNumbers = Array.from({ length: framesInChunk }, (_, i) => range.startFrame + i);
@@ -11764,7 +11825,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11764
11825
  dimensions: plan2.dimensions,
11765
11826
  encoder,
11766
11827
  videoCount: planVideos?.videos.length ?? 0,
11767
- html: readFileSync10(join27(compiledDir, "index.html"), "utf-8"),
11828
+ html: readFileSync10(join28(compiledDir, "index.html"), "utf-8"),
11768
11829
  // The plan ships a deferred source only to chunks that show it; don't wait on the rest.
11769
11830
  skipReadinessVideoIds: deferredVideos.filter(
11770
11831
  (video) => !shownFrames.get(video.videoId)?.size || remoteVideoIds.has(video.videoId)
@@ -11932,10 +11993,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11932
11993
  const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
11933
11994
  const videoOnlyPath = encoder.chunksCarryAudio ? `${outputChunkPath}.video.mp4` : outputChunkPath;
11934
11995
  if (isPngSequence) {
11935
- if (!existsSync19(outputChunkPath)) mkdirSync14(outputChunkPath, { recursive: true });
11996
+ if (!existsSync20(outputChunkPath)) mkdirSync14(outputChunkPath, { recursive: true });
11936
11997
  } else {
11937
- const outDir = join27(outputChunkPath, "..");
11938
- if (!existsSync19(outDir)) mkdirSync14(outDir, { recursive: true });
11998
+ const outDir = join28(outputChunkPath, "..");
11999
+ if (!existsSync20(outDir)) mkdirSync14(outDir, { recursive: true });
11939
12000
  }
11940
12001
  const encodeInput = {
11941
12002
  job,
@@ -12178,8 +12239,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
12178
12239
 
12179
12240
  // src/services/distributed/planV2Execution.ts
12180
12241
  async function renderChunkV2(planV2Dir, chunkIndex, outputChunkPath, options) {
12181
- const workRoot = mkdtempSync6(join28(tmpdir2(), "hf-plan-v2-chunk-"));
12182
- const materializedPlanDir = join28(workRoot, "plan");
12242
+ const workRoot = mkdtempSync6(join29(tmpdir2(), "hf-plan-v2-chunk-"));
12243
+ const materializedPlanDir = join29(workRoot, "plan");
12183
12244
  try {
12184
12245
  materializePlanV2Target(planV2Dir, { role: "chunk", chunkIndex }, materializedPlanDir);
12185
12246
  return await renderChunk(materializedPlanDir, chunkIndex, outputChunkPath, options);
@@ -12188,8 +12249,8 @@ async function renderChunkV2(planV2Dir, chunkIndex, outputChunkPath, options) {
12188
12249
  }
12189
12250
  }
12190
12251
  async function assembleV2(planV2Dir, chunkPaths, outputPath, options) {
12191
- const workRoot = mkdtempSync6(join28(tmpdir2(), "hf-plan-v2-assembler-"));
12192
- const materializedPlanDir = join28(workRoot, "plan");
12252
+ const workRoot = mkdtempSync6(join29(tmpdir2(), "hf-plan-v2-assembler-"));
12253
+ const materializedPlanDir = join29(workRoot, "plan");
12193
12254
  try {
12194
12255
  const materialized = materializePlanV2Target(
12195
12256
  planV2Dir,
@@ -12481,7 +12542,7 @@ function validateIntDimension(field, value) {
12481
12542
  // src/services/distributed/projectHash.ts
12482
12543
  import { closeSync as closeSync5, openSync as openSync5, readdirSync as readdirSync10, readSync as readSync4, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
12483
12544
  import { createHash as createHash8 } from "node:crypto";
12484
- import { join as join29 } from "node:path";
12545
+ import { join as join30 } from "node:path";
12485
12546
  var SITE_ID_SCHEME = "site-v2\0";
12486
12547
  var READ_CHUNK_BYTES = 256 * 1024;
12487
12548
  function listSiteFiles(projectDir) {
@@ -12490,7 +12551,7 @@ function listSiteFiles(projectDir) {
12490
12551
  function walk(dir, rel) {
12491
12552
  for (const name of readdirSync10(dir).sort()) {
12492
12553
  if (rel === "" && PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(name)) continue;
12493
- const full = join29(dir, name);
12554
+ const full = join30(dir, name);
12494
12555
  const relPath = rel === "" ? name : `${rel}/${name}`;
12495
12556
  let stat;
12496
12557
  try {
@@ -12520,7 +12581,7 @@ function hashProjectDir(projectDir, files = listSiteFiles(projectDir)) {
12520
12581
  for (const rel of files) {
12521
12582
  hash.update(rel);
12522
12583
  hash.update("\0");
12523
- const fd = openSync5(join29(projectDir, rel), "r");
12584
+ const fd = openSync5(join30(projectDir, rel), "r");
12524
12585
  try {
12525
12586
  let read;
12526
12587
  while ((read = readSync4(fd, chunk, 0, chunk.length, null)) > 0) {